[nelson] 10.20221207.2.100038 u-boot source

GitOrigin-RevId: 1e5df0332f2cb6c034d41b03747071196c848166
Change-Id: Ia414078c61b8965571da9dbe2487e1c6d1b8e045
Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/724790
Reviewed-by: Austin Schreiber <acschreiber@google.com>
diff --git a/.checkpatch.conf b/.checkpatch.conf
new file mode 100644
index 0000000..95f1963
--- /dev/null
+++ b/.checkpatch.conf
@@ -0,0 +1,30 @@
+# Not Linux, so don't expect a Linux tree.
+--no-tree
+
+# Temporary for false positive in checkpatch
+--ignore COMPLEX_MACRO
+
+# For CONFIG_SYS_I2C_NOPROBES
+--ignore MULTISTATEMENT_MACRO_USE_DO_WHILE
+
+# For simple_strtoul
+--ignore CONSIDER_KSTRTO
+
+# For min/max
+--ignore MINMAX
+
+# enable more tests
+--strict
+
+# Not Linux, so we don't recommend usleep_range() over udelay()
+--ignore USLEEP_RANGE
+
+# Ignore networking block comment style
+--ignore NETWORKING_BLOCK_COMMENT_STYLE
+
+# Ignore "WARNING: Prefer ether_addr_copy() over memcpy() if the Ethernet
+# addresses are __aligned(2)".
+--ignore PREFER_ETHER_ADDR_COPY
+
+# A bit shorter of a description is OK with us.
+--min-conf-desc-length=2
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..196ca31
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,504 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# clang-format configuration file. Intended for clang-format >= 4.
+#
+# For more information, see:
+#
+#   Documentation/process/clang-format.rst
+#   https://clang.llvm.org/docs/ClangFormat.html
+#   https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+#
+---
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
+AlignOperands: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+  AfterClass: false
+  AfterControlStatement: false
+  AfterEnum: false
+  AfterFunction: true
+  AfterNamespace: true
+  AfterObjCDeclaration: false
+  AfterStruct: false
+  AfterUnion: false
+  #AfterExternBlock: false # Unknown to clang-format-5.0
+  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
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+#CompactNamespaces: false # Unknown to clang-format-4.0
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+#FixNamespaceComments: false # Unknown to clang-format-4.0
+
+# Taken from:
+#   git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
+#   | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$,  - '\1'," \
+#   | sort | uniq
+ForEachMacros:
+  - '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_integrity_vec'
+  - '__bio_for_each_segment'
+  - 'bio_for_each_segment'
+  - 'bio_for_each_segment_all'
+  - 'bio_list_for_each'
+  - 'bip_for_each_vec'
+  - '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_for_each_spilled_reg'
+  - 'btree_for_each_safe128'
+  - 'btree_for_each_safe32'
+  - 'btree_for_each_safe64'
+  - 'btree_for_each_safel'
+  - 'card_for_each_dev'
+  - 'cgroup_taskset_for_each'
+  - 'cgroup_taskset_for_each_leader'
+  - 'cpufreq_for_each_entry'
+  - 'cpufreq_for_each_entry_idx'
+  - 'cpufreq_for_each_valid_entry'
+  - 'cpufreq_for_each_valid_entry_idx'
+  - 'css_for_each_child'
+  - 'css_for_each_descendant_post'
+  - 'css_for_each_descendant_pre'
+  - 'device_for_each_child_node'
+  - 'dma_fence_chain_for_each'
+  - 'drm_atomic_crtc_for_each_plane'
+  - 'drm_atomic_crtc_state_for_each_plane'
+  - 'drm_atomic_crtc_state_for_each_plane_state'
+  - 'drm_atomic_for_each_plane_damage'
+  - 'drm_client_for_each_connector_iter'
+  - 'drm_client_for_each_modeset'
+  - 'drm_connector_for_each_possible_encoder'
+  - 'drm_for_each_connector_iter'
+  - 'drm_for_each_crtc'
+  - 'drm_for_each_encoder'
+  - 'drm_for_each_encoder_mask'
+  - 'drm_for_each_fb'
+  - 'drm_for_each_legacy_plane'
+  - 'drm_for_each_plane'
+  - 'drm_for_each_plane_mask'
+  - 'drm_for_each_privobj'
+  - 'drm_mm_for_each_hole'
+  - 'drm_mm_for_each_node'
+  - 'drm_mm_for_each_node_in_range'
+  - 'drm_mm_for_each_node_safe'
+  - 'flow_action_for_each'
+  - 'for_each_active_dev_scope'
+  - 'for_each_active_drhd_unit'
+  - 'for_each_active_iommu'
+  - 'for_each_available_child_of_node'
+  - 'for_each_bio'
+  - 'for_each_board_func_rsrc'
+  - 'for_each_bvec'
+  - 'for_each_card_components'
+  - 'for_each_card_links'
+  - 'for_each_card_links_safe'
+  - 'for_each_card_prelinks'
+  - 'for_each_card_rtds'
+  - 'for_each_card_rtds_safe'
+  - 'for_each_cgroup_storage_type'
+  - 'for_each_child_of_node'
+  - 'for_each_clear_bit'
+  - 'for_each_clear_bit_from'
+  - 'for_each_cmsghdr'
+  - '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_dev_addr'
+  - 'for_each_dev_scope'
+  - 'for_each_displayid_db'
+  - 'for_each_dma_cap_mask'
+  - 'for_each_dpcm_be'
+  - 'for_each_dpcm_be_rollback'
+  - 'for_each_dpcm_be_safe'
+  - 'for_each_dpcm_fe'
+  - 'for_each_drhd_unit'
+  - 'for_each_dss_dev'
+  - '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_evictable_lru'
+  - 'for_each_fib6_node_rt_rcu'
+  - 'for_each_fib6_walker_rt'
+  - 'for_each_free_mem_pfn_range_in_zone'
+  - 'for_each_free_mem_pfn_range_in_zone_from'
+  - 'for_each_free_mem_range'
+  - 'for_each_free_mem_range_reverse'
+  - 'for_each_func_rsrc'
+  - 'for_each_hstate'
+  - 'for_each_if'
+  - 'for_each_iommu'
+  - 'for_each_ip_tunnel_rcu'
+  - 'for_each_irq_nr'
+  - 'for_each_link_codecs'
+  - 'for_each_link_platforms'
+  - 'for_each_lru'
+  - 'for_each_matching_node'
+  - 'for_each_matching_node_and_match'
+  - 'for_each_memblock'
+  - 'for_each_memblock_type'
+  - 'for_each_memcg_cache_index'
+  - 'for_each_mem_pfn_range'
+  - 'for_each_mem_range'
+  - 'for_each_mem_range_rev'
+  - 'for_each_migratetype_order'
+  - 'for_each_msi_entry'
+  - 'for_each_msi_entry_safe'
+  - 'for_each_net'
+  - 'for_each_netdev'
+  - 'for_each_netdev_continue'
+  - 'for_each_netdev_continue_rcu'
+  - 'for_each_netdev_feature'
+  - 'for_each_netdev_in_bond_rcu'
+  - '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_private_obj_in_state'
+  - 'for_each_node'
+  - 'for_each_node_by_name'
+  - 'for_each_node_by_type'
+  - 'for_each_node_mask'
+  - 'for_each_node_state'
+  - 'for_each_node_with_cpus'
+  - 'for_each_node_with_property'
+  - 'for_each_of_allnodes'
+  - 'for_each_of_allnodes_from'
+  - 'for_each_of_cpu_node'
+  - 'for_each_of_pci_range'
+  - 'for_each_old_connector_in_state'
+  - 'for_each_old_crtc_in_state'
+  - 'for_each_old_mst_mgr_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_pci_bridge'
+  - 'for_each_pci_dev'
+  - 'for_each_pci_msi_entry'
+  - 'for_each_populated_zone'
+  - 'for_each_possible_cpu'
+  - 'for_each_present_cpu'
+  - 'for_each_prime_number'
+  - 'for_each_prime_number_from'
+  - 'for_each_process'
+  - 'for_each_process_thread'
+  - 'for_each_property_of_node'
+  - 'for_each_registered_fb'
+  - 'for_each_reserved_mem_region'
+  - 'for_each_rtd_codec_dai'
+  - 'for_each_rtd_codec_dai_rollback'
+  - 'for_each_rtdcom'
+  - 'for_each_rtdcom_safe'
+  - 'for_each_set_bit'
+  - 'for_each_set_bit_from'
+  - 'for_each_sg'
+  - 'for_each_sg_dma_page'
+  - 'for_each_sg_page'
+  - 'for_each_sibling_event'
+  - 'for_each_subelement'
+  - 'for_each_subelement_extid'
+  - 'for_each_subelement_id'
+  - '__for_each_thread'
+  - 'for_each_thread'
+  - 'for_each_zone'
+  - 'for_each_zone_zonelist'
+  - 'for_each_zone_zonelist_nodemask'
+  - 'fwnode_for_each_available_child_node'
+  - 'fwnode_for_each_child_node'
+  - 'fwnode_graph_for_each_endpoint'
+  - 'gadget_for_each_ep'
+  - 'genradix_for_each'
+  - 'genradix_for_each_from'
+  - 'hash_for_each'
+  - 'hash_for_each_possible'
+  - 'hash_for_each_possible_rcu'
+  - 'hash_for_each_possible_rcu_notrace'
+  - 'hash_for_each_possible_safe'
+  - 'hash_for_each_rcu'
+  - 'hash_for_each_safe'
+  - 'hctx_for_each_ctx'
+  - 'hlist_bl_for_each_entry'
+  - 'hlist_bl_for_each_entry_rcu'
+  - 'hlist_bl_for_each_entry_safe'
+  - 'hlist_for_each'
+  - 'hlist_for_each_entry'
+  - 'hlist_for_each_entry_continue'
+  - 'hlist_for_each_entry_continue_rcu'
+  - 'hlist_for_each_entry_continue_rcu_bh'
+  - 'hlist_for_each_entry_from'
+  - 'hlist_for_each_entry_from_rcu'
+  - 'hlist_for_each_entry_rcu'
+  - 'hlist_for_each_entry_rcu_bh'
+  - 'hlist_for_each_entry_rcu_notrace'
+  - 'hlist_for_each_entry_safe'
+  - '__hlist_for_each_rcu'
+  - 'hlist_for_each_safe'
+  - 'hlist_nulls_for_each_entry'
+  - 'hlist_nulls_for_each_entry_from'
+  - 'hlist_nulls_for_each_entry_rcu'
+  - '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'
+  - 'idr_for_each_entry_ul'
+  - 'in_dev_for_each_ifa_rcu'
+  - 'in_dev_for_each_ifa_rtnl'
+  - 'inet_bind_bucket_for_each'
+  - 'inet_lhash2_for_each_icsk_rcu'
+  - 'key_for_each'
+  - 'key_for_each_safe'
+  - 'klp_for_each_func'
+  - 'klp_for_each_func_safe'
+  - 'klp_for_each_func_static'
+  - 'klp_for_each_object'
+  - 'klp_for_each_object_safe'
+  - 'klp_for_each_object_static'
+  - 'kvm_for_each_memslot'
+  - 'kvm_for_each_vcpu'
+  - 'list_for_each'
+  - 'list_for_each_codec'
+  - 'list_for_each_codec_safe'
+  - 'list_for_each_entry'
+  - 'list_for_each_entry_continue'
+  - 'list_for_each_entry_continue_rcu'
+  - 'list_for_each_entry_continue_reverse'
+  - 'list_for_each_entry_from'
+  - 'list_for_each_entry_from_rcu'
+  - 'list_for_each_entry_from_reverse'
+  - 'list_for_each_entry_lockless'
+  - 'list_for_each_entry_rcu'
+  - 'list_for_each_entry_reverse'
+  - 'list_for_each_entry_safe'
+  - 'list_for_each_entry_safe_continue'
+  - 'list_for_each_entry_safe_from'
+  - 'list_for_each_entry_safe_reverse'
+  - 'list_for_each_prev'
+  - 'list_for_each_prev_safe'
+  - 'list_for_each_safe'
+  - 'llist_for_each'
+  - 'llist_for_each_entry'
+  - 'llist_for_each_entry_safe'
+  - 'llist_for_each_safe'
+  - 'media_device_for_each_entity'
+  - 'media_device_for_each_intf'
+  - 'media_device_for_each_link'
+  - 'media_device_for_each_pad'
+  - 'nanddev_io_for_each_page'
+  - 'netdev_for_each_lower_dev'
+  - 'netdev_for_each_lower_private'
+  - 'netdev_for_each_lower_private_rcu'
+  - 'netdev_for_each_mc_addr'
+  - 'netdev_for_each_uc_addr'
+  - 'netdev_for_each_upper_dev_rcu'
+  - 'netdev_hw_addr_list_for_each'
+  - 'nft_rule_for_each_expr'
+  - 'nla_for_each_attr'
+  - 'nla_for_each_nested'
+  - 'nlmsg_for_each_attr'
+  - 'nlmsg_for_each_msg'
+  - 'nr_neigh_for_each'
+  - 'nr_neigh_for_each_safe'
+  - 'nr_node_for_each'
+  - 'nr_node_for_each_safe'
+  - 'of_for_each_phandle'
+  - 'of_property_for_each_string'
+  - 'of_property_for_each_u32'
+  - 'pci_bus_for_each_resource'
+  - 'ping_portaddr_for_each_entry'
+  - 'plist_for_each'
+  - 'plist_for_each_continue'
+  - 'plist_for_each_entry'
+  - 'plist_for_each_entry_continue'
+  - 'plist_for_each_entry_safe'
+  - 'plist_for_each_safe'
+  - 'pnp_for_each_card'
+  - 'pnp_for_each_dev'
+  - 'protocol_for_each_card'
+  - 'protocol_for_each_dev'
+  - 'queue_for_each_hw_ctx'
+  - 'radix_tree_for_each_slot'
+  - 'radix_tree_for_each_tagged'
+  - 'rbtree_postorder_for_each_entry_safe'
+  - 'rdma_for_each_block'
+  - 'rdma_for_each_port'
+  - 'resource_list_for_each_entry'
+  - 'resource_list_for_each_entry_safe'
+  - 'rhl_for_each_entry_rcu'
+  - 'rhl_for_each_rcu'
+  - 'rht_for_each'
+  - 'rht_for_each_entry'
+  - 'rht_for_each_entry_from'
+  - 'rht_for_each_entry_rcu'
+  - 'rht_for_each_entry_rcu_from'
+  - 'rht_for_each_entry_safe'
+  - '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'
+  - 'scsi_for_each_prot_sg'
+  - 'scsi_for_each_sg'
+  - 'sctp_for_each_hentry'
+  - 'sctp_skb_for_each'
+  - 'shdma_for_each_chan'
+  - '__shost_for_each_device'
+  - 'shost_for_each_device'
+  - 'sk_for_each'
+  - 'sk_for_each_bound'
+  - 'sk_for_each_entry_offset_rcu'
+  - 'sk_for_each_from'
+  - 'sk_for_each_rcu'
+  - 'sk_for_each_safe'
+  - 'sk_nulls_for_each'
+  - 'sk_nulls_for_each_from'
+  - 'sk_nulls_for_each_rcu'
+  - 'snd_array_for_each'
+  - 'snd_pcm_group_for_each_entry'
+  - 'snd_soc_dapm_widget_for_each_path'
+  - 'snd_soc_dapm_widget_for_each_path_safe'
+  - 'snd_soc_dapm_widget_for_each_sink_path'
+  - 'snd_soc_dapm_widget_for_each_source_path'
+  - 'tb_property_for_each'
+  - 'tcf_exts_for_each_action'
+  - 'udp_portaddr_for_each_entry'
+  - 'udp_portaddr_for_each_entry_rcu'
+  - 'usb_hub_for_each_child'
+  - 'v4l2_device_for_each_subdev'
+  - 'v4l2_m2m_for_each_dst_buf'
+  - 'v4l2_m2m_for_each_dst_buf_safe'
+  - 'v4l2_m2m_for_each_src_buf'
+  - 'v4l2_m2m_for_each_src_buf_safe'
+  - 'virtio_device_for_each_vq'
+  - 'xa_for_each'
+  - 'xa_for_each_marked'
+  - 'xa_for_each_start'
+  - 'xas_for_each'
+  - 'xas_for_each_conflict'
+  - 'xas_for_each_marked'
+  - 'zorro_for_each_dev'
+
+#IncludeBlocks: Preserve # Unknown to clang-format-5.0
+IncludeCategories:
+  - Regex: '.*'
+    Priority: 1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+#IndentPPDirectives: None # Unknown to clang-format-5.0
+IndentWidth: 8
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: Inner
+#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
+ObjCBlockIndentWidth: 8
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: true
+
+# Taken from git's rules
+#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakString: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 60
+
+PointerAlignment: Right
+ReflowComments: false
+SortIncludes: false
+#SortUsingDeclarations: false # Unknown to clang-format-4.0
+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
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp03
+TabWidth: 8
+UseTab: Always
+...
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..23599b9
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,3 @@
+Please do not submit a Pull Request via github.  Our project makes use of
+mailing lists for patch submission and review.  For more details please
+see https://www.denx.de/wiki/U-Boot/Patches
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c7df373
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,106 @@
+#
+# NOTE! Don't add files that are generated in specific
+# subdirectories here. Add them in the ".gitignore" file
+# in that subdirectory instead.
+#
+# Normal rules (sorted alphabetically)
+#
+.*
+*.a
+*.bin
+*.cfgout
+*.dtb
+*.dtb.S
+*.elf
+*.exe
+*.gcda
+*.gcno
+*.i
+*.lex.c
+*.lst
+*.mod.c
+*.o
+*.o.*
+*.order
+*.patch
+*.s
+*.su
+*.swp
+*.tab.[ch]
+
+# Build tree
+/build-*
+
+#
+# Top-level generic files
+#
+fit-dtb.blob
+/MLO*
+/SPL*
+/System.map
+/u-boot*
+/boards.cfg
+
+#
+# git files that we don't want to ignore even it they are dot-files
+#
+!.gitignore
+!.mailmap
+
+#
+# Generated files
+#
+/spl/
+/tpl/
+/defconfig
+board/amlogic/sm1_elaine_*/firmware/acs.d
+board/amlogic/sm1_elaine_*/firmware/acs.dump
+board/amlogic/sm1_elaine_*/firmware/acs.ld
+board/amlogic/sm1_elaine_*/firmware/acs.ld.d
+board/amlogic/sm1_elaine_*/firmware/acs.map
+board/amlogic/sm1_elaine_*/firmware/acs_entry.d
+build/*
+fip/build/*
+fip/sm1/aml_ddr.fw
+fip/sm1/bl31.img
+fip/sm1/bl32.img
+scp_task/*
+
+#
+# Generated include files
+#
+/include/config/
+/include/generated/
+
+# stgit generated dirs
+patches-*
+.stgit-edit.txt
+
+# quilt's files
+patches
+series
+
+# gdb files
+.gdb_history
+
+# cscope files
+cscope.*
+
+# tags files
+/tags
+/ctags
+/etags
+
+# gnu global files
+GPATH
+GRTAGS
+GSYMS
+GTAGS
+
+*.orig
+*~
+\#*#
+
+# add .clang-format back in
+!.clang-format
+
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..1bee048
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,38 @@
+#
+# This list is used by git-shortlog to fix a few botched name translations
+# in the git archive, either because the author's full name was messed up
+# and/or not always written the same way, making contributions from the
+# same person appearing not to be so or badly displayed.
+#
+# This file can be modified by hand or updated by the following command:
+#  scripts/mailmapper > tmp; mv tmp .mailmap
+#
+
+Allen Martin <amartin@nvidia.com>
+Andreas Bießmann <andreas.devel@googlemail.com>
+Andreas Bießmann <andreas@biessmann.org>
+Aneesh V <aneesh@ti.com>
+Dirk Behme <dirk.behme@googlemail.com>
+Fabio Estevam <fabio.estevam@nxp.com>
+Jagan Teki <402jagan@gmail.com>
+Jagan Teki <jaganna@gmail.com>
+Jagan Teki <jaganna@xilinx.com>
+Jagan Teki <jagannadh.teki@gmail.com>
+Jagan Teki <jagannadha.sutradharudu-teki@xilinx.com>
+Markus Klotzbuecher <mk@denx.de>
+Paul Burton <paul.burton@mips.com> <paul.burton@imgtec.com>
+Prabhakar Kushwaha <prabhakar@freescale.com>
+Rajeshwari Shinde <rajeshwari.s@samsung.com>
+Ricardo Ribalda <ricardo.ribalda@uam.es>
+Ricardo Ribalda <ricardo.ribalda@gmail.com>
+Sandeep Paulraj <s-paulraj@ti.com>
+Shaohui Xie <Shaohui.Xie@freescale.com>
+Stefan Roese <stroese>
+Stefano Babic <sbabic@denx.de>
+TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+Wolfgang Denk <wdenk>
+York Sun <yorksun@freescale.com>
+York Sun <york.sun@nxp.com>
+Ɓukasz Majewski <l.majewski@samsung.com>
+Lukasz Majewski <lukma@denx.de>
+Mirza <Taimoor_Mirza@mentor.com>
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..321fd79
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,465 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright Roger Meier <r.meier@siemens.com>
+
+# build U-Boot on Travis CI - https://travis-ci.org/
+
+sudo: required
+dist: trusty
+
+language: c
+
+addons:
+  apt:
+    sources:
+    - ubuntu-toolchain-r-test
+    - llvm-toolchain-trusty-7
+    packages:
+    - cppcheck
+    - sloccount
+    - sparse
+    - bc
+    - build-essential
+    - libsdl1.2-dev
+    - python
+    - python-virtualenv
+    - swig
+    - libpython-dev
+    - iasl
+    - grub-efi-ia32-bin
+    - grub-efi-amd64-bin
+    - rpm2cpio
+    - wget
+    - device-tree-compiler
+    - lzop
+    - liblz4-tool
+    - libisl15
+    - clang-7
+
+install:
+ # Clone uboot-test-hooks
+ - git clone --depth=1 git://github.com/swarren/uboot-test-hooks.git /tmp/uboot-test-hooks
+ - ln -s travis-ci /tmp/uboot-test-hooks/bin/`hostname`
+ - ln -s travis-ci /tmp/uboot-test-hooks/py/`hostname`
+ # prepare buildman environment
+ - echo -e "[toolchain]\nroot = /usr" > ~/.buildman
+ - echo -e "arc = /tmp/arc_gnu_2018.09_prebuilt_uclibc_le_archs_linux_install" >> ~/.buildman
+ - echo -e "\n[toolchain-alias]\nsh = sh2\n" >> ~/.buildman
+ - cat ~/.buildman
+ - virtualenv /tmp/venv
+ - . /tmp/venv/bin/activate
+ - pip install pytest==2.8.7
+ - pip install python-subunit
+ - grub-mkimage -o ~/grub_x86.efi -O i386-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
+ - grub-mkimage -o ~/grub_x64.efi -O x86_64-efi normal  echo lsefimmap lsefi lsefisystab efinet tftp minicmd
+ - mkdir ~/grub2-arm
+ - ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/suse/armv7hl/grub2-arm-efi-2.02~beta2-87.1.armv7hl.rpm | rpm2cpio | cpio -di )
+ - mkdir ~/grub2-arm64
+ - ( cd ~/grub2-arm64; wget -O - http://download.opensuse.org/ports/aarch64/distribution/leap/42.2/repo/oss/suse/aarch64/grub2-arm64-efi-2.02~beta2-87.1.aarch64.rpm | rpm2cpio | cpio -di )
+
+env:
+  global:
+    - PATH=/tmp/qemu-install/bin:/tmp/uboot-test-hooks/bin:/usr/bin:/bin
+    - PYTHONPATH=/tmp/uboot-test-hooks/py/travis-ci
+    - BUILD_DIR=build
+    - HOSTCC="cc"
+    - HOSTCXX="c++"
+
+before_script:
+  # install toolchains based on TOOLCHAIN} variable
+  - if [[ "${TOOLCHAIN}" == *m68k* ]]; then ./tools/buildman/buildman --fetch-arch m68k ; fi
+  - if [[ "${TOOLCHAIN}" == *microblaze* ]]; then ./tools/buildman/buildman --fetch-arch microblaze ; fi
+  - if [[ "${TOOLCHAIN}" == *mips* ]]; then ./tools/buildman/buildman --fetch-arch mips ; fi
+  - if [[ "${TOOLCHAIN}" == *sh* ]]; then ./tools/buildman/buildman --fetch-arch sh2 ; fi
+  - if [[ "${TOOLCHAIN}" == *i386* ]]; then
+      ./tools/buildman/buildman --fetch-arch i386;
+      echo -e "\n[toolchain-alias]\nx86 = i386" >> ~/.buildman;
+    fi
+  - if [[ "${TOOLCHAIN}" == arc ]]; then
+       wget https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases/download/arc-2018.09-release/arc_gnu_2018.09_prebuilt_uclibc_le_archs_linux_install.tar.gz &&
+       tar -C /tmp -xf arc_gnu_2018.09_prebuilt_uclibc_le_archs_linux_install.tar.gz;
+    fi
+  - if [[ "${TOOLCHAIN}" == *xtensa* ]]; then
+       wget https://github.com/foss-xtensa/toolchain/releases/download/2018.02/x86_64-2018.02-${TOOLCHAIN}.tar.gz &&
+       tar -C /tmp -xf x86_64-2018.02-${TOOLCHAIN}.tar.gz &&
+       echo -e "\n[toolchain-prefix]\nxtensa = /tmp/2018.02/${TOOLCHAIN}/bin/${TOOLCHAIN}-" >> ~/.buildman;
+    fi
+  # If TOOLCHAIN is unset, we're on some flavour of ARM.
+  - if [[ "${TOOLCHAIN}" == "" ]]; then
+       ./tools/buildman/buildman --fetch-arch arm &&
+       ./tools/buildman/buildman --fetch-arch aarch64;
+    fi
+  - if [[ "${TOOLCHAIN}" == "powerpc" ]]; then ./tools/buildman/buildman --fetch-arch powerpc; fi
+  - if [[ "${TOOLCHAIN}" == "riscv" ]]; then
+       ./tools/buildman/buildman --fetch-arch riscv64;
+       echo -e "\n[toolchain-alias]\nriscv = riscv64" >> ~/.buildman;
+    fi
+  - if [[ "${QEMU_TARGET}" != "" ]]; then
+       git clone git://git.qemu.org/qemu.git /tmp/qemu;
+       pushd /tmp/qemu;
+       git submodule update --init dtc &&
+       git checkout v3.0.0 &&
+       ./configure --prefix=/tmp/qemu-install --target-list=${QEMU_TARGET} &&
+       make -j4 all install;
+       popd;
+    fi
+
+script:
+ # Comments must be outside the command strings below, or the Travis parser
+ # will get confused.
+ #
+ # From buildman, exit code 129 means warnings only.  If we've been asked to
+ # use clang only do one configuration.
+ - if [[ "${TOOLCHAIN}" == "clang" ]]; then
+     ret=0;
+     make O=../.bm-work/${TEST_PY_BD} HOSTCC=clang-7 CC=clang-7 -j$(nproc)
+       KCFLAGS=-Werror sandbox_config all || ret=$?;
+     if [[ $ret -ne 0 ]]; then
+       exit $ret;
+     fi;
+   elif [[ "${BUILDMAN}" != "" ]]; then
+     ret=0;
+     tools/buildman/buildman -P -E ${BUILDMAN} || ret=$?;
+     if [[ $ret -ne 0 && $ret -ne 129 ]]; then
+       tools/buildman/buildman -sdeP ${BUILDMAN};
+       exit $ret;
+     fi;
+   fi
+ # "not a_test_which_does_not_exist" is a dummy -k parameter which will
+ # never prevent any test from running. That way, we can always pass
+ # "-k something" even when $TEST_PY_TEST_SPEC doesnt need a custom
+ # value.
+ - export UBOOT_TRAVIS_BUILD_DIR=`cd .. && pwd`/.bm-work/${TEST_PY_BD};
+   cp ~/grub_x86.efi $UBOOT_TRAVIS_BUILD_DIR/;
+   cp ~/grub_x64.efi $UBOOT_TRAVIS_BUILD_DIR/;
+   cp ~/grub2-arm/usr/lib/grub2/arm-efi/grub.efi $UBOOT_TRAVIS_BUILD_DIR/grub_arm.efi;
+   cp ~/grub2-arm64/usr/lib/grub2/arm64-efi/grub.efi $UBOOT_TRAVIS_BUILD_DIR/grub_arm64.efi;
+   if [[ "${TEST_PY_BD}" != "" ]]; then
+     ./test/py/test.py --bd ${TEST_PY_BD} ${TEST_PY_ID}
+       -k "${TEST_PY_TEST_SPEC:-not a_test_which_does_not_exist}"
+       --build-dir "$UBOOT_TRAVIS_BUILD_DIR";
+     ret=$?;
+     if [[ $ret -ne 0 ]]; then
+       exit $ret;
+     fi;
+   fi;
+   if [[ -n "${TEST_PY_TOOLS}" ]]; then
+     PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt"
+     PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}"
+     ./tools/binman/binman -t &&
+     ./tools/patman/patman --test &&
+     ./tools/buildman/buildman -t &&
+     PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt"
+     PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}"
+     ./tools/dtoc/dtoc -t;
+   fi
+
+matrix:
+  include:
+  # we need to build by vendor due to 50min time limit for builds
+  # each env setting here is a dedicated build
+    - name: "buildman arc"
+      env:
+        - BUILDMAN="arc"
+          TOOLCHAIN="arc"
+    - name: "buildman arm11 arm7 arm920t arm946es"
+      env:
+        - BUILDMAN="arm11 arm7 arm920t arm946es"
+    - name: "buildman arm926ejs (non-freescale,siemens,atmel,kirkwood,spear)"
+      env:
+        - JOB="arm926ejs"
+          BUILDMAN="arm926ejs -x freescale,siemens,atmel,kirkwood,spear"
+    - name: "buildman atmel"
+      env:
+        - BUILDMAN="atmel"
+    - name: "buildman boundary engicam toradex"
+      env:
+        - BUILDMAN="boundary engicam toradex"
+    - name: "buildman Freescale ARM32"
+      env:
+        - BUILDMAN="freescale -x powerpc,m68k,aarch64"
+    - name: "buildman Freescale AArch64 LS10xx"
+      env:
+        - BUILDMAN="freescale&aarch64&&ls1"
+    - name: "buildman Freescale AArch64 LS20xx"
+      env:
+        - BUILDMAN="freescale&aarch64&&ls2"
+    - name: "buildman i.MX6 (non-Freescale)"
+      env:
+        - BUILDMAN="mx6 -x freescale,toradex,boundary,engicam"
+    - name: "buildman i.MX (non-Freescale,i.MX6,toradex)"
+      env:
+        - BUILDMAN="mx -x freescale,mx6,toradex"
+    - name: "buildman k2"
+      env:
+        - BUILDMAN="k2"
+    - name: "buildman samsung socfpga"
+      env:
+        - BUILDMAN="samsung socfpga"
+    - name: "buildman spear"
+      env:
+        - BUILDMAN="spear"
+    - name: "buildman sun4i"
+      env:
+        - BUILDMAN="sun4i"
+    - name: "buildman sun5i"
+      env:
+        - BUILDMAN="sun5i"
+    - name: "buildman sun6i"
+      env:
+        - BUILDMAN="sun6i"
+    - name: "buildman sun7i"
+      env:
+        - BUILDMAN="sun7i"
+    - name: "buildman sun8i"
+      env:
+        - BUILDMAN="sun8i"
+    - name: "buildman sun9i"
+      env:
+        - BUILDMAN="sun9i"
+    - name: "buildman sun50i"
+      env:
+        - BUILDMAN="sun50i"
+    - name: "buildman catch-all ARM"
+      env:
+        - BUILDMAN="arm -x arm11,arm7,arm9,aarch64,atmel,freescale,kirkwood,mvebu,siemens,tegra,uniphier,mx,samsung,sunxi,am33xx,omap,pxa,rockchip,toradex,socfpga,k2,xilinx"
+    - name: "buildman sandbox x86"
+      env:
+        - BUILDMAN="sandbox x86"
+          TOOLCHAIN="i386"
+    - name: "buildman kirkwood (excluding openrd)"
+      env:
+        - BUILDMAN="kirkwood -x openrd"
+    - name: "buildman mvebu"
+      env:
+        - BUILDMAN="mvebu"
+    - name: "buildman PXA (non-toradex)"
+      env:
+        - BUILDMAN="pxa -x toradex"
+    - name: "buildman m68k"
+      env:
+        - BUILDMAN="m68k"
+          TOOLCHAIN="m68k"
+    - name: "buildman microblaze"
+      env:
+        - BUILDMAN="microblaze"
+          TOOLCHAIN="microblaze"
+    - name: "buildman mips"
+      env:
+        - BUILDMAN="mips"
+          TOOLCHAIN="mips"
+    - name: "buildman non-Freescale PowerPC"
+      env:
+        - BUILDMAN="powerpc -x freescale"
+          TOOLCHAIN="powerpc"
+    - name: "buildman mpc85xx&freescale (excluding many)"
+      env:
+        - BUILDMAN="mpc85xx&freescale -x t208xrdb -x t4qds -x t102* -x p1_p2_rdb_pc -x p1010rdb -x corenet_ds -x b4860qds -x bsc91*"
+          TOOLCHAIN="powerpc"
+    - name: "buildman t208xrdb corenet_ds"
+      env:
+        - BUILDMAN="t208xrdb corenet_ds"
+          TOOLCHAIN="powerpc"
+    - name: "buildman Freescale PowerPC"
+      env:
+        - BUILDMAN="t4qds b4860qds mpc83xx&freescale mpc86xx&freescale"
+          TOOLCHAIN="powerpc"
+    - name: "buildman t102*"
+      env:
+        - BUILDMAN="t102*"
+          TOOLCHAIN="powerpc"
+    - name: "buildman p1_p2_rdb_pc"
+      env:
+        - BUILDMAN="p1_p2_rdb_pc"
+          TOOLCHAIN="powerpc"
+    - name: "buildman p1010rdb bsc91"
+      env:
+        - BUILDMAN="p1010rdb bsc91"
+          TOOLCHAIN="powerpc"
+    - name: "buildman siemens"
+      env:
+        - BUILDMAN="siemens"
+    - name: "buildman tegra"
+      env:
+        - BUILDMAN="tegra -x toradex"
+    - name: "buildman am33xx (no siemens)"
+      env:
+        - BUILDMAN="am33xx -x siemens"
+    - name: "buildman omap"
+      env:
+        - BUILDMAN="omap"
+    - name: "buildman uniphier"
+      env:
+        - BUILDMAN="uniphier"
+    - name: "buildman catch-all AArch64"
+      env:
+        - BUILDMAN="aarch64 -x tegra,ls1,ls2,mvebu,uniphier,sunxi,samsung,rockchip,xilinx"
+    - name: "buildman rockchip"
+      env:
+        - BUILDMAN="rockchip"
+    - name: "buildman sh"
+      env:
+        - BUILDMAN="sh -x arm"
+          TOOLCHAIN="sh"
+    - name: "buildman Xilinx (ARM)"
+      env:
+        - BUILDMAN="xilinx -x microblaze"
+    - name: "buildman xtensa"
+      env:
+        - BUILDMAN="xtensa"
+          TOOLCHAIN="xtensa-dc233c-elf"
+    - name: "buildman riscv"
+      env:
+        - BUILDMAN="riscv"
+          TOOLCHAIN="riscv"
+
+    # QA jobs for code analytics
+    # static code analysis with cppcheck (we can add --enable=all later)
+    - name: "cppcheck"
+      script:
+        - cppcheck --force --quiet --inline-suppr .
+    # search for TODO within source tree
+    - name: "grep TODO"
+      script:
+        - grep -r TODO .
+    # search for FIXME within source tree
+    - name: "grep FIXME HACK"
+      script:
+        - grep -r FIXME .
+    # search for HACK within source tree and ignore HACKKIT board
+      script:
+        - grep -r HACK . | grep -v HACKKIT
+    # some statistics about the code base
+    - name: "sloccount"
+      script:
+        - sloccount .
+    # ensure all configs have MAINTAINERS entries
+    - name: "Check for configs without MAINTAINERS entry"
+      script:
+        - if [ `./tools/genboardscfg.py -f 2>&1 | wc -l` -ne 0 ]; then exit 1; fi
+    # Ensure host tools build
+    - name: "Build tools-only"
+      script:
+        - make tools-only_config tools-only -j$(nproc)
+
+    # test/py
+    - name: "test/py sandbox"
+      env:
+        - TEST_PY_BD="sandbox"
+          BUILDMAN="^sandbox$"
+          TOOLCHAIN="i386"
+    - name: "test/py sandbox with clang"
+      env:
+        - TEST_PY_BD="sandbox"
+          BUILDMAN="^sandbox$"
+          TOOLCHAIN="clang"
+    - name: "test/py sandbox_spl"
+      env:
+        - TEST_PY_BD="sandbox_spl"
+          TEST_PY_TEST_SPEC="test_ofplatdata"
+          BUILDMAN="^sandbox$"
+          TOOLCHAIN="i386"
+          TEST_PY_TOOLS="yes"
+    - name: "test/py sandbox_flattree"
+      env:
+        - TEST_PY_BD="sandbox_flattree"
+          BUILDMAN="^sandbox_flattree$"
+          TOOLCHAIN="i386"
+    - name: "test/py vexpress_ca15_tc2"
+      env:
+        - TEST_PY_BD="vexpress_ca15_tc2"
+          TEST_PY_ID="--id qemu"
+          QEMU_TARGET="arm-softmmu"
+          BUILDMAN="^vexpress_ca15_tc2$"
+    - name: "test/py vexpress_ca9x4"
+      env:
+        - TEST_PY_BD="vexpress_ca9x4"
+          TEST_PY_ID="--id qemu"
+          QEMU_TARGET="arm-softmmu"
+          BUILDMAN="^vexpress_ca9x4$"
+    - name: "test/py integratorcp_cm926ejs"
+      env:
+        - TEST_PY_BD="integratorcp_cm926ejs"
+          TEST_PY_TEST_SPEC="not sleep"
+          TEST_PY_ID="--id qemu"
+          QEMU_TARGET="arm-softmmu"
+          BUILDMAN="^integratorcp_cm926ejs$"
+    - name: "test/py qemu_arm"
+      env:
+        - TEST_PY_BD="qemu_arm"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="arm-softmmu"
+          BUILDMAN="^qemu_arm$"
+    - name: "test/py qemu_arm64"
+      env:
+        - TEST_PY_BD="qemu_arm64"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="aarch64-softmmu"
+          BUILDMAN="^qemu_arm64$"
+    - name: "test/py qemu_mips"
+      env:
+        - TEST_PY_BD="qemu_mips"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="mips-softmmu"
+          BUILDMAN="^qemu_mips$"
+          TOOLCHAIN="mips"
+    - name: "test/py qemu_mipsel"
+      env:
+        - TEST_PY_BD="qemu_mipsel"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="mipsel-softmmu"
+          BUILDMAN="^qemu_mipsel$"
+          TOOLCHAIN="mips"
+    - name: "test/py qemu_mips64"
+      env:
+        - TEST_PY_BD="qemu_mips64"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="mips64-softmmu"
+          BUILDMAN="^qemu_mips64$"
+          TOOLCHAIN="mips"
+    - name: "test/py qemu_mips64el"
+      env:
+        - TEST_PY_BD="qemu_mips64el"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="mips64el-softmmu"
+          BUILDMAN="^qemu_mips64el$"
+          TOOLCHAIN="mips"
+    - name: "test/py qemu-ppce500"
+      env:
+        - TEST_PY_BD="qemu-ppce500"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="ppc-softmmu"
+          BUILDMAN="^qemu-ppce500$"
+          TOOLCHAIN="powerpc"
+    - name: "test/py qemu-x86"
+      env:
+        - TEST_PY_BD="qemu-x86"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="i386-softmmu"
+          BUILDMAN="^qemu-x86$"
+          TOOLCHAIN="i386"
+          BUILD_ROM="yes"
+    - name: "test/py qemu-x86_64"
+      env:
+        - TEST_PY_BD="qemu-x86_64"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="x86_64-softmmu"
+          BUILDMAN="^qemu-x86_64$"
+          TOOLCHAIN="i386"
+          BUILD_ROM="yes"
+    - name: "test/py zynq_zc702"
+      env:
+        - TEST_PY_BD="zynq_zc702"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="arm-softmmu"
+          TEST_PY_ID="--id qemu"
+          BUILDMAN="^zynq_zc702$"
+    - name: "test/py xtfpga"
+      env:
+        - TEST_PY_BD="xtfpga"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="xtensa-softmmu"
+          TEST_PY_ID="--id qemu"
+          BUILDMAN="^xtfpga$"
+          TOOLCHAIN="xtensa-dc233c-elf"
+
+# TODO make it perfect ;-r
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 9a86ba0..0000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# How to Contribute
-
-We'd love to accept your patches and contributions to this project. There are
-just a few small guidelines you need to follow.
-
-## Contributor License Agreement
-
-Contributions to this project must be accompanied by a Contributor License
-Agreement. You (or your employer) retain the copyright to your contribution;
-this simply gives us permission to use and redistribute your contributions as
-part of the project. Head over to <https://cla.developers.google.com/> to see
-your current agreements on file or to sign a new one.
-
-You generally only need to submit a CLA once, so if you've already submitted one
-(even if it was for a different project), you probably don't need to do it
-again.
-
-## Code reviews
-
-All submissions, including submissions by project members, require review. We
-use GitHub pull requests for this purpose. Consult
-[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
-information on using pull requests.
-
-## Community Guidelines
-
-This project follows
-[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
new file mode 100644
index 0000000..e74fec8
--- /dev/null
+++ b/Documentation/.gitignore
@@ -0,0 +1,2 @@
+output
+*.pyc
diff --git a/Documentation/Makefile b/Documentation/Makefile
new file mode 100644
index 0000000..2ca77ad
--- /dev/null
+++ b/Documentation/Makefile
@@ -0,0 +1,124 @@
+# -*- makefile -*-
+# Makefile for Sphinx documentation
+#
+
+subdir-y :=
+
+# You can set these variables from the command line.
+SPHINXBUILD   = sphinx-build
+SPHINXOPTS    =
+SPHINXDIRS    = .
+_SPHINXDIRS   = $(patsubst $(srctree)/Documentation/%/conf.py,%,$(wildcard $(srctree)/Documentation/*/conf.py))
+SPHINX_CONF   = conf.py
+PAPER         =
+BUILDDIR      = $(obj)/output
+PDFLATEX      = xelatex
+LATEXOPTS     = -interaction=batchmode
+
+# User-friendly check for sphinx-build
+HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
+
+ifeq ($(HAVE_SPHINX),0)
+
+.DEFAULT:
+	$(warning The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed and in PATH, or set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable.)
+	@echo
+	@./scripts/sphinx-pre-install
+	@echo "  SKIP    Sphinx $@ target."
+
+else # HAVE_SPHINX
+
+# User-friendly check for pdflatex
+HAVE_PDFLATEX := $(shell if which $(PDFLATEX) >/dev/null 2>&1; then echo 1; else echo 0; fi)
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+KERNELDOC       = $(srctree)/scripts/kernel-doc
+KERNELDOC_CONF  = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC)
+ALLSPHINXOPTS   =  $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS)
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+# commands; the 'cmd' from scripts/Kbuild.include is not *loopable*
+loop_cmd = $(echo-cmd) $(cmd_$(1)) || exit;
+
+# $2 sphinx builder e.g. "html"
+# $3 name of the build subfolder / e.g. "media", used as:
+#    * dest folder relative to $(BUILDDIR) and
+#    * cache folder relative to $(BUILDDIR)/.doctrees
+# $4 dest subfolder e.g. "man" for man pages at media/man
+# $5 reST source folder relative to $(srctree)/$(src),
+#    e.g. "media" for the linux-tv book-set at ./Documentation/media
+
+quiet_cmd_sphinx = SPHINX  $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
+      cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media $2 && \
+	PYTHONDONTWRITEBYTECODE=1 \
+	BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
+	$(SPHINXBUILD) \
+	-b $2 \
+	-c $(abspath $(srctree)/$(src)) \
+	-d $(abspath $(BUILDDIR)/.doctrees/$3) \
+	-D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) \
+	$(ALLSPHINXOPTS) \
+	$(abspath $(srctree)/$(src)/$5) \
+	$(abspath $(BUILDDIR)/$3/$4)
+
+htmldocs:
+	@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
+
+linkcheckdocs:
+	@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var)))
+
+latexdocs:
+	@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
+
+ifeq ($(HAVE_PDFLATEX),0)
+
+pdfdocs:
+	$(warning The '$(PDFLATEX)' command was not found. Make sure you have it installed and in PATH to produce PDF output.)
+	@echo "  SKIP    Sphinx $@ target."
+
+else # HAVE_PDFLATEX
+
+pdfdocs: latexdocs
+	$(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex || exit;)
+
+endif # HAVE_PDFLATEX
+
+epubdocs:
+	@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,epub,$(var),epub,$(var)))
+
+xmldocs:
+	@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,xml,$(var),xml,$(var)))
+
+endif # HAVE_SPHINX
+
+# The following targets are independent of HAVE_SPHINX, and the rules should
+# work or silently pass without Sphinx.
+
+refcheckdocs:
+	$(Q)cd $(srctree);scripts/documentation-file-ref-check
+
+cleandocs:
+	$(Q)rm -rf $(BUILDDIR)
+	$(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media clean
+
+dochelp:
+	@echo  ' Linux kernel internal documentation in different formats from ReST:'
+	@echo  '  htmldocs        - HTML'
+	@echo  '  latexdocs       - LaTeX'
+	@echo  '  pdfdocs         - PDF'
+	@echo  '  epubdocs        - EPUB'
+	@echo  '  xmldocs         - XML'
+	@echo  '  linkcheckdocs   - check for broken external links (will connect to external hosts)'
+	@echo  '  refcheckdocs    - check for references to non-existing files under Documentation'
+	@echo  '  cleandocs       - clean all generated files'
+	@echo
+	@echo  '  make SPHINXDIRS="s1 s2" [target] Generate only docs of folder s1, s2'
+	@echo  '  valid values for SPHINXDIRS are: $(_SPHINXDIRS)'
+	@echo
+	@echo  '  make SPHINX_CONF={conf-file} [target] use *additional* sphinx-build'
+	@echo  '  configuration. This is e.g. useful to build with nit-picking config.'
+	@echo
+	@echo  '  Default location for the generated documents is Documentation/output'
diff --git a/Documentation/conf.py b/Documentation/conf.py
new file mode 100644
index 0000000..168c313
--- /dev/null
+++ b/Documentation/conf.py
@@ -0,0 +1,528 @@
+# -*- coding: utf-8 -*-
+#
+# The U-Boot documentation build configuration file, created by
+# sphinx-quickstart on Fri Feb 12 13:51:46 2016.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+import sphinx
+
+# Get Sphinx version
+major, minor, patch = sphinx.version_info[:3]
+
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('sphinx'))
+from load_config import loadConfig
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.3'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure']
+
+# The name of the math extension changed on Sphinx 1.4
+if major == 1 and minor > 3:
+    extensions.append("sphinx.ext.imgmath")
+else:
+    extensions.append("sphinx.ext.pngmath")
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'Das U-Boot'
+copyright = 'The U-Boot development community'
+author = 'The U-Boot development community'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# In a normal build, version and release are are set to KERNELVERSION and
+# KERNELRELEASE, respectively, from the Makefile via Sphinx command line
+# arguments.
+#
+# The following code tries to extract the information by reading the Makefile,
+# when Sphinx is run directly (e.g. by Read the Docs).
+try:
+    makefile_version = None
+    makefile_patchlevel = None
+    for line in open('../Makefile'):
+        key, val = [x.strip() for x in line.split('=', 2)]
+        if key == 'VERSION':
+            makefile_version = val
+        elif key == 'PATCHLEVEL':
+            makefile_patchlevel = val
+        if makefile_version and makefile_patchlevel:
+            break
+except:
+    pass
+finally:
+    if makefile_version and makefile_patchlevel:
+        version = release = makefile_version + '.' + makefile_patchlevel
+    else:
+        version = release = "unknown version"
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['output']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+primary_domain = 'c'
+highlight_language = 'none'
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+
+# The Read the Docs theme is available from
+# - https://github.com/snide/sphinx_rtd_theme
+# - https://pypi.python.org/pypi/sphinx_rtd_theme
+# - python-sphinx-rtd-theme package (on Debian)
+try:
+    import sphinx_rtd_theme
+    html_theme = 'sphinx_rtd_theme'
+    html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+except ImportError:
+    sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n')
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+
+html_static_path = ['sphinx-static']
+
+html_context = {
+    'css_files': [
+        '_static/theme_overrides.css',
+    ],
+}
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+#   'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
+#   'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'TheUBootdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+'papersize': 'a4paper',
+
+# The font size ('10pt', '11pt' or '12pt').
+'pointsize': '8pt',
+
+# Latex figure (float) alignment
+#'figure_align': 'htbp',
+
+# Don't mangle with UTF-8 chars
+'inputenc': '',
+'utf8extra': '',
+
+# Additional stuff for the LaTeX preamble.
+    'preamble': '''
+	% Use some font with UTF-8 support with XeLaTeX
+        \\usepackage{fontspec}
+        \\setsansfont{DejaVu Serif}
+        \\setromanfont{DejaVu Sans}
+        \\setmonofont{DejaVu Sans Mono}
+
+     '''
+}
+
+# Fix reference escape troubles with Sphinx 1.4.x
+if major == 1 and minor > 3:
+    latex_elements['preamble']  += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
+
+if major == 1 and minor <= 4:
+    latex_elements['preamble']  += '\\usepackage[margin=0.5in, top=1in, bottom=1in]{geometry}'
+elif major == 1 and (minor > 5 or (minor == 5 and patch >= 3)):
+    latex_elements['sphinxsetup'] = 'hmargin=0.5in, vmargin=1in'
+    latex_elements['preamble']  += '\\fvset{fontsize=auto}\n'
+
+# Customize notice background colors on Sphinx < 1.6:
+if major == 1 and minor < 6:
+   latex_elements['preamble']  += '''
+        \\usepackage{ifthen}
+
+        % Put notes in color and let them be inside a table
+	\\definecolor{NoteColor}{RGB}{204,255,255}
+	\\definecolor{WarningColor}{RGB}{255,204,204}
+	\\definecolor{AttentionColor}{RGB}{255,255,204}
+	\\definecolor{ImportantColor}{RGB}{192,255,204}
+	\\definecolor{OtherColor}{RGB}{204,204,204}
+        \\newlength{\\mynoticelength}
+        \\makeatletter\\newenvironment{coloredbox}[1]{%
+	   \\setlength{\\fboxrule}{1pt}
+	   \\setlength{\\fboxsep}{7pt}
+	   \\setlength{\\mynoticelength}{\\linewidth}
+	   \\addtolength{\\mynoticelength}{-2\\fboxsep}
+	   \\addtolength{\\mynoticelength}{-2\\fboxrule}
+           \\begin{lrbox}{\\@tempboxa}\\begin{minipage}{\\mynoticelength}}{\\end{minipage}\\end{lrbox}%
+	   \\ifthenelse%
+	      {\\equal{\\py@noticetype}{note}}%
+	      {\\colorbox{NoteColor}{\\usebox{\\@tempboxa}}}%
+	      {%
+	         \\ifthenelse%
+	         {\\equal{\\py@noticetype}{warning}}%
+	         {\\colorbox{WarningColor}{\\usebox{\\@tempboxa}}}%
+		 {%
+	            \\ifthenelse%
+	            {\\equal{\\py@noticetype}{attention}}%
+	            {\\colorbox{AttentionColor}{\\usebox{\\@tempboxa}}}%
+		    {%
+	               \\ifthenelse%
+	               {\\equal{\\py@noticetype}{important}}%
+	               {\\colorbox{ImportantColor}{\\usebox{\\@tempboxa}}}%
+	               {\\colorbox{OtherColor}{\\usebox{\\@tempboxa}}}%
+		    }%
+		 }%
+	      }%
+        }\\makeatother
+
+        \\makeatletter
+        \\renewenvironment{notice}[2]{%
+          \\def\\py@noticetype{#1}
+          \\begin{coloredbox}{#1}
+          \\bf\\it
+          \\par\\strong{#2}
+          \\csname py@noticestart@#1\\endcsname
+        }
+	{
+          \\csname py@noticeend@\\py@noticetype\\endcsname
+          \\end{coloredbox}
+        }
+	\\makeatother
+
+     '''
+
+# With Sphinx 1.6, it is possible to change the Bg color directly
+# by using:
+#	\definecolor{sphinxnoteBgColor}{RGB}{204,255,255}
+#	\definecolor{sphinxwarningBgColor}{RGB}{255,204,204}
+#	\definecolor{sphinxattentionBgColor}{RGB}{255,255,204}
+#	\definecolor{sphinximportantBgColor}{RGB}{192,255,204}
+#
+# However, it require to use sphinx heavy box with:
+#
+#	\renewenvironment{sphinxlightbox} {%
+#		\\begin{sphinxheavybox}
+#	}
+#		\\end{sphinxheavybox}
+#	}
+#
+# Unfortunately, the implementation is buggy: if a note is inside a
+# table, it isn't displayed well. So, for now, let's use boring
+# black and white notes.
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+# Sorted in alphabetical order
+latex_documents = [
+    ('index', 'u-boot-hacker-manual.tex', 'U-Boot Hacker Manual',
+     'The U-Boot development community', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'dasuboot', 'The U-Boot Documentation',
+     [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'DasUBoot', 'The U-Boot Documentation',
+     author, 'DasUBoot', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The basename for the epub file. It defaults to the project name.
+#epub_basename = project
+
+# The HTML theme for the epub output. Since the default themes are not
+# optimized for small screen space, using the same theme for HTML and epub
+# output is usually not wise. This defaults to 'epub', a theme designed to save
+# visual space.
+#epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or 'en' if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files that should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#epub_tocscope = 'default'
+
+# Fix unsupported image types using the Pillow.
+#epub_fix_images = False
+
+# Scale large images.
+#epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#epub_use_index = True
+
+#=======
+# rst2pdf
+#
+# Grouping the document tree into PDF files. List of tuples
+# (source start file, target name, title, author, options).
+#
+# See the Sphinx chapter of http://ralsina.me/static/manual.pdf
+#
+# FIXME: Do not add the index file here; the result will be too big. Adding
+# multiple PDF files here actually tries to get the cross-referencing right
+# *between* PDF files.
+pdf_documents = [
+    ('uboot-documentation', u'U-Boot', u'U-Boot', u'J. Random Bozo'),
+]
+
+# kernel-doc extension configuration for running Sphinx directly (e.g. by Read
+# the Docs). In a normal build, these are supplied from the Makefile via command
+# line arguments.
+kerneldoc_bin = '../scripts/kernel-doc'
+kerneldoc_srctree = '..'
+
+# ------------------------------------------------------------------------------
+# Since loadConfig overwrites settings from the global namespace, it has to be
+# the last statement in the conf.py file
+# ------------------------------------------------------------------------------
+loadConfig(globals())
diff --git a/Documentation/devicetree/bindings/axi/gdsys,ihs_axi.txt b/Documentation/devicetree/bindings/axi/gdsys,ihs_axi.txt
new file mode 100644
index 0000000..110788f
--- /dev/null
+++ b/Documentation/devicetree/bindings/axi/gdsys,ihs_axi.txt
@@ -0,0 +1,22 @@
+gdsys AXI busses of IHS FPGA devices
+
+Certain gdsys IHS FPGAs offer a interface to their built-in AXI bus with which
+the connected devices (usually IP cores) can be controlled via software.
+
+Required properties:
+- compatible: must be "gdsys,ihs_axi"
+- reg: describes the address and length of the AXI bus's register map (within
+  the FPGA's register space)
+
+Example:
+
+fpga0_axi_video0 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "gdsys,ihs_axi";
+	reg = <0x170 0x10>;
+
+	axi_dev_1 {
+        ...
+	};
+};
diff --git a/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt
new file mode 100644
index 0000000..28c1080
--- /dev/null
+++ b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt
@@ -0,0 +1,46 @@
+gdsys Gazerbeam board driver
+
+This driver provides capabilities to access the gdsys Gazerbeam board's device
+information. Furthermore, phandles to some internal devices are provided for
+the board files.
+
+Required properties:
+- compatible:  should be "gdsys,board_gazerbeam"
+- csb:         phandle to the board's coherent system bus (CSB) device node
+- rxaui[0-3]:  phandles to the rxaui control device nodes
+- fpga[0-1]:   phandles to the board's gdsys FPGA device nodes
+- ioep[0-1]:   phandles to the board's IO endpoint device nodes
+- ver-gpios:   GPIO list to read the hardware version from
+- var-gpios:   GPIO list to read the hardware variant information from
+- reset-gpios: GPIO list for the board's reset GPIOs
+
+Example:
+
+
+board {
+	compatible = "gdsys,board_gazerbeam";
+	csb = <&board_soc>;
+	serdes = <&SERDES>;
+	rxaui0 = <&RXAUI0>;
+	rxaui1 = <&RXAUI1>;
+	rxaui2 = <&RXAUI2>;
+	rxaui3 = <&RXAUI3>;
+	fpga0 = <&FPGA0>;
+	fpga1 = <&FPGA1>;
+	ioep0 = <&IOEP0>;
+	ioep1 = <&IOEP1>;
+
+	ver-gpios = <&PPCPCA 12 0
+		     &PPCPCA 13 0
+		     &PPCPCA 14 0
+		     &PPCPCA 15 0>;
+
+	/* MC2/SC-Board */
+	var-gpios-mc2 = <&GPIO_VB0 0 0    /* VAR-MC_SC */
+			 &GPIO_VB0 11 0>; /* VAR-CON */
+	/* MC4-Board */
+	var-gpios-mc4 = <&GPIO_VB1 0 0    /* VAR-MC_SC */
+			 &GPIO_VB1 11 0>; /* VAR-CON */
+
+	reset-gpios = <&gpio0 1 0 &gpio0 2 1>;
+};
diff --git a/Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt b/Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt
new file mode 100644
index 0000000..8313da8
--- /dev/null
+++ b/Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt
@@ -0,0 +1,23 @@
+MPC83xx system clock devices
+
+MPC83xx SoCs supply a variety of clocks to drive various components of a
+system.
+
+Required properties:
+- compatible: must be one of "fsl,mpc8308-clk",
+                             "fsl,mpc8309-clk",
+                             "fsl,mpc8313-clk",
+                             "fsl,mpc8315-clk",
+                             "fsl,mpc832x-clk",
+                             "fsl,mpc8349-clk",
+                             "fsl,mpc8360-clk",
+                             "fsl,mpc8379-clk"
+  depending on which SoC is employed
+- #clock-cells: Must be 1
+
+Example:
+
+socclocks: clocks {
+	compatible = "fsl,mpc832x-clk";
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt b/Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt
new file mode 100644
index 0000000..ac563d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt
@@ -0,0 +1,34 @@
+MPC83xx CPU devices
+
+MPC83xx SoCs contain a e300 core as their main processor.
+
+Required properties:
+- compatible: must be one of "fsl,mpc83xx",
+                             "fsl,mpc8308",
+                             "fsl,mpc8309",
+                             "fsl,mpc8313",
+                             "fsl,mpc8315",
+                             "fsl,mpc832x",
+                             "fsl,mpc8349",
+                             "fsl,mpc8360",
+                             "fsl,mpc8379"
+- clocks: has to have two entries, which must be the core clock at index 0 and
+  the CSB (Coherent System Bus) clock at index 1. Both are given by a suitable
+  "fsl,mpc83xx-clk" device
+
+Example:
+
+socclocks: clocks {
+	compatible = "fsl,mpc8315-clk";
+	#clock-cells = <1>;
+};
+
+cpus {
+	compatible = "cpu_bus";
+
+	PowerPC,8315@0 {
+		compatible = "fsl,mpc8315";
+		clocks = <&socclocks MPC83XX_CLK_CORE
+		          &socclocks MPC83XX_CLK_CSB>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/misc/fsl,mpc83xx-serdes.txt b/Documentation/devicetree/bindings/misc/fsl,mpc83xx-serdes.txt
new file mode 100644
index 0000000..64a9b5b
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/fsl,mpc83xx-serdes.txt
@@ -0,0 +1,24 @@
+MPC83xx SerDes controller devices
+
+MPC83xx SoCs contain a built-in SerDes controller that determines which
+protocols (SATA, PCI Express, SGMII, ...) are used on the system's serdes lines
+and how the lines are configured.
+
+Required properties:
+- compatible: must be "fsl,mpc83xx-serdes"
+- reg: must point to the serdes controller's register map
+- proto: selects for which protocol the serdes lines are configured. One of
+  "sata", "pex", "pex-x2", "sgmii"
+- serdes-clk: determines the frequency the serdes lines are configured for. One
+  of 100, 125, 150.
+- vdd: determines whether 1.0V core VDD is used or not
+
+Example:
+
+SERDES: serdes@e3000 {
+	reg = <0xe3000 0x200>;
+	compatible = "fsl,mpc83xx-serdes";
+	proto = "pex";
+	serdes-clk = <100>;
+	vdd;
+};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,io-endpoint.txt b/Documentation/devicetree/bindings/misc/gdsys,io-endpoint.txt
new file mode 100644
index 0000000..db2ff8c
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/gdsys,io-endpoint.txt
@@ -0,0 +1,20 @@
+gdsys IO endpoint of IHS FPGA devices
+
+The IO endpoint of IHS FPGA devices is a packet-based transmission interface
+that allows interconnected gdsys devices to send and receive data over the
+FPGA's main ethernet connection.
+
+Required properties:
+- compatible: must be "gdsys,io-endpoint"
+- reg: describes the address and length of the endpoint's register map (within
+  the FPGA's register space)
+
+Example:
+
+fpga0_ep0 {
+	compatible = "gdsys,io-endpoint";
+	reg = <0x020 0x10
+           0x320 0x10
+           0x340 0x10
+           0x360 0x10>;
+};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt
new file mode 100644
index 0000000..acd466f
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt
@@ -0,0 +1,19 @@
+gdsys IHS FPGA for CON devices
+
+The gdsys IHS FPGA is the main FPGA on gdsys CON devices. This driver provides
+support for enabling and starting the FPGA, as well as verifying working bus
+communication.
+
+Required properties:
+- compatible: must be "gdsys,iocon_fpga"
+- reset-gpios: List of GPIOs controlling the FPGA's reset
+- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
+              done
+
+Example:
+
+FPGA0 {
+	compatible = "gdsys,iocon_fpga";
+	reset-gpios = <&PPCPCA 26 0>;
+	done-gpios = <&GPIO_VB0 19 0>;
+};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt
new file mode 100644
index 0000000..819db22
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt
@@ -0,0 +1,19 @@
+gdsys IHS FPGA for CPU devices
+
+The gdsys IHS FPGA is the main FPGA on gdsys CPU devices. This driver provides
+support for enabling and starting the FPGA, as well as verifying working bus
+communication.
+
+Required properties:
+- compatible: must be "gdsys,iocpu_fpga"
+- reset-gpios: List of GPIOs controlling the FPGA's reset
+- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
+              done
+
+Example:
+
+FPGA0 {
+	compatible = "gdsys,iocpu_fpga";
+	reset-gpios = <&PPCPCA 26 0>;
+	done-gpios = <&GPIO_VB0 19 0>;
+};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,soc.txt b/Documentation/devicetree/bindings/misc/gdsys,soc.txt
new file mode 100644
index 0000000..278e935
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/gdsys,soc.txt
@@ -0,0 +1,16 @@
+gdsys soc bus driver
+
+This driver provides a simple interface for the busses associated with gdsys
+IHS FPGAs. The bus itself contains devices whose register maps are contained
+within the FPGA's register space.
+
+Required properties:
+- fpga: A phandle to the controlling IHS FPGA
+
+Example:
+
+FPGA0BUS: fpga0bus {
+	compatible = "gdsys,soc";
+	ranges = <0x0 0xe0600000 0x00004000>;
+	fpga = <&FPGA0>;
+};
diff --git a/Documentation/devicetree/bindings/ram/fsl,mpc83xx-mem-controller.txt b/Documentation/devicetree/bindings/ram/fsl,mpc83xx-mem-controller.txt
new file mode 100644
index 0000000..da01fe9
--- /dev/null
+++ b/Documentation/devicetree/bindings/ram/fsl,mpc83xx-mem-controller.txt
@@ -0,0 +1,314 @@
+MPC83xx RAM controller
+
+This driver supplies support for the embedded RAM controller on MCP83xx-series
+SoCs.
+
+For static configuration mode, each controller node should have child nodes
+describing the actual RAM modules installed.
+
+Controller node
+===============
+
+Required properties:
+- compatible:                Must be "fsl,mpc83xx-mem-controller"
+- reg:                       The address of the RAM controller's register space
+- #address-cells:            Must be 2
+- #size-cells:               Must be 1
+- driver_software_override:  DDR driver software override is enabled (1) or
+                             disabled (0)
+- p_impedance_override:      DDR driver software p-impedance override; possible
+                             values:
+                              * DSO_P_IMPEDANCE_HIGHEST_Z
+                              * DSO_P_IMPEDANCE_MUCH_HIGHER_Z
+                              * DSO_P_IMPEDANCE_HIGHER_Z
+                              * DSO_P_IMPEDANCE_NOMINAL
+                              * DSO_P_IMPEDANCE_LOWER_Z
+- n_impedance_override:      DDR driver software n-impedance override; possible
+                             values:
+                              * DSO_N_IMPEDANCE_HIGHEST_Z
+                              * DSO_N_IMPEDANCE_MUCH_HIGHER_Z
+                              * DSO_N_IMPEDANCE_HIGHER_Z
+                              * DSO_N_IMPEDANCE_NOMINAL
+                              * DSO_N_IMPEDANCE_LOWER_Z
+- odt_termination_value:     ODT termination value for I/Os; possible values:
+                              * ODT_TERMINATION_75_OHM
+                              * ODT_TERMINATION_150_OHM
+- ddr_type:                  Selects voltage level for DDR pads; possible
+                             values:
+                              * DDR_TYPE_DDR2_1_8_VOLT
+                              * DDR_TYPE_DDR1_2_5_VOLT
+- mvref_sel:                 Determine where MVREF_SEL signal is generated;
+                             possible values:
+                              * MVREF_SEL_EXTERNAL
+                              * MVREF_SEL_INTERNAL_GVDD
+- m_odr:                     Disable memory transaction reordering; possible
+                             values:
+                              * M_ODR_ENABLE
+                              * M_ODR_DISABLE
+- clock_adjust:              Clock adjust; possible values:
+                              * CLOCK_ADJUST_025
+                              * CLOCK_ADJUST_05
+                              * CLOCK_ADJUST_075
+                              * CLOCK_ADJUST_1
+- ext_refresh_rec:           Extended refresh recovery time; possible values:
+                              0, 16, 32, 48, 64, 80, 96, 112
+- read_to_write:             Read-to-write turnaround; possible values:
+                              0, 1, 2, 3
+- write_to_read:             Write-to-read turnaround; possible values:
+                              0, 1, 2, 3
+- read_to_read:              Read-to-read turnaround; possible values:
+                              0, 1, 2, 3
+- write_to_write:            Write-to-write turnaround; possible values:
+                              0, 1, 2, 3
+- active_powerdown_exit:     Active powerdown exit timing; possible values:
+                              1, 2, 3, 4, 5, 6, 7
+- precharge_powerdown_exit:  Precharge powerdown exit timing; possible values:
+                              1, 2, 3, 4, 5, 6, 7
+- odt_powerdown_exit:        ODT powerdown exit timing; possible values:
+                              0, 1, 2, 3, 4, 5, 6, 7, 8,
+                              9, 10, 11, 12, 13, 14, 15
+- mode_reg_set_cycle:        Mode register set cycle time; possible values:
+                              1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+- precharge_to_activate:     Precharge-to-acitvate interval; possible values:
+                              1, 2, 3, 4, 5, 6, 7
+- activate_to_precharge:     Activate to precharge interval; possible values:
+                              4, 5, 6, 7, 8, 9, 10, 11, 12,
+                              13, 14, 15, 16, 17, 18, 19
+- activate_to_readwrite:     Activate to read/write interval for SDRAM;
+                             possible values:
+                              1, 2, 3, 4, 5, 6, 7
+- mcas_latency:              MCAS latency from READ command; possible values:
+                              * CASLAT_20
+                              * CASLAT_25
+                              * CASLAT_30
+                              * CASLAT_35
+                              * CASLAT_40
+                              * CASLAT_45
+                              * CASLAT_50
+                              * CASLAT_55
+                              * CASLAT_60
+                              * CASLAT_65
+                              * CASLAT_70
+                              * CASLAT_75
+                              * CASLAT_80
+- refresh_recovery:          Refresh recovery time; possible values:
+                              8, 9, 10, 11, 12, 13, 14, 15,
+                              16, 17, 18, 19, 20, 21, 22, 23
+- last_data_to_precharge:    Last data to precharge minimum interval; possible
+                             values:
+                              1, 2, 3, 4, 5, 6, 7
+- activate_to_activate:      Activate-to-activate interval; possible values:
+                              1, 2, 3, 4, 5, 6, 7
+- last_write_data_to_read:   Last write data pair to read command issue
+                             interval; possible values:
+                              1, 2, 3, 4, 5, 6, 7
+- additive_latency:          Additive latency; possible values:
+                              0, 1, 2, 3, 4, 5
+- mcas_to_preamble_override: MCAS-to-preamble-override; possible values:
+                              * READ_LAT
+                              * READ_LAT_PLUS_1_4
+                              * READ_LAT_PLUS_1_2
+                              * READ_LAT_PLUS_3_4
+                              * READ_LAT_PLUS_1
+                              * READ_LAT_PLUS_5_4
+                              * READ_LAT_PLUS_3_2
+                              * READ_LAT_PLUS_7_4
+                              * READ_LAT_PLUS_2
+                              * READ_LAT_PLUS_9_4
+                              * READ_LAT_PLUS_5_2
+                              * READ_LAT_PLUS_11_4
+                              * READ_LAT_PLUS_3
+                              * READ_LAT_PLUS_13_4
+                              * READ_LAT_PLUS_7_2
+                              * READ_LAT_PLUS_15_4
+                              * READ_LAT_PLUS_4
+                              * READ_LAT_PLUS_17_4
+                              * READ_LAT_PLUS_9_2
+                              * READ_LAT_PLUS_19_4
+- write_latency:             Write latency; possible values:
+                              1, 2, 3, 4, 5, 6, 7
+- read_to_precharge:         Read to precharge; possible values:
+                              1, 2, 3, 4
+- write_cmd_to_write_data:   Write command to write data strobe timing
+                             adjustment; possible values:
+                              * CLOCK_DELAY_0
+                              * CLOCK_DELAY_1_4
+                              * CLOCK_DELAY_1_2
+                              * CLOCK_DELAY_3_4
+                              * CLOCK_DELAY_1
+                              * CLOCK_DELAY_5_4
+                              * CLOCK_DELAY_3_2
+- minimum_cke_pulse_width:   Minimum CKE pulse width; possible values:
+                              1, 2, 3, 4
+- four_activates_window:     Window for four activates; possible values:
+                              1, 2, 3, 4 8, 9, 10, 11, 12,
+                              13, 14, 15, 16, 17, 18, 19
+- self_refresh:              Self refresh (during sleep); possible values:
+                              * SREN_DISABLE
+                              * SREN_ENABLE
+- ecc:                       Support for ECC; possible values:
+                              * ECC_DISABLE
+                              * ECC_ENABLE
+- registered_dram:           Support for registered DRAM; possible values:
+                              * RD_DISABLE
+                              * RD_ENABLE
+- sdram_type:                Type of SDRAM device to be used; possible values:
+                              * TYPE_DDR1
+                              * TYPE_DDR2
+- dynamic_power_management:  Dynamic power management mode; possible values:
+                              * DYN_PWR_DISABLE
+                              * DYN_PWR_ENABLE
+- databus_width:             DRAM data bus width; possible values
+                              * DATA_BUS_WIDTH_16
+                              * DATA_BUS_WIDTH_32
+- nc_auto_precharge:         Non-concurrent auto-precharge; possible values:
+                              * NCAP_DISABLE
+                              * NCAP_ENABLE
+- timing_2t:                 2T timing; possible values:
+                              * TIMING_1T
+                              * TIMING_2T
+- bank_interleaving_ctrl:    Bank (chip select) interleaving control; possible
+                             values:
+                              * INTERLEAVE_NONE
+                              * INTERLEAVE_1_AND_2
+- precharge_bit_8:           Precharge bin 8; possible values
+                              * PRECHARGE_MA_10
+                              * PRECHARGE_MA_8
+- half_strength:             Global half-strength override; possible values:
+                              * STRENGTH_FULL
+                              * STRENGTH_HALF
+- bypass_initialization:     Bypass initialization; possible values:
+                              * INITIALIZATION_DONT_BYPASS
+                              * INITIALIZATION_BYPASS
+- force_self_refresh:         Force self refresh; possible values:
+                               * MODE_NORMAL
+                               * MODE_REFRESH
+- dll_reset:                  DLL reset; possible values:
+                               * DLL_RESET_ENABLE
+                               * DLL_RESET_DISABLE
+- dqs_config:                 DQS configuration; possible values:
+                               * DQS_TRUE
+- odt_config:                 ODT configuration; possible values:
+                               * ODT_ASSERT_NEVER
+                               * ODT_ASSERT_WRITES
+                               * ODT_ASSERT_READS
+                               * ODT_ASSERT_ALWAYS
+- posted_refreshes:           Number of posted refreshes
+                               1, 2, 3, 4, 5, 6, 7, 8
+- sdmode:                     Initial value loaded into the DDR SDRAM mode
+                              register
+- esdmode:                    Initial value loaded into the DDR SDRAM extended
+                              mode register
+- esdmode2:                   Initial value loaded into the DDR SDRAM extended
+                              mode 2 register
+- esdmode3:                   Initial value loaded into the DDR SDRAM extended
+                              mode 3 register
+- refresh_interval:           Refresh interval; possible values:
+                               0 - 65535
+- precharge_interval:         Precharge interval; possible values:
+                               0 - 16383
+
+RAM module node:
+================
+
+Required properties:
+- reg:            A triple <cs addr size>, which consists of:
+                   * cs - the chipselect used to drive this RAM module
+                   * addr - the address where this RAM module's memory is map
+                     to in the global memory space
+                   * size - the size of the RAM module's memory in bytes
+- auto_precharge: Chip select auto-precharge; possible values:
+                   * AUTO_PRECHARGE_ENABLE
+                   * AUTO_PRECHARGE_DISABLE
+- odt_rd_cfg:     ODT for reads configuration; possible values:
+                   * ODT_RD_NEVER
+                   * ODT_RD_ONLY_CURRENT
+                   * ODT_RD_ONLY_OTHER_CS
+                   * ODT_RD_ONLY_OTHER_DIMM
+                   * ODT_RD_ALL
+- odt_wr_cfg:     ODT for writes configuration; possible values:
+                   * ODT_WR_NEVER
+                   * ODT_WR_ONLY_CURRENT
+                   * ODT_WR_ONLY_OTHER_CS
+                   * ODT_WR_ONLY_OTHER_DIMM
+                   * ODT_WR_ALL
+- bank_bits:      Number of bank bits for SDRAM on chip select; possible
+                  values:
+                   2, 3
+- row_bits:       Number of row bits for SDRAM on chip select; possible values:
+                   12, 13, 14
+- col_bits:       Number of column bits for SDRAM on chip select; possible
+                  values:
+                   8, 9, 10, 11
+
+Example:
+
+memory@2000 {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	compatible = "fsl,mpc83xx-mem-controller";
+	reg = <0x2000 0x1000>;
+	device_type = "memory";
+	u-boot,dm-pre-reloc;
+
+	driver_software_override = <DSO_ENABLE>;
+	p_impedance_override = <DSO_P_IMPEDANCE_NOMINAL>;
+	n_impedance_override = <DSO_N_IMPEDANCE_NOMINAL>;
+	odt_termination_value = <ODT_TERMINATION_150_OHM>;
+	ddr_type = <DDR_TYPE_DDR2_1_8_VOLT>;
+
+	clock_adjust = <CLOCK_ADJUST_05>;
+
+	read_to_write = <0>;
+	write_to_read = <0>;
+	read_to_read = <0>;
+	write_to_write = <0>;
+	active_powerdown_exit = <2>;
+	precharge_powerdown_exit = <6>;
+	odt_powerdown_exit = <8>;
+	mode_reg_set_cycle = <2>;
+
+	precharge_to_activate = <2>;
+	activate_to_precharge = <6>;
+	activate_to_readwrite = <2>;
+	mcas_latency = <CASLAT_40>;
+	refresh_recovery = <17>;
+	last_data_to_precharge = <2>;
+	activate_to_activate = <2>;
+	last_write_data_to_read = <2>;
+
+	additive_latency = <0>;
+	mcas_to_preamble_override = <READ_LAT_PLUS_1_2>;
+	write_latency = <3>;
+	read_to_precharge = <2>;
+	write_cmd_to_write_data = <CLOCK_DELAY_1_2>;
+	minimum_cke_pulse_width = <3>;
+	four_activates_window = <5>;
+
+	self_refresh = <SREN_ENABLE>;
+	sdram_type = <TYPE_DDR2>;
+	databus_width = <DATA_BUS_WIDTH_32>;
+
+	force_self_refresh = <MODE_NORMAL>;
+	dll_reset = <DLL_RESET_ENABLE>;
+	dqs_config = <DQS_TRUE>;
+	odt_config = <ODT_ASSERT_READS>;
+	posted_refreshes = <1>;
+
+	refresh_interval = <2084>;
+	precharge_interval = <256>;
+
+	sdmode = <0x0242>;
+	esdmode = <0x0440>;
+
+	ram@0 {
+		reg = <0x0 0x0 0x8000000>;
+		compatible = "nanya,nt5tu64m16hg";
+
+		odt_rd_cfg = <ODT_RD_NEVER>;
+		odt_wr_cfg = <ODT_WR_ONLY_CURRENT>;
+		bank_bits = <3>;
+		row_bits = <13>;
+		col_bits = <10>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/timer/fsl,mpc83xx-timer.txt b/Documentation/devicetree/bindings/timer/fsl,mpc83xx-timer.txt
new file mode 100644
index 0000000..608d241
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/fsl,mpc83xx-timer.txt
@@ -0,0 +1,21 @@
+MPC83xx timer devices
+
+MPC83xx SoCs offer a decrementer interrupt that can be used to implement delay
+functionality, and periodically triggered actions.
+
+Required properties:
+- compatible: must be "fsl,mpc83xx-timer"
+- clocks: must be a reference to the system's CSB (coherent system bus) clock,
+  provided by one of the "fsl,mpc83xx-clk" devices
+
+Example:
+
+socclocks: clocks {
+	compatible = "fsl,mpc832x-clk";
+	#clock-cells = <1>;
+};
+
+timer {
+	compatible = "fsl,mpc83xx-timer";
+	clocks = <&socclocks MPC83XX_CLK_CSB>;
+};
diff --git a/Documentation/efi.rst b/Documentation/efi.rst
new file mode 100644
index 0000000..51c1de2
--- /dev/null
+++ b/Documentation/efi.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+EFI subsystem
+=============
+
+Boot services
+-------------
+
+.. kernel-doc:: lib/efi_loader/efi_boottime.c
+   :internal:
+
+Runtime services
+----------------
+
+.. kernel-doc:: lib/efi_loader/efi_runtime.c
+   :internal:
diff --git a/Documentation/index.rst b/Documentation/index.rst
new file mode 100644
index 0000000..0353c10
--- /dev/null
+++ b/Documentation/index.rst
@@ -0,0 +1,11 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+#######################
+U-Boot Developer Manual
+#######################
+
+.. toctree::
+
+   efi
+   linker_lists
+   serial
diff --git a/Documentation/linker_lists.rst b/Documentation/linker_lists.rst
new file mode 100644
index 0000000..72f514e
--- /dev/null
+++ b/Documentation/linker_lists.rst
@@ -0,0 +1,100 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Linker-Generated Arrays
+=======================
+
+A linker list is constructed by grouping together linker input
+sections, each containing one entry of the list. Each input section
+contains a constant initialized variable which holds the entry's
+content. Linker list input sections are constructed from the list
+and entry names, plus a prefix which allows grouping all lists
+together. Assuming _list and _entry are the list and entry names,
+then the corresponding input section name is
+
+::
+
+  .u_boot_list_ + 2_ + @_list + _2_ + @_entry
+
+and the C variable name is
+
+::
+
+  _u_boot_list + _2_ + @_list + _2_ + @_entry
+
+This ensures uniqueness for both input section and C variable name.
+
+Note that the names differ only in the first character, "." for the
+section and "_" for the variable, so that the linker cannot confuse
+section and symbol names. From now on, both names will be referred
+to as
+
+::
+
+  %u_boot_list_ + 2_ + @_list + _2_ + @_entry
+
+Entry variables need never be referred to directly.
+
+The naming scheme for input sections allows grouping all linker lists
+into a single linker output section and grouping all entries for a
+single list.
+
+Note the two '_2_' constant components in the names: their presence
+allows putting a start and end symbols around a list, by mapping
+these symbols to sections names with components "1" (before) and
+"3" (after) instead of "2" (within).
+Start and end symbols for a list can generally be defined as
+
+::
+
+  %u_boot_list_2_ + @_list + _1_...
+  %u_boot_list_2_ + @_list + _3_...
+
+Start and end symbols for the whole of the linker lists area can be
+defined as
+
+::
+
+  %u_boot_list_1_...
+  %u_boot_list_3_...
+
+Here is an example of the sorted sections which result from a list
+"array" made up of three entries : "first", "second" and "third",
+iterated at least once.
+
+::
+
+  .u_boot_list_2_array_1
+  .u_boot_list_2_array_2_first
+  .u_boot_list_2_array_2_second
+  .u_boot_list_2_array_2_third
+  .u_boot_list_2_array_3
+
+If lists must be divided into sublists (e.g. for iterating only on
+part of a list), one can simply give the list a name of the form
+'outer_2_inner', where 'outer' is the global list name and 'inner'
+is the sub-list name. Iterators for the whole list should use the
+global list name ("outer"); iterators for only a sub-list should use
+the full sub-list name ("outer_2_inner").
+
+Here is an example of the sections generated from a global list
+named "drivers", two sub-lists named "i2c" and "pci", and iterators
+defined for the whole list and each sub-list:
+
+::
+
+  %u_boot_list_2_drivers_1
+  %u_boot_list_2_drivers_2_i2c_1
+  %u_boot_list_2_drivers_2_i2c_2_first
+  %u_boot_list_2_drivers_2_i2c_2_first
+  %u_boot_list_2_drivers_2_i2c_2_second
+  %u_boot_list_2_drivers_2_i2c_2_third
+  %u_boot_list_2_drivers_2_i2c_3
+  %u_boot_list_2_drivers_2_pci_1
+  %u_boot_list_2_drivers_2_pci_2_first
+  %u_boot_list_2_drivers_2_pci_2_second
+  %u_boot_list_2_drivers_2_pci_2_third
+  %u_boot_list_2_drivers_2_pci_3
+  %u_boot_list_2_drivers_3
+
+.. kernel-doc:: include/linker_lists.h
+   :internal:
diff --git a/Documentation/media/Makefile b/Documentation/media/Makefile
new file mode 100644
index 0000000..0efd18a
--- /dev/null
+++ b/Documentation/media/Makefile
@@ -0,0 +1,38 @@
+# Rules to convert a .h file to inline RST documentation
+
+SRC_DIR=$(srctree)/Documentation/media
+PARSER = $(srctree)/Documentation/sphinx/parse-headers.pl
+API = $(srctree)/include
+
+FILES = linker_lists.h.rst
+
+TARGETS := $(addprefix $(BUILDDIR)/, $(FILES))
+
+gen_rst = \
+	echo ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions; \
+	${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
+
+quiet_gen_rst = echo '  PARSE   $(patsubst $(srctree)/%,%,$<)'; \
+	${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
+
+silent_gen_rst = ${gen_rst}
+
+$(BUILDDIR)/linker_lists.h.rst: ${API}/linker_lists.h ${PARSER} $(SRC_DIR)/linker_lists.h.rst.exceptions
+	@$($(quiet)gen_rst)
+
+# Media build rules
+
+.PHONY: all html epub xml latex
+
+all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
+html: all
+epub: all
+xml: all
+latex: $(IMGPDF) all
+linkcheck:
+
+clean:
+	-rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null
+
+$(BUILDDIR):
+	$(Q)mkdir -p $@
diff --git a/Documentation/media/linker_lists.h.rst.exceptions b/Documentation/media/linker_lists.h.rst.exceptions
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Documentation/media/linker_lists.h.rst.exceptions
diff --git a/Documentation/serial.rst b/Documentation/serial.rst
new file mode 100644
index 0000000..ed34e59
--- /dev/null
+++ b/Documentation/serial.rst
@@ -0,0 +1,7 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Serial system
+=============
+
+.. kernel-doc:: drivers/serial/serial.c
+   :internal:
diff --git a/Documentation/sphinx-static/theme_overrides.css b/Documentation/sphinx-static/theme_overrides.css
new file mode 100644
index 0000000..522b6d4
--- /dev/null
+++ b/Documentation/sphinx-static/theme_overrides.css
@@ -0,0 +1,89 @@
+/* -*- coding: utf-8; mode: css -*-
+ *
+ * Sphinx HTML theme customization: read the doc
+ *
+ */
+
+/* Interim: Code-blocks with line nos - lines and line numbers don't line up.
+ * see: https://github.com/rtfd/sphinx_rtd_theme/issues/419
+ */
+
+div[class^="highlight"] pre {
+    line-height: normal;
+}
+.rst-content .highlight > pre {
+    line-height: normal;
+}
+
+@media screen {
+
+    /* content column
+     *
+     * RTD theme's default is 800px as max width for the content, but we have
+     * tables with tons of columns, which need the full width of the view-port.
+     */
+
+    .wy-nav-content{max-width: none; }
+
+    /* table:
+     *
+     *   - Sequences of whitespace should collapse into a single whitespace.
+     *   - make the overflow auto (scrollbar if needed)
+     *   - align caption "left" ("center" is unsuitable on vast tables)
+     */
+
+    .wy-table-responsive table td { white-space: normal; }
+    .wy-table-responsive { overflow: auto; }
+    .rst-content table.docutils caption { text-align: left; font-size: 100%; }
+
+    /* captions:
+     *
+     *   - captions should have 100% (not 85%) font size
+     *   - hide the permalink symbol as long as link is not hovered
+     */
+
+    .toc-title {
+        font-size: 150%;
+	font-weight: bold;
+    }
+
+    caption, .wy-table caption, .rst-content table.field-list caption {
+        font-size: 100%;
+    }
+    caption a.headerlink { opacity: 0; }
+    caption a.headerlink:hover { opacity: 1; }
+
+    /* Menu selection and keystrokes */
+
+    span.menuselection {
+	color: blue;
+	font-family: "Courier New", Courier, monospace
+    }
+
+    code.kbd, code.kbd span {
+	color: white;
+	background-color: darkblue;
+	font-weight: bold;
+	font-family: "Courier New", Courier, monospace
+    }
+
+    /* fix bottom margin of lists items */
+
+    .rst-content .section ul li:last-child, .rst-content .section ul li p:last-child {
+          margin-bottom: 12px;
+    }
+
+    /* inline literal: drop the borderbox, padding and red color */
+
+    code, .rst-content tt, .rst-content code {
+        color: inherit;
+        border: none;
+        padding: unset;
+        background: inherit;
+        font-size: 85%;
+    }
+
+    .rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal {
+        color: inherit;
+    }
+}
diff --git a/Documentation/sphinx/cdomain.py b/Documentation/sphinx/cdomain.py
new file mode 100644
index 0000000..cf13ff3
--- /dev/null
+++ b/Documentation/sphinx/cdomain.py
@@ -0,0 +1,165 @@
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=W0141,C0113,C0103,C0325
+u"""
+    cdomain
+    ~~~~~~~
+
+    Replacement for the sphinx c-domain.
+
+    :copyright:  Copyright (C) 2016  Markus Heiser
+    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
+
+    List of customizations:
+
+    * Moved the *duplicate C object description* warnings for function
+      declarations in the nitpicky mode. See Sphinx documentation for
+      the config values for ``nitpick`` and ``nitpick_ignore``.
+
+    * Add option 'name' to the "c:function:" directive.  With option 'name' the
+      ref-name of a function can be modified. E.g.::
+
+          .. c:function:: int ioctl( int fd, int request )
+             :name: VIDIOC_LOG_STATUS
+
+      The func-name (e.g. ioctl) remains in the output but the ref-name changed
+      from 'ioctl' to 'VIDIOC_LOG_STATUS'. The function is referenced by::
+
+          * :c:func:`VIDIOC_LOG_STATUS` or
+          * :any:`VIDIOC_LOG_STATUS` (``:any:`` needs sphinx 1.3)
+
+     * Handle signatures of function-like macros well. Don't try to deduce
+       arguments types of function-like macros.
+
+"""
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+import sphinx
+from sphinx import addnodes
+from sphinx.domains.c import c_funcptr_sig_re, c_sig_re
+from sphinx.domains.c import CObject as Base_CObject
+from sphinx.domains.c import CDomain as Base_CDomain
+
+__version__  = '1.0'
+
+# Get Sphinx version
+major, minor, patch = sphinx.version_info[:3]
+
+def setup(app):
+
+    app.override_domain(CDomain)
+
+    return dict(
+        version = __version__,
+        parallel_read_safe = True,
+        parallel_write_safe = True
+    )
+
+class CObject(Base_CObject):
+
+    """
+    Description of a C language object.
+    """
+    option_spec = {
+        "name" : directives.unchanged
+    }
+
+    def handle_func_like_macro(self, sig, signode):
+        u"""Handles signatures of function-like macros.
+
+        If the objtype is 'function' and the the signature ``sig`` is a
+        function-like macro, the name of the macro is returned. Otherwise
+        ``False`` is returned.  """
+
+        if not self.objtype == 'function':
+            return False
+
+        m = c_funcptr_sig_re.match(sig)
+        if m is None:
+            m = c_sig_re.match(sig)
+            if m is None:
+                raise ValueError('no match')
+
+        rettype, fullname, arglist, _const = m.groups()
+        arglist = arglist.strip()
+        if rettype or not arglist:
+            return False
+
+        arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
+        arglist = [a.strip() for a in arglist.split(",")]
+
+        # has the first argument a type?
+        if len(arglist[0].split(" ")) > 1:
+            return False
+
+        # This is a function-like macro, it's arguments are typeless!
+        signode  += addnodes.desc_name(fullname, fullname)
+        paramlist = addnodes.desc_parameterlist()
+        signode  += paramlist
+
+        for argname in arglist:
+            param = addnodes.desc_parameter('', '', noemph=True)
+            # separate by non-breaking space in the output
+            param += nodes.emphasis(argname, argname)
+            paramlist += param
+
+        return fullname
+
+    def handle_signature(self, sig, signode):
+        """Transform a C signature into RST nodes."""
+
+        fullname = self.handle_func_like_macro(sig, signode)
+        if not fullname:
+            fullname = super(CObject, self).handle_signature(sig, signode)
+
+        if "name" in self.options:
+            if self.objtype == 'function':
+                fullname = self.options["name"]
+            else:
+                # FIXME: handle :name: value of other declaration types?
+                pass
+        return fullname
+
+    def add_target_and_index(self, name, sig, signode):
+        # for C API items we add a prefix since names are usually not qualified
+        # by a module name and so easily clash with e.g. section titles
+        targetname = 'c.' + name
+        if targetname not in self.state.document.ids:
+            signode['names'].append(targetname)
+            signode['ids'].append(targetname)
+            signode['first'] = (not self.names)
+            self.state.document.note_explicit_target(signode)
+            inv = self.env.domaindata['c']['objects']
+            if (name in inv and self.env.config.nitpicky):
+                if self.objtype == 'function':
+                    if ('c:func', name) not in self.env.config.nitpick_ignore:
+                        self.state_machine.reporter.warning(
+                            'duplicate C object description of %s, ' % name +
+                            'other instance in ' + self.env.doc2path(inv[name][0]),
+                            line=self.lineno)
+            inv[name] = (self.env.docname, self.objtype)
+
+        indextext = self.get_index_text(name)
+        if indextext:
+            if major == 1 and minor < 4:
+                # indexnode's tuple changed in 1.4
+                # https://github.com/sphinx-doc/sphinx/commit/e6a5a3a92e938fcd75866b4227db9e0524d58f7c
+                self.indexnode['entries'].append(
+                    ('single', indextext, targetname, ''))
+            else:
+                self.indexnode['entries'].append(
+                    ('single', indextext, targetname, '', None))
+
+class CDomain(Base_CDomain):
+
+    """C language domain."""
+    name = 'c'
+    label = 'C'
+    directives = {
+        'function': CObject,
+        'member':   CObject,
+        'macro':    CObject,
+        'type':     CObject,
+        'var':      CObject,
+    }
diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py
new file mode 100755
index 0000000..f523aa6
--- /dev/null
+++ b/Documentation/sphinx/kernel_include.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=R0903, C0330, R0914, R0912, E0401
+
+u"""
+    kernel-include
+    ~~~~~~~~~~~~~~
+
+    Implementation of the ``kernel-include`` reST-directive.
+
+    :copyright:  Copyright (C) 2016  Markus Heiser
+    :license:    GPL Version 2, June 1991 see linux/COPYING for details.
+
+    The ``kernel-include`` reST-directive is a replacement for the ``include``
+    directive. The ``kernel-include`` directive expand environment variables in
+    the path name and allows to include files from arbitrary locations.
+
+    .. hint::
+
+      Including files from arbitrary locations (e.g. from ``/etc``) is a
+      security risk for builders. This is why the ``include`` directive from
+      docutils *prohibit* pathnames pointing to locations *above* the filesystem
+      tree where the reST document with the include directive is placed.
+
+    Substrings of the form $name or ${name} are replaced by the value of
+    environment variable name. Malformed variable names and references to
+    non-existing variables are left unchanged.
+"""
+
+# ==============================================================================
+# imports
+# ==============================================================================
+
+import os.path
+
+from docutils import io, nodes, statemachine
+from docutils.utils.error_reporting import SafeString, ErrorString
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.directives.body import CodeBlock, NumberLines
+from docutils.parsers.rst.directives.misc import Include
+
+__version__  = '1.0'
+
+# ==============================================================================
+def setup(app):
+# ==============================================================================
+
+    app.add_directive("kernel-include", KernelInclude)
+    return dict(
+        version = __version__,
+        parallel_read_safe = True,
+        parallel_write_safe = True
+    )
+
+# ==============================================================================
+class KernelInclude(Include):
+# ==============================================================================
+
+    u"""KernelInclude (``kernel-include``) directive"""
+
+    def run(self):
+        path = os.path.realpath(
+            os.path.expandvars(self.arguments[0]))
+
+        # to get a bit security back, prohibit /etc:
+        if path.startswith(os.sep + "etc"):
+            raise self.severe(
+                'Problems with "%s" directive, prohibited path: %s'
+                % (self.name, path))
+
+        self.arguments[0] = path
+
+        #return super(KernelInclude, self).run() # won't work, see HINTs in _run()
+        return self._run()
+
+    def _run(self):
+        """Include a file as part of the content of this reST file."""
+
+        # HINT: I had to copy&paste the whole Include.run method. I'am not happy
+        # with this, but due to security reasons, the Include.run method does
+        # not allow absolute or relative pathnames pointing to locations *above*
+        # the filesystem tree where the reST document is placed.
+
+        if not self.state.document.settings.file_insertion_enabled:
+            raise self.warning('"%s" directive disabled.' % self.name)
+        source = self.state_machine.input_lines.source(
+            self.lineno - self.state_machine.input_offset - 1)
+        source_dir = os.path.dirname(os.path.abspath(source))
+        path = directives.path(self.arguments[0])
+        if path.startswith('<') and path.endswith('>'):
+            path = os.path.join(self.standard_include_path, path[1:-1])
+        path = os.path.normpath(os.path.join(source_dir, path))
+
+        # HINT: this is the only line I had to change / commented out:
+        #path = utils.relative_path(None, path)
+
+        path = nodes.reprunicode(path)
+        encoding = self.options.get(
+            'encoding', self.state.document.settings.input_encoding)
+        e_handler=self.state.document.settings.input_encoding_error_handler
+        tab_width = self.options.get(
+            'tab-width', self.state.document.settings.tab_width)
+        try:
+            self.state.document.settings.record_dependencies.add(path)
+            include_file = io.FileInput(source_path=path,
+                                        encoding=encoding,
+                                        error_handler=e_handler)
+        except UnicodeEncodeError as error:
+            raise self.severe('Problems with "%s" directive path:\n'
+                              'Cannot encode input file path "%s" '
+                              '(wrong locale?).' %
+                              (self.name, SafeString(path)))
+        except IOError as error:
+            raise self.severe('Problems with "%s" directive path:\n%s.' %
+                      (self.name, ErrorString(error)))
+        startline = self.options.get('start-line', None)
+        endline = self.options.get('end-line', None)
+        try:
+            if startline or (endline is not None):
+                lines = include_file.readlines()
+                rawtext = ''.join(lines[startline:endline])
+            else:
+                rawtext = include_file.read()
+        except UnicodeError as error:
+            raise self.severe('Problem with "%s" directive:\n%s' %
+                              (self.name, ErrorString(error)))
+        # start-after/end-before: no restrictions on newlines in match-text,
+        # and no restrictions on matching inside lines vs. line boundaries
+        after_text = self.options.get('start-after', None)
+        if after_text:
+            # skip content in rawtext before *and incl.* a matching text
+            after_index = rawtext.find(after_text)
+            if after_index < 0:
+                raise self.severe('Problem with "start-after" option of "%s" '
+                                  'directive:\nText not found.' % self.name)
+            rawtext = rawtext[after_index + len(after_text):]
+        before_text = self.options.get('end-before', None)
+        if before_text:
+            # skip content in rawtext after *and incl.* a matching text
+            before_index = rawtext.find(before_text)
+            if before_index < 0:
+                raise self.severe('Problem with "end-before" option of "%s" '
+                                  'directive:\nText not found.' % self.name)
+            rawtext = rawtext[:before_index]
+
+        include_lines = statemachine.string2lines(rawtext, tab_width,
+                                                  convert_whitespace=True)
+        if 'literal' in self.options:
+            # Convert tabs to spaces, if `tab_width` is positive.
+            if tab_width >= 0:
+                text = rawtext.expandtabs(tab_width)
+            else:
+                text = rawtext
+            literal_block = nodes.literal_block(rawtext, source=path,
+                                    classes=self.options.get('class', []))
+            literal_block.line = 1
+            self.add_name(literal_block)
+            if 'number-lines' in self.options:
+                try:
+                    startline = int(self.options['number-lines'] or 1)
+                except ValueError:
+                    raise self.error(':number-lines: with non-integer '
+                                     'start value')
+                endline = startline + len(include_lines)
+                if text.endswith('\n'):
+                    text = text[:-1]
+                tokens = NumberLines([([], text)], startline, endline)
+                for classes, value in tokens:
+                    if classes:
+                        literal_block += nodes.inline(value, value,
+                                                      classes=classes)
+                    else:
+                        literal_block += nodes.Text(value, value)
+            else:
+                literal_block += nodes.Text(text, text)
+            return [literal_block]
+        if 'code' in self.options:
+            self.options['source'] = path
+            codeblock = CodeBlock(self.name,
+                                  [self.options.pop('code')], # arguments
+                                  self.options,
+                                  include_lines, # content
+                                  self.lineno,
+                                  self.content_offset,
+                                  self.block_text,
+                                  self.state,
+                                  self.state_machine)
+            return codeblock.run()
+        self.state_machine.insert_input(include_lines, path)
+        return []
diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
new file mode 100644
index 0000000..fbedcc3
--- /dev/null
+++ b/Documentation/sphinx/kerneldoc.py
@@ -0,0 +1,146 @@
+# coding=utf-8
+#
+# Copyright © 2016 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# Authors:
+#    Jani Nikula <jani.nikula@intel.com>
+#
+# Please make sure this works on both python2 and python3.
+#
+
+import codecs
+import os
+import subprocess
+import sys
+import re
+import glob
+
+from docutils import nodes, statemachine
+from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives, Directive
+from sphinx.ext.autodoc import AutodocReporter
+
+__version__  = '1.0'
+
+class KernelDocDirective(Directive):
+    """Extract kernel-doc comments from the specified file"""
+    required_argument = 1
+    optional_arguments = 4
+    option_spec = {
+        'doc': directives.unchanged_required,
+        'functions': directives.unchanged_required,
+        'export': directives.unchanged,
+        'internal': directives.unchanged,
+    }
+    has_content = False
+
+    def run(self):
+        env = self.state.document.settings.env
+        cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
+
+        filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
+        export_file_patterns = []
+
+        # Tell sphinx of the dependency
+        env.note_dependency(os.path.abspath(filename))
+
+        tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
+
+        # FIXME: make this nicer and more robust against errors
+        if 'export' in self.options:
+            cmd += ['-export']
+            export_file_patterns = str(self.options.get('export')).split()
+        elif 'internal' in self.options:
+            cmd += ['-internal']
+            export_file_patterns = str(self.options.get('internal')).split()
+        elif 'doc' in self.options:
+            cmd += ['-function', str(self.options.get('doc'))]
+        elif 'functions' in self.options:
+            for f in str(self.options.get('functions')).split():
+                cmd += ['-function', f]
+
+        for pattern in export_file_patterns:
+            for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
+                env.note_dependency(os.path.abspath(f))
+                cmd += ['-export-file', f]
+
+        cmd += [filename]
+
+        try:
+            env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd)))
+
+            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            out, err = p.communicate()
+
+            out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
+
+            if p.returncode != 0:
+                sys.stderr.write(err)
+
+                env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
+                return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
+            elif env.config.kerneldoc_verbosity > 0:
+                sys.stderr.write(err)
+
+            lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
+            result = ViewList()
+
+            lineoffset = 0;
+            line_regex = re.compile("^#define LINENO ([0-9]+)$")
+            for line in lines:
+                match = line_regex.search(line)
+                if match:
+                    # sphinx counts lines from 0
+                    lineoffset = int(match.group(1)) - 1
+                    # we must eat our comments since the upset the markup
+                else:
+                    result.append(line, filename, lineoffset)
+                    lineoffset += 1
+
+            node = nodes.section()
+            buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+            self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
+            self.state.memo.title_styles, self.state.memo.section_level = [], 0
+            try:
+                self.state.nested_parse(result, 0, node, match_titles=1)
+            finally:
+                self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
+
+            return node.children
+
+        except Exception as e:  # pylint: disable=W0703
+            env.app.warn('kernel-doc \'%s\' processing failed with: %s' %
+                         (" ".join(cmd), str(e)))
+            return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
+
+def setup(app):
+    app.add_config_value('kerneldoc_bin', None, 'env')
+    app.add_config_value('kerneldoc_srctree', None, 'env')
+    app.add_config_value('kerneldoc_verbosity', 1, 'env')
+
+    app.add_directive('kernel-doc', KernelDocDirective)
+
+    return dict(
+        version = __version__,
+        parallel_read_safe = True,
+        parallel_write_safe = True
+    )
diff --git a/Documentation/sphinx/kfigure.py b/Documentation/sphinx/kfigure.py
new file mode 100644
index 0000000..b97228d
--- /dev/null
+++ b/Documentation/sphinx/kfigure.py
@@ -0,0 +1,551 @@
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=C0103, R0903, R0912, R0915
+u"""
+    scalable figure and image handling
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Sphinx extension which implements scalable image handling.
+
+    :copyright:  Copyright (C) 2016  Markus Heiser
+    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
+
+    The build for image formats depend on image's source format and output's
+    destination format. This extension implement methods to simplify image
+    handling from the author's POV. Directives like ``kernel-figure`` implement
+    methods *to* always get the best output-format even if some tools are not
+    installed. For more details take a look at ``convert_image(...)`` which is
+    the core of all conversions.
+
+    * ``.. kernel-image``: for image handling / a ``.. image::`` replacement
+
+    * ``.. kernel-figure``: for figure handling / a ``.. figure::`` replacement
+
+    * ``.. kernel-render``: for render markup / a concept to embed *render*
+      markups (or languages). Supported markups (see ``RENDER_MARKUP_EXT``)
+
+      - ``DOT``: render embedded Graphviz's **DOC**
+      - ``SVG``: render embedded Scalable Vector Graphics (**SVG**)
+      - ... *developable*
+
+    Used tools:
+
+    * ``dot(1)``: Graphviz (http://www.graphviz.org). If Graphviz is not
+      available, the DOT language is inserted as literal-block.
+
+    * SVG to PDF: To generate PDF, you need at least one of this tools:
+
+      - ``convert(1)``: ImageMagick (https://www.imagemagick.org)
+
+    List of customizations:
+
+    * generate PDF from SVG / used by PDF (LaTeX) builder
+
+    * generate SVG (html-builder) and PDF (latex-builder) from DOT files.
+      DOT: see http://www.graphviz.org/content/dot-language
+
+    """
+
+import os
+from os import path
+import subprocess
+from hashlib import sha1
+import sys
+
+from docutils import nodes
+from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.directives import images
+import sphinx
+
+from sphinx.util.nodes import clean_astext
+from six import iteritems
+
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    _unicode = str
+else:
+    _unicode = unicode
+
+# Get Sphinx version
+major, minor, patch = sphinx.version_info[:3]
+if major == 1 and minor > 3:
+    # patches.Figure only landed in Sphinx 1.4
+    from sphinx.directives.patches import Figure  # pylint: disable=C0413
+else:
+    Figure = images.Figure
+
+__version__  = '1.0.0'
+
+# simple helper
+# -------------
+
+def which(cmd):
+    """Searches the ``cmd`` in the ``PATH`` environment.
+
+    This *which* searches the PATH for executable ``cmd`` . First match is
+    returned, if nothing is found, ``None` is returned.
+    """
+    envpath = os.environ.get('PATH', None) or os.defpath
+    for folder in envpath.split(os.pathsep):
+        fname = folder + os.sep + cmd
+        if path.isfile(fname):
+            return fname
+
+def mkdir(folder, mode=0o775):
+    if not path.isdir(folder):
+        os.makedirs(folder, mode)
+
+def file2literal(fname):
+    with open(fname, "r") as src:
+        data = src.read()
+        node = nodes.literal_block(data, data)
+    return node
+
+def isNewer(path1, path2):
+    """Returns True if ``path1`` is newer than ``path2``
+
+    If ``path1`` exists and is newer than ``path2`` the function returns
+    ``True`` is returned otherwise ``False``
+    """
+    return (path.exists(path1)
+            and os.stat(path1).st_ctime > os.stat(path2).st_ctime)
+
+def pass_handle(self, node):           # pylint: disable=W0613
+    pass
+
+# setup conversion tools and sphinx extension
+# -------------------------------------------
+
+# Graphviz's dot(1) support
+dot_cmd = None
+
+# ImageMagick' convert(1) support
+convert_cmd = None
+
+
+def setup(app):
+    # check toolchain first
+    app.connect('builder-inited', setupTools)
+
+    # image handling
+    app.add_directive("kernel-image",  KernelImage)
+    app.add_node(kernel_image,
+                 html    = (visit_kernel_image, pass_handle),
+                 latex   = (visit_kernel_image, pass_handle),
+                 texinfo = (visit_kernel_image, pass_handle),
+                 text    = (visit_kernel_image, pass_handle),
+                 man     = (visit_kernel_image, pass_handle), )
+
+    # figure handling
+    app.add_directive("kernel-figure", KernelFigure)
+    app.add_node(kernel_figure,
+                 html    = (visit_kernel_figure, pass_handle),
+                 latex   = (visit_kernel_figure, pass_handle),
+                 texinfo = (visit_kernel_figure, pass_handle),
+                 text    = (visit_kernel_figure, pass_handle),
+                 man     = (visit_kernel_figure, pass_handle), )
+
+    # render handling
+    app.add_directive('kernel-render', KernelRender)
+    app.add_node(kernel_render,
+                 html    = (visit_kernel_render, pass_handle),
+                 latex   = (visit_kernel_render, pass_handle),
+                 texinfo = (visit_kernel_render, pass_handle),
+                 text    = (visit_kernel_render, pass_handle),
+                 man     = (visit_kernel_render, pass_handle), )
+
+    app.connect('doctree-read', add_kernel_figure_to_std_domain)
+
+    return dict(
+        version = __version__,
+        parallel_read_safe = True,
+        parallel_write_safe = True
+    )
+
+
+def setupTools(app):
+    u"""
+    Check available build tools and log some *verbose* messages.
+
+    This function is called once, when the builder is initiated.
+    """
+    global dot_cmd, convert_cmd   # pylint: disable=W0603
+    app.verbose("kfigure: check installed tools ...")
+
+    dot_cmd = which('dot')
+    convert_cmd = which('convert')
+
+    if dot_cmd:
+        app.verbose("use dot(1) from: " + dot_cmd)
+    else:
+        app.warn("dot(1) not found, for better output quality install "
+                 "graphviz from http://www.graphviz.org")
+    if convert_cmd:
+        app.verbose("use convert(1) from: " + convert_cmd)
+    else:
+        app.warn(
+            "convert(1) not found, for SVG to PDF conversion install "
+            "ImageMagick (https://www.imagemagick.org)")
+
+
+# integrate conversion tools
+# --------------------------
+
+RENDER_MARKUP_EXT = {
+    # The '.ext' must be handled by convert_image(..) function's *in_ext* input.
+    # <name> : <.ext>
+    'DOT' : '.dot',
+    'SVG' : '.svg'
+}
+
+def convert_image(img_node, translator, src_fname=None):
+    """Convert a image node for the builder.
+
+    Different builder prefer different image formats, e.g. *latex* builder
+    prefer PDF while *html* builder prefer SVG format for images.
+
+    This function handles output image formats in dependence of source the
+    format (of the image) and the translator's output format.
+    """
+    app = translator.builder.app
+
+    fname, in_ext = path.splitext(path.basename(img_node['uri']))
+    if src_fname is None:
+        src_fname = path.join(translator.builder.srcdir, img_node['uri'])
+        if not path.exists(src_fname):
+            src_fname = path.join(translator.builder.outdir, img_node['uri'])
+
+    dst_fname = None
+
+    # in kernel builds, use 'make SPHINXOPTS=-v' to see verbose messages
+
+    app.verbose('assert best format for: ' + img_node['uri'])
+
+    if in_ext == '.dot':
+
+        if not dot_cmd:
+            app.verbose("dot from graphviz not available / include DOT raw.")
+            img_node.replace_self(file2literal(src_fname))
+
+        elif translator.builder.format == 'latex':
+            dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
+            img_node['uri'] = fname + '.pdf'
+            img_node['candidates'] = {'*': fname + '.pdf'}
+
+
+        elif translator.builder.format == 'html':
+            dst_fname = path.join(
+                translator.builder.outdir,
+                translator.builder.imagedir,
+                fname + '.svg')
+            img_node['uri'] = path.join(
+                translator.builder.imgpath, fname + '.svg')
+            img_node['candidates'] = {
+                '*': path.join(translator.builder.imgpath, fname + '.svg')}
+
+        else:
+            # all other builder formats will include DOT as raw
+            img_node.replace_self(file2literal(src_fname))
+
+    elif in_ext == '.svg':
+
+        if translator.builder.format == 'latex':
+            if convert_cmd is None:
+                app.verbose("no SVG to PDF conversion available / include SVG raw.")
+                img_node.replace_self(file2literal(src_fname))
+            else:
+                dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
+                img_node['uri'] = fname + '.pdf'
+                img_node['candidates'] = {'*': fname + '.pdf'}
+
+    if dst_fname:
+        # the builder needs not to copy one more time, so pop it if exists.
+        translator.builder.images.pop(img_node['uri'], None)
+        _name = dst_fname[len(translator.builder.outdir) + 1:]
+
+        if isNewer(dst_fname, src_fname):
+            app.verbose("convert: {out}/%s already exists and is newer" % _name)
+
+        else:
+            ok = False
+            mkdir(path.dirname(dst_fname))
+
+            if in_ext == '.dot':
+                app.verbose('convert DOT to: {out}/' + _name)
+                ok = dot2format(app, src_fname, dst_fname)
+
+            elif in_ext == '.svg':
+                app.verbose('convert SVG to: {out}/' + _name)
+                ok = svg2pdf(app, src_fname, dst_fname)
+
+            if not ok:
+                img_node.replace_self(file2literal(src_fname))
+
+
+def dot2format(app, dot_fname, out_fname):
+    """Converts DOT file to ``out_fname`` using ``dot(1)``.
+
+    * ``dot_fname`` pathname of the input DOT file, including extension ``.dot``
+    * ``out_fname`` pathname of the output file, including format extension
+
+    The *format extension* depends on the ``dot`` command (see ``man dot``
+    option ``-Txxx``). Normally you will use one of the following extensions:
+
+    - ``.ps`` for PostScript,
+    - ``.svg`` or ``svgz`` for Structured Vector Graphics,
+    - ``.fig`` for XFIG graphics and
+    - ``.png`` or ``gif`` for common bitmap graphics.
+
+    """
+    out_format = path.splitext(out_fname)[1][1:]
+    cmd = [dot_cmd, '-T%s' % out_format, dot_fname]
+    exit_code = 42
+
+    with open(out_fname, "w") as out:
+        exit_code = subprocess.call(cmd, stdout = out)
+        if exit_code != 0:
+            app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
+    return bool(exit_code == 0)
+
+def svg2pdf(app, svg_fname, pdf_fname):
+    """Converts SVG to PDF with ``convert(1)`` command.
+
+    Uses ``convert(1)`` from ImageMagick (https://www.imagemagick.org) for
+    conversion.  Returns ``True`` on success and ``False`` if an error occurred.
+
+    * ``svg_fname`` pathname of the input SVG file with extension (``.svg``)
+    * ``pdf_name``  pathname of the output PDF file with extension (``.pdf``)
+
+    """
+    cmd = [convert_cmd, svg_fname, pdf_fname]
+    # use stdout and stderr from parent
+    exit_code = subprocess.call(cmd)
+    if exit_code != 0:
+        app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
+    return bool(exit_code == 0)
+
+
+# image handling
+# ---------------------
+
+def visit_kernel_image(self, node):    # pylint: disable=W0613
+    """Visitor of the ``kernel_image`` Node.
+
+    Handles the ``image`` child-node with the ``convert_image(...)``.
+    """
+    img_node = node[0]
+    convert_image(img_node, self)
+
+class kernel_image(nodes.image):
+    """Node for ``kernel-image`` directive."""
+    pass
+
+class KernelImage(images.Image):
+    u"""KernelImage directive
+
+    Earns everything from ``.. image::`` directive, except *remote URI* and
+    *glob* pattern. The KernelImage wraps a image node into a
+    kernel_image node. See ``visit_kernel_image``.
+    """
+
+    def run(self):
+        uri = self.arguments[0]
+        if uri.endswith('.*') or uri.find('://') != -1:
+            raise self.severe(
+                'Error in "%s: %s": glob pattern and remote images are not allowed'
+                % (self.name, uri))
+        result = images.Image.run(self)
+        if len(result) == 2 or isinstance(result[0], nodes.system_message):
+            return result
+        (image_node,) = result
+        # wrap image node into a kernel_image node / see visitors
+        node = kernel_image('', image_node)
+        return [node]
+
+# figure handling
+# ---------------------
+
+def visit_kernel_figure(self, node):   # pylint: disable=W0613
+    """Visitor of the ``kernel_figure`` Node.
+
+    Handles the ``image`` child-node with the ``convert_image(...)``.
+    """
+    img_node = node[0][0]
+    convert_image(img_node, self)
+
+class kernel_figure(nodes.figure):
+    """Node for ``kernel-figure`` directive."""
+
+class KernelFigure(Figure):
+    u"""KernelImage directive
+
+    Earns everything from ``.. figure::`` directive, except *remote URI* and
+    *glob* pattern.  The KernelFigure wraps a figure node into a kernel_figure
+    node. See ``visit_kernel_figure``.
+    """
+
+    def run(self):
+        uri = self.arguments[0]
+        if uri.endswith('.*') or uri.find('://') != -1:
+            raise self.severe(
+                'Error in "%s: %s":'
+                ' glob pattern and remote images are not allowed'
+                % (self.name, uri))
+        result = Figure.run(self)
+        if len(result) == 2 or isinstance(result[0], nodes.system_message):
+            return result
+        (figure_node,) = result
+        # wrap figure node into a kernel_figure node / see visitors
+        node = kernel_figure('', figure_node)
+        return [node]
+
+
+# render handling
+# ---------------------
+
+def visit_kernel_render(self, node):
+    """Visitor of the ``kernel_render`` Node.
+
+    If rendering tools available, save the markup of the ``literal_block`` child
+    node into a file and replace the ``literal_block`` node with a new created
+    ``image`` node, pointing to the saved markup file. Afterwards, handle the
+    image child-node with the ``convert_image(...)``.
+    """
+    app = self.builder.app
+    srclang = node.get('srclang')
+
+    app.verbose('visit kernel-render node lang: "%s"' % (srclang))
+
+    tmp_ext = RENDER_MARKUP_EXT.get(srclang, None)
+    if tmp_ext is None:
+        app.warn('kernel-render: "%s" unknown / include raw.' % (srclang))
+        return
+
+    if not dot_cmd and tmp_ext == '.dot':
+        app.verbose("dot from graphviz not available / include raw.")
+        return
+
+    literal_block = node[0]
+
+    code      = literal_block.astext()
+    hashobj   = code.encode('utf-8') #  str(node.attributes)
+    fname     = path.join('%s-%s' % (srclang, sha1(hashobj).hexdigest()))
+
+    tmp_fname = path.join(
+        self.builder.outdir, self.builder.imagedir, fname + tmp_ext)
+
+    if not path.isfile(tmp_fname):
+        mkdir(path.dirname(tmp_fname))
+        with open(tmp_fname, "w") as out:
+            out.write(code)
+
+    img_node = nodes.image(node.rawsource, **node.attributes)
+    img_node['uri'] = path.join(self.builder.imgpath, fname + tmp_ext)
+    img_node['candidates'] = {
+        '*': path.join(self.builder.imgpath, fname + tmp_ext)}
+
+    literal_block.replace_self(img_node)
+    convert_image(img_node, self, tmp_fname)
+
+
+class kernel_render(nodes.General, nodes.Inline, nodes.Element):
+    """Node for ``kernel-render`` directive."""
+    pass
+
+class KernelRender(Figure):
+    u"""KernelRender directive
+
+    Render content by external tool.  Has all the options known from the
+    *figure*  directive, plus option ``caption``.  If ``caption`` has a
+    value, a figure node with the *caption* is inserted. If not, a image node is
+    inserted.
+
+    The KernelRender directive wraps the text of the directive into a
+    literal_block node and wraps it into a kernel_render node. See
+    ``visit_kernel_render``.
+    """
+    has_content = True
+    required_arguments = 1
+    optional_arguments = 0
+    final_argument_whitespace = False
+
+    # earn options from 'figure'
+    option_spec = Figure.option_spec.copy()
+    option_spec['caption'] = directives.unchanged
+
+    def run(self):
+        return [self.build_node()]
+
+    def build_node(self):
+
+        srclang = self.arguments[0].strip()
+        if srclang not in RENDER_MARKUP_EXT.keys():
+            return [self.state_machine.reporter.warning(
+                'Unknown source language "%s", use one of: %s.' % (
+                    srclang, ",".join(RENDER_MARKUP_EXT.keys())),
+                line=self.lineno)]
+
+        code = '\n'.join(self.content)
+        if not code.strip():
+            return [self.state_machine.reporter.warning(
+                'Ignoring "%s" directive without content.' % (
+                    self.name),
+                line=self.lineno)]
+
+        node = kernel_render()
+        node['alt'] = self.options.get('alt','')
+        node['srclang'] = srclang
+        literal_node = nodes.literal_block(code, code)
+        node += literal_node
+
+        caption = self.options.get('caption')
+        if caption:
+            # parse caption's content
+            parsed = nodes.Element()
+            self.state.nested_parse(
+                ViewList([caption], source=''), self.content_offset, parsed)
+            caption_node = nodes.caption(
+                parsed[0].rawsource, '', *parsed[0].children)
+            caption_node.source = parsed[0].source
+            caption_node.line = parsed[0].line
+
+            figure_node = nodes.figure('', node)
+            for k,v in self.options.items():
+                figure_node[k] = v
+            figure_node += caption_node
+
+            node = figure_node
+
+        return node
+
+def add_kernel_figure_to_std_domain(app, doctree):
+    """Add kernel-figure anchors to 'std' domain.
+
+    The ``StandardDomain.process_doc(..)`` method does not know how to resolve
+    the caption (label) of ``kernel-figure`` directive (it only knows about
+    standard nodes, e.g. table, figure etc.). Without any additional handling
+    this will result in a 'undefined label' for kernel-figures.
+
+    This handle adds labels of kernel-figure to the 'std' domain labels.
+    """
+
+    std = app.env.domains["std"]
+    docname = app.env.docname
+    labels = std.data["labels"]
+
+    for name, explicit in iteritems(doctree.nametypes):
+        if not explicit:
+            continue
+        labelid = doctree.nameids[name]
+        if labelid is None:
+            continue
+        node = doctree.ids[labelid]
+
+        if node.tagname == 'kernel_figure':
+            for n in node.next_node():
+                if n.tagname == 'caption':
+                    sectname = clean_astext(n)
+                    # add label to std domain
+                    labels[name] = docname, labelid, sectname
+                    break
diff --git a/Documentation/sphinx/load_config.py b/Documentation/sphinx/load_config.py
new file mode 100644
index 0000000..301a21a
--- /dev/null
+++ b/Documentation/sphinx/load_config.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=R0903, C0330, R0914, R0912, E0401
+
+import os
+import sys
+from sphinx.util.pycompat import execfile_
+
+# ------------------------------------------------------------------------------
+def loadConfig(namespace):
+# ------------------------------------------------------------------------------
+
+    u"""Load an additional configuration file into *namespace*.
+
+    The name of the configuration file is taken from the environment
+    ``SPHINX_CONF``. The external configuration file extends (or overwrites) the
+    configuration values from the origin ``conf.py``.  With this you are able to
+    maintain *build themes*.  """
+
+    config_file = os.environ.get("SPHINX_CONF", None)
+    if (config_file is not None
+        and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ):
+        config_file = os.path.abspath(config_file)
+
+        if os.path.isfile(config_file):
+            sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
+            config = namespace.copy()
+            config['__file__'] = config_file
+            execfile_(config_file, config)
+            del config['__file__']
+            namespace.update(config)
+        else:
+            sys.stderr.write("WARNING: additional sphinx-config not found: %s\n" % config_file)
diff --git a/Documentation/sphinx/parse-headers.pl b/Documentation/sphinx/parse-headers.pl
new file mode 100755
index 0000000..d410f47
--- /dev/null
+++ b/Documentation/sphinx/parse-headers.pl
@@ -0,0 +1,401 @@
+#!/usr/bin/perl
+use strict;
+use Text::Tabs;
+use Getopt::Long;
+use Pod::Usage;
+
+my $debug;
+my $help;
+my $man;
+
+GetOptions(
+	"debug" => \$debug,
+	'usage|?' => \$help,
+	'help' => \$man
+) or pod2usage(2);
+
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+pod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3);
+
+my ($file_in, $file_out, $file_exceptions) = @ARGV;
+
+my $data;
+my %ioctls;
+my %defines;
+my %typedefs;
+my %enums;
+my %enum_symbols;
+my %structs;
+
+require Data::Dumper if ($debug);
+
+#
+# read the file and get identifiers
+#
+
+my $is_enum = 0;
+my $is_comment = 0;
+open IN, $file_in or die "Can't open $file_in";
+while (<IN>) {
+	$data .= $_;
+
+	my $ln = $_;
+	if (!$is_comment) {
+		$ln =~ s,/\*.*(\*/),,g;
+
+		$is_comment = 1 if ($ln =~ s,/\*.*,,);
+	} else {
+		if ($ln =~ s,^(.*\*/),,) {
+			$is_comment = 0;
+		} else {
+			next;
+		}
+	}
+
+	if ($is_enum && $ln =~ m/^\s*([_\w][\w\d_]+)\s*[\,=]?/) {
+		my $s = $1;
+		my $n = $1;
+		$n =~ tr/A-Z/a-z/;
+		$n =~ tr/_/-/;
+
+		$enum_symbols{$s} =  "\\ :ref:`$s <$n>`\\ ";
+
+		$is_enum = 0 if ($is_enum && m/\}/);
+		next;
+	}
+	$is_enum = 0 if ($is_enum && m/\}/);
+
+	if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+_IO/) {
+		my $s = $1;
+		my $n = $1;
+		$n =~ tr/A-Z/a-z/;
+
+		$ioctls{$s} = "\\ :ref:`$s <$n>`\\ ";
+		next;
+	}
+
+	if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+/) {
+		my $s = $1;
+		my $n = $1;
+		$n =~ tr/A-Z/a-z/;
+		$n =~ tr/_/-/;
+
+		$defines{$s} = "\\ :ref:`$s <$n>`\\ ";
+		next;
+	}
+
+	if ($ln =~ m/^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);/) {
+		my $s = $2;
+		my $n = $3;
+
+		$typedefs{$n} = "\\ :c:type:`$n <$s>`\\ ";
+		next;
+	}
+	if ($ln =~ m/^\s*enum\s+([_\w][\w\d_]+)\s+\{/
+	    || $ln =~ m/^\s*enum\s+([_\w][\w\d_]+)$/
+	    || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)\s+\{/
+	    || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)$/) {
+		my $s = $1;
+
+		$enums{$s} =  "enum :c:type:`$s`\\ ";
+
+		$is_enum = $1;
+		next;
+	}
+	if ($ln =~ m/^\s*struct\s+([_\w][\w\d_]+)\s+\{/
+	    || $ln =~ m/^\s*struct\s+([[_\w][\w\d_]+)$/
+	    || $ln =~ m/^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s+\{/
+	    || $ln =~ m/^\s*typedef\s*struct\s+([[_\w][\w\d_]+)$/
+	    ) {
+		my $s = $1;
+
+		$structs{$s} = "struct :c:type:`$s`\\ ";
+		next;
+	}
+}
+close IN;
+
+#
+# Handle multi-line typedefs
+#
+
+my @matches = ($data =~ m/typedef\s+struct\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,
+	       $data =~ m/typedef\s+enum\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,);
+foreach my $m (@matches) {
+	my $s = $m;
+
+	$typedefs{$s} = "\\ :c:type:`$s`\\ ";
+	next;
+}
+
+#
+# Handle exceptions, if any
+#
+
+my %def_reftype = (
+	"ioctl"   => ":ref",
+	"define"  => ":ref",
+	"symbol"  => ":ref",
+	"typedef" => ":c:type",
+	"enum"    => ":c:type",
+	"struct"  => ":c:type",
+);
+
+if ($file_exceptions) {
+	open IN, $file_exceptions or die "Can't read $file_exceptions";
+	while (<IN>) {
+		next if (m/^\s*$/ || m/^\s*#/);
+
+		# Parsers to ignore a symbol
+
+		if (m/^ignore\s+ioctl\s+(\S+)/) {
+			delete $ioctls{$1} if (exists($ioctls{$1}));
+			next;
+		}
+		if (m/^ignore\s+define\s+(\S+)/) {
+			delete $defines{$1} if (exists($defines{$1}));
+			next;
+		}
+		if (m/^ignore\s+typedef\s+(\S+)/) {
+			delete $typedefs{$1} if (exists($typedefs{$1}));
+			next;
+		}
+		if (m/^ignore\s+enum\s+(\S+)/) {
+			delete $enums{$1} if (exists($enums{$1}));
+			next;
+		}
+		if (m/^ignore\s+struct\s+(\S+)/) {
+			delete $structs{$1} if (exists($structs{$1}));
+			next;
+		}
+		if (m/^ignore\s+symbol\s+(\S+)/) {
+			delete $enum_symbols{$1} if (exists($enum_symbols{$1}));
+			next;
+		}
+
+		# Parsers to replace a symbol
+		my ($type, $old, $new, $reftype);
+
+		if (m/^replace\s+(\S+)\s+(\S+)\s+(\S+)/) {
+			$type = $1;
+			$old = $2;
+			$new = $3;
+		} else {
+			die "Can't parse $file_exceptions: $_";
+		}
+
+		if ($new =~ m/^\:c\:(data|func|macro|type)\:\`(.+)\`/) {
+			$reftype = ":c:$1";
+			$new = $2;
+		} elsif ($new =~ m/\:ref\:\`(.+)\`/) {
+			$reftype = ":ref";
+			$new = $1;
+		} else {
+			$reftype = $def_reftype{$type};
+		}
+		$new = "$reftype:`$old <$new>`";
+
+		if ($type eq "ioctl") {
+			$ioctls{$old} = $new if (exists($ioctls{$old}));
+			next;
+		}
+		if ($type eq "define") {
+			$defines{$old} = $new if (exists($defines{$old}));
+			next;
+		}
+		if ($type eq "symbol") {
+			$enum_symbols{$old} = $new if (exists($enum_symbols{$old}));
+			next;
+		}
+		if ($type eq "typedef") {
+			$typedefs{$old} = $new if (exists($typedefs{$old}));
+			next;
+		}
+		if ($type eq "enum") {
+			$enums{$old} = $new if (exists($enums{$old}));
+			next;
+		}
+		if ($type eq "struct") {
+			$structs{$old} = $new if (exists($structs{$old}));
+			next;
+		}
+
+		die "Can't parse $file_exceptions: $_";
+	}
+}
+
+if ($debug) {
+	print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls);
+	print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs);
+	print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums);
+	print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs);
+	print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines);
+	print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols);
+}
+
+#
+# Align block
+#
+$data = expand($data);
+$data = "    " . $data;
+$data =~ s/\n/\n    /g;
+$data =~ s/\n\s+$/\n/g;
+$data =~ s/\n\s+\n/\n\n/g;
+
+#
+# Add escape codes for special characters
+#
+$data =~ s,([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^]),\\$1,g;
+
+$data =~ s,DEPRECATED,**DEPRECATED**,g;
+
+#
+# Add references
+#
+
+my $start_delim = "[ \n\t\(\=\*\@]";
+my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)";
+
+foreach my $r (keys %ioctls) {
+	my $s = $ioctls{$r};
+
+	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+	print "$r -> $s\n" if ($debug);
+
+	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+foreach my $r (keys %defines) {
+	my $s = $defines{$r};
+
+	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+	print "$r -> $s\n" if ($debug);
+
+	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+foreach my $r (keys %enum_symbols) {
+	my $s = $enum_symbols{$r};
+
+	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+	print "$r -> $s\n" if ($debug);
+
+	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+foreach my $r (keys %enums) {
+	my $s = $enums{$r};
+
+	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+	print "$r -> $s\n" if ($debug);
+
+	$data =~ s/enum\s+($r)$end_delim/$s$2/g;
+}
+
+foreach my $r (keys %structs) {
+	my $s = $structs{$r};
+
+	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+	print "$r -> $s\n" if ($debug);
+
+	$data =~ s/struct\s+($r)$end_delim/$s$2/g;
+}
+
+foreach my $r (keys %typedefs) {
+	my $s = $typedefs{$r};
+
+	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+	print "$r -> $s\n" if ($debug);
+	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+$data =~ s/\\ ([\n\s])/\1/g;
+
+#
+# Generate output file
+#
+
+my $title = $file_in;
+$title =~ s,.*/,,;
+
+open OUT, "> $file_out" or die "Can't open $file_out";
+print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n";
+print OUT "$title\n";
+print OUT "=" x length($title);
+print OUT "\n\n.. parsed-literal::\n\n";
+print OUT $data;
+close OUT;
+
+__END__
+
+=head1 NAME
+
+parse_headers.pl - parse a C file, in order to identify functions, structs,
+enums and defines and create cross-references to a Sphinx book.
+
+=head1 SYNOPSIS
+
+B<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
+
+Where <options> can be: --debug, --help or --man.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--debug>
+
+Put the script in verbose mode, useful for debugging.
+
+=item B<--usage>
+
+Prints a brief help message and exits.
+
+=item B<--help>
+
+Prints a more detailed help message and exits.
+
+=back
+
+=head1 DESCRIPTION
+
+Convert a C header or source file (C_FILE), into a ReStructured Text
+included via ..parsed-literal block with cross-references for the
+documentation files that describe the API. It accepts an optional
+EXCEPTIONS_FILE with describes what elements will be either ignored or
+be pointed to a non-default reference.
+
+The output is written at the (OUT_FILE).
+
+It is capable of identifying defines, functions, structs, typedefs,
+enums and enum symbols and create cross-references for all of them.
+It is also capable of distinguish #define used for specifying a Linux
+ioctl.
+
+The EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or
+to replace the default references by a custom one.
+
+Please read Documentation/doc-guide/parse-headers.rst at the Kernel's
+tree for more details.
+
+=head1 BUGS
+
+Report bugs to Mauro Carvalho Chehab <mchehab@kernel.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+=cut
diff --git a/Documentation/sphinx/requirements.txt b/Documentation/sphinx/requirements.txt
new file mode 100644
index 0000000..742be3e
--- /dev/null
+++ b/Documentation/sphinx/requirements.txt
@@ -0,0 +1,3 @@
+docutils==0.12
+Sphinx==1.4.9
+sphinx_rtd_theme
diff --git a/Documentation/sphinx/rstFlatTable.py b/Documentation/sphinx/rstFlatTable.py
new file mode 100755
index 0000000..25feb0d
--- /dev/null
+++ b/Documentation/sphinx/rstFlatTable.py
@@ -0,0 +1,376 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=C0330, R0903, R0912
+
+u"""
+    flat-table
+    ~~~~~~~~~~
+
+    Implementation of the ``flat-table`` reST-directive.
+
+    :copyright:  Copyright (C) 2016  Markus Heiser
+    :license:    GPL Version 2, June 1991 see linux/COPYING for details.
+
+    The ``flat-table`` (:py:class:`FlatTable`) is a double-stage list similar to
+    the ``list-table`` with some additional features:
+
+    * *column-span*: with the role ``cspan`` a cell can be extended through
+      additional columns
+
+    * *row-span*: with the role ``rspan`` a cell can be extended through
+      additional rows
+
+    * *auto span* rightmost cell of a table row over the missing cells on the
+      right side of that table-row.  With Option ``:fill-cells:`` this behavior
+      can changed from *auto span* to *auto fill*, which automaticly inserts
+      (empty) cells instead of spanning the last cell.
+
+    Options:
+
+    * header-rows:   [int] count of header rows
+    * stub-columns:  [int] count of stub columns
+    * widths:        [[int] [int] ... ] widths of columns
+    * fill-cells:    instead of autospann missing cells, insert missing cells
+
+    roles:
+
+    * cspan: [int] additionale columns (*morecols*)
+    * rspan: [int] additionale rows (*morerows*)
+"""
+
+# ==============================================================================
+# imports
+# ==============================================================================
+
+import sys
+
+from docutils import nodes
+from docutils.parsers.rst import directives, roles
+from docutils.parsers.rst.directives.tables import Table
+from docutils.utils import SystemMessagePropagation
+
+# ==============================================================================
+# common globals
+# ==============================================================================
+
+# The version numbering follows numbering of the specification
+# (Documentation/books/kernel-doc-HOWTO).
+__version__  = '1.0'
+
+PY3 = sys.version_info[0] == 3
+PY2 = sys.version_info[0] == 2
+
+if PY3:
+    # pylint: disable=C0103, W0622
+    unicode     = str
+    basestring  = str
+
+# ==============================================================================
+def setup(app):
+# ==============================================================================
+
+    app.add_directive("flat-table", FlatTable)
+    roles.register_local_role('cspan', c_span)
+    roles.register_local_role('rspan', r_span)
+
+    return dict(
+        version = __version__,
+        parallel_read_safe = True,
+        parallel_write_safe = True
+    )
+
+# ==============================================================================
+def c_span(name, rawtext, text, lineno, inliner, options=None, content=None):
+# ==============================================================================
+    # pylint: disable=W0613
+
+    options  = options if options is not None else {}
+    content  = content if content is not None else []
+    nodelist = [colSpan(span=int(text))]
+    msglist  = []
+    return nodelist, msglist
+
+# ==============================================================================
+def r_span(name, rawtext, text, lineno, inliner, options=None, content=None):
+# ==============================================================================
+    # pylint: disable=W0613
+
+    options  = options if options is not None else {}
+    content  = content if content is not None else []
+    nodelist = [rowSpan(span=int(text))]
+    msglist  = []
+    return nodelist, msglist
+
+
+# ==============================================================================
+class rowSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321
+class colSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321
+# ==============================================================================
+
+# ==============================================================================
+class FlatTable(Table):
+# ==============================================================================
+
+    u"""FlatTable (``flat-table``) directive"""
+
+    option_spec = {
+        'name': directives.unchanged
+        , 'class': directives.class_option
+        , 'header-rows': directives.nonnegative_int
+        , 'stub-columns': directives.nonnegative_int
+        , 'widths': directives.positive_int_list
+        , 'fill-cells' : directives.flag }
+
+    def run(self):
+
+        if not self.content:
+            error = self.state_machine.reporter.error(
+                'The "%s" directive is empty; content required.' % self.name,
+                nodes.literal_block(self.block_text, self.block_text),
+                line=self.lineno)
+            return [error]
+
+        title, messages = self.make_title()
+        node = nodes.Element()          # anonymous container for parsing
+        self.state.nested_parse(self.content, self.content_offset, node)
+
+        tableBuilder = ListTableBuilder(self)
+        tableBuilder.parseFlatTableNode(node)
+        tableNode = tableBuilder.buildTableNode()
+        # SDK.CONSOLE()  # print --> tableNode.asdom().toprettyxml()
+        if title:
+            tableNode.insert(0, title)
+        return [tableNode] + messages
+
+
+# ==============================================================================
+class ListTableBuilder(object):
+# ==============================================================================
+
+    u"""Builds a table from a double-stage list"""
+
+    def __init__(self, directive):
+        self.directive = directive
+        self.rows      = []
+        self.max_cols  = 0
+
+    def buildTableNode(self):
+
+        colwidths    = self.directive.get_column_widths(self.max_cols)
+        if isinstance(colwidths, tuple):
+            # Since docutils 0.13, get_column_widths returns a (widths,
+            # colwidths) tuple, where widths is a string (i.e. 'auto').
+            # See https://sourceforge.net/p/docutils/patches/120/.
+            colwidths = colwidths[1]
+        stub_columns = self.directive.options.get('stub-columns', 0)
+        header_rows  = self.directive.options.get('header-rows', 0)
+
+        table = nodes.table()
+        tgroup = nodes.tgroup(cols=len(colwidths))
+        table += tgroup
+
+
+        for colwidth in colwidths:
+            colspec = nodes.colspec(colwidth=colwidth)
+            # FIXME: It seems, that the stub method only works well in the
+            # absence of rowspan (observed by the html buidler, the docutils-xml
+            # build seems OK).  This is not extraordinary, because there exists
+            # no table directive (except *this* flat-table) which allows to
+            # define coexistent of rowspan and stubs (there was no use-case
+            # before flat-table). This should be reviewed (later).
+            if stub_columns:
+                colspec.attributes['stub'] = 1
+                stub_columns -= 1
+            tgroup += colspec
+        stub_columns = self.directive.options.get('stub-columns', 0)
+
+        if header_rows:
+            thead = nodes.thead()
+            tgroup += thead
+            for row in self.rows[:header_rows]:
+                thead += self.buildTableRowNode(row)
+
+        tbody = nodes.tbody()
+        tgroup += tbody
+
+        for row in self.rows[header_rows:]:
+            tbody += self.buildTableRowNode(row)
+        return table
+
+    def buildTableRowNode(self, row_data, classes=None):
+        classes = [] if classes is None else classes
+        row = nodes.row()
+        for cell in row_data:
+            if cell is None:
+                continue
+            cspan, rspan, cellElements = cell
+
+            attributes = {"classes" : classes}
+            if rspan:
+                attributes['morerows'] = rspan
+            if cspan:
+                attributes['morecols'] = cspan
+            entry = nodes.entry(**attributes)
+            entry.extend(cellElements)
+            row += entry
+        return row
+
+    def raiseError(self, msg):
+        error =  self.directive.state_machine.reporter.error(
+            msg
+            , nodes.literal_block(self.directive.block_text
+                                  , self.directive.block_text)
+            , line = self.directive.lineno )
+        raise SystemMessagePropagation(error)
+
+    def parseFlatTableNode(self, node):
+        u"""parses the node from a :py:class:`FlatTable` directive's body"""
+
+        if len(node) != 1 or not isinstance(node[0], nodes.bullet_list):
+            self.raiseError(
+                'Error parsing content block for the "%s" directive: '
+                'exactly one bullet list expected.' % self.directive.name )
+
+        for rowNum, rowItem in enumerate(node[0]):
+            row = self.parseRowItem(rowItem, rowNum)
+            self.rows.append(row)
+        self.roundOffTableDefinition()
+
+    def roundOffTableDefinition(self):
+        u"""Round off the table definition.
+
+        This method rounds off the table definition in :py:member:`rows`.
+
+        * This method inserts the needed ``None`` values for the missing cells
+        arising from spanning cells over rows and/or columns.
+
+        * recount the :py:member:`max_cols`
+
+        * Autospan or fill (option ``fill-cells``) missing cells on the right
+          side of the table-row
+        """
+
+        y = 0
+        while y < len(self.rows):
+            x = 0
+
+            while x < len(self.rows[y]):
+                cell = self.rows[y][x]
+                if cell is None:
+                    x += 1
+                    continue
+                cspan, rspan = cell[:2]
+                # handle colspan in current row
+                for c in range(cspan):
+                    try:
+                        self.rows[y].insert(x+c+1, None)
+                    except: # pylint: disable=W0702
+                        # the user sets ambiguous rowspans
+                        pass # SDK.CONSOLE()
+                # handle colspan in spanned rows
+                for r in range(rspan):
+                    for c in range(cspan + 1):
+                        try:
+                            self.rows[y+r+1].insert(x+c, None)
+                        except: # pylint: disable=W0702
+                            # the user sets ambiguous rowspans
+                            pass # SDK.CONSOLE()
+                x += 1
+            y += 1
+
+        # Insert the missing cells on the right side. For this, first
+        # re-calculate the max columns.
+
+        for row in self.rows:
+            if self.max_cols < len(row):
+                self.max_cols = len(row)
+
+        # fill with empty cells or cellspan?
+
+        fill_cells = False
+        if 'fill-cells' in self.directive.options:
+            fill_cells = True
+
+        for row in self.rows:
+            x =  self.max_cols - len(row)
+            if x and not fill_cells:
+                if row[-1] is None:
+                    row.append( ( x - 1, 0, []) )
+                else:
+                    cspan, rspan, content = row[-1]
+                    row[-1] = (cspan + x, rspan, content)
+            elif x and fill_cells:
+                for i in range(x):
+                    row.append( (0, 0, nodes.comment()) )
+
+    def pprint(self):
+        # for debugging
+        retVal = "[   "
+        for row in self.rows:
+            retVal += "[ "
+            for col in row:
+                if col is None:
+                    retVal += ('%r' % col)
+                    retVal += "\n    , "
+                else:
+                    content = col[2][0].astext()
+                    if len (content) > 30:
+                        content = content[:30] + "..."
+                    retVal += ('(cspan=%s, rspan=%s, %r)'
+                               % (col[0], col[1], content))
+                    retVal += "]\n    , "
+            retVal = retVal[:-2]
+            retVal += "]\n  , "
+        retVal = retVal[:-2]
+        return retVal + "]"
+
+    def parseRowItem(self, rowItem, rowNum):
+        row = []
+        childNo = 0
+        error   = False
+        cell    = None
+        target  = None
+
+        for child in rowItem:
+            if (isinstance(child , nodes.comment)
+                or isinstance(child, nodes.system_message)):
+                pass
+            elif isinstance(child , nodes.target):
+                target = child
+            elif isinstance(child, nodes.bullet_list):
+                childNo += 1
+                cell = child
+            else:
+                error = True
+                break
+
+        if childNo != 1 or error:
+            self.raiseError(
+                'Error parsing content block for the "%s" directive: '
+                'two-level bullet list expected, but row %s does not '
+                'contain a second-level bullet list.'
+                % (self.directive.name, rowNum + 1))
+
+        for cellItem in cell:
+            cspan, rspan, cellElements = self.parseCellItem(cellItem)
+            if target is not None:
+                cellElements.insert(0, target)
+            row.append( (cspan, rspan, cellElements) )
+        return row
+
+    def parseCellItem(self, cellItem):
+        # search and remove cspan, rspan colspec from the first element in
+        # this listItem (field).
+        cspan = rspan = 0
+        if not len(cellItem):
+            return cspan, rspan, []
+        for elem in cellItem[0]:
+            if isinstance(elem, colSpan):
+                cspan = elem.get("span")
+                elem.parent.remove(elem)
+                continue
+            if isinstance(elem, rowSpan):
+                rspan = elem.get("span")
+                elem.parent.remove(elem)
+                continue
+        return cspan, rspan, cellItem[:]
diff --git a/Kbuild b/Kbuild
new file mode 100644
index 0000000..e2e3b29
--- /dev/null
+++ b/Kbuild
@@ -0,0 +1,68 @@
+#
+# Kbuild for top-level directory of U-Boot
+# This file takes care of the following:
+# 1) Generate generic-asm-offsets.h
+# 2) Generate asm-offsets.h
+
+# Default sed regexp - multiline due to syntax constraints
+define sed-y
+	"s:[[:space:]]*\.ascii[[:space:]]*\"\(.*\)\":\1:; \
+	/^->/{s:->#\(.*\):/* \1 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+	s:->::; p;}"
+endef
+
+# Use filechk to avoid rebuilds when a header changes, but the resulting file
+# does not
+define filechk_offsets
+	(set -e; \
+	 echo "#ifndef $2"; \
+	 echo "#define $2"; \
+	 echo "/*"; \
+	 echo " * DO NOT MODIFY."; \
+	 echo " *"; \
+	 echo " * This file was generated by Kbuild"; \
+	 echo " */"; \
+	 echo ""; \
+	 sed -ne $(sed-y); \
+	 echo ""; \
+	 echo "#endif" )
+endef
+
+#####
+# 1) Generate generic-asm-offsets.h
+
+generic-offsets-file := include/generated/generic-asm-offsets.h
+
+always  := $(generic-offsets-file)
+targets := lib/asm-offsets.s
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+lib/asm-offsets.s: lib/asm-offsets.c FORCE
+	$(Q)mkdir -p $(dir $@)
+	$(call if_changed_dep,cc_s_c)
+
+$(obj)/$(generic-offsets-file): lib/asm-offsets.s FORCE
+	$(call filechk,offsets,__GENERIC_ASM_OFFSETS_H__)
+
+#####
+# 2) Generate asm-offsets.h
+#
+
+ifneq ($(wildcard $(srctree)/arch/$(ARCH)/lib/asm-offsets.c),)
+offsets-file := include/generated/asm-offsets.h
+endif
+
+always  += $(offsets-file)
+targets += arch/$(ARCH)/lib/asm-offsets.s
+
+CFLAGS_asm-offsets.o := -DDO_DEPS_ONLY
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+arch/$(ARCH)/lib/asm-offsets.s: arch/$(ARCH)/lib/asm-offsets.c FORCE
+	$(Q)mkdir -p $(dir $@)
+	$(call if_changed_dep,cc_s_c)
+
+$(obj)/$(offsets-file): arch/$(ARCH)/lib/asm-offsets.s FORCE
+	$(call filechk,offsets,__ASM_OFFSETS_H__)
diff --git a/Kconfig b/Kconfig
new file mode 100644
index 0000000..cdc2d5a
--- /dev/null
+++ b/Kconfig
@@ -0,0 +1,524 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file Documentation/kbuild/kconfig-language.txt in the
+# Linux kernel source tree.
+#
+mainmenu "U-Boot $UBOOTVERSION Configuration"
+
+config UBOOTVERSION
+	string
+	option env="UBOOTVERSION"
+
+# Allow defaults in arch-specific code to override any given here
+source "arch/Kconfig"
+
+menu "General setup"
+
+config BROKEN
+	bool
+	help
+	  This option cannot be enabled. It is used as dependency
+	  for broken and incomplete features.
+
+config LOCALVERSION
+	string "Local version - append to U-Boot release"
+	help
+	  Append an extra string to the end of your U-Boot version.
+	  This will show up in your boot log, for example.
+	  The string you set here will be appended after the contents of
+	  any files with a filename matching localversion* in your
+	  object and source tree, in that order.  Your total string can
+	  be a maximum of 64 characters.
+
+config LOCALVERSION_AUTO
+	bool "Automatically append version information to the version string"
+	default y
+	help
+	  This will try to automatically determine if the current tree is a
+	  release tree by looking for Git tags that belong to the current
+	  top of tree revision.
+
+	  A string of the format -gxxxxxxxx will be added to the localversion
+	  if a Git-based tree is found.  The string generated by this will be
+	  appended after any matching localversion* files, and after the value
+	  set in CONFIG_LOCALVERSION.
+
+	  (The actual string used here is the first eight characters produced
+	  by running the command:
+
+	    $ git rev-parse --verify HEAD
+
+	  which is done within the script "scripts/setlocalversion".)
+
+config CC_OPTIMIZE_FOR_SIZE
+	bool "Optimize for size"
+	default y
+	help
+	  Enabling this option will pass "-Os" instead of "-O2" to gcc
+	  resulting in a smaller U-Boot image.
+
+	  This option is enabled by default for U-Boot.
+
+config CC_COVERAGE
+	bool "Enable code coverage analysis"
+	depends on SANDBOX
+	help
+	  Enabling this option will pass "--coverage" to gcc to compile
+	  and link code instrumented for coverage analysis.
+
+config DISTRO_DEFAULTS
+	bool "Select defaults suitable for booting general purpose Linux distributions"
+	select AUTO_COMPLETE
+	select CMDLINE_EDITING
+	select CMD_BOOTI if ARM64
+	select CMD_BOOTZ if ARM && !ARM64
+	select CMD_DHCP if CMD_NET
+	select CMD_PING if CMD_NET
+	select CMD_ENV_EXISTS
+	select CMD_EXT4
+	select CMD_FAT
+	select CMD_FS_GENERIC
+	select CMD_PART if PARTITIONS
+	select CMD_PING if CMD_NET
+	select CMD_PXE if NET
+	select ENV_VARS_UBOOT_CONFIG
+	select HUSH_PARSER
+	select SUPPORT_RAW_INITRD
+	select SYS_LONGHELP
+	imply CMD_MII if NET
+	imply USB_STORAGE
+	imply USE_BOOTCOMMAND
+	help
+	  Select this to enable various options and commands which are suitable
+	  for building u-boot for booting general purpose Linux distributions.
+
+config ENV_VARS_UBOOT_CONFIG
+	bool "Add arch, board, vendor and soc variables to default environment"
+	help
+	  Define this in order to add variables describing the
+	  U-Boot build configuration to the default environment.
+	  These will be named arch, cpu, board, vendor, and soc.
+	  Enabling this option will cause the following to be defined:
+	  - CONFIG_SYS_ARCH
+	  - CONFIG_SYS_CPU
+	  - CONFIG_SYS_BOARD
+	  - CONFIG_SYS_VENDOR
+	  - CONFIG_SYS_SOC
+
+config NR_DRAM_BANKS
+	int "Number of DRAM banks"
+	default 4
+	help
+	  This defines the number of DRAM banks.
+
+config SYS_BOOT_GET_CMDLINE
+	bool "Enable kernel command line setup"
+	help
+	  Enables allocating and saving kernel cmdline in space between
+	  "bootm_low" and "bootm_low" + BOOTMAPSZ.
+
+config SYS_BOOT_GET_KBD
+	bool "Enable kernel board information setup"
+	help
+	  Enables allocating and saving a kernel copy of the bd_info in
+	  space between "bootm_low" and "bootm_low" + BOOTMAPSZ.
+
+config SYS_MALLOC_F
+	bool "Enable malloc() pool before relocation"
+	default y if DM
+
+	help
+	  Before relocation, memory is very limited on many platforms. Still,
+	  we can provide a small malloc() pool if needed. Driver model in
+	  particular needs this to operate, so that it can allocate the
+	  initial serial device and any others that are needed.
+
+config SYS_MALLOC_F_LEN
+	hex "Size of malloc() pool before relocation"
+	depends on SYS_MALLOC_F
+	default 0x1000 if AM33XX
+	default 0x2800 if SANDBOX
+	default 0x400
+	help
+	  Before relocation, memory is very limited on many platforms. Still,
+	  we can provide a small malloc() pool if needed. Driver model in
+	  particular needs this to operate, so that it can allocate the
+	  initial serial device and any others that are needed.
+
+config SYS_MALLOC_LEN
+	hex "Define memory for Dynamic allocation"
+	depends on ARCH_ZYNQ || ARCH_VERSAL
+	help
+	  This defines memory to be allocated for Dynamic allocation
+	  TODO: Use for other architectures
+
+config SPL_SYS_MALLOC_F_LEN
+	hex "Size of malloc() pool in SPL before relocation"
+	depends on SYS_MALLOC_F
+	default SYS_MALLOC_F_LEN
+	help
+	  Before relocation, memory is very limited on many platforms. Still,
+	  we can provide a small malloc() pool if needed. Driver model in
+	  particular needs this to operate, so that it can allocate the
+	  initial serial device and any others that are needed.
+
+config TPL_SYS_MALLOC_F_LEN
+	hex "Size of malloc() pool in TPL before relocation"
+	depends on SYS_MALLOC_F
+	default SYS_MALLOC_F_LEN
+	help
+	  Before relocation, memory is very limited on many platforms. Still,
+	  we can provide a small malloc() pool if needed. Driver model in
+	  particular needs this to operate, so that it can allocate the
+	  initial serial device and any others that are needed.
+
+menuconfig EXPERT
+	bool "Configure standard U-Boot features (expert users)"
+	default y
+	help
+	  This option allows certain base U-Boot options and settings
+	  to be disabled or tweaked. This is for specialized
+	  environments which can tolerate a "non-standard" U-Boot.
+	  Use this only if you really know what you are doing.
+
+if EXPERT
+	config SYS_MALLOC_CLEAR_ON_INIT
+	bool "Init with zeros the memory reserved for malloc (slow)"
+	default y
+	help
+	  This setting is enabled by default. The reserved malloc
+	  memory is initialized with zeros, so first malloc calls
+	  will return the pointer to the zeroed memory. But this
+	  slows the boot time.
+
+	  It is recommended to disable it, when CONFIG_SYS_MALLOC_LEN
+	  value, has more than few MiB, e.g. when uses bzip2 or bmp logo.
+	  Then the boot time can be significantly reduced.
+	  Warning:
+	  When disabling this, please check if malloc calls, maybe
+	  should be replaced by calloc - if one expects zeroed memory.
+
+config TOOLS_DEBUG
+	bool "Enable debug information for tools"
+	help
+	  Enable generation of debug information for tools such as mkimage.
+	  This can be used for debugging purposes. With debug information
+	  it is possible to set breakpoints on particular lines, single-step
+	  debug through the source code, etc.
+
+endif # EXPERT
+
+config PHYS_64BIT
+	bool "64bit physical address support"
+	help
+	  Say Y here to support 64bit physical memory address.
+	  This can be used not only for 64bit SoCs, but also for
+	  large physical address extention on 32bit SoCs.
+
+config BUILD_ROM
+	bool "Build U-Boot as BIOS replacement"
+	depends on X86
+	help
+	  This option allows to build a ROM version of U-Boot.
+	  The build process generally requires several binary blobs
+	  which are not shipped in the U-Boot source tree.
+	  Please, see doc/README.x86 for details.
+
+endmenu		# General setup
+
+menu "Boot images"
+
+config ANDROID_BOOT_IMAGE
+	bool "Enable support for Android Boot Images"
+	default y if FASTBOOT
+	help
+	  This enables support for booting images which use the Android
+	  image format header.
+
+config FIT
+	bool "Support Flattened Image Tree"
+	select MD5
+	select SHA1
+	help
+	  This option allows you to boot the new uImage structure,
+	  Flattened Image Tree.  FIT is formally a FDT, which can include
+	  images of various types (kernel, FDT blob, ramdisk, etc.)
+	  in a single blob.  To boot this new uImage structure,
+	  pass the address of the blob to the "bootm" command.
+	  FIT is very flexible, supporting compression, multiple images,
+	  multiple configurations, verification through hashing and also
+	  verified boot (secure boot using RSA).
+
+if FIT
+
+config FIT_EXTERNAL_OFFSET
+	hex "Text Base"
+	default 0x0
+	help
+	  This specifies a data offset in fit image.
+	  The offset is from data payload offset to the beginning of
+	  fit image header. When specifies a offset, specific data
+	  could be put in the hole between data payload and fit image
+	  header, such as CSF data on i.MX platform.
+
+config FIT_ENABLE_SHA256_SUPPORT
+	bool "Support SHA256 checksum of FIT image contents"
+	default y
+	select SHA256
+	help
+	  Enable this to support SHA256 checksum of FIT image contents. A
+	  SHA256 checksum is a 256-bit (32-byte) hash value used to check that
+	  the image contents have not been corrupted. SHA256 is recommended
+	  for use in secure applications since (as at 2016) there is no known
+	  feasible attack that could produce a 'collision' with differing
+	  input data. Use this for the highest security. Note that only the
+	  SHA256 variant is supported: SHA512 and others are not currently
+	  supported in U-Boot.
+
+config FIT_SIGNATURE
+	bool "Enable signature verification of FIT uImages"
+	depends on DM
+	select HASH
+	select RSA
+	help
+	  This option enables signature verification of FIT uImages,
+	  using a hash signed and verified using RSA. If
+	  CONFIG_SHA_PROG_HW_ACCEL is defined, i.e support for progressive
+	  hashing is available using hardware, then the RSA library will use
+	  it. See doc/uImage.FIT/signature.txt for more details.
+
+	  WARNING: When relying on signed FIT images with a required signature
+	  check the legacy image format is disabled by default, so that
+	  unsigned images cannot be loaded. If a board needs the legacy image
+	  format support in this case, enable it using
+	  CONFIG_IMAGE_FORMAT_LEGACY.
+
+config FIT_SIGNATURE_MAX_SIZE
+	hex "Max size of signed FIT structures"
+	depends on FIT_SIGNATURE
+	default 0x10000000
+	help
+	  This option sets a max size in bytes for verified FIT uImages.
+	  A sane value of 256MB protects corrupted DTB structures from overlapping
+	  device memory. Assure this size does not extend past expected storage
+	  space.
+
+config FIT_ENABLE_RSASSA_PSS_SUPPORT
+	bool "Support rsassa-pss signature scheme of FIT image contents"
+	depends on FIT_SIGNATURE
+	default n
+	help
+	  Enable this to support the pss padding algorithm as described
+	  in the rfc8017 (https://tools.ietf.org/html/rfc8017).
+
+config FIT_VERBOSE
+	bool "Show verbose messages when FIT images fail"
+	help
+	  Generally a system will have valid FIT images so debug messages
+	  are a waste of code space. If you are debugging your images then
+	  you can enable this option to get more verbose information about
+	  failures.
+
+config FIT_BEST_MATCH
+	bool "Select the best match for the kernel device tree"
+	help
+	  When no configuration is explicitly selected, default to the
+	  one whose fdt's compatibility field best matches that of
+	  U-Boot itself. A match is considered "best" if it matches the
+	  most specific compatibility entry of U-Boot's fdt's root node.
+	  The order of entries in the configuration's fdt is ignored.
+
+config FIT_IMAGE_POST_PROCESS
+	bool "Enable post-processing of FIT artifacts after loading by U-Boot"
+	depends on TI_SECURE_DEVICE
+	help
+	  Allows doing any sort of manipulation to blobs after they got extracted
+	  from FIT images like stripping off headers or modifying the size of the
+	  blob, verification, authentication, decryption etc. in a platform or
+	  board specific way. In order to use this feature a platform or board-
+	  specific implementation of board_fit_image_post_process() must be
+	  provided. Also, anything done during this post-processing step would
+	  need to be comprehended in how the images were prepared before being
+	  injected into the FIT creation (i.e. the blobs would have been pre-
+	  processed before being added to the FIT image).
+
+if SPL
+
+config SPL_FIT
+	bool "Support Flattened Image Tree within SPL"
+	depends on SPL
+	select SPL_OF_LIBFDT
+
+config SPL_FIT_PRINT
+	bool "Support FIT printing within SPL"
+	depends on SPL_FIT
+	help
+	  Support printing the content of the fitImage in a verbose manner in SPL.
+
+config SPL_FIT_SIGNATURE
+	bool "Enable signature verification of FIT firmware within SPL"
+	depends on SPL_DM
+	select SPL_FIT
+	select SPL_RSA
+
+config SPL_LOAD_FIT
+	bool "Enable SPL loading U-Boot as a FIT"
+	select SPL_FIT
+	help
+	  Normally with the SPL framework a legacy image is generated as part
+	  of the build. This contains U-Boot along with information as to
+	  where it should be loaded. This option instead enables generation
+	  of a FIT (Flat Image Tree) which provides more flexibility. In
+	  particular it can handle selecting from multiple device tree
+	  and passing the correct one to U-Boot.
+
+config SPL_LOAD_FIT_FULL
+	bool "Enable SPL loading U-Boot as a FIT"
+	select SPL_FIT
+	help
+	  Normally with the SPL framework a legacy image is generated as part
+	  of the build. This contains U-Boot along with information as to
+	  where it should be loaded. This option instead enables generation
+	  of a FIT (Flat Image Tree) which provides more flexibility. In
+	  particular it can handle selecting from multiple device tree
+	  and passing the correct one to U-Boot.
+
+config SPL_FIT_IMAGE_POST_PROCESS
+	bool "Enable post-processing of FIT artifacts after loading by the SPL"
+	depends on SPL_LOAD_FIT
+	help
+	  Allows doing any sort of manipulation to blobs after they got extracted
+	  from the U-Boot FIT image like stripping off headers or modifying the
+	  size of the blob, verification, authentication, decryption etc. in a
+	  platform or board specific way. In order to use this feature a platform
+	  or board-specific implementation of board_fit_image_post_process() must
+	  be provided. Also, anything done during this post-processing step would
+	  need to be comprehended in how the images were prepared before being
+	  injected into the FIT creation (i.e. the blobs would have been pre-
+	  processed before being added to the FIT image).
+
+config SPL_FIT_SOURCE
+	string ".its source file for U-Boot FIT image"
+	depends on SPL_FIT
+	help
+	  Specifies a (platform specific) FIT source file to generate the
+	  U-Boot FIT image. This could specify further image to load and/or
+	  execute.
+
+config SPL_FIT_GENERATOR
+	string ".its file generator script for U-Boot FIT image"
+	depends on SPL_FIT
+	default "board/sunxi/mksunxi_fit_atf.sh" if SPL_LOAD_FIT && ARCH_SUNXI
+	help
+	  Specifies a (platform specific) script file to generate the FIT
+	  source file used to build the U-Boot FIT image file. This gets
+	  passed a list of supported device tree file stub names to
+	  include in the generated image.
+
+endif # SPL
+
+endif # FIT
+
+config IMAGE_FORMAT_LEGACY
+	bool "Enable support for the legacy image format"
+	default y if !FIT_SIGNATURE
+	help
+	  This option enables the legacy image format. It is enabled by
+	  default for backward compatibility, unless FIT_SIGNATURE is
+	  set where it is disabled so that unsigned images cannot be
+	  loaded. If a board needs the legacy image format support in this
+	  case, enable it here.
+
+config OF_BOARD_SETUP
+	bool "Set up board-specific details in device tree before boot"
+	depends on OF_LIBFDT
+	help
+	  This causes U-Boot to call ft_board_setup() before booting into
+	  the Operating System. This function can set up various
+	  board-specific information in the device tree for use by the OS.
+	  The device tree is then passed to the OS.
+
+config OF_SYSTEM_SETUP
+	bool "Set up system-specific details in device tree before boot"
+	depends on OF_LIBFDT
+	help
+	  This causes U-Boot to call ft_system_setup() before booting into
+	  the Operating System. This function can set up various
+	  system-specific information in the device tree for use by the OS.
+	  The device tree is then passed to the OS.
+
+config OF_STDOUT_VIA_ALIAS
+	bool "Update the device-tree stdout alias from U-Boot"
+	depends on OF_LIBFDT
+	help
+	  This uses U-Boot's serial alias from the aliases node to update
+	  the device tree passed to the OS. The "linux,stdout-path" property
+	  in the chosen node is set to point to the correct serial node.
+	  This option currently references CONFIG_CONS_INDEX, which is
+	  incorrect when used with device tree as this option does not
+	  exist / should not be used.
+
+config SYS_EXTRA_OPTIONS
+	string "Extra Options (DEPRECATED)"
+	help
+	  The old configuration infrastructure (= mkconfig + boards.cfg)
+	  provided the extra options field. If you have something like
+	  "HAS_BAR,BAZ=64", the optional options
+	    #define CONFIG_HAS
+	    #define CONFIG_BAZ	64
+	  will be defined in include/config.h.
+	  This option was prepared for the smooth migration from the old
+	  configuration to Kconfig. Since this option will be removed sometime,
+	  new boards should not use this option.
+
+config SYS_TEXT_BASE
+	depends on !NIOS2 && !XTENSA
+	depends on !EFI_APP
+	default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3
+	default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S
+	default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I
+	default 0x42e00000 if ARCH_SUNXI && MACH_SUN8I_V3S
+	hex "Text Base"
+	help
+	  The address in memory that U-Boot will be running from, initially.
+
+
+
+config SYS_CLK_FREQ
+	depends on ARC || ARCH_SUNXI
+	int "CPU clock frequency"
+	help
+	  TODO: Move CONFIG_SYS_CLK_FREQ for all the architecture
+
+config ARCH_FIXUP_FDT_MEMORY
+	bool "Enable arch_fixup_memory_banks() call"
+	default y
+	help
+	  Enable FDT memory map syncup before OS boot. This feature can be
+	  used for booting OS with different memory setup where the part of
+	  the memory location should be used for different purpose.
+
+endmenu		# Boot images
+
+source "api/Kconfig"
+
+source "common/Kconfig"
+
+source "cmd/Kconfig"
+
+source "disk/Kconfig"
+
+source "dts/Kconfig"
+
+source "env/Kconfig"
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "lib/Kconfig"
+
+source "test/Kconfig"
+
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index d159169..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,339 +0,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                            NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644
index 0000000..f86fdf9
--- /dev/null
+++ b/MAINTAINERS
@@ -0,0 +1,742 @@
+Descriptions of section entries:
+
+	P: Person (obsolete)
+	M: Mail patches to: FullName <address@domain>
+	R: Designated reviewer: FullName <address@domain>
+	   These reviewers should be CCed on patches.
+	L: Mailing list that is relevant to this area
+	W: Web-page with status/info
+	Q: Patchwork web based patch tracking system site
+	T: SCM tree type and location.
+	   Type is one of: git, hg, quilt, stgit, topgit
+	S: Status, one of the following:
+	   Supported:	Someone is actually paid to look after this.
+	   Maintained:	Someone actually looks after it.
+	   Odd Fixes:	It has a maintainer but they don't have time to do
+			much other than throw the odd patch in. See below..
+	   Orphan:	No current maintainer [but maybe you could take the
+			role as you write your new code].
+	   Obsolete:	Old code. Something tagged obsolete generally means
+			it has been replaced by a better system and you
+			should be using that.
+	F: Files and directories with wildcard patterns.
+	   A trailing slash includes all files and subdirectory files.
+	   F:	drivers/net/	all files in and below drivers/net
+	   F:	drivers/net/*	all files in drivers/net, but not below
+	   F:	*/net/*		all files in "any top level directory"/net
+	   One pattern per line.  Multiple F: lines acceptable.
+	N: Files and directories with regex patterns.
+	   N:	[^a-z]tegra	all files whose path contains the word tegra
+	   One pattern per line.  Multiple N: lines acceptable.
+	   scripts/get_maintainer.pl has different behavior for files that
+	   match F: pattern and matches of N: patterns.  By default,
+	   get_maintainer will not look at git log history when an F: pattern
+	   match occurs.  When an N: match occurs, git log history is used
+	   to also notify the people that have git commit signatures.
+	X: Files and directories that are NOT maintained, same rules as F:
+	   Files exclusions are tested before file matches.
+	   Can be useful for excluding a specific subdirectory, for instance:
+	   F:	net/
+	   X:	net/ipv6/
+	   matches all files in and below net excluding net/ipv6/
+	K: Keyword perl extended regex pattern to match content in a
+	   patch or file.  For instance:
+	   K: of_get_profile
+	      matches patches or files that contain "of_get_profile"
+	   K: \b(printk|pr_(info|err))\b
+	      matches patches or files that contain one or more of the words
+	      printk, pr_info or pr_err
+	   One regex pattern per line.  Multiple K: lines acceptable.
+
+Note: For the hard of thinking, this list is meant to remain in alphabetical
+order. If you could add yourselves to it in alphabetical order that would be
+so much easier [Ed]
+
+Maintainers List (try to look for most precise areas first)
+
+		-----------------------------------
+ARC
+M:	Alexey Brodkin <alexey.brodkin@synopsys.com>
+M:	Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+S:	Maintained
+L:	uboot-snps-arc@synopsys.com
+T:	git git://git.denx.de/u-boot-arc.git
+F:	arch/arc/
+F:	board/synopsys/
+
+ARC HSDK CGU CLOCK
+M:	Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+S:	Maintained
+L:	uboot-snps-arc@synopsys.com
+F:	drivers/clk/clk-hsdk-cgu.c
+F:	include/dt-bindings/clock/snps,hsdk-cgu.h
+F:	doc/device-tree-bindings/clock/snps,hsdk-cgu.txt
+
+ARC HSDK CREG GPIO
+M:	Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+S:	Maintained
+L:	uboot-snps-arc@synopsys.com
+F:	doc/device-tree-bindings/gpio/snps,creg-gpio.txt
+F:	drivers/gpio/hsdk-creg-gpio.c
+
+ARM
+M:	Albert Aribaud <albert.u.boot@aribaud.net>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-arm.git
+F:	arch/arm/
+
+ARM ALTERA SOCFPGA
+M:	Marek Vasut <marex@denx.de>
+S:	Maintainted
+T:	git git://git.denx.de/u-boot-socfpga.git
+F:	arch/arm/mach-socfpga/
+
+ARM ATMEL AT91
+M:	Andreas Bießmann <andreas@biessmann.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-atmel.git
+F:	arch/arm/mach-at91/
+
+ARM BROADCOM BCM283X
+M:	Alexander Graf <agraf@suse.de>
+S:	Maintained
+F:	arch/arm/mach-bcm283x/
+F:	drivers/gpio/bcm2835_gpio.c
+F:	drivers/mmc/bcm2835_sdhci.c
+F:	drivers/mmc/bcm2835_sdhost.c
+F:	drivers/serial/serial_bcm283x_mu.c
+F:	drivers/serial/serial_bcm283x_pl011.c
+F:	drivers/video/bcm2835.c
+F:	include/dm/platform_data/serial_bcm283x_mu.h
+F:	drivers/pinctrl/broadcom/
+
+ARM BROADCOM BCMSTB
+M:	Thomas Fitzsimmons <fitzsim@fitzsim.org>
+S:	Maintained
+F:	arch/arm/mach-bcmstb/
+F:	board/broadcom/bcmstb/
+F:	configs/bcm7*_defconfig
+F:	doc/README.bcm7xxx
+F:	drivers/mmc/bcmstb_sdhci.c
+F:	drivers/spi/bcmstb_spi.c
+
+ARM FREESCALE IMX
+M:	Stefano Babic <sbabic@denx.de>
+M:	Fabio Estevam <fabio.estevam@nxp.com>
+R:	NXP i.MX U-Boot Team <uboot-imx@nxp.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-imx.git
+F:	arch/arm/cpu/arm1136/mx*/
+F:	arch/arm/cpu/arm926ejs/mx*/
+F:	arch/arm/cpu/armv7/vf610/
+F:	arch/arm/mach-imx/
+F:	arch/arm/include/asm/arch-imx/
+F:	arch/arm/include/asm/arch-mx*/
+F:	arch/arm/include/asm/arch-vf610/
+F:	arch/arm/include/asm/mach-imx/
+F:	board/freescale/*mx*/
+
+ARM HISILICON
+M:	Peter Griffin <peter.griffin@linaro.org>
+S:	Maintained
+F:	arch/arm/cpu/armv8/hisilicon
+F:	arch/arm/include/asm/arch-hi6220/
+
+ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX
+M:	Prafulla Wadaskar <prafulla@marvell.com>
+M:	Luka Perkov <luka.perkov@sartura.hr>
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-marvell.git
+F:	arch/arm/mach-kirkwood/
+F:	arch/arm/mach-mvebu/
+F:	drivers/ata/ahci_mvebu.c
+F:	drivers/phy/marvell/
+
+ARM MARVELL PXA
+M:	Marek Vasut <marex@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-pxa.git
+F:	arch/arm/cpu/pxa/
+F:	arch/arm/include/asm/arch-pxa/
+
+ARM MEDIATEK
+M:	Ryder Lee <ryder.lee@mediatek.com>
+M:	Weijie Gao <weijie.gao@mediatek.com>
+S:	Maintained
+F:	arch/arm/mach-mediatek/
+F:	arch/arm/include/asm/arch-mediatek/
+F:	board/mediatek/
+F:	doc/README.mediatek
+F:	drivers/clk/mediatek/
+F:	drivers/mmc/mtk-sd.c
+F:	drivers/pinctrl/mediatek/
+F:	drivers/power/domain/mtk-power-domain.c
+F:	drivers/ram/mediatek/
+F:	drivers/spi/mtk_qspi.c
+F:	drivers/timer/mtk_timer.c
+F:	drivers/watchdog/mtk_wdt.c
+F:	tools/mtk_image.c
+F:	tools/mtk_image.h
+N:	mediatek
+
+ARM OWL
+M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+S:	Maintained
+F:	arch/arm/include/asm/arch-owl/
+F:	arch/arm/mach-owl/
+F:	board/ucRobotics/
+F:	drivers/clk/owl/
+F:	drivers/serial/serial_owl.c
+
+ARM RENESAS RMOBILE/R-CAR
+M:	Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+M:	Marek Vasut <marek.vasut+renesas@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-sh.git
+F:	arch/arm/mach-rmobile/
+
+ARM ROCKCHIP
+M:	Simon Glass <sjg@chromium.org>
+M:	Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-rockchip.git
+F:	arch/arm/include/asm/arch-rockchip/
+F:	arch/arm/mach-rockchip/
+F:	board/rockchip/
+F:	drivers/clk/rockchip/
+F:	drivers/gpio/rk_gpio.c
+F:	drivers/misc/rockchip-efuse.c
+F:	drivers/mmc/rockchip_sdhci.c
+F:	drivers/mmc/rockchip_dw_mmc.c
+F:	drivers/pinctrl/rockchip/
+F:	drivers/ram/rockchip/
+F:	drivers/sysreset/sysreset_rockchip.c
+F:	drivers/video/rockchip/
+F:	tools/rkcommon.c
+F:	tools/rkcommon.h
+F:	tools/rkimage.c
+F:	tools/rksd.c
+F:	tools/rkspi.c
+
+ARM SAMSUNG
+M:	Minkyu Kang <mk7.kang@samsung.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-samsung.git
+F:	arch/arm/mach-exynos/
+F:	arch/arm/mach-s5pc1xx/
+F:	arch/arm/cpu/armv7/s5p-common/
+
+ARM SNAPDRAGON
+M:	Ramon Fried <ramon.fried@gmail.com>
+S:	Maintained
+F:	arch/arm/mach-snapdragon/
+F:	drivers/gpio/msm_gpio.c
+F:	drivers/mmc/msm_sdhci.c
+F:	drivers/phy/msm8916-usbh-phy.c
+F:	drivers/serial/serial_msm.c
+F:	drivers/smem/msm_smem.c
+F:	drivers/usb/host/ehci-msm.c
+
+ARM STI
+M:	Patrice Chotard <patrice.chotard@st.com>
+S:	Maintained
+F:	arch/arm/mach-sti/
+F:	arch/arm/include/asm/arch-sti*/
+
+ARM STM SPEAR
+#M:	Vipin Kumar <vipin.kumar@st.com>
+S:	Orphaned (Since 2016-02)
+T:	git git://git.denx.de/u-boot-stm.git
+F:	arch/arm/cpu/arm926ejs/spear/
+F:	arch/arm/include/asm/arch-spear/
+
+ARM STM STM32MP
+M:	Patrick Delaunay <patrick.delaunay@st.com>
+M:	Christophe Kerello <christophe.kerello@st.com>
+M:	Patrice Chotard <patrice.chotard@st.com>
+L:	uboot-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-stm32mp
+F:	drivers/clk/clk_stm32mp1.c
+F:	drivers/i2c/stm32f7_i2c.c
+F:	drivers/misc/stm32mp_fuse.c
+F:	drivers/mmc/stm32_sdmmc2.c
+F:	drivers/phy/phy-stm32-usbphyc.c
+F:	drivers/pinctrl/pinctrl_stm32.c
+F:	drivers/power/regulator/stm32-vrefbuf.c
+F:	drivers/ram/stm32mp1/
+F:	drivers/misc/stm32_rcc.c
+F:	drivers/reset/stm32-reset.c
+F:	drivers/spi/stm32_qspi.c
+
+ARM STM STV0991
+M:	Vikas Manocha <vikas.manocha@st.com>
+S:	Maintained
+F:	arch/arm/cpu/armv7/stv0991/
+F:	arch/arm/include/asm/arch-stv0991/
+
+ARM SUNXI
+M:	Jagan Teki <jagan@openedev.com>
+M:	Maxime Ripard <maxime.ripard@bootlin.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-sunxi.git
+F:	arch/arm/cpu/armv7/sunxi/
+F:	arch/arm/include/asm/arch-sunxi/
+F:	arch/arm/mach-sunxi/
+F:	board/sunxi/
+
+ARM TEGRA
+M:	Tom Warren <twarren@nvidia.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-tegra.git
+F:	arch/arm/mach-tegra/
+F:	arch/arm/include/asm/arch-tegra*/
+
+ARM TI
+M:	Tom Rini <trini@konsulko.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-ti.git
+F:	arch/arm/mach-davinci/
+F:	arch/arm/mach-k3/
+F:	arch/arm/mach-keystone/
+F:	arch/arm/include/asm/arch-omap*/
+F:	arch/arm/include/asm/ti-common/
+
+ARM UNIPHIER
+M:	Masahiro Yamada <yamada.masahiro@socionext.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-uniphier.git
+F:	arch/arm/mach-uniphier/
+F:	configs/uniphier_*_defconfig
+N:	uniphier
+
+ARM VERSAL
+M:	Michal Simek <michal.simek@xilinx.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	arch/arm/mach-versal/
+
+ARM VERSATILE EXPRESS DRIVERS
+M:	Liviu Dudau <liviu.dudau@foss.arm.com>
+S:	Maintained
+T:	git git://github.com/ARM-software/u-boot.git
+F:	drivers/misc/vexpress_config.c
+N:	vexpress
+
+ARM ZYNQ
+M:	Michal Simek <monstr@monstr.eu>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	arch/arm/mach-zynq/
+F:	drivers/clk/clk_zynq.c
+F:	drivers/fpga/zynqpl.c
+F:	drivers/gpio/zynq_gpio.c
+F:	drivers/i2c/i2c-cdns.c
+F:	drivers/i2c/muxes/pca954x.c
+F:	drivers/i2c/zynq_i2c.c
+F:	drivers/mmc/zynq_sdhci.c
+F:	drivers/mtd/nand/raw/zynq_nand.c
+F:	drivers/net/phy/xilinx_phy.c
+F:	drivers/net/zynq_gem.c
+F:	drivers/serial/serial_zynq.c
+F:	drivers/spi/zynq_qspi.c
+F:	drivers/spi/zynq_spi.c
+F:	drivers/usb/host/ehci-zynq.c
+F:	drivers/watchdog/cdns_wdt.c
+F:	include/zynqpl.h
+F:	tools/zynqimage.c
+N:	zynq
+
+ARM ZYNQMP
+M:	Michal Simek <michal.simek@xilinx.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	arch/arm/cpu/armv8/zynqmp/
+F:	drivers/clk/clk_zynqmp.c
+F:	drivers/fpga/zynqpl.c
+F:	drivers/gpio/zynq_gpio.c
+F:	drivers/i2c/i2c-cdns.c
+F:	drivers/i2c/muxes/pca954x.c
+F:	drivers/i2c/zynq_i2c.c
+F:	drivers/mmc/zynq_sdhci.c
+F:	drivers/mtd/nand/raw/zynq_nand.c
+F:	drivers/net/phy/xilinx_phy.c
+F:	drivers/net/zynq_gem.c
+F:	drivers/serial/serial_zynq.c
+F:	drivers/spi/zynq_qspi.c
+F:	drivers/spi/zynq_spi.c
+F:	drivers/timer/cadence-ttc.c
+F:	drivers/usb/host/ehci-zynq.c
+F:	drivers/watchdog/cdns_wdt.c
+F:	include/zynqmppl.h
+F:	tools/zynqmp*
+N:	ultra96
+N:	zynqmp
+
+ARM ZYNQMP R5
+M:	Michal Simek <michal.simek@xilinx.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	arch/arm/mach-zynqmp-r5/
+
+BINMAN
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	tools/binman/
+
+BUILDMAN
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	tools/buildman/
+
+CFI FLASH
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-cfi-flash.git
+F:	drivers/mtd/cfi_flash.c
+F:	drivers/mtd/jedec_flash.c
+
+COLDFIRE
+M:	Huan Wang <alison.wang@nxp.com>
+M:	Angelo Dureghello <angelo@sysam.it>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-coldfire.git
+F:	arch/m68k/
+
+DFU
+M:	Lukasz Majewski <lukma@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-dfu.git
+F:	drivers/dfu/
+F:	drivers/usb/gadget/
+
+DRIVER MODEL
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-dm.git
+F:	drivers/core/
+F:	include/dm/
+F:	test/dm/
+
+EFI PAYLOAD
+M:	Alexander Graf <agraf@suse.de>
+R:	Heinrich Schuchardt <xypron.glpk@gmx.de>
+S:	Maintained
+T:	git git://github.com/agraf/u-boot.git
+F:	doc/README.uefi
+F:	doc/README.iscsi
+F:	Documentation/efi.rst
+F:	include/capitalization.h
+F:	include/cp1250.h
+F:	include/cp437.h
+F:	include/efi*
+F:	include/pe.h
+F:	include/asm-generic/pe.h
+F:	lib/charset.c
+F:	lib/efi*/
+F:	test/py/tests/test_efi*
+F:	test/unicode_ut.c
+F:	cmd/bootefi.c
+F:	tools/file2include.c
+
+FPGA
+M:	Michal Simek <michal.simek@xilinx.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	drivers/fpga/
+F:	cmd/fpga.c
+F:	include/fpga.h
+
+FLATTENED DEVICE TREE
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-fdt.git
+F:	lib/fdtdec*
+F:	lib/libfdt/
+F:	include/fdt*
+F:	include/linux/libfdt*
+F:	cmd/fdt.c
+F:	common/fdt_support.c
+
+FREEBSD
+M:	Rafal Jaworowski <raj@semihalf.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-freebsd.git
+
+FREESCALE QORIQ
+M:	York Sun <york.sun@nxp.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-fsl-qoriq.git
+
+I2C
+M:	Heiko Schocher <hs@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-i2c.git
+F:	drivers/i2c/
+
+LOGGING
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot.git
+F:	common/log.c
+F:	cmd/log.c
+F:	test/log/log_test.c
+F:	test/py/tests/test_log.py
+
+MALI DISPLAY PROCESSORS
+M:	Liviu Dudau <liviu.dudau@foss.arm.com>
+S:	Supported
+T:	git git://github.com/ARM-software/u-boot.git
+F:	drivers/video/mali_dp.c
+F:	drivers/i2c/i2c-versatile.c
+
+MICROBLAZE
+M:	Michal Simek <monstr@monstr.eu>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	arch/microblaze/
+F:	cmd/mfsl.c
+F:	drivers/gpio/xilinx_gpio.c
+F:	drivers/net/xilinx_axi_emac.c
+F:	drivers/net/xilinx_emaclite.c
+F:	drivers/serial/serial_xuartlite.c
+F:	drivers/spi/xilinx_spi.c
+F:	drivers/sysreset/sysreset_gpio.c
+F:	drivers/watchdog/xilinx_tb_wdt.c
+N:	xilinx
+
+MIPS
+M:	Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mips.git
+F:	arch/mips/
+
+MIPS MSCC
+M:	Gregory CLEMENT <gregory.clement@bootlin.com>
+M:	Lars Povlsen <lars.povlsen@microchip.com>
+M:	Horatiu Vultur <horatiu.vultur@microchip.com>
+S:	Maintained
+F:	arch/mips/mach-mscc/
+F:	arch/mips/dts/luton*
+F:	arch/mips/dts/mscc*
+F:	arch/mips/dts/ocelot*
+F:	board/mscc/
+F:	configs/mscc*
+F:	include/configs/vcoreiii.h
+
+MIPS JZ4780
+M:	Ezequiel Garcia <ezequiel@collabora.com>
+S:	Maintained
+F:	arch/mips/mach-jz47xx/
+
+MMC
+M:	Jaehoon Chung <jh80.chung@samsung.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mmc.git
+F:	drivers/mmc/
+
+NAND FLASH
+#M:	Scott Wood <oss@buserror.net>
+S:	Orphaned (Since 2018-07)
+T:	git git://git.denx.de/u-boot-nand-flash.git
+F:	drivers/mtd/nand/raw/
+
+NDS32
+M:	Macpaul Lin <macpaul@andestech.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-nds32.git
+F:	arch/nds32/
+
+NETWORK
+M:	Joe Hershberger <joe.hershberger@ni.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-net.git
+F:	drivers/net/
+F:	net/
+
+NIOS
+M:	Thomas Chou <thomas@wytron.com.tw>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-nios.git
+F:	arch/nios2/
+
+ONENAND
+#M:	Lukasz Majewski <l.majewski@majess.pl>
+S:	Orphaned (Since 2017-01)
+T:	git git://git.denx.de/u-boot-onenand.git
+F:	drivers/mtd/onenand/
+
+PATMAN
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	tools/patman/
+
+POWER
+M:	Jaehoon Chung <jh80.chung@samsung.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-pmic.git
+F:	drivers/power/
+
+POWERPC
+M:	Wolfgang Denk <wd@denx.de>
+S:	Maintained
+F:	arch/powerpc/
+
+POWERPC MPC8XX
+M:	Christophe Leroy <christophe.leroy@c-s.fr>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc8xx.git
+F:	arch/powerpc/cpu/mpc8xx/
+
+POWERPC MPC83XX
+M:	Mario Six <mario.six@gdsys.cc>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc83xx.git
+F:	drivers/ram/mpc83xx_sdram.c
+F:	include/dt-bindings/memory/mpc83xx-sdram.h
+F:	drivers/sysreset/sysreset_mpc83xx.c
+F:	drivers/sysreset/sysreset_mpc83xx.h
+F:	drivers/clk/mpc83xx_clk.c
+F:	drivers/clk/mpc83xx_clk.h
+F:	include/dt-bindings/clk/mpc83xx-clk.h
+F:	drivers/timer/mpc83xx_timer.c
+F:	drivers/cpu/mpc83xx_cpu.c
+F:	drivers/cpu/mpc83xx_cpu.h
+F:	drivers/misc/mpc83xx_serdes.c
+F:	arch/powerpc/cpu/mpc83xx/
+F:	arch/powerpc/include/asm/arch-mpc83xx/
+
+POWERPC MPC85XX
+M:	York Sun <york.sun@nxp.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc85xx.git
+F:	arch/powerpc/cpu/mpc85xx/
+
+POWERPC MPC86XX
+M:	York Sun <york.sun@nxp.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc86xx.git
+F:	arch/powerpc/cpu/mpc86xx/
+
+RISC-V
+M:	Rick Chen <rick@andestech.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-riscv.git
+F:	arch/riscv/
+F:	tools/prelink-riscv.c
+
+ROCKUSB
+M:	Eddie Cai <eddie.cai.linux@gmail.com>
+S:	Maintained
+F:	drivers/usb/gadget/f_rockusb.c
+F:	cmd/rockusb.c
+F:	doc/README.rockusb
+
+SANDBOX
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	arch/sandbox/
+
+SH
+M:	Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-sh.git
+F:	arch/sh/
+
+SPI
+M:	Jagan Teki <jagan@openedev.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-spi.git
+F:	drivers/mtd/spi/
+F:	drivers/spi/
+F:	include/spi*
+
+SPMI
+M:	Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+S:	Maintained
+F:	drivers/spmi/
+F:	include/spmi/
+
+TDA19988 HDMI ENCODER
+M:	Liviu Dudau <liviu.dudau@foss.arm.com>
+S:	Maintained
+F:	drivers/video/tda19988.c
+
+TI SYSTEM SECURITY
+M:	Andrew F. Davis <afd@ti.com>
+S:	Supported
+F:	arch/arm/mach-omap2/omap5/sec_entry_cpu1.S
+F:	arch/arm/mach-omap2/sec-common.c
+F:	arch/arm/mach-omap2/config_secure.mk
+F:	configs/am335x_hs_evm_defconfig
+F:	configs/am335x_hs_evm_uart_defconfig
+F:	configs/am43xx_hs_evm_defconfig
+F:	configs/am57xx_hs_evm_defconfig
+F:	configs/dra7xx_hs_evm_defconfig
+F:	configs/k2hk_hs_evm_defconfig
+F:	configs/k2e_hs_evm_defconfig
+F:	configs/k2g_hs_evm_defconfig
+F:	configs/k2l_hs_evm_defconfig
+
+TQ GROUP
+#M:	Martin Krause <martin.krause@tq-systems.de>
+S:	Orphaned (Since 2016-02)
+T:	git git://git.denx.de/u-boot-tq-group.git
+
+TEE
+M:	Jens Wiklander <jens.wiklander@linaro.org>
+S:	Maintained
+F:	drivers/tee/
+F:	include/tee.h
+F:	include/tee/
+
+UBI
+M:	Kyungmin Park <kmpark@infradead.org>
+M:	Heiko Schocher <hs@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-ubi.git
+F:	drivers/mtd/ubi/
+
+USB
+M:	Marek Vasut <marex@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-usb.git
+F:	drivers/usb/
+
+USB xHCI
+M:	Bin Meng <bmeng.cn@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-usb.git topic-xhci
+F:	drivers/usb/host/xhci*
+
+VIDEO
+M:	Anatolij Gustschin <agust@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-video.git
+F:	drivers/video/
+F:	common/lcd*.c
+F:	include/lcd*.h
+F:	include/video*.h
+
+X86
+M:	Simon Glass <sjg@chromium.org>
+M:	Bin Meng <bmeng.cn@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-x86.git
+F:	arch/x86/
+
+XTENSA
+M:	Max Filippov <jcmvbkbc@gmail.com>
+S:	Maintained
+F:	arch/xtensa/
+
+THE REST
+M:	Tom Rini <trini@konsulko.com>
+L:	u-boot@lists.denx.de
+Q:	http://patchwork.ozlabs.org/project/uboot/list/
+S:	Maintained
+T:	git git://git.denx.de/u-boot.git
+F:	configs/tools-only_defconfig
+F:	*
+F:	*/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a278718
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,2052 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+VERSION = 2019
+PATCHLEVEL = 01
+SUBLEVEL =
+EXTRAVERSION =
+NAME =
+
+# *DOCUMENTATION*
+# To see a list of typical targets execute "make help"
+# More info can be located in ./README
+# Comments in this file are targeted only to the developer, do not
+# expect to learn how to build the kernel reading this file.
+
+# o Do not use make's built-in rules and variables
+#   (this increases performance and avoids hard-to-debug behaviour);
+# o Look for make include files relative to root of kernel src
+MAKEFLAGS += -rR --include-dir=$(CURDIR)
+
+# Avoid funny character set dependencies
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+# Avoid interference with shell env settings
+unexport GREP_OPTIONS
+
+# We are using a recursive build, so we need to do a little thinking
+# to get the ordering right.
+#
+# Most importantly: sub-Makefiles should only ever modify files in
+# their own directory. If in some directory we have a dependency on
+# a file in another dir (which doesn't happen often, but it's often
+# unavoidable when linking the built-in.o targets which finally
+# turn into vmlinux), we will call a sub make in that other dir, and
+# after that we are sure that everything which is in that other dir
+# is now up to date.
+#
+# The only cases where we need to modify files which have global
+# effects are thus separated out and done before the recursive
+# descending is started. They are now explicitly listed as the
+# prepare rule.
+
+# We use U_BOOT_DATE and U_BOOT_TIME to record u-boot build timestamp.
+# make T=0 or by default to use local time (date) as build timestamp.
+# make T=1 to use latest git commit time as build timestamp.
+ifeq ("$(origin T)", "command line")
+	KBUILD_TIME_STAMP = $(T)
+endif
+ifndef KBUILD_TIME_STAMP
+	KBUILD_TIME_STAMP = 0
+endif
+
+# Beautify output
+# ---------------------------------------------------------------------------
+#
+# Normally, we echo the whole command before executing it. By making
+# that echo $($(quiet)$(cmd)), we now have the possibility to set
+# $(quiet) to choose other forms of output instead, e.g.
+#
+#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
+#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
+#
+# If $(quiet) is empty, the whole command will be printed.
+# If it is set to "quiet_", only the short version will be printed.
+# If it is set to "silent_", nothing will be printed at all, since
+# the variable $(silent_cmd_cc_o_c) doesn't exist.
+#
+# A simple variant is to prefix commands with $(Q) - that's useful
+# for commands that shall be hidden in non-verbose mode.
+#
+#	$(Q)ln $@ :<
+#
+# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
+# If KBUILD_VERBOSE equals 1 then the above command is displayed.
+#
+# To put more focus on warnings, be less verbose as default
+# Use 'make V=1' to see the full commands
+
+ifeq ("$(origin V)", "command line")
+  KBUILD_VERBOSE = $(V)
+endif
+ifndef KBUILD_VERBOSE
+  KBUILD_VERBOSE = 0
+endif
+
+ifeq ($(KBUILD_VERBOSE),1)
+  quiet =
+  Q =
+else
+  quiet=quiet_
+  Q = @
+endif
+
+# If the user is running make -s (silent mode), suppress echoing of
+# commands
+
+ifneq ($(filter 4.%,$(MAKE_VERSION)),)	# make-4
+ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
+  quiet=silent_
+endif
+else					# make-3.8x
+ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
+  quiet=silent_
+endif
+endif
+
+export quiet Q KBUILD_VERBOSE
+
+# kbuild supports saving output files in a separate directory.
+# To locate output files in a separate directory two syntaxes are supported.
+# In both cases the working directory must be the root of the kernel src.
+# 1) O=
+# Use "make O=dir/to/store/output/files/"
+#
+# 2) Set KBUILD_OUTPUT
+# Set the environment variable KBUILD_OUTPUT to point to the directory
+# where the output files shall be placed.
+# export KBUILD_OUTPUT=dir/to/store/output/files/
+# make
+#
+# The O= assignment takes precedence over the KBUILD_OUTPUT environment
+# variable.
+
+# KBUILD_SRC is set on invocation of make in OBJ directory
+# KBUILD_SRC is not intended to be used by the regular user (for now)
+ifeq ($(KBUILD_SRC),)
+
+# OK, Make called in directory where kernel src resides
+# Do we want to locate output files in a separate directory?
+ifeq ("$(origin O)", "command line")
+  KBUILD_OUTPUT := $(O)
+endif
+
+# That's our default target when none is given on the command line
+PHONY := _all
+_all:
+
+# Cancel implicit rules on top Makefile
+$(CURDIR)/Makefile Makefile: ;
+
+ifneq ($(KBUILD_OUTPUT),)
+# Invoke a second make in the output directory, passing relevant variables
+# check that the output directory actually exists
+saved-output := $(KBUILD_OUTPUT)
+KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
+								&& /bin/pwd)
+$(if $(KBUILD_OUTPUT),, \
+     $(error failed to create output directory "$(saved-output)"))
+
+PHONY += $(MAKECMDGOALS) sub-make
+
+$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
+	@:
+
+sub-make: FORCE
+	$(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \
+	-f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+endif # ifneq ($(KBUILD_OUTPUT),)
+endif # ifeq ($(KBUILD_SRC),)
+
+# We process the rest of the Makefile if this is the final invocation of make
+ifeq ($(skip-makefile),)
+
+# Do not print "Entering directory ...",
+# but we want to display it when entering to the output directory
+# so that IDEs/editors are able to understand relative filenames.
+MAKEFLAGS += --no-print-directory
+
+# Call a source code checker (by default, "sparse") as part of the
+# C compilation.
+#
+# Use 'make C=1' to enable checking of only re-compiled files.
+# Use 'make C=2' to enable checking of *all* source files, regardless
+# of whether they are re-compiled or not.
+#
+# See the file "Documentation/sparse.txt" for more details, including
+# where to get the "sparse" utility.
+
+ifeq ("$(origin C)", "command line")
+  KBUILD_CHECKSRC = $(C)
+endif
+ifndef KBUILD_CHECKSRC
+  KBUILD_CHECKSRC = 0
+endif
+
+# Use make M=dir to specify directory of external module to build
+# Old syntax make ... SUBDIRS=$PWD is still supported
+# Setting the environment variable KBUILD_EXTMOD take precedence
+ifdef SUBDIRS
+  KBUILD_EXTMOD ?= $(SUBDIRS)
+endif
+
+ifeq ("$(origin M)", "command line")
+  KBUILD_EXTMOD := $(M)
+endif
+
+# If building an external module we do not care about the all: rule
+# but instead _all depend on modules
+PHONY += all
+ifeq ($(KBUILD_EXTMOD),)
+_all: all
+else
+_all: modules
+endif
+
+ifeq ($(KBUILD_SRC),)
+        # building in the source tree
+        srctree := .
+else
+        ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
+                # building in a subdirectory of the source tree
+                srctree := ..
+        else
+                srctree := $(KBUILD_SRC)
+        endif
+endif
+objtree		:= .
+src		:= $(srctree)
+obj		:= $(objtree)
+
+VPATH		:= $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
+
+buildsrc	:= $(abspath $(srctree))
+buildtree	:= $(abspath $(CURDIR)/$(KBUILD_OUTPUT))
+
+export srctree objtree VPATH buildsrc buildtree
+
+# Make sure CDPATH settings don't interfere
+unexport CDPATH
+
+#########################################################################
+
+HOSTARCH := $(shell uname -m | \
+	sed -e s/i.86/x86/ \
+	    -e s/sun4u/sparc64/ \
+	    -e s/arm.*/arm/ \
+	    -e s/sa110/arm/ \
+	    -e s/ppc64/powerpc/ \
+	    -e s/ppc/powerpc/ \
+	    -e s/macppc/powerpc/\
+	    -e s/sh.*/sh/)
+
+HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
+	    sed -e 's/\(cygwin\).*/cygwin/')
+
+export	HOSTARCH HOSTOS
+
+#########################################################################
+
+# set default to nothing for native builds
+ifeq ($(HOSTARCH),$(ARCH))
+CROSS_COMPILE ?=
+endif
+
+KCONFIG_CONFIG	?= .config
+export KCONFIG_CONFIG
+
+# SHELL used by kbuild
+CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
+	  else if [ -x /bin/bash ]; then echo /bin/bash; \
+	  else echo sh; fi ; fi)
+
+HOSTCC       = cc
+HOSTCXX      = c++
+HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \
+		$(if $(CONFIG_TOOLS_DEBUG),-g)
+HOSTCXXFLAGS = -O2
+
+# With the move to GCC 6, we have implicitly upgraded our language
+# standard to GNU11 (see https://gcc.gnu.org/gcc-5/porting_to.html).
+# Some Linux distributions (including RHEL7, SLES13, Debian 8) still
+# have older compilers as their default, so we make it explicit for
+# these that our host tools are GNU11 (i.e. C11 w/ GNU extensions).
+CSTD_FLAG := -std=gnu11
+ifeq ($(HOSTOS),linux)
+HOSTCFLAGS += $(CSTD_FLAG)
+endif
+
+ifeq ($(HOSTOS),cygwin)
+HOSTCFLAGS	+= -ansi
+endif
+
+# Mac OS X / Darwin's C preprocessor is Apple specific.  It
+# generates numerous errors and warnings.  We want to bypass it
+# and use GNU C's cpp.	To do this we pass the -traditional-cpp
+# option to the compiler.  Note that the -traditional-cpp flag
+# DOES NOT have the same semantics as GNU C's flag, all it does
+# is invoke the GNU preprocessor in stock ANSI/ISO C fashion.
+#
+# Apple's linker is similar, thanks to the new 2 stage linking
+# multiple symbol definitions are treated as errors, hence the
+# -multiply_defined suppress option to turn off this error.
+#
+ifeq ($(HOSTOS),darwin)
+# get major and minor product version (e.g. '10' and '6' for Snow Leopard)
+DARWIN_MAJOR_VERSION	= $(shell sw_vers -productVersion | cut -f 1 -d '.')
+DARWIN_MINOR_VERSION	= $(shell sw_vers -productVersion | cut -f 2 -d '.')
+
+os_x_before	= $(shell if [ $(DARWIN_MAJOR_VERSION) -le $(1) -a \
+	$(DARWIN_MINOR_VERSION) -le $(2) ] ; then echo "$(3)"; else echo "$(4)"; fi ;)
+
+# Snow Leopards build environment has no longer restrictions as described above
+HOSTCC       = $(call os_x_before, 10, 5, "cc", "gcc")
+HOSTCFLAGS  += $(call os_x_before, 10, 4, "-traditional-cpp")
+HOSTLDFLAGS += $(call os_x_before, 10, 5, "-multiply_defined suppress")
+
+# since Lion (10.7) ASLR is on by default, but we use linker generated lists
+# in some host tools which is a problem then ... so disable ASLR for these
+# tools
+HOSTLDFLAGS += $(call os_x_before, 10, 7, "", "-Xlinker -no_pie")
+endif
+
+# Decide whether to build built-in, modular, or both.
+# Normally, just do built-in.
+
+KBUILD_MODULES :=
+KBUILD_BUILTIN := 1
+
+# If we have only "make modules", don't compile built-in objects.
+# When we're building modules with modversions, we need to consider
+# the built-in objects during the descend as well, in order to
+# make sure the checksums are up to date before we record them.
+
+ifeq ($(MAKECMDGOALS),modules)
+  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
+endif
+
+# If we have "make <whatever> modules", compile modules
+# in addition to whatever we do anyway.
+# Just "make" or "make all" shall build modules as well
+
+# U-Boot does not need modules
+#ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
+#  KBUILD_MODULES := 1
+#endif
+
+#ifeq ($(MAKECMDGOALS),)
+#  KBUILD_MODULES := 1
+#endif
+
+export KBUILD_MODULES KBUILD_BUILTIN
+export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
+export BL33_DEBUG
+
+# We need some generic definitions (do not try to remake the file).
+scripts/Kbuild.include: ;
+include scripts/Kbuild.include
+
+# Make variables (CC, etc...)
+
+AS		= $(CROSS_COMPILE)as
+# Always use GNU ld
+ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),)
+LD		= $(CROSS_COMPILE)ld.bfd
+else
+LD		= $(CROSS_COMPILE)ld
+endif
+CC		= $(CROSS_COMPILE)gcc
+CPP		= $(CC) -E
+AR		= $(CROSS_COMPILE)ar
+NM		= $(CROSS_COMPILE)nm
+LDR		= $(CROSS_COMPILE)ldr
+STRIP		= $(CROSS_COMPILE)strip
+OBJCOPY		= $(CROSS_COMPILE)objcopy
+OBJDUMP		= $(CROSS_COMPILE)objdump
+LEX		= flex
+YACC		= bison
+AWK		= awk
+PERL		= perl
+PYTHON		?= python
+PYTHON2		= python2
+PYTHON3		= python3
+DTC		?= $(objtree)/scripts/dtc/dtc
+CHECK		= sparse
+
+CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
+		  -Wbitwise -Wno-return-void -D__CHECK_ENDIAN__ $(CF)
+
+KBUILD_CPPFLAGS := -D__KERNEL__ -D__UBOOT__
+
+KBUILD_CFLAGS   := -Wall -Wstrict-prototypes \
+		   -Wno-format-security \
+		   -fno-builtin -ffreestanding $(CSTD_FLAG) \
+		   -Werror
+KBUILD_CFLAGS	+= -fshort-wchar -fno-strict-aliasing
+KBUILD_AFLAGS   := -D__ASSEMBLY__
+ifeq ($(BL33_DEBUG), 1)
+	KBUILD_CFLAGS+=-DBL33_DEBUG_PRINT
+endif
+
+# Don't generate position independent code
+KBUILD_CFLAGS	+= $(call cc-option,-fno-PIE)
+KBUILD_AFLAGS	+= $(call cc-option,-fno-PIE)
+
+# Read UBOOTRELEASE from include/config/uboot.release (if it exists)
+UBOOTRELEASE = $(shell cat include/config/uboot.release 2> /dev/null)
+UBOOTVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
+
+export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION
+export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
+export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC
+export CPP AR NM LDR STRIP OBJCOPY OBJDUMP
+export MAKE LEX YACC AWK PERL PYTHON PYTHON2 PYTHON3
+export HOSTCXX HOSTCXXFLAGS CHECK CHECKFLAGS DTC DTC_FLAGS
+
+export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS
+export KBUILD_CFLAGS KBUILD_AFLAGS
+
+# When compiling out-of-tree modules, put MODVERDIR in the module
+# tree rather than in the kernel tree. The kernel tree might
+# even be read-only.
+export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
+
+# Files to ignore in find ... statements
+
+export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o    \
+			  -name CVS -o -name .pc -o -name .hg -o -name .git \) \
+			  -prune -o
+export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
+			 --exclude CVS --exclude .pc --exclude .hg --exclude .git
+
+# ===========================================================================
+# Rules shared between *config targets and build targets
+
+# Basic helpers built in scripts/
+PHONY += scripts_basic
+scripts_basic:
+	$(Q)$(MAKE) $(build)=scripts/basic
+	$(Q)rm -f .tmp_quiet_recordmcount
+
+# To avoid any implicit rule to kick in, define an empty command.
+scripts/basic/%: scripts_basic ;
+
+PHONY += outputmakefile
+# outputmakefile generates a Makefile in the output directory, if using a
+# separate output directory. This allows convenient use of make in the
+# output directory.
+outputmakefile:
+ifneq ($(KBUILD_SRC),)
+	$(Q)ln -fsn $(srctree) source
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
+	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
+endif
+
+# To make sure we do not include .config for any of the *config targets
+# catch them early, and hand them over to scripts/kconfig/Makefile
+# It is allowed to specify more targets when calling make, including
+# mixing *config targets and build targets.
+# For example 'make oldconfig all'.
+# Detect when mixed targets is specified, and make a second invocation
+# of make so .config is not included in this case either (for *config).
+
+version_h := include/generated/version_autogenerated.h
+timestamp_h := include/generated/timestamp_autogenerated.h
+defaultenv_h := include/generated/defaultenv_autogenerated.h
+timestamp_git_h := include/generated/timestamp_autogenerated.h
+
+no-dot-config-targets := clean clobber mrproper distclean \
+			 help %docs check% coccicheck \
+			 ubootversion backup tests check qcheck
+
+config-targets := 0
+mixed-targets  := 0
+dot-config     := 1
+
+ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
+	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
+		dot-config := 0
+	endif
+endif
+
+ifeq ($(KBUILD_EXTMOD),)
+        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
+                config-targets := 1
+                ifneq ($(words $(MAKECMDGOALS)),1)
+                        mixed-targets := 1
+                endif
+        endif
+endif
+
+ifneq ($(ENABLE_UBOOT_UPDATE),1)
+	KBUILD_CFLAGS += -DAML_DISABLE_UPDATE_MODE
+endif
+
+ifeq ($(ENABLE_COMMANDLINE),1)
+	# This doesn't actually affect the generated .config, but for this
+	# particular config the only switches are in the code so a standard
+	# preprocessor definition works.
+	KBUILD_CFLAGS += -DCONFIG_CLI_ENABLED
+endif
+
+ifeq ($(mixed-targets),1)
+# ===========================================================================
+# We're called with mixed targets (*config and build targets).
+# Handle them one by one.
+
+PHONY += $(MAKECMDGOALS) __build_one_by_one
+
+$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one
+	@:
+
+__build_one_by_one:
+	$(Q)set -e; \
+	for i in $(MAKECMDGOALS); do \
+		$(MAKE) -f $(srctree)/Makefile $$i; \
+	done
+
+else
+ifeq ($(config-targets),1)
+# ===========================================================================
+# *config targets only - make sure prerequisites are updated, and descend
+# in scripts/kconfig to make the *config target
+
+KBUILD_DEFCONFIG := sandbox_defconfig
+export KBUILD_DEFCONFIG KBUILD_KCONFIG
+
+config: scripts_basic outputmakefile FORCE
+	$(Q)$(MAKE) $(build)=scripts/kconfig $@
+
+%config: scripts_basic outputmakefile FORCE
+	$(Q)$(MAKE) $(build)=scripts/kconfig $@
+
+else
+# ===========================================================================
+# Build targets only - this includes vmlinux, arch specific targets, clean
+# targets and others. In general all targets except *config targets.
+
+# Additional helpers built in scripts/
+# Carefully list dependencies so we do not try to build scripts twice
+# in parallel
+PHONY += scripts
+scripts: scripts_basic include/config/auto.conf
+	$(Q)$(MAKE) $(build)=$(@)
+
+ifeq ($(dot-config),1)
+# Read in config
+-include include/config/auto.conf
+
+# Read in dependencies to all Kconfig* files, make sure to run
+# oldconfig if changes are detected.
+-include include/config/auto.conf.cmd
+
+# To avoid any implicit rule to kick in, define an empty command
+$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
+
+# If .config is newer than include/config/auto.conf, someone tinkered
+# with it and forgot to run make oldconfig.
+# if auto.conf.cmd is missing then we are probably in a cleaned tree so
+# we execute the config step to be sure to catch updated Kconfig files
+include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+	$(Q)$(MAKE) -f $(srctree)/Makefile syncconfig
+	@# If the following part fails, include/config/auto.conf should be
+	@# deleted so "make silentoldconfig" will be re-run on the next build.
+	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf || \
+		{ rm -f include/config/auto.conf; false; }
+	@# include/config.h has been updated after "make silentoldconfig".
+	@# We need to touch include/config/auto.conf so it gets newer
+	@# than include/config.h.
+	@# Otherwise, 'make silentoldconfig' would be invoked twice.
+	$(Q)touch include/config/auto.conf
+
+u-boot.cfg spl/u-boot.cfg tpl/u-boot.cfg: include/config.h FORCE
+	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf $(@)
+
+-include include/autoconf.mk
+-include include/autoconf.mk.dep
+
+# We want to include arch/$(ARCH)/config.mk only when include/config/auto.conf
+# is up-to-date. When we switch to a different board configuration, old CONFIG
+# macros are still remaining in include/config/auto.conf. Without the following
+# gimmick, wrong config.mk would be included leading nasty warnings/errors.
+ifneq ($(wildcard $(KCONFIG_CONFIG)),)
+ifneq ($(wildcard include/config/auto.conf),)
+autoconf_is_old := $(shell find . -path ./$(KCONFIG_CONFIG) -newer \
+						include/config/auto.conf)
+ifeq ($(autoconf_is_old),)
+include config.mk
+include arch/$(ARCH)/Makefile
+endif
+endif
+endif
+
+# These are set by the arch-specific config.mk. Make sure they are exported
+# so they can be used when building an EFI application.
+export EFI_LDS		# Filename of EFI link script in arch/$(ARCH)/lib
+export EFI_CRT0		# Filename of EFI CRT0 in arch/$(ARCH)/lib
+export EFI_RELOC	# Filename of EFU relocation code in arch/$(ARCH)/lib
+export CFLAGS_EFI	# Compiler flags to add when building EFI app
+export CFLAGS_NON_EFI	# Compiler flags to remove when building EFI app
+export EFI_TARGET	# binutils target if EFI is natively supported
+
+# If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use
+# that (or fail if absent).  Otherwise, search for a linker script in a
+# standard location.
+
+ifndef LDSCRIPT
+	#LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds.debug
+	ifdef CONFIG_SYS_LDSCRIPT
+		# need to strip off double quotes
+		LDSCRIPT := $(srctree)/$(CONFIG_SYS_LDSCRIPT:"%"=%)
+	endif
+endif
+
+# If there is no specified link script, we look in a number of places for it
+ifndef LDSCRIPT
+	ifeq ($(wildcard $(LDSCRIPT)),)
+		LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds
+	endif
+	ifeq ($(wildcard $(LDSCRIPT)),)
+		LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds
+	endif
+	ifeq ($(wildcard $(LDSCRIPT)),)
+		LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot.lds
+	endif
+endif
+
+else
+# Dummy target needed, because used as prerequisite
+include/config/auto.conf: ;
+endif # $(dot-config)
+
+#
+# Xtensa linker script cannot be preprocessed with -ansi because of
+# preprocessor operations on strings that don't make C identifiers.
+#
+ifeq ($(CONFIG_XTENSA),)
+LDPPFLAGS	+= -ansi
+endif
+
+ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+KBUILD_CFLAGS	+= -Os
+else
+KBUILD_CFLAGS	+= -O2
+endif
+
+ifeq ("$(BUILD_CONFIG)","dev")
+  KBUILD_CFLAGS += -DDEV_BUILD_CONFIG
+else ifeq ("$(BUILD_CONFIG)","dogfood")
+  KBUILD_CFLAGS += -DDOGFOOD_BUILD_CONFIG
+else ifeq ("$(BUILD_CONFIG)","prod")
+  KBUILD_CFLAGS += -DPROD_BUILD_CONFIG
+else
+  KBUILD_CFLAGS += -DDEV_BUILD_CONFIG
+endif
+
+KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
+KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks)
+
+# change __FILE__ to the relative path from the srctree
+KBUILD_CFLAGS	+= $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
+
+KBUILD_CFLAGS	+= -g
+# $(KBUILD_AFLAGS) sets -g, which causes gcc to pass a suitable -g<format>
+# option to the assembler.
+KBUILD_AFLAGS	+= -g
+
+# Report stack usage if supported
+# ARC tools based on GCC 7.1 has an issue with stack usage
+# with naked functions, see commit message for more details
+ifndef CONFIG_ARC
+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-stack-usage.sh $(CC)),y)
+	KBUILD_CFLAGS += -fstack-usage
+endif
+endif
+
+KBUILD_CFLAGS += $(call cc-option,-Wno-format-nonliteral)
+ifeq ($(cc-name),clang)
+KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
+KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier)
+KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
+KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
+KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior)
+endif
+
+# turn jbsr into jsr for m68k
+ifeq ($(ARCH),m68k)
+ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4)
+KBUILD_AFLAGS += -Wa,-gstabs,-S
+endif
+endif
+
+# Prohibit date/time macros, which would make the build non-deterministic
+KBUILD_CFLAGS   += $(call cc-option,-Werror=date-time)
+
+include scripts/Makefile.extrawarn
+
+# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
+KBUILD_CPPFLAGS += $(KCPPFLAGS)
+KBUILD_AFLAGS += $(KAFLAGS)
+KBUILD_CFLAGS += $(KCFLAGS)
+
+ifdef BOARD_NAME
+KBUILD_CFLAGS += -DBOARD_NAME='"$(BOARD_NAME)"'
+endif
+
+# Use UBOOTINCLUDE when you must reference the include/ directory.
+# Needed to be compatible with the O= option
+#
+# Many headers in the firmware sdk include other firmware sdk headers
+# using #include <...>. Some of them live directly under sysroot/include.
+# For this reason, we make an exception and add it to the global include
+# path.
+UBOOTINCLUDE    := \
+		-Iinclude \
+		$(if $(KBUILD_SRC), -I$(srctree)/include) \
+		$(if $(CONFIG_$(SPL_)SYS_THUMB_BUILD), \
+			$(if $(CONFIG_HAS_THUMB2),, \
+				-I$(srctree)/arch/$(ARCH)/thumb1/include),) \
+		$(if $(CONFIG_ZIRCON_BOOT_IMAGE), \
+			-I$(srctree)/lib/fuchsia/firmware_sdk/arch/arm64/sysroot/include) \
+		-I$(srctree)/arch/$(ARCH)/include \
+		-include $(srctree)/include/linux/kconfig.h
+
+NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+CHECKFLAGS     += $(NOSTDINC_FLAGS)
+
+# FIX ME
+cpp_flags := $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS) $(UBOOTINCLUDE) \
+							$(NOSTDINC_FLAGS)
+c_flags := $(KBUILD_CFLAGS) $(cpp_flags)
+
+#########################################################################
+# U-Boot objects....order is important (i.e. start must be first)
+
+HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
+
+libs-y += lib/
+libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
+libs-$(CONFIG_OF_EMBED) += dts/
+libs-y += fs/
+libs-y += net/
+libs-y += disk/
+libs-y += drivers/
+libs-y += drivers/dma/
+libs-y += drivers/gpio/
+libs-y += drivers/i2c/
+libs-y += drivers/mtd/
+libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/raw/
+libs-y += drivers/mtd/onenand/
+libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/
+libs-y += drivers/mtd/spi/
+libs-y += drivers/net/
+libs-y += drivers/net/phy/
+libs-y += drivers/power/ \
+	drivers/power/domain/ \
+	drivers/power/fuel_gauge/ \
+	drivers/power/mfd/ \
+	drivers/power/pmic/ \
+	drivers/power/battery/ \
+	drivers/power/regulator/
+libs-y += drivers/spi/
+libs-$(CONFIG_FMAN_ENET) += drivers/net/fm/
+libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
+libs-$(CONFIG_SYS_FSL_MMDC) += drivers/ddr/fsl/
+libs-$(CONFIG_ALTERA_SDRAM) += drivers/ddr/altera/
+libs-y += drivers/serial/
+libs-y += drivers/usb/dwc3/
+libs-y += drivers/usb/common/
+libs-y += drivers/usb/emul/
+libs-y += drivers/usb/eth/
+libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/
+libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/udc/
+libs-y += drivers/usb/host/
+libs-y += drivers/usb/musb/
+libs-y += drivers/usb/musb-new/
+libs-y += drivers/usb/phy/
+libs-y += drivers/usb/ulpi/
+libs-y += cmd/
+libs-y += common/
+libs-y += env/
+libs-$(CONFIG_API) += api/
+libs-$(CONFIG_HAS_POST) += post/
+libs-$(CONFIG_UNIT_TEST) += test/ test/dm/
+libs-$(CONFIG_UT_ENV) += test/env/
+libs-$(CONFIG_UT_OVERLAY) += test/overlay/
+
+libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
+
+libs-y := $(sort $(libs-y))
+
+u-boot-dirs	:= $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples
+
+u-boot-alldirs	:= $(sort $(u-boot-dirs) $(patsubst %/,%,$(filter %/, $(libs-))))
+
+libs-y		:= $(patsubst %/, %/built-in.o, $(libs-y))
+
+u-boot-init := $(head-y)
+u-boot-main := $(libs-y)
+
+
+# Add GCC lib
+ifeq ($(CONFIG_USE_PRIVATE_LIBGCC),y)
+PLATFORM_LIBGCC = arch/$(ARCH)/lib/lib.a
+else
+PLATFORM_LIBGCC := -L $(shell dirname `$(CC) $(c_flags) -print-libgcc-file-name`) -lgcc
+endif
+PLATFORM_LIBS += $(PLATFORM_LIBGCC)
+
+ifdef CONFIG_CC_COVERAGE
+KBUILD_CFLAGS += --coverage
+PLATFORM_LIBGCC += -lgcov
+endif
+
+export PLATFORM_LIBS
+export PLATFORM_LIBGCC
+
+# Special flags for CPP when processing the linker script.
+# Pass the version down so we can handle backwards compatibility
+# on the fly.
+LDPPFLAGS += \
+	-include $(srctree)/include/u-boot/u-boot.lds.h \
+	-DCPUDIR=$(CPUDIR) \
+	$(shell $(LD) --version | \
+	  sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')
+
+#########################################################################
+#########################################################################
+
+ifneq ($(CONFIG_BOARD_SIZE_LIMIT),)
+BOARD_SIZE_CHECK = \
+	@actual=`wc -c $@ | awk '{print $$1}'`; \
+	limit=`printf "%d" $(CONFIG_BOARD_SIZE_LIMIT)`; \
+	if test $$actual -gt $$limit; then \
+		echo "$@ exceeds file size limit:" >&2 ; \
+		echo "  limit:  $$limit bytes" >&2 ; \
+		echo "  actual: $$actual bytes" >&2 ; \
+		echo "  excess: $$((actual - limit)) bytes" >&2; \
+		exit 1; \
+	fi
+else
+BOARD_SIZE_CHECK =
+endif
+
+# Statically apply RELA-style relocations (currently arm64 only)
+# This is useful for arm64 where static relocation needs to be performed on
+# the raw binary, but certain simulators only accept an ELF file (but don't
+# do the relocation).
+ifneq ($(CONFIG_STATIC_RELA),)
+# $(1) is u-boot ELF, $(2) is u-boot bin, $(3) is text base
+DO_STATIC_RELA = \
+	start=$$($(NM) $(1) | grep __rel_dyn_start | cut -f 1 -d ' '); \
+	end=$$($(NM) $(1) | grep __rel_dyn_end | cut -f 1 -d ' '); \
+	tools/relocate-rela $(2) $(3) $$start $$end
+else
+DO_STATIC_RELA =
+endif
+
+# Always append ALL so that arch config.mk's can add custom ones
+ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map binary_size_check
+ALL-y += bl301.bin
+
+ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
+ifeq ($(CONFIG_SPL_FSL_PBL),y)
+ALL-$(CONFIG_RAMBOOT_PBL) += u-boot-with-spl-pbl.bin
+else
+ifneq ($(CONFIG_SECURE_BOOT), y)
+# For Secure Boot The Image needs to be signed and Header must also
+# be included. So The image has to be built explicitly
+ALL-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl
+endif
+endif
+ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
+ifeq ($(CONFIG_MX6)$(CONFIG_SECURE_BOOT), yy)
+ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot-ivt.img
+else
+ifeq ($(CONFIG_MX7)$(CONFIG_SECURE_BOOT), yy)
+ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot-ivt.img
+else
+ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
+endif
+endif
+ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
+ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb
+ifeq ($(CONFIG_SPL_FRAMEWORK),y)
+ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb.img
+endif
+ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
+ifneq ($(CONFIG_SPL_TARGET),)
+ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
+endif
+ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
+ALL-$(CONFIG_EFI_APP) += u-boot-app.efi
+ALL-$(CONFIG_EFI_STUB) += u-boot-payload.efi
+
+ifneq ($(BUILD_ROM)$(CONFIG_BUILD_ROM),)
+ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+endif
+
+# Build a combined spl + u-boot image for sunxi
+ifeq ($(CONFIG_ARCH_SUNXI)$(CONFIG_SPL),yy)
+ALL-y += u-boot-sunxi-with-spl.bin
+endif
+
+# enable combined SPL/u-boot/dtb rules for tegra
+ifeq ($(CONFIG_TEGRA)$(CONFIG_SPL),yy)
+ALL-y += u-boot-tegra.bin u-boot-nodtb-tegra.bin
+ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb-tegra.bin
+endif
+
+ALL-$(CONFIG_ARCH_MEDIATEK) += u-boot-mtk.bin
+
+# Add optional build target if defined in board/cpu/soc headers
+ifneq ($(CONFIG_BUILD_TARGET),)
+ALL-y += $(CONFIG_BUILD_TARGET:"%"=%)
+endif
+
+ifneq ($(CONFIG_SYS_INIT_SP_BSS_OFFSET),)
+ALL-y += init_sp_bss_offset_check
+endif
+
+ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy)
+ALL-y += u-boot-with-dtb.bin
+endif
+
+LDFLAGS_u-boot += $(LDFLAGS_FINAL)
+
+# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.
+LDFLAGS_u-boot += $(call ld-option, --no-dynamic-linker)
+
+ifeq ($(CONFIG_ARC)$(CONFIG_NIOS2)$(CONFIG_X86)$(CONFIG_XTENSA),)
+LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
+endif
+
+# Normally we fill empty space with 0xff
+quiet_cmd_objcopy = OBJCOPY $@
+cmd_objcopy = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS) \
+	$(OBJCOPYFLAGS_$(@F)) $< $@
+
+# Provide a version which does not do this, for use by EFI
+quiet_cmd_zobjcopy = OBJCOPY $@
+cmd_zobjcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
+
+quiet_cmd_efipayload = OBJCOPY $@
+cmd_efipayload = $(OBJCOPY) -I binary -O $(EFIPAYLOAD_BFDTARGET) -B $(EFIPAYLOAD_BFDARCH) $< $@
+
+MKIMAGEOUTPUT ?= /dev/null
+
+quiet_cmd_mkimage = MKIMAGE $@
+cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \
+	>$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT))
+
+quiet_cmd_mkfitimage = MKIMAGE $@
+cmd_mkfitimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -f $(U_BOOT_ITS) -E $@ -p $(CONFIG_FIT_EXTERNAL_OFFSET)\
+	>$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT))
+
+quiet_cmd_cat = CAT     $@
+cmd_cat = cat $(filter-out $(PHONY), $^) > $@
+
+append = cat $(filter-out $< $(PHONY), $^) >> $@
+
+quiet_cmd_pad_cat = CAT     $@
+cmd_pad_cat = $(cmd_objcopy) && $(append) || rm -f $@
+
+cfg: u-boot.cfg
+
+quiet_cmd_cfgcheck = CFGCHK  $2
+cmd_cfgcheck = $(srctree)/scripts/check-config.sh $2 \
+		$(srctree)/scripts/config_whitelist.txt $(srctree)
+
+all:		$(ALL-y) cfg
+ifeq ($(CONFIG_DM_I2C_COMPAT)$(CONFIG_SANDBOX),y)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
+	@echo >&2 "(possibly in a subsequent patch in your series)"
+	@echo >&2 "before sending patches to the mailing list."
+	@echo >&2 "===================================================="
+endif
+ifeq ($(CONFIG_MMC),y)
+ifneq ($(CONFIG_DM_MMC)$(CONFIG_OF_CONTROL)$(CONFIG_BLK),yyy)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does not use CONFIG_DM_MMC. Please update"
+	@echo >&2 "the board to use CONFIG_DM_MMC before the v2019.04 release."
+	@echo >&2 "Failure to update by the deadline may result in board removal."
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+endif
+ifeq ($(CONFIG_USB),y)
+ifneq ($(CONFIG_DM_USB)$(CONFIG_OF_CONTROL)$(CONFIG_BLK),yyy)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does not use CONFIG_DM_USB. Please update"
+	@echo >&2 "the board to use CONFIG_DM_USB before the v2019.07 release."
+	@echo >&2 "Failure to update by the deadline may result in board removal."
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+endif
+ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y)
+ifneq ($(CONFIG_DM_SCSI),y)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does not use CONFIG_DM_SCSI. Please update"
+	@echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release."
+	@echo >&2 "Failure to update by the deadline may result in board removal."
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+endif
+ifeq ($(CONFIG_PCI),y)
+ifneq ($(CONFIG_DM_PCI),y)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does not use CONFIG_DM_PCI Please update"
+	@echo >&2 "the board to use CONFIG_DM_PCI before the v2019.07 release."
+	@echo >&2 "Failure to update by the deadline may result in board removal."
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+endif
+ifneq ($(CONFIG_LCD)$(CONFIG_VIDEO),)
+ifneq ($(CONFIG_DM_VIDEO),y)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does not use CONFIG_DM_VIDEO Please update"
+	@echo >&2 "the board to use CONFIG_DM_VIDEO before the v2019.07 release."
+	@echo >&2 "Failure to update by the deadline may result in board removal."
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+endif
+ifeq ($(CONFIG_OF_EMBED),y)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "CONFIG_OF_EMBED is enabled. This option should only"
+	@echo >&2 "be used for debugging purposes. Please use"
+	@echo >&2 "CONFIG_OF_SEPARATE for boards in mainline."
+	@echo >&2 "See doc/README.fdt-control for more info."
+	@echo >&2 "===================================================="
+endif
+ifeq ($(CONFIG_SPI),y)
+ifneq ($(CONFIG_DM_SPI)$(CONFIG_OF_CONTROL),yy)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does not use CONFIG_DM_SPI. Please update"
+	@echo >&2 "the board before v2019.04 for no dm conversion"
+	@echo >&2 "and v2019.07 for partially dm converted drivers."
+	@echo >&2 "Failure to update can lead to driver/board removal"
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+endif
+ifeq ($(CONFIG_SPI_FLASH),y)
+ifneq ($(CONFIG_DM_SPI_FLASH)$(CONFIG_OF_CONTROL),yy)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does not use CONFIG_DM_SPI_FLASH. Please update"
+	@echo >&2 "the board to use CONFIG_SPI_FLASH before the v2019.07 release."
+	@echo >&2 "Failure to update by the deadline may result in board removal."
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+endif
+	@# Check that this build does not use CONFIG options that we do not
+	@# know about unless they are in Kconfig. All the existing CONFIG
+	@# options are whitelisted, so new ones should not be added.
+	$(call cmd,cfgcheck,u-boot.cfg)
+
+PHONY += dtbs
+dtbs: dts/dt.dtb
+	@:
+dts/dt.dtb: u-boot
+	$(Q)$(MAKE) $(build)=dts dtbs
+
+quiet_cmd_copy = COPY    $@
+      cmd_copy = cp $< $@
+
+ifeq ($(CONFIG_MULTI_DTB_FIT),y)
+
+fit-dtb.blob: dts/dt.dtb FORCE
+	$(call if_changed,mkimage)
+
+MKIMAGEFLAGS_fit-dtb.blob = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
+	-a 0 -e 0 -E \
+	$(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) -d /dev/null
+
+u-boot-fit-dtb.bin: u-boot-nodtb.bin fit-dtb.blob
+	$(call if_changed,cat)
+
+u-boot.bin: u-boot-fit-dtb.bin FORCE
+	$(call if_changed,copy)
+else ifeq ($(CONFIG_OF_SEPARATE),y)
+u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE
+	$(call if_changed,cat)
+
+u-boot.bin: u-boot-dtb.bin FORCE
+	$(call if_changed,copy)
+else
+u-boot.bin: u-boot-nodtb.bin FORCE
+	$(call if_changed,copy)
+endif
+
+.PHONY : bl301.bin
+bl301.bin: tools prepare acs.bin bl21.bin
+	$(Q)$(MAKE) -C $(srctree)/arch/arm/mach-meson/${SOC}/firmware/scp_task
+
+.PHONY : acs.bin
+acs.bin: tools prepare u-boot.bin
+	$(Q)$(MAKE) -C $(srctree)/arch/arm/mach-meson/${SOC}/firmware/acs all FIRMWARE=$@
+
+.PHONY : bl21.bin
+bl21.bin: tools prepare u-boot.bin acs.bin
+	$(Q)$(MAKE) -C $(srctree)/arch/arm/mach-meson/${SOC}/firmware/bl21 all FIRMWARE=$@
+
+%.imx: %.bin
+	$(Q)$(MAKE) $(build)=arch/arm/mach-imx $@
+
+%.vyb: %.imx
+	$(Q)$(MAKE) $(build)=arch/arm/cpu/armv7/vf610 $@
+
+quiet_cmd_copy = COPY    $@
+      cmd_copy = cp $< $@
+
+u-boot.dtb: dts/dt.dtb
+	$(call cmd,copy)
+
+OBJCOPYFLAGS_u-boot.hex := -O ihex
+
+OBJCOPYFLAGS_u-boot.srec := -O srec
+
+u-boot.hex u-boot.srec: u-boot FORCE
+	$(call if_changed,objcopy)
+
+OBJCOPYFLAGS_u-boot-elf.srec := $(OBJCOPYFLAGS_u-boot.srec)
+
+u-boot-elf.srec: u-boot.elf FORCE
+	$(call if_changed,objcopy)
+
+OBJCOPYFLAGS_u-boot-spl.srec = $(OBJCOPYFLAGS_u-boot.srec)
+
+spl/u-boot-spl.srec: spl/u-boot-spl FORCE
+	$(call if_changed,objcopy)
+
+OBJCOPYFLAGS_u-boot-nodtb.bin := -O binary \
+		$(if $(CONFIG_X86_16BIT_INIT),-R .start16 -R .resetvec) \
+		$(if $(CONFIG_MPC85XX_HAVE_RESET_VECTOR),-R .bootpg -R .resetvec)
+
+OBJCOPYFLAGS_u-boot-spl.hex = $(OBJCOPYFLAGS_u-boot.hex)
+
+spl/u-boot-spl.hex: spl/u-boot-spl FORCE
+	$(call if_changed,objcopy)
+
+binary_size_check: u-boot-nodtb.bin FORCE
+	@file_size=$(shell wc -c u-boot-nodtb.bin | awk '{print $$1}') ; \
+	map_size=$(shell cat u-boot.map | \
+		awk '/_image_copy_start/ {start = $$1} /_image_binary_end/ {end = $$1} END {if (start != "" && end != "") print "ibase=16; " toupper(end) " - " toupper(start)}' \
+		| sed 's/0X//g' \
+		| bc); \
+	if [ "" != "$$map_size" ]; then \
+		if test $$map_size -ne $$file_size; then \
+			echo "u-boot.map shows a binary size of $$map_size" >&2 ; \
+			echo "  but u-boot-nodtb.bin shows $$file_size" >&2 ; \
+			exit 1; \
+		fi \
+	fi
+
+ifneq ($(CONFIG_SYS_INIT_SP_BSS_OFFSET),)
+ifneq ($(CONFIG_SYS_MALLOC_F_LEN),)
+subtract_sys_malloc_f_len = space=$$(($${space} - $(CONFIG_SYS_MALLOC_F_LEN)))
+else
+subtract_sys_malloc_f_len = true
+endif
+# The 1/4 margin below is somewhat arbitrary. The likely initial SP usage is
+# so low that the DTB could probably use 90%+ of the available space, for
+# current values of CONFIG_SYS_INIT_SP_BSS_OFFSET at least. However, let's be
+# safe for now and tweak this later if space becomes tight.
+# A rejected alternative would be to check that some absolute minimum stack
+# space was available. However, since CONFIG_SYS_INIT_SP_BSS_OFFSET is
+# deliberately build-specific, to take account of build-to-build stack usage
+# differences due to different feature sets, there is no common absolute value
+# to check against.
+init_sp_bss_offset_check: u-boot.dtb FORCE
+	@dtb_size=$(shell wc -c u-boot.dtb | awk '{print $$1}') ; \
+	space=$(CONFIG_SYS_INIT_SP_BSS_OFFSET) ; \
+	$(subtract_sys_malloc_f_len) ; \
+	quarter_space=$$(($${space} / 4)) ; \
+	if [ $${dtb_size} -gt $${quarter_space} ]; then \
+		echo "u-boot.dtb is larger than 1 quarter of " >&2 ; \
+		echo "(CONFIG_SYS_INIT_SP_BSS_OFFSET - CONFIG_SYS_MALLOC_F_LEN)" >&2 ; \
+		exit 1 ; \
+	fi
+endif
+
+u-boot-nodtb.bin: u-boot FORCE
+	$(call if_changed,objcopy)
+	$(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
+	$(BOARD_SIZE_CHECK)
+
+u-boot.ldr:	u-boot
+		$(CREATE_LDR_ENV)
+		$(LDR) -T $(CONFIG_CPU) -c $@ $< $(LDR_FLAGS)
+		$(BOARD_SIZE_CHECK)
+
+# binman
+# ---------------------------------------------------------------------------
+# Use 'make BINMAN_DEBUG=1' to enable debugging
+quiet_cmd_binman = BINMAN  $@
+cmd_binman = $(srctree)/tools/binman/binman -u -d u-boot.dtb -O . -m \
+		-I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \
+		$(if $(BINMAN_DEBUG),-D) $(BINMAN_$(@F)) $<
+
+OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex
+
+OBJCOPYFLAGS_u-boot.ldr.srec := -I binary -O srec
+
+u-boot.ldr.hex u-boot.ldr.srec: u-boot.ldr FORCE
+	$(call if_changed,objcopy)
+
+#
+# U-Boot entry point, needed for booting of full-blown U-Boot
+# from the SPL U-Boot version.
+#
+ifndef CONFIG_SYS_UBOOT_START
+CONFIG_SYS_UBOOT_START := 0
+endif
+
+# Boards with more complex image requirments can provide an .its source file
+# or a generator script
+ifneq ($(CONFIG_SPL_FIT_SOURCE),"")
+U_BOOT_ITS = $(subst ",,$(CONFIG_SPL_FIT_SOURCE))
+else
+ifneq ($(CONFIG_SPL_FIT_GENERATOR),"")
+U_BOOT_ITS := u-boot.its
+ifeq ($(CONFIG_SPL_FIT_GENERATOR),"arch/arm/mach-imx/mkimage_fit_atf.sh")
+U_BOOT_ITS_DEPS += u-boot-nodtb.bin
+endif
+ifeq ($(CONFIG_SPL_FIT_GENERATOR),"arch/arm/mach-rockchip/make_fit_atf.py")
+U_BOOT_ITS_DEPS += u-boot
+endif
+$(U_BOOT_ITS): $(U_BOOT_ITS_DEPS) FORCE
+	$(srctree)/$(CONFIG_SPL_FIT_GENERATOR) \
+	$(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) > $@
+endif
+endif
+
+ifdef CONFIG_SPL_LOAD_FIT
+MKIMAGEFLAGS_u-boot.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
+	-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
+	-n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \
+	$(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST)))
+else
+MKIMAGEFLAGS_u-boot.img = -A $(ARCH) -T firmware -C none -O u-boot \
+	-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
+	-n "U-Boot $(UBOOTRELEASE) for $(BOARD) board"
+MKIMAGEFLAGS_u-boot-ivt.img = -A $(ARCH) -T firmware_ivt -C none -O u-boot \
+	-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
+	-n "U-Boot $(UBOOTRELEASE) for $(BOARD) board"
+u-boot-ivt.img: MKIMAGEOUTPUT = u-boot-ivt.img.log
+CLEAN_FILES += u-boot-ivt.img.log u-boot-dtb.imx.log SPL.log u-boot.imx.log
+endif
+
+MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img)
+
+MKIMAGEFLAGS_u-boot.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
+	-T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
+
+MKIMAGEFLAGS_u-boot-spl.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
+	-T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \
+	$(if $(KEYDIR),-k $(KEYDIR))
+
+MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
+		-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
+
+u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \
+		$(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE
+	$(call if_changed,mkimage)
+
+u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE
+	$(call if_changed,mkfitimage)
+	$(BOARD_SIZE_CHECK)
+
+u-boot-spl.kwb: u-boot.img spl/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
+u-boot.sha1:	u-boot.bin
+		tools/ubsha1 u-boot.bin
+
+u-boot.dis:	u-boot
+		$(OBJDUMP) -d $< > $@
+
+ifneq ($(CONFIG_SPL_PAYLOAD),)
+SPL_PAYLOAD := $(CONFIG_SPL_PAYLOAD:"%"=%)
+else
+SPL_PAYLOAD := u-boot.bin
+endif
+
+OBJCOPYFLAGS_u-boot-with-spl.bin = -I binary -O binary \
+				   --pad-to=$(CONFIG_SPL_PAD_TO)
+u-boot-with-spl.bin: spl/u-boot-spl.bin $(SPL_PAYLOAD) FORCE
+	$(call if_changed,pad_cat)
+
+ifeq ($(CONFIG_ARCH_LPC32XX)$(CONFIG_SPL),yy)
+MKIMAGEFLAGS_lpc32xx-spl.img = -T lpc32xximage -a $(CONFIG_SPL_TEXT_BASE)
+
+lpc32xx-spl.img: spl/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
+OBJCOPYFLAGS_lpc32xx-boot-0.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO)
+
+lpc32xx-boot-0.bin: lpc32xx-spl.img FORCE
+	$(call if_changed,objcopy)
+
+OBJCOPYFLAGS_lpc32xx-boot-1.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO)
+
+lpc32xx-boot-1.bin: lpc32xx-spl.img FORCE
+	$(call if_changed,objcopy)
+
+lpc32xx-full.bin: lpc32xx-boot-0.bin lpc32xx-boot-1.bin u-boot.img FORCE
+	$(call if_changed,cat)
+
+CLEAN_FILES += lpc32xx-*
+endif
+
+OBJCOPYFLAGS_u-boot-with-tpl.bin = -I binary -O binary \
+				   --pad-to=$(CONFIG_TPL_PAD_TO)
+tpl/u-boot-with-tpl.bin: tpl/u-boot-tpl.bin u-boot.bin FORCE
+	$(call if_changed,pad_cat)
+
+SPL: spl/u-boot-spl.bin FORCE
+	$(Q)$(MAKE) $(build)=arch/arm/mach-imx $@
+
+ifeq ($(CONFIG_ARCH_IMX8M), y)
+flash.bin: spl/u-boot-spl.bin u-boot.itb FORCE
+	$(Q)$(MAKE) $(build)=arch/arm/mach-imx $@
+endif
+
+u-boot-with-spl.imx u-boot-with-nand-spl.imx: SPL u-boot.bin FORCE
+	$(Q)$(MAKE) $(build)=arch/arm/mach-imx $@
+
+MKIMAGEFLAGS_u-boot.ubl = -n $(UBL_CONFIG) -T ublimage -e $(CONFIG_SYS_TEXT_BASE)
+
+u-boot.ubl: u-boot-with-spl.bin FORCE
+	$(call if_changed,mkimage)
+
+MKIMAGEFLAGS_u-boot-spl.ais = -s -n $(if $(CONFIG_AIS_CONFIG_FILE), \
+	$(srctree)/$(CONFIG_AIS_CONFIG_FILE:"%"=%),"/dev/null") \
+	-T aisimage -e $(CONFIG_SPL_TEXT_BASE)
+spl/u-boot-spl.ais: spl/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
+OBJCOPYFLAGS_u-boot.ais = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO)
+u-boot.ais: spl/u-boot-spl.ais u-boot.img FORCE
+	$(call if_changed,pad_cat)
+
+u-boot-signed.sb: u-boot.bin spl/u-boot-spl.bin
+	$(Q)$(MAKE) $(build)=arch/arm/cpu/arm926ejs/mxs u-boot-signed.sb
+u-boot.sb: u-boot.bin spl/u-boot-spl.bin
+	$(Q)$(MAKE) $(build)=arch/arm/cpu/arm926ejs/mxs u-boot.sb
+
+# On x600 (SPEAr600) U-Boot is appended to U-Boot SPL.
+# Both images are created using mkimage (crc etc), so that the ROM
+# bootloader can check its integrity. Padding needs to be done to the
+# SPL image (with mkimage header) and not the binary. Otherwise the resulting image
+# which is loaded/copied by the ROM bootloader to SRAM doesn't fit.
+# The resulting image containing both U-Boot images is called u-boot.spr
+MKIMAGEFLAGS_u-boot-spl.img = -A $(ARCH) -T firmware -C none \
+	-a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE) -n XLOADER
+spl/u-boot-spl.img: spl/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
+OBJCOPYFLAGS_u-boot.spr = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) \
+			  --gap-fill=0xff
+u-boot.spr: spl/u-boot-spl.img u-boot.img FORCE
+	$(call if_changed,pad_cat)
+
+ifneq ($(CONFIG_ARCH_SOCFPGA),)
+quiet_cmd_socboot = SOCBOOT $@
+cmd_socboot = cat	spl/u-boot-spl.sfp spl/u-boot-spl.sfp	\
+			spl/u-boot-spl.sfp spl/u-boot-spl.sfp	\
+			u-boot.img > $@ || rm -f $@
+u-boot-with-spl.sfp: spl/u-boot-spl.sfp u-boot.img FORCE
+	$(call if_changed,socboot)
+endif
+
+ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy)
+u-boot-with-dtb.bin: u-boot.bin u-boot.dtb \
+	$(if $(CONFIG_MPC85XX_HAVE_RESET_VECTOR), u-boot-br.bin) FORCE
+	$(call if_changed,binman)
+
+ifeq ($(CONFIG_MPC85XX_HAVE_RESET_VECTOR),y)
+OBJCOPYFLAGS_u-boot-br.bin := -O binary -j .bootpg -j .resetvec
+u-boot-br.bin: u-boot FORCE
+	$(call if_changed,objcopy)
+endif
+endif
+
+# x86 uses a large ROM. We fill it with 0xff, put the 16-bit stuff (including
+# reset vector) at the top, Intel ME descriptor at the bottom, and U-Boot in
+# the middle. This is handled by binman based on an image description in the
+# board's device tree.
+ifneq ($(CONFIG_X86_RESET_VECTOR),)
+rom: u-boot.rom FORCE
+
+refcode.bin: $(srctree)/board/$(BOARDDIR)/refcode.bin FORCE
+	$(call if_changed,copy)
+
+quiet_cmd_ldr = LD      $@
+cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
+	       $(filter-out FORCE,$^) -o $@
+
+u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \
+		$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
+		$(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE
+	$(call if_changed,binman)
+
+OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec
+u-boot-x86-16bit.bin: u-boot FORCE
+	$(call if_changed,objcopy)
+endif
+
+ifneq ($(CONFIG_ARCH_SUNXI),)
+ifeq ($(CONFIG_ARM64),)
+u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img u-boot.dtb FORCE
+	$(call if_changed,binman)
+else
+u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.itb FORCE
+	$(call if_changed,cat)
+endif
+endif
+
+ifneq ($(CONFIG_TEGRA),)
+ifneq ($(CONFIG_BINMAN),)
+# Makes u-boot-dtb-tegra.bin u-boot-tegra.bin u-boot-nodtb-tegra.bin
+%-dtb-tegra.bin %-tegra.bin %-nodtb-tegra.bin: \
+		spl/%-spl %.bin FORCE
+	$(call if_changed,binman)
+else
+OBJCOPYFLAGS_u-boot-nodtb-tegra.bin = -O binary --pad-to=$(CONFIG_SYS_TEXT_BASE)
+u-boot-nodtb-tegra.bin: spl/u-boot-spl u-boot-nodtb.bin FORCE
+	$(call if_changed,pad_cat)
+
+OBJCOPYFLAGS_u-boot-tegra.bin = -O binary --pad-to=$(CONFIG_SYS_TEXT_BASE)
+u-boot-tegra.bin: spl/u-boot-spl u-boot.bin FORCE
+	$(call if_changed,pad_cat)
+
+u-boot-dtb-tegra.bin: u-boot-tegra.bin FORCE
+	$(call if_changed,copy)
+endif  # binman
+endif
+
+OBJCOPYFLAGS_u-boot-app.efi := $(OBJCOPYFLAGS_EFI)
+u-boot-app.efi: u-boot FORCE
+	$(call if_changed,zobjcopy)
+
+u-boot.bin.o: u-boot.bin FORCE
+	$(call if_changed,efipayload)
+
+u-boot-payload.lds: $(LDSCRIPT_EFI) FORCE
+	$(call if_changed_dep,cpp_lds)
+
+# Rule to link the EFI payload which contains a stub and a U-Boot binary
+quiet_cmd_u-boot_payload ?= LD      $@
+      cmd_u-boot_payload ?= $(LD) $(LDFLAGS_EFI_PAYLOAD) -o $@ \
+      -T u-boot-payload.lds arch/x86/cpu/call32.o \
+      lib/efi/efi.o lib/efi/efi_stub.o u-boot.bin.o \
+      $(addprefix arch/$(ARCH)/lib/,$(EFISTUB))
+
+u-boot-payload: u-boot.bin.o u-boot-payload.lds FORCE
+	$(call if_changed,u-boot_payload)
+
+OBJCOPYFLAGS_u-boot-payload.efi := $(OBJCOPYFLAGS_EFI)
+u-boot-payload.efi: u-boot-payload FORCE
+	$(call if_changed,zobjcopy)
+
+u-boot-img.bin: spl/u-boot-spl.bin u-boot.img FORCE
+	$(call if_changed,cat)
+
+#Add a target to create boot binary having SPL binary in PBI format
+#concatenated with u-boot binary. It is need by PowerPC SoC having
+#internal SRAM <= 512KB.
+MKIMAGEFLAGS_u-boot-spl.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
+		-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage \
+		-A $(ARCH) -a $(CONFIG_SPL_TEXT_BASE)
+
+spl/u-boot-spl.pbl: spl/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
+ifeq ($(ARCH),arm)
+UBOOT_BINLOAD := u-boot.img
+else
+ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy)
+UBOOT_BINLOAD := u-boot-with-dtb.bin
+else
+UBOOT_BINLOAD := u-boot.bin
+endif
+endif
+
+OBJCOPYFLAGS_u-boot-with-spl-pbl.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) \
+			  --gap-fill=0xff
+
+u-boot-with-spl-pbl.bin: spl/u-boot-spl.pbl $(UBOOT_BINLOAD) FORCE
+	$(call if_changed,pad_cat)
+
+# PPC4xx needs the SPL at the end of the image, since the reset vector
+# is located at 0xfffffffc. So we can't use the "u-boot-img.bin" target
+# and need to introduce a new build target with the full blown U-Boot
+# at the start padded up to the start of the SPL image. And then concat
+# the SPL image to the end.
+
+OBJCOPYFLAGS_u-boot-img-spl-at-end.bin := -I binary -O binary \
+	--pad-to=$(CONFIG_UBOOT_PAD_TO) --gap-fill=0xff
+u-boot-img-spl-at-end.bin: u-boot.img spl/u-boot-spl.bin FORCE
+	$(call if_changed,pad_cat)
+
+# Create a new ELF from a raw binary file.
+ifndef PLATFORM_ELFENTRY
+  PLATFORM_ELFENTRY = "_start"
+endif
+quiet_cmd_u-boot-elf ?= LD      $@
+	cmd_u-boot-elf ?= $(LD) u-boot-elf.o -o $@ \
+	--defsym=$(PLATFORM_ELFENTRY)=$(CONFIG_SYS_TEXT_BASE) \
+	-Ttext=$(CONFIG_SYS_TEXT_BASE)
+u-boot.elf: u-boot.bin
+	$(Q)$(OBJCOPY) -I binary $(PLATFORM_ELFFLAGS) $< u-boot-elf.o
+	$(call if_changed,u-boot-elf)
+
+# MediaTek's ARM-based u-boot needs a header to contains its load address
+# which is parsed by the BootROM.
+# If the SPL build is enabled, the header will be added to the spl binary,
+# and the spl binary and the u-boot.img will be combined into one file.
+# Otherwise the header will be added to the u-boot.bin directly.
+
+ifeq ($(CONFIG_SPL),y)
+spl/u-boot-spl-mtk.bin: spl/u-boot-spl
+
+u-boot-mtk.bin: u-boot.dtb u-boot.img spl/u-boot-spl-mtk.bin FORCE
+	$(call if_changed,binman)
+else
+MKIMAGEFLAGS_u-boot-mtk.bin = -T mtk_image \
+	-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \
+	-n "$(patsubst "%",%,$(CONFIG_MTK_BROM_HEADER_INFO))"
+
+u-boot-mtk.bin: u-boot.bin FORCE
+	$(call if_changed,mkimage)
+endif
+
+ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink)
+
+# Rule to link u-boot
+# May be overridden by arch/$(ARCH)/config.mk
+quiet_cmd_u-boot__ ?= LD      $@
+      cmd_u-boot__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_u-boot) -o $@ \
+      -T u-boot.lds $(u-boot-init)                             \
+      --start-group $(u-boot-main) --end-group                 \
+      $(PLATFORM_LIBS) -Map u-boot.map;                        \
+      $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+
+quiet_cmd_smap = GEN     common/system_map.o
+cmd_smap = \
+	smap=`$(call SYSTEM_MAP,u-boot) | \
+		awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\\\000"}'` ; \
+	$(CC) $(c_flags) -DSYSTEM_MAP="\"$${smap}\"" \
+		-c $(srctree)/common/system_map.c -o common/system_map.o
+
+u-boot:	$(u-boot-init) $(u-boot-main) u-boot.lds FORCE
+	+$(call if_changed,u-boot__)
+ifeq ($(CONFIG_KALLSYMS),y)
+	$(call cmd,smap)
+	$(call cmd,u-boot__) common/system_map.o
+endif
+
+ifeq ($(CONFIG_RISCV),y)
+	@tools/prelink-riscv $@ 0
+endif
+
+quiet_cmd_sym ?= SYM     $@
+      cmd_sym ?= $(OBJDUMP) -t $< > $@
+u-boot.sym: u-boot FORCE
+	$(call if_changed,sym)
+
+# The actual objects are generated when descending,
+# make sure no implicit rule kicks in
+$(sort $(u-boot-init) $(u-boot-main)): $(u-boot-dirs) ;
+
+# Handle descending into subdirectories listed in $(vmlinux-dirs)
+# Preset locale variables to speed up the build process. Limit locale
+# tweaks to this spot to avoid wrong language settings when running
+# make menuconfig etc.
+# Error messages still appears in the original language
+
+PHONY += $(u-boot-dirs)
+$(u-boot-dirs): prepare scripts
+	$(Q)$(MAKE) $(build)=$@
+
+tools: prepare
+# The "tools" are needed early
+$(filter-out tools, $(u-boot-dirs)): tools
+# The "examples" conditionally depend on U-Boot (say, when USE_PRIVATE_LIBGCC
+# is "yes"), so compile examples after U-Boot is compiled.
+examples: $(filter-out examples, $(u-boot-dirs))
+
+define filechk_uboot.release
+	echo "$(UBOOTVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"
+endef
+
+# Store (new) UBOOTRELEASE string in include/config/uboot.release
+include/config/uboot.release: include/config/auto.conf FORCE
+	$(call filechk,uboot.release)
+
+
+# Things we need to do before we recursively start building the kernel
+# or the modules are listed in "prepare".
+# A multi level approach is used. prepareN is processed before prepareN-1.
+# archprepare is used in arch Makefiles and when processed asm symlink,
+# version.h and scripts_basic is processed / created.
+
+# Listed in dependency order
+PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
+
+# prepare3 is used to check if we are building in a separate output directory,
+# and if so do:
+# 1) Check that make has not been executed in the kernel src $(srctree)
+prepare3: include/config/uboot.release
+ifneq ($(KBUILD_SRC),)
+	@$(kecho) '  Using $(srctree) as source for U-Boot'
+	$(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
+		echo >&2 "  $(srctree) is not clean, please run 'make mrproper'"; \
+		echo >&2 "  in the '$(srctree)' directory.";\
+		/bin/false; \
+	fi;
+endif
+
+# prepare2 creates a makefile if using a separate output directory
+prepare2: prepare3 outputmakefile
+
+prepare1: prepare2 $(version_h) $(timestamp_h) \
+                   include/config/auto.conf
+ifeq ($(wildcard $(LDSCRIPT)),)
+	@echo >&2 "  Could not find linker script."
+	@/bin/false
+endif
+
+ifeq ($(CONFIG_USE_DEFAULT_ENV_FILE),y)
+prepare1: $(defaultenv_h)
+endif
+
+archprepare: prepare1 scripts_basic
+
+prepare0: archprepare FORCE
+	$(Q)$(MAKE) $(build)=.
+
+# All the preparing..
+prepare: prepare0
+
+# Generate some files
+# ---------------------------------------------------------------------------
+
+define filechk_version.h
+	(echo \#define PLAIN_VERSION \"$(UBOOTRELEASE)\"; \
+	echo \#define U_BOOT_VERSION \"U-Boot \" PLAIN_VERSION; \
+	echo \#define CONFIG_SYSTEM_AS_ROOT \"${SYSTEMMODE}\"; \
+	echo \#define CONFIG_AVB2 \"${AVBMODE}\"; \
+	echo \#define CC_VERSION_STRING \"$$(LC_ALL=C $(CC) --version | head -n 1)\"; \
+	echo \#define LD_VERSION_STRING \"$$(LC_ALL=C $(LD) --version | head -n 1)\"; )
+endef
+
+# The SOURCE_DATE_EPOCH mechanism requires a date that behaves like GNU date.
+# The BSD date on the other hand behaves different and would produce errors
+# with the misused '-d' switch.  Respect that and search a working date with
+# well known pre- and suffixes for the GNU variant of date.
+define filechk_timestamp.h
+	(if test -n "$${SOURCE_DATE_EPOCH}"; then \
+		SOURCE_DATE="@$${SOURCE_DATE_EPOCH}"; \
+		DATE=""; \
+		for date in gdate date.gnu date; do \
+			$${date} -u -d "$${SOURCE_DATE}" >/dev/null 2>&1 && DATE="$${date}"; \
+		done; \
+		if test -n "$${DATE}"; then \
+			LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DATE "%b %d %C%y"'; \
+			LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TIME "%T"'; \
+			LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TZ "%z"'; \
+			LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \
+			LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; \
+		else \
+			return 42; \
+		fi; \
+	else \
+		LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"'; \
+		LC_ALL=C date +'#define U_BOOT_TIME "%T"'; \
+		LC_ALL=C date +'#define U_BOOT_TZ "%z"'; \
+		LC_ALL=C date +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \
+		LC_ALL=C date +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; \
+	fi)
+endef
+
+define filechk_defaultenv.h
+	(grep -v '^#' | \
+	 grep -v '^$$' | \
+	 tr '\n' '\0' | \
+	 sed -e 's/\\\x0/\n/' | \
+	 xxd -i ; echo ", 0x00" ; )
+endef
+
+define filechk_timestamp_git.h
+	(echo \#define U_BOOT_DATE \"$(shell git log -1 --format=%cd --date=format:"%b %d %C%y")\"; \
+	echo \#define U_BOOT_TIME \"$(shell git log -1 --format=%cd --date=format:"%T")\"; \
+	echo \#define U_BOOT_TZ \"$(shell git log -1 --format=%cd --date=format:"%Z")\"; \
+	echo \#define U_BOOT_DMI_DATE \"$(shell git log -1 --format=%cd --date=format:"%m/%d/%Y")\"; \
+	echo \#define U_BOOT_BUILD_DATE \"$(shell git log -1 --format=%cd --date=format:"0x%Y%m%d")\";)
+endef
+
+export U_BOOT_TIME_GIT=$(shell git log -1 --format=%cd --date=format:"%T")
+export U_BOOT_DATE_GIT=$(shell git log -1 --format=%cd --date=format:"%b %d %C%y")
+
+$(version_h): include/config/uboot.release FORCE
+	$(call filechk,version.h)
+
+
+ifeq ($(KBUILD_TIME_STAMP),0)
+$(timestamp_h): $(srctree)/Makefile FORCE
+	$(call filechk,timestamp.h)
+else
+$(timestamp_git_h): $(srctree)/Makefile FORCE
+	$(call filechk,timestamp_git.h)
+endif
+
+$(defaultenv_h): $(CONFIG_DEFAULT_ENV_FILE:"%"=%) FORCE
+	$(call filechk,defaultenv.h)
+
+# ---------------------------------------------------------------------------
+quiet_cmd_cpp_lds = LDS     $@
+cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
+		-D__ASSEMBLY__ -x assembler-with-cpp -std=c99 -P -o $@ $<
+
+u-boot.lds: $(LDSCRIPT) prepare FORCE
+	$(call if_changed_dep,cpp_lds)
+
+spl/u-boot-spl.bin: spl/u-boot-spl
+	@:
+spl/u-boot-spl: tools prepare \
+		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb) \
+		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_TPL_OF_PLATDATA),dts/dt.dtb)
+	$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
+
+spl/sunxi-spl.bin: spl/u-boot-spl
+	@:
+
+spl/sunxi-spl-with-ecc.bin: spl/sunxi-spl.bin
+	@:
+
+spl/u-boot-spl.sfp: spl/u-boot-spl
+	@:
+
+spl/boot.bin: spl/u-boot-spl
+	@:
+
+tpl/u-boot-tpl.bin: tools prepare \
+		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb)
+	$(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all
+
+TAG_SUBDIRS := $(patsubst %,$(srctree)/%,$(u-boot-dirs) include)
+
+FIND := find
+FINDFLAGS := -L
+
+tags ctags:
+		ctags -w -o ctags `$(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) \
+						-name '*.[chS]' -print`
+		ln -s ctags tags
+
+etags:
+		etags -a -o etags `$(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) \
+						-name '*.[chS]' -print`
+cscope:
+		$(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) -name '*.[chS]' -print > \
+						cscope.files
+		cscope -b -q -k
+
+SYSTEM_MAP = \
+		$(NM) $1 | \
+		grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
+		LC_ALL=C sort
+System.map:	u-boot
+		@$(call SYSTEM_MAP,$<) > $@
+
+#########################################################################
+
+# ARM relocations should all be R_ARM_RELATIVE (32-bit) or
+# R_AARCH64_RELATIVE (64-bit).
+checkarmreloc: u-boot
+	@RELOC="`$(CROSS_COMPILE)readelf -r -W $< | cut -d ' ' -f 4 | \
+		grep R_A | sort -u`"; \
+	if test "$$RELOC" != "R_ARM_RELATIVE" -a \
+		 "$$RELOC" != "R_AARCH64_RELATIVE"; then \
+		echo "$< contains unexpected relocations: $$RELOC"; \
+		false; \
+	fi
+
+envtools: scripts_basic $(version_h) $(timestamp_h)
+	$(Q)$(MAKE) $(build)=tools/env
+
+tools-only: scripts_basic $(version_h) $(timestamp_h)
+	$(Q)$(MAKE) $(build)=tools
+
+tools-all: export HOST_TOOLS_ALL=y
+tools-all: envtools tools ;
+
+cross_tools: export CROSS_BUILD_TOOLS=y
+cross_tools: tools ;
+
+.PHONY : CHANGELOG
+CHANGELOG:
+	git log --no-merges U-Boot-1_1_5.. | \
+	unexpand -a | sed -e 's/\s\s*$$//' > $@
+
+#########################################################################
+
+###
+# Cleaning is done on three levels.
+# make clean     Delete most generated files
+#                Leave enough to build external modules
+# make mrproper  Delete the current configuration, and all generated files
+# make distclean Remove editor backup files, patch leftover files and the like
+
+# Directories & files removed with 'make clean'
+CLEAN_DIRS  += $(MODVERDIR) \
+	       $(foreach d, spl tpl, $(patsubst %,$d/%, \
+			$(filter-out include, $(shell ls -1 $d 2>/dev/null))))
+
+CLEAN_FILES += include/bmp_logo.h include/bmp_logo_data.h \
+	       u-boot.* MLO* SPL System.map fit-dtb.blob
+
+# Directories & files removed with 'make mrproper'
+MRPROPER_DIRS  += include/config include/generated spl tpl \
+		  .tmp_objdiff
+MRPROPER_FILES += .config .config.old include/autoconf.mk* include/config.h \
+		  ctags etags tags
+
+# clean - Delete most, but leave enough to build external modules
+#
+clean: rm-dirs  := $(CLEAN_DIRS)
+clean: rm-files := $(CLEAN_FILES)
+
+clean-dirs	:= $(foreach f,$(u-boot-alldirs),$(if $(wildcard $(srctree)/$f/Makefile),$f))
+
+clean-dirs      := $(addprefix _clean_, $(clean-dirs))
+
+PHONY += $(clean-dirs) clean archclean
+$(clean-dirs):
+	$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
+
+clean: $(clean-dirs)
+	$(call cmd,rmdirs)
+	$(call cmd,rmfiles)
+	@find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+		-o -name '*.ko.*' -o -name '*.su' \
+		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
+		-o -name '*.lex.c' -o -name '*.tab.[ch]' \
+		-o -name '*.symtypes' -o -name 'modules.order' \
+		-o -name modules.builtin -o -name '.tmp_*.o.*' \
+		-o -name 'dsdt.aml' -o -name 'dsdt.asl.tmp' -o -name 'dsdt.c' \
+		-o -name '*.efi' -o -name '*.gcno' -o -name '*.so' \) \
+		-type f -print | xargs rm -f
+
+# mrproper - Delete all generated files, including .config
+#
+mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
+mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
+mrproper-dirs      := $(addprefix _mrproper_,scripts)
+
+PHONY += $(mrproper-dirs) mrproper archmrproper
+$(mrproper-dirs):
+	$(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
+
+mrproper: clean $(mrproper-dirs)
+	$(call cmd,rmdirs)
+	$(call cmd,rmfiles)
+	@rm -f arch/*/include/asm/arch
+
+# distclean
+#
+PHONY += distclean
+
+distclean: mrproper
+	@find $(srctree) $(RCS_FIND_IGNORE) \
+		\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
+		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
+		-o -name '.*.rej' -o -name '*%' -o -name 'core' \
+		-o -name '*.pyc' \) \
+		-type f -print | xargs rm -f
+	@rm -f boards.cfg
+
+backup:
+	F=`basename $(srctree)` ; cd .. ; \
+	gtar --force-local -zcvf `LC_ALL=C date "+$$F-%Y-%m-%d-%T.tar.gz"` $$F
+
+help:
+	@echo  'Cleaning targets:'
+	@echo  '  clean		  - Remove most generated files but keep the config'
+	@echo  '  mrproper	  - Remove all generated files + config + various backup files'
+	@echo  '  distclean	  - mrproper + remove editor backup and patch files'
+	@echo  ''
+	@echo  'Configuration targets:'
+	@$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
+	@echo  ''
+	@echo  'Test targets:'
+	@echo  ''
+	@echo  '  check           - Run all automated tests that use sandbox'
+	@echo  '  qcheck          - Run quick automated tests that use sandbox'
+	@echo  ''
+	@echo  'Other generic targets:'
+	@echo  '  all		  - Build all necessary images depending on configuration'
+	@echo  '  tests		  - Build U-Boot for sandbox and run tests'
+	@echo  '* u-boot	  - Build the bare u-boot'
+	@echo  '  dir/            - Build all files in dir and below'
+	@echo  '  dir/file.[oisS] - Build specified target only'
+	@echo  '  dir/file.lst    - Build specified mixed source/assembly target only'
+	@echo  '                    (requires a recent binutils and recent build (System.map))'
+	@echo  '  tags/ctags	  - Generate ctags file for editors'
+	@echo  '  etags		  - Generate etags file for editors'
+	@echo  '  cscope	  - Generate cscope index'
+	@echo  '  ubootrelease	  - Output the release version string (use with make -s)'
+	@echo  '  ubootversion	  - Output the version stored in Makefile (use with make -s)'
+	@echo  "  cfg		  - Don't build, just create the .cfg files"
+	@echo  "  envtools	  - Build only the target-side environment tools"
+	@echo  ''
+	@echo  'Static analysers'
+	@echo  '  checkstack      - Generate a list of stack hogs'
+	@echo  '  coccicheck      - Execute static code analysis with Coccinelle'
+	@echo  ''
+	@echo  'Documentation targets:'
+	@$(MAKE) -f $(srctree)/Documentation/Makefile dochelp
+	@echo  ''
+	@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
+	@echo  '  make V=2   [targets] 2 => give reason for rebuild of target'
+	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
+	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
+	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
+	@echo  '  make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections'
+	@echo  '  make W=n   [targets] Enable extra gcc checks, n=1,2,3 where'
+	@echo  '		1: warnings which may be relevant and do not occur too often'
+	@echo  '		2: warnings which occur quite often but may still be relevant'
+	@echo  '		3: more obscure warnings, can most likely be ignored'
+	@echo  '		Multiple levels can be combined with W=12 or W=123'
+	@echo  '  make T=0   [targets] 0 => use local time (date) as build timestamp'
+	@echo  '  make T=1   [targets] 1 => use latest git commit time as build timestamp'
+	@echo  ''
+	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
+	@echo  'For further info see the ./README file'
+
+tests check:
+	$(srctree)/test/run
+
+qcheck:
+	$(srctree)/test/run quick
+
+# Documentation targets
+# ---------------------------------------------------------------------------
+DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
+	       linkcheckdocs dochelp refcheckdocs
+PHONY += $(DOC_TARGETS)
+$(DOC_TARGETS): scripts_basic FORCE
+	$(Q)$(MAKE) $(build)=Documentation $@
+
+endif #ifeq ($(config-targets),1)
+endif #ifeq ($(mixed-targets),1)
+
+PHONY += checkstack ubootrelease ubootversion
+
+checkstack:
+	$(OBJDUMP) -d u-boot $$(find . -name u-boot-spl) | \
+	$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
+
+ubootrelease:
+	@echo "$(UBOOTVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"
+
+ubootversion:
+	@echo $(UBOOTVERSION)
+
+# Single targets
+# ---------------------------------------------------------------------------
+# Single targets are compatible with:
+# - build with mixed source and output
+# - build with separate output dir 'make O=...'
+# - external modules
+#
+#  target-dir => where to store outputfile
+#  build-dir  => directory in kernel source tree to use
+
+ifeq ($(KBUILD_EXTMOD),)
+        build-dir  = $(patsubst %/,%,$(dir $@))
+        target-dir = $(dir $@)
+else
+        zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
+        build-dir  = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+        target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
+endif
+
+%.s: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.i: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.o: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.lst: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.s: %.S prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.o: %.S prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.symtypes: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+
+# Modules
+/: prepare scripts FORCE
+	$(cmd_crmodverdir)
+	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+	$(build)=$(build-dir)
+%/: prepare scripts FORCE
+	$(cmd_crmodverdir)
+	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+	$(build)=$(build-dir)
+%.ko: prepare scripts FORCE
+	$(cmd_crmodverdir)
+	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
+	$(build)=$(build-dir) $(@:.ko=.o)
+	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+
+# Consistency checks
+# ---------------------------------------------------------------------------
+
+PHONY += coccicheck
+
+coccicheck:
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@
+
+# FIXME Should go into a make.lib or something
+# ===========================================================================
+
+quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
+      cmd_rmdirs = rm -rf $(rm-dirs)
+
+quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
+      cmd_rmfiles = rm -f $(rm-files)
+
+# read all saved command lines
+
+targets := $(wildcard $(sort $(targets)))
+cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
+
+ifneq ($(cmd_files),)
+  $(cmd_files): ;	# Do not try to update included dependency files
+  include $(cmd_files)
+endif
+
+endif	# skip-makefile
+
+PHONY += FORCE
+FORCE:
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/README b/README
new file mode 100644
index 0000000..17d56b8
--- /dev/null
+++ b/README
@@ -0,0 +1,5050 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000 - 2013
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+Summary:
+========
+
+This directory contains the source code for U-Boot, a boot loader for
+Embedded boards based on PowerPC, ARM, MIPS and several other
+processors, which can be installed in a boot ROM and used to
+initialize and test the hardware or to download and run application
+code.
+
+The development of U-Boot is closely related to Linux: some parts of
+the source code originate in the Linux source tree, we have some
+header files in common, and special provision has been made to
+support booting of Linux images.
+
+Some attention has been paid to make this software easily
+configurable and extendable. For instance, all monitor commands are
+implemented with the same call interface, so that it's very easy to
+add new commands. Also, instead of permanently adding rarely used
+code (for instance hardware test utilities) to the monitor, you can
+load and run it dynamically.
+
+
+Status:
+=======
+
+In general, all boards for which a configuration option exists in the
+Makefile have been tested to some extent and can be considered
+"working". In fact, many of them are used in production systems.
+
+In case of problems see the CHANGELOG file to find out who contributed
+the specific port. In addition, there are various MAINTAINERS files
+scattered throughout the U-Boot source identifying the people or
+companies responsible for various boards and subsystems.
+
+Note: As of August, 2010, there is no longer a CHANGELOG file in the
+actual U-Boot source tree; however, it can be created dynamically
+from the Git log using:
+
+	make CHANGELOG
+
+
+Where to get help:
+==================
+
+In case you have questions about, problems with or contributions for
+U-Boot, you should send a message to the U-Boot mailing list at
+<u-boot@lists.denx.de>. There is also an archive of previous traffic
+on the mailing list - please search the archive before asking FAQ's.
+Please see http://lists.denx.de/pipermail/u-boot and
+http://dir.gmane.org/gmane.comp.boot-loaders.u-boot
+
+
+Where to get source code:
+=========================
+
+The U-Boot source code is maintained in the Git repository at
+git://www.denx.de/git/u-boot.git ; you can browse it online at
+http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=summary
+
+The "snapshot" links on this page allow you to download tarballs of
+any version you might be interested in. Official releases are also
+available for FTP download from the ftp://ftp.denx.de/pub/u-boot/
+directory.
+
+Pre-built (and tested) images are available from
+ftp://ftp.denx.de/pub/u-boot/images/
+
+
+Where we come from:
+===================
+
+- start from 8xxrom sources
+- create PPCBoot project (http://sourceforge.net/projects/ppcboot)
+- clean up code
+- make it easier to add custom boards
+- make it possible to add other [PowerPC] CPUs
+- extend functions, especially:
+  * Provide extended interface to Linux boot loader
+  * S-Record download
+  * network boot
+  * PCMCIA / CompactFlash / ATA disk / SCSI ... boot
+- create ARMBoot project (http://sourceforge.net/projects/armboot)
+- add other CPU families (starting with ARM)
+- create U-Boot project (http://sourceforge.net/projects/u-boot)
+- current project page: see http://www.denx.de/wiki/U-Boot
+
+
+Names and Spelling:
+===================
+
+The "official" name of this project is "Das U-Boot". The spelling
+"U-Boot" shall be used in all written text (documentation, comments
+in source files etc.). Example:
+
+	This is the README file for the U-Boot project.
+
+File names etc. shall be based on the string "u-boot". Examples:
+
+	include/asm-ppc/u-boot.h
+
+	#include <asm/u-boot.h>
+
+Variable names, preprocessor constants etc. shall be either based on
+the string "u_boot" or on "U_BOOT". Example:
+
+	U_BOOT_VERSION		u_boot_logo
+	IH_OS_U_BOOT		u_boot_hush_start
+
+
+Versioning:
+===========
+
+Starting with the release in October 2008, the names of the releases
+were changed from numerical release numbers without deeper meaning
+into a time stamp based numbering. Regular releases are identified by
+names consisting of the calendar year and month of the release date.
+Additional fields (if present) indicate release candidates or bug fix
+releases in "stable" maintenance trees.
+
+Examples:
+	U-Boot v2009.11	    - Release November 2009
+	U-Boot v2009.11.1   - Release 1 in version November 2009 stable tree
+	U-Boot v2010.09-rc1 - Release candidate 1 for September 2010 release
+
+
+Directory Hierarchy:
+====================
+
+/arch			Architecture specific files
+  /arc			Files generic to ARC architecture
+  /arm			Files generic to ARM architecture
+  /m68k			Files generic to m68k architecture
+  /microblaze		Files generic to microblaze architecture
+  /mips			Files generic to MIPS architecture
+  /nds32		Files generic to NDS32 architecture
+  /nios2		Files generic to Altera NIOS2 architecture
+  /openrisc		Files generic to OpenRISC architecture
+  /powerpc		Files generic to PowerPC architecture
+  /riscv		Files generic to RISC-V architecture
+  /sandbox		Files generic to HW-independent "sandbox"
+  /sh			Files generic to SH architecture
+  /x86			Files generic to x86 architecture
+/api			Machine/arch independent API for external apps
+/board			Board dependent files
+/cmd			U-Boot commands functions
+/common			Misc architecture independent functions
+/configs		Board default configuration files
+/disk			Code for disk drive partition handling
+/doc			Documentation (don't expect too much)
+/drivers		Commonly used device drivers
+/dts			Contains Makefile for building internal U-Boot fdt.
+/examples		Example code for standalone applications, etc.
+/fs			Filesystem code (cramfs, ext2, jffs2, etc.)
+/include		Header Files
+/lib			Library routines generic to all architectures
+/Licenses		Various license files
+/net			Networking code
+/post			Power On Self Test
+/scripts		Various build scripts and Makefiles
+/test			Various unit test files
+/tools			Tools to build S-Record or U-Boot images, etc.
+
+Software Configuration:
+=======================
+
+Configuration is usually done using C preprocessor defines; the
+rationale behind that is to avoid dead code whenever possible.
+
+There are two classes of configuration variables:
+
+* Configuration _OPTIONS_:
+  These are selectable by the user and have names beginning with
+  "CONFIG_".
+
+* Configuration _SETTINGS_:
+  These depend on the hardware etc. and should not be meddled with if
+  you don't know what you're doing; they have names beginning with
+  "CONFIG_SYS_".
+
+Previously, all configuration was done by hand, which involved creating
+symbolic links and editing configuration files manually. More recently,
+U-Boot has added the Kbuild infrastructure used by the Linux kernel,
+allowing you to use the "make menuconfig" command to configure your
+build.
+
+
+Selection of Processor Architecture and Board Type:
+---------------------------------------------------
+
+For all supported boards there are ready-to-use default
+configurations available; just type "make <board_name>_defconfig".
+
+Example: For a TQM823L module type:
+
+	cd u-boot
+	make TQM823L_defconfig
+
+Note: If you're looking for the default configuration file for a board
+you're sure used to be there but is now missing, check the file
+doc/README.scrapyard for a list of no longer supported boards.
+
+Sandbox Environment:
+--------------------
+
+U-Boot can be built natively to run on a Linux host using the 'sandbox'
+board. This allows feature development which is not board- or architecture-
+specific to be undertaken on a native platform. The sandbox is also used to
+run some of U-Boot's tests.
+
+See board/sandbox/README.sandbox for more details.
+
+
+Board Initialisation Flow:
+--------------------------
+
+This is the intended start-up flow for boards. This should apply for both
+SPL and U-Boot proper (i.e. they both follow the same rules).
+
+Note: "SPL" stands for "Secondary Program Loader," which is explained in
+more detail later in this file.
+
+At present, SPL mostly uses a separate code path, but the function names
+and roles of each function are the same. Some boards or architectures
+may not conform to this.  At least most ARM boards which use
+CONFIG_SPL_FRAMEWORK conform to this.
+
+Execution typically starts with an architecture-specific (and possibly
+CPU-specific) start.S file, such as:
+
+	- arch/arm/cpu/armv7/start.S
+	- arch/powerpc/cpu/mpc83xx/start.S
+	- arch/mips/cpu/start.S
+
+and so on. From there, three functions are called; the purpose and
+limitations of each of these functions are described below.
+
+lowlevel_init():
+	- purpose: essential init to permit execution to reach board_init_f()
+	- no global_data or BSS
+	- there is no stack (ARMv7 may have one but it will soon be removed)
+	- must not set up SDRAM or use console
+	- must only do the bare minimum to allow execution to continue to
+		board_init_f()
+	- this is almost never needed
+	- return normally from this function
+
+board_init_f():
+	- purpose: set up the machine ready for running board_init_r():
+		i.e. SDRAM and serial UART
+	- global_data is available
+	- stack is in SRAM
+	- BSS is not available, so you cannot use global/static variables,
+		only stack variables and global_data
+
+	Non-SPL-specific notes:
+	- dram_init() is called to set up DRAM. If already done in SPL this
+		can do nothing
+
+	SPL-specific notes:
+	- you can override the entire board_init_f() function with your own
+		version as needed.
+	- preloader_console_init() can be called here in extremis
+	- should set up SDRAM, and anything needed to make the UART work
+	- these is no need to clear BSS, it will be done by crt0.S
+	- must return normally from this function (don't call board_init_r()
+		directly)
+
+Here the BSS is cleared. For SPL, if CONFIG_SPL_STACK_R is defined, then at
+this point the stack and global_data are relocated to below
+CONFIG_SPL_STACK_R_ADDR. For non-SPL, U-Boot is relocated to run at the top of
+memory.
+
+board_init_r():
+	- purpose: main execution, common code
+	- global_data is available
+	- SDRAM is available
+	- BSS is available, all static/global variables can be used
+	- execution eventually continues to main_loop()
+
+	Non-SPL-specific notes:
+	- U-Boot is relocated to the top of memory and is now running from
+		there.
+
+	SPL-specific notes:
+	- stack is optionally in SDRAM, if CONFIG_SPL_STACK_R is defined and
+		CONFIG_SPL_STACK_R_ADDR points into SDRAM
+	- preloader_console_init() can be called here - typically this is
+		done by selecting CONFIG_SPL_BOARD_INIT and then supplying a
+		spl_board_init() function containing this call
+	- loads U-Boot or (in falcon mode) Linux
+
+
+
+Configuration Options:
+----------------------
+
+Configuration depends on the combination of board and CPU type; all
+such information is kept in a configuration file
+"include/configs/<board_name>.h".
+
+Example: For a TQM823L module, all configuration settings are in
+"include/configs/TQM823L.h".
+
+
+Many of the options are named exactly as the corresponding Linux
+kernel configuration options. The intention is to make it easier to
+build a config tool - later.
+
+- ARM Platform Bus Type(CCI):
+		CoreLink Cache Coherent Interconnect (CCI) is ARM BUS which
+		provides full cache coherency between two clusters of multi-core
+		CPUs and I/O coherency for devices and I/O masters
+
+		CONFIG_SYS_FSL_HAS_CCI400
+
+		Defined For SoC that has cache coherent interconnect
+		CCN-400
+
+		CONFIG_SYS_FSL_HAS_CCN504
+
+		Defined for SoC that has cache coherent interconnect CCN-504
+
+The following options need to be configured:
+
+- CPU Type:	Define exactly one, e.g. CONFIG_MPC85XX.
+
+- Board Type:	Define exactly one, e.g. CONFIG_MPC8540ADS.
+
+- 85xx CPU Options:
+		CONFIG_SYS_PPC64
+
+		Specifies that the core is a 64-bit PowerPC implementation (implements
+		the "64" category of the Power ISA). This is necessary for ePAPR
+		compliance, among other possible reasons.
+
+		CONFIG_SYS_FSL_TBCLK_DIV
+
+		Defines the core time base clock divider ratio compared to the
+		system clock.  On most PQ3 devices this is 8, on newer QorIQ
+		devices it can be 16 or 32.  The ratio varies from SoC to Soc.
+
+		CONFIG_SYS_FSL_PCIE_COMPAT
+
+		Defines the string to utilize when trying to match PCIe device
+		tree nodes for the given platform.
+
+		CONFIG_SYS_FSL_ERRATUM_A004510
+
+		Enables a workaround for erratum A004510.  If set,
+		then CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV and
+		CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY must be set.
+
+		CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
+		CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 (optional)
+
+		Defines one or two SoC revisions (low 8 bits of SVR)
+		for which the A004510 workaround should be applied.
+
+		The rest of SVR is either not relevant to the decision
+		of whether the erratum is present (e.g. p2040 versus
+		p2041) or is implied by the build target, which controls
+		whether CONFIG_SYS_FSL_ERRATUM_A004510 is set.
+
+		See Freescale App Note 4493 for more information about
+		this erratum.
+
+		CONFIG_A003399_NOR_WORKAROUND
+		Enables a workaround for IFC erratum A003399. It is only
+		required during NOR boot.
+
+		CONFIG_A008044_WORKAROUND
+		Enables a workaround for T1040/T1042 erratum A008044. It is only
+		required during NAND boot and valid for Rev 1.0 SoC revision
+
+		CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
+
+		This is the value to write into CCSR offset 0x18600
+		according to the A004510 workaround.
+
+		CONFIG_SYS_FSL_DSP_DDR_ADDR
+		This value denotes start offset of DDR memory which is
+		connected exclusively to the DSP cores.
+
+		CONFIG_SYS_FSL_DSP_M2_RAM_ADDR
+		This value denotes start offset of M2 memory
+		which is directly connected to the DSP core.
+
+		CONFIG_SYS_FSL_DSP_M3_RAM_ADDR
+		This value denotes start offset of M3 memory which is directly
+		connected to the DSP core.
+
+		CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
+		This value denotes start offset of DSP CCSR space.
+
+		CONFIG_SYS_FSL_SINGLE_SOURCE_CLK
+		Single Source Clock is clocking mode present in some of FSL SoC's.
+		In this mode, a single differential clock is used to supply
+		clocks to the sysclock, ddrclock and usbclock.
+
+		CONFIG_SYS_CPC_REINIT_F
+		This CONFIG is defined when the CPC is configured as SRAM at the
+		time of U-Boot entry and is required to be re-initialized.
+
+		CONFIG_DEEP_SLEEP
+		Indicates this SoC supports deep sleep feature. If deep sleep is
+		supported, core will start to execute uboot when wakes up.
+
+- Generic CPU options:
+		CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN
+
+		Defines the endianess of the CPU. Implementation of those
+		values is arch specific.
+
+		CONFIG_SYS_FSL_DDR
+		Freescale DDR driver in use. This type of DDR controller is
+		found in mpc83xx, mpc85xx, mpc86xx as well as some ARM core
+		SoCs.
+
+		CONFIG_SYS_FSL_DDR_ADDR
+		Freescale DDR memory-mapped register base.
+
+		CONFIG_SYS_FSL_DDR_EMU
+		Specify emulator support for DDR. Some DDR features such as
+		deskew training are not available.
+
+		CONFIG_SYS_FSL_DDRC_GEN1
+		Freescale DDR1 controller.
+
+		CONFIG_SYS_FSL_DDRC_GEN2
+		Freescale DDR2 controller.
+
+		CONFIG_SYS_FSL_DDRC_GEN3
+		Freescale DDR3 controller.
+
+		CONFIG_SYS_FSL_DDRC_GEN4
+		Freescale DDR4 controller.
+
+		CONFIG_SYS_FSL_DDRC_ARM_GEN3
+		Freescale DDR3 controller for ARM-based SoCs.
+
+		CONFIG_SYS_FSL_DDR1
+		Board config to use DDR1. It can be enabled for SoCs with
+		Freescale DDR1 or DDR2 controllers, depending on the board
+		implemetation.
+
+		CONFIG_SYS_FSL_DDR2
+		Board config to use DDR2. It can be enabled for SoCs with
+		Freescale DDR2 or DDR3 controllers, depending on the board
+		implementation.
+
+		CONFIG_SYS_FSL_DDR3
+		Board config to use DDR3. It can be enabled for SoCs with
+		Freescale DDR3 or DDR3L controllers.
+
+		CONFIG_SYS_FSL_DDR3L
+		Board config to use DDR3L. It can be enabled for SoCs with
+		DDR3L controllers.
+
+		CONFIG_SYS_FSL_DDR4
+		Board config to use DDR4. It can be enabled for SoCs with
+		DDR4 controllers.
+
+		CONFIG_SYS_FSL_IFC_BE
+		Defines the IFC controller register space as Big Endian
+
+		CONFIG_SYS_FSL_IFC_LE
+		Defines the IFC controller register space as Little Endian
+
+		CONFIG_SYS_FSL_IFC_CLK_DIV
+		Defines divider of platform clock(clock input to IFC controller).
+
+		CONFIG_SYS_FSL_LBC_CLK_DIV
+		Defines divider of platform clock(clock input to eLBC controller).
+
+		CONFIG_SYS_FSL_PBL_PBI
+		It enables addition of RCW (Power on reset configuration) in built image.
+		Please refer doc/README.pblimage for more details
+
+		CONFIG_SYS_FSL_PBL_RCW
+		It adds PBI(pre-boot instructions) commands in u-boot build image.
+		PBI commands can be used to configure SoC before it starts the execution.
+		Please refer doc/README.pblimage for more details
+
+		CONFIG_SPL_FSL_PBL
+		It adds a target to create boot binary having SPL binary in PBI format
+		concatenated with u-boot binary.
+
+		CONFIG_SYS_FSL_DDR_BE
+		Defines the DDR controller register space as Big Endian
+
+		CONFIG_SYS_FSL_DDR_LE
+		Defines the DDR controller register space as Little Endian
+
+		CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY
+		Physical address from the view of DDR controllers. It is the
+		same as CONFIG_SYS_DDR_SDRAM_BASE for  all Power SoCs. But
+		it could be different for ARM SoCs.
+
+		CONFIG_SYS_FSL_DDR_INTLV_256B
+		DDR controller interleaving on 256-byte. This is a special
+		interleaving mode, handled by Dickens for Freescale layerscape
+		SoCs with ARM core.
+
+		CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS
+		Number of controllers used as main memory.
+
+		CONFIG_SYS_FSL_OTHER_DDR_NUM_CTRLS
+		Number of controllers used for other than main memory.
+
+		CONFIG_SYS_FSL_HAS_DP_DDR
+		Defines the SoC has DP-DDR used for DPAA.
+
+		CONFIG_SYS_FSL_SEC_BE
+		Defines the SEC controller register space as Big Endian
+
+		CONFIG_SYS_FSL_SEC_LE
+		Defines the SEC controller register space as Little Endian
+
+- MIPS CPU options:
+		CONFIG_SYS_INIT_SP_OFFSET
+
+		Offset relative to CONFIG_SYS_SDRAM_BASE for initial stack
+		pointer. This is needed for the temporary stack before
+		relocation.
+
+		CONFIG_XWAY_SWAP_BYTES
+
+		Enable compilation of tools/xway-swap-bytes needed for Lantiq
+		XWAY SoCs for booting from NOR flash. The U-Boot image needs to
+		be swapped if a flash programmer is used.
+
+- ARM options:
+		CONFIG_SYS_EXCEPTION_VECTORS_HIGH
+
+		Select high exception vectors of the ARM core, e.g., do not
+		clear the V bit of the c1 register of CP15.
+
+		COUNTER_FREQUENCY
+		Generic timer clock source frequency.
+
+		COUNTER_FREQUENCY_REAL
+		Generic timer clock source frequency if the real clock is
+		different from COUNTER_FREQUENCY, and can only be determined
+		at run time.
+
+- Tegra SoC options:
+		CONFIG_TEGRA_SUPPORT_NON_SECURE
+
+		Support executing U-Boot in non-secure (NS) mode. Certain
+		impossible actions will be skipped if the CPU is in NS mode,
+		such as ARM architectural timer initialization.
+
+- Linux Kernel Interface:
+		CONFIG_CLOCKS_IN_MHZ
+
+		U-Boot stores all clock information in Hz
+		internally. For binary compatibility with older Linux
+		kernels (which expect the clocks passed in the
+		bd_info data to be in MHz) the environment variable
+		"clocks_in_mhz" can be defined so that U-Boot
+		converts clock data to MHZ before passing it to the
+		Linux kernel.
+		When CONFIG_CLOCKS_IN_MHZ is defined, a definition of
+		"clocks_in_mhz=1" is automatically included in the
+		default environment.
+
+		CONFIG_MEMSIZE_IN_BYTES		[relevant for MIPS only]
+
+		When transferring memsize parameter to Linux, some versions
+		expect it to be in bytes, others in MB.
+		Define CONFIG_MEMSIZE_IN_BYTES to make it in bytes.
+
+		CONFIG_OF_LIBFDT
+
+		New kernel versions are expecting firmware settings to be
+		passed using flattened device trees (based on open firmware
+		concepts).
+
+		CONFIG_OF_LIBFDT
+		 * New libfdt-based support
+		 * Adds the "fdt" command
+		 * The bootm command automatically updates the fdt
+
+		OF_TBCLK - The timebase frequency.
+		OF_STDOUT_PATH - The path to the console device
+
+		boards with QUICC Engines require OF_QE to set UCC MAC
+		addresses
+
+		CONFIG_OF_BOARD_SETUP
+
+		Board code has addition modification that it wants to make
+		to the flat device tree before handing it off to the kernel
+
+		CONFIG_OF_SYSTEM_SETUP
+
+		Other code has addition modification that it wants to make
+		to the flat device tree before handing it off to the kernel.
+		This causes ft_system_setup() to be called before booting
+		the kernel.
+
+		CONFIG_OF_IDE_FIXUP
+
+		U-Boot can detect if an IDE device is present or not.
+		If not, and this new config option is activated, U-Boot
+		removes the ATA node from the DTS before booting Linux,
+		so the Linux IDE driver does not probe the device and
+		crash. This is needed for buggy hardware (uc101) where
+		no pull down resistor is connected to the signal IDE5V_DD7.
+
+		CONFIG_MACH_TYPE	[relevant for ARM only][mandatory]
+
+		This setting is mandatory for all boards that have only one
+		machine type and must be used to specify the machine type
+		number as it appears in the ARM machine registry
+		(see http://www.arm.linux.org.uk/developer/machines/).
+		Only boards that have multiple machine types supported
+		in a single configuration file and the machine type is
+		runtime discoverable, do not have to use this setting.
+
+- vxWorks boot parameters:
+
+		bootvx constructs a valid bootline using the following
+		environments variables: bootdev, bootfile, ipaddr, netmask,
+		serverip, gatewayip, hostname, othbootargs.
+		It loads the vxWorks image pointed bootfile.
+
+		Note: If a "bootargs" environment is defined, it will overwride
+		the defaults discussed just above.
+
+- Cache Configuration:
+		CONFIG_SYS_ICACHE_OFF - Do not enable instruction cache in U-Boot
+		CONFIG_SYS_DCACHE_OFF - Do not enable data cache in U-Boot
+		CONFIG_SYS_L2CACHE_OFF- Do not enable L2 cache in U-Boot
+
+- Cache Configuration for ARM:
+		CONFIG_SYS_L2_PL310 - Enable support for ARM PL310 L2 cache
+				      controller
+		CONFIG_SYS_PL310_BASE - Physical base address of PL310
+					controller register space
+
+- Serial Ports:
+		CONFIG_PL010_SERIAL
+
+		Define this if you want support for Amba PrimeCell PL010 UARTs.
+
+		CONFIG_PL011_SERIAL
+
+		Define this if you want support for Amba PrimeCell PL011 UARTs.
+
+		CONFIG_PL011_CLOCK
+
+		If you have Amba PrimeCell PL011 UARTs, set this variable to
+		the clock speed of the UARTs.
+
+		CONFIG_PL01x_PORTS
+
+		If you have Amba PrimeCell PL010 or PL011 UARTs on your board,
+		define this to a list of base addresses for each (supported)
+		port. See e.g. include/configs/versatile.h
+
+		CONFIG_SERIAL_HW_FLOW_CONTROL
+
+		Define this variable to enable hw flow control in serial driver.
+		Current user of this option is drivers/serial/nsl16550.c driver
+
+- Console Baudrate:
+		CONFIG_BAUDRATE - in bps
+		Select one of the baudrates listed in
+		CONFIG_SYS_BAUDRATE_TABLE, see below.
+
+- Autoboot Command:
+		CONFIG_BOOTCOMMAND
+		Only needed when CONFIG_BOOTDELAY is enabled;
+		define a command string that is automatically executed
+		when no character is read on the console interface
+		within "Boot Delay" after reset.
+
+		CONFIG_RAMBOOT and CONFIG_NFSBOOT
+		The value of these goes into the environment as
+		"ramboot" and "nfsboot" respectively, and can be used
+		as a convenience, when switching between booting from
+		RAM and NFS.
+
+- Pre-Boot Commands:
+		CONFIG_PREBOOT
+
+		When this option is #defined, the existence of the
+		environment variable "preboot" will be checked
+		immediately before starting the CONFIG_BOOTDELAY
+		countdown and/or running the auto-boot command resp.
+		entering interactive mode.
+
+		This feature is especially useful when "preboot" is
+		automatically generated or modified. For an example
+		see the LWMON board specific code: here "preboot" is
+		modified when the user holds down a certain
+		combination of keys on the (special) keyboard when
+		booting the systems
+
+- Serial Download Echo Mode:
+		CONFIG_LOADS_ECHO
+		If defined to 1, all characters received during a
+		serial download (using the "loads" command) are
+		echoed back. This might be needed by some terminal
+		emulations (like "cu"), but may as well just take
+		time on others. This setting #define's the initial
+		value of the "loads_echo" environment variable.
+
+- Kgdb Serial Baudrate: (if CONFIG_CMD_KGDB is defined)
+		CONFIG_KGDB_BAUDRATE
+		Select one of the baudrates listed in
+		CONFIG_SYS_BAUDRATE_TABLE, see below.
+
+- Removal of commands
+		If no commands are needed to boot, you can disable
+		CONFIG_CMDLINE to remove them. In this case, the command line
+		will not be available, and when U-Boot wants to execute the
+		boot command (on start-up) it will call board_run_command()
+		instead. This can reduce image size significantly for very
+		simple boot procedures.
+
+- Regular expression support:
+		CONFIG_REGEX
+		If this variable is defined, U-Boot is linked against
+		the SLRE (Super Light Regular Expression) library,
+		which adds regex support to some commands, as for
+		example "env grep" and "setexpr".
+
+- Device tree:
+		CONFIG_OF_CONTROL
+		If this variable is defined, U-Boot will use a device tree
+		to configure its devices, instead of relying on statically
+		compiled #defines in the board file. This option is
+		experimental and only available on a few boards. The device
+		tree is available in the global data as gd->fdt_blob.
+
+		U-Boot needs to get its device tree from somewhere. This can
+		be done using one of the three options below:
+
+		CONFIG_OF_EMBED
+		If this variable is defined, U-Boot will embed a device tree
+		binary in its image. This device tree file should be in the
+		board directory and called <soc>-<board>.dts. The binary file
+		is then picked up in board_init_f() and made available through
+		the global data structure as gd->fdt_blob.
+
+		CONFIG_OF_SEPARATE
+		If this variable is defined, U-Boot will build a device tree
+		binary. It will be called u-boot.dtb. Architecture-specific
+		code will locate it at run-time. Generally this works by:
+
+			cat u-boot.bin u-boot.dtb >image.bin
+
+		and in fact, U-Boot does this for you, creating a file called
+		u-boot-dtb.bin which is useful in the common case. You can
+		still use the individual files if you need something more
+		exotic.
+
+		CONFIG_OF_BOARD
+		If this variable is defined, U-Boot will use the device tree
+		provided by the board at runtime instead of embedding one with
+		the image. Only boards defining board_fdt_blob_setup() support
+		this option (see include/fdtdec.h file).
+
+- Watchdog:
+		CONFIG_WATCHDOG
+		If this variable is defined, it enables watchdog
+		support for the SoC. There must be support in the SoC
+		specific code for a watchdog. For the 8xx
+		CPUs, the SIU Watchdog feature is enabled in the SYPCR
+		register.  When supported for a specific SoC is
+		available, then no further board specific code should
+		be needed to use it.
+
+		CONFIG_HW_WATCHDOG
+		When using a watchdog circuitry external to the used
+		SoC, then define this variable and provide board
+		specific code for the "hw_watchdog_reset" function.
+
+		CONFIG_AT91_HW_WDT_TIMEOUT
+		specify the timeout in seconds. default 2 seconds.
+
+- Real-Time Clock:
+
+		When CONFIG_CMD_DATE is selected, the type of the RTC
+		has to be selected, too. Define exactly one of the
+		following options:
+
+		CONFIG_RTC_PCF8563	- use Philips PCF8563 RTC
+		CONFIG_RTC_MC13XXX	- use MC13783 or MC13892 RTC
+		CONFIG_RTC_MC146818	- use MC146818 RTC
+		CONFIG_RTC_DS1307	- use Maxim, Inc. DS1307 RTC
+		CONFIG_RTC_DS1337	- use Maxim, Inc. DS1337 RTC
+		CONFIG_RTC_DS1338	- use Maxim, Inc. DS1338 RTC
+		CONFIG_RTC_DS1339	- use Maxim, Inc. DS1339 RTC
+		CONFIG_RTC_DS164x	- use Dallas DS164x RTC
+		CONFIG_RTC_ISL1208	- use Intersil ISL1208 RTC
+		CONFIG_RTC_MAX6900	- use Maxim, Inc. MAX6900 RTC
+		CONFIG_RTC_DS1337_NOOSC	- Turn off the OSC output for DS1337
+		CONFIG_SYS_RV3029_TCR	- enable trickle charger on
+					  RV3029 RTC.
+
+		Note that if the RTC uses I2C, then the I2C interface
+		must also be configured. See I2C Support, below.
+
+- GPIO Support:
+		CONFIG_PCA953X		- use NXP's PCA953X series I2C GPIO
+
+		The CONFIG_SYS_I2C_PCA953X_WIDTH option specifies a list of
+		chip-ngpio pairs that tell the PCA953X driver the number of
+		pins supported by a particular chip.
+
+		Note that if the GPIO device uses I2C, then the I2C interface
+		must also be configured. See I2C Support, below.
+
+- I/O tracing:
+		When CONFIG_IO_TRACE is selected, U-Boot intercepts all I/O
+		accesses and can checksum them or write a list of them out
+		to memory. See the 'iotrace' command for details. This is
+		useful for testing device drivers since it can confirm that
+		the driver behaves the same way before and after a code
+		change. Currently this is supported on sandbox and arm. To
+		add support for your architecture, add '#include <iotrace.h>'
+		to the bottom of arch/<arch>/include/asm/io.h and test.
+
+		Example output from the 'iotrace stats' command is below.
+		Note that if the trace buffer is exhausted, the checksum will
+		still continue to operate.
+
+			iotrace is enabled
+			Start:  10000000	(buffer start address)
+			Size:   00010000	(buffer size)
+			Offset: 00000120	(current buffer offset)
+			Output: 10000120	(start + offset)
+			Count:  00000018	(number of trace records)
+			CRC32:  9526fb66	(CRC32 of all trace records)
+
+- Timestamp Support:
+
+		When CONFIG_TIMESTAMP is selected, the timestamp
+		(date and time) of an image is printed by image
+		commands like bootm or iminfo. This option is
+		automatically enabled when you select CONFIG_CMD_DATE .
+
+- Partition Labels (disklabels) Supported:
+		Zero or more of the following:
+		CONFIG_MAC_PARTITION   Apple's MacOS partition table.
+		CONFIG_ISO_PARTITION   ISO partition table, used on CDROM etc.
+		CONFIG_EFI_PARTITION   GPT partition table, common when EFI is the
+				       bootloader.  Note 2TB partition limit; see
+				       disk/part_efi.c
+		CONFIG_SCSI) you must configure support for at
+		least one non-MTD partition type as well.
+
+- IDE Reset method:
+		CONFIG_IDE_RESET_ROUTINE - this is defined in several
+		board configurations files but used nowhere!
+
+		CONFIG_IDE_RESET - is this is defined, IDE Reset will
+		be performed by calling the function
+			ide_set_reset(int reset)
+		which has to be defined in a board specific file
+
+- ATAPI Support:
+		CONFIG_ATAPI
+
+		Set this to enable ATAPI support.
+
+- LBA48 Support
+		CONFIG_LBA48
+
+		Set this to enable support for disks larger than 137GB
+		Also look at CONFIG_SYS_64BIT_LBA.
+		Whithout these , LBA48 support uses 32bit variables and will 'only'
+		support disks up to 2.1TB.
+
+		CONFIG_SYS_64BIT_LBA:
+			When enabled, makes the IDE subsystem use 64bit sector addresses.
+			Default is 32bit.
+
+- SCSI Support:
+		CONFIG_SYS_SCSI_MAX_LUN [8], CONFIG_SYS_SCSI_MAX_SCSI_ID [7] and
+		CONFIG_SYS_SCSI_MAX_DEVICE [CONFIG_SYS_SCSI_MAX_SCSI_ID *
+		CONFIG_SYS_SCSI_MAX_LUN] can be adjusted to define the
+		maximum numbers of LUNs, SCSI ID's and target
+		devices.
+
+		The environment variable 'scsidevs' is set to the number of
+		SCSI devices found during the last scan.
+
+- NETWORK Support (PCI):
+		CONFIG_E1000
+		Support for Intel 8254x/8257x gigabit chips.
+
+		CONFIG_E1000_SPI
+		Utility code for direct access to the SPI bus on Intel 8257x.
+		This does not do anything useful unless you set at least one
+		of CONFIG_CMD_E1000 or CONFIG_E1000_SPI_GENERIC.
+
+		CONFIG_E1000_SPI_GENERIC
+		Allow generic access to the SPI bus on the Intel 8257x, for
+		example with the "sspi" command.
+
+		CONFIG_EEPRO100
+		Support for Intel 82557/82559/82559ER chips.
+		Optional CONFIG_EEPRO100_SROM_WRITE enables EEPROM
+		write routine for first time initialisation.
+
+		CONFIG_TULIP
+		Support for Digital 2114x chips.
+		Optional CONFIG_TULIP_SELECT_MEDIA for board specific
+		modem chip initialisation (KS8761/QS6611).
+
+		CONFIG_NATSEMI
+		Support for National dp83815 chips.
+
+		CONFIG_NS8382X
+		Support for National dp8382[01] gigabit chips.
+
+- NETWORK Support (other):
+
+		CONFIG_DRIVER_AT91EMAC
+		Support for AT91RM9200 EMAC.
+
+			CONFIG_RMII
+			Define this to use reduced MII inteface
+
+			CONFIG_DRIVER_AT91EMAC_QUIET
+			If this defined, the driver is quiet.
+			The driver doen't show link status messages.
+
+		CONFIG_CALXEDA_XGMAC
+		Support for the Calxeda XGMAC device
+
+		CONFIG_LAN91C96
+		Support for SMSC's LAN91C96 chips.
+
+			CONFIG_LAN91C96_USE_32_BIT
+			Define this to enable 32 bit addressing
+
+		CONFIG_SMC91111
+		Support for SMSC's LAN91C111 chip
+
+			CONFIG_SMC91111_BASE
+			Define this to hold the physical address
+			of the device (I/O space)
+
+			CONFIG_SMC_USE_32_BIT
+			Define this if data bus is 32 bits
+
+			CONFIG_SMC_USE_IOFUNCS
+			Define this to use i/o functions instead of macros
+			(some hardware wont work with macros)
+
+			CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT
+			Define this if you have more then 3 PHYs.
+
+		CONFIG_FTGMAC100
+		Support for Faraday's FTGMAC100 Gigabit SoC Ethernet
+
+			CONFIG_FTGMAC100_EGIGA
+			Define this to use GE link update with gigabit PHY.
+			Define this if FTGMAC100 is connected to gigabit PHY.
+			If your system has 10/100 PHY only, it might not occur
+			wrong behavior. Because PHY usually return timeout or
+			useless data when polling gigabit status and gigabit
+			control registers. This behavior won't affect the
+			correctnessof 10/100 link speed update.
+
+		CONFIG_SH_ETHER
+		Support for Renesas on-chip Ethernet controller
+
+			CONFIG_SH_ETHER_USE_PORT
+			Define the number of ports to be used
+
+			CONFIG_SH_ETHER_PHY_ADDR
+			Define the ETH PHY's address
+
+			CONFIG_SH_ETHER_CACHE_WRITEBACK
+			If this option is set, the driver enables cache flush.
+
+- PWM Support:
+		CONFIG_PWM_IMX
+		Support for PWM module on the imx6.
+
+- TPM Support:
+		CONFIG_TPM
+		Support TPM devices.
+
+		CONFIG_TPM_TIS_INFINEON
+		Support for Infineon i2c bus TPM devices. Only one device
+		per system is supported at this time.
+
+			CONFIG_TPM_TIS_I2C_BURST_LIMITATION
+			Define the burst count bytes upper limit
+
+		CONFIG_TPM_ST33ZP24
+		Support for STMicroelectronics TPM devices. Requires DM_TPM support.
+
+			CONFIG_TPM_ST33ZP24_I2C
+			Support for STMicroelectronics ST33ZP24 I2C devices.
+			Requires TPM_ST33ZP24 and I2C.
+
+			CONFIG_TPM_ST33ZP24_SPI
+			Support for STMicroelectronics ST33ZP24 SPI devices.
+			Requires TPM_ST33ZP24 and SPI.
+
+		CONFIG_TPM_ATMEL_TWI
+		Support for Atmel TWI TPM device. Requires I2C support.
+
+		CONFIG_TPM_TIS_LPC
+		Support for generic parallel port TPM devices. Only one device
+		per system is supported at this time.
+
+			CONFIG_TPM_TIS_BASE_ADDRESS
+			Base address where the generic TPM device is mapped
+			to. Contemporary x86 systems usually map it at
+			0xfed40000.
+
+		CONFIG_TPM
+		Define this to enable the TPM support library which provides
+		functional interfaces to some TPM commands.
+		Requires support for a TPM device.
+
+		CONFIG_TPM_AUTH_SESSIONS
+		Define this to enable authorized functions in the TPM library.
+		Requires CONFIG_TPM and CONFIG_SHA1.
+
+- USB Support:
+		At the moment only the UHCI host controller is
+		supported (PIP405, MIP405); define
+		CONFIG_USB_UHCI to enable it.
+		define CONFIG_USB_KEYBOARD to enable the USB Keyboard
+		and define CONFIG_USB_STORAGE to enable the USB
+		storage devices.
+		Note:
+		Supported are USB Keyboards and USB Floppy drives
+		(TEAC FD-05PUB).
+
+		CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the
+		txfilltuning field in the EHCI controller on reset.
+
+		CONFIG_USB_DWC2_REG_ADDR the physical CPU address of the DWC2
+		HW module registers.
+
+- USB Device:
+		Define the below if you wish to use the USB console.
+		Once firmware is rebuilt from a serial console issue the
+		command "setenv stdin usbtty; setenv stdout usbtty" and
+		attach your USB cable. The Unix command "dmesg" should print
+		it has found a new device. The environment variable usbtty
+		can be set to gserial or cdc_acm to enable your device to
+		appear to a USB host as a Linux gserial device or a
+		Common Device Class Abstract Control Model serial device.
+		If you select usbtty = gserial you should be able to enumerate
+		a Linux host by
+		# modprobe usbserial vendor=0xVendorID product=0xProductID
+		else if using cdc_acm, simply setting the environment
+		variable usbtty to be cdc_acm should suffice. The following
+		might be defined in YourBoardName.h
+
+			CONFIG_USB_DEVICE
+			Define this to build a UDC device
+
+			CONFIG_USB_TTY
+			Define this to have a tty type of device available to
+			talk to the UDC device
+
+			CONFIG_USBD_HS
+			Define this to enable the high speed support for usb
+			device and usbtty. If this feature is enabled, a routine
+			int is_usbd_high_speed(void)
+			also needs to be defined by the driver to dynamically poll
+			whether the enumeration has succeded at high speed or full
+			speed.
+
+			CONFIG_SYS_CONSOLE_IS_IN_ENV
+			Define this if you want stdin, stdout &/or stderr to
+			be set to usbtty.
+
+		If you have a USB-IF assigned VendorID then you may wish to
+		define your own vendor specific values either in BoardName.h
+		or directly in usbd_vendor_info.h. If you don't define
+		CONFIG_USBD_MANUFACTURER, CONFIG_USBD_PRODUCT_NAME,
+		CONFIG_USBD_VENDORID and CONFIG_USBD_PRODUCTID, then U-Boot
+		should pretend to be a Linux device to it's target host.
+
+			CONFIG_USBD_MANUFACTURER
+			Define this string as the name of your company for
+			- CONFIG_USBD_MANUFACTURER "my company"
+
+			CONFIG_USBD_PRODUCT_NAME
+			Define this string as the name of your product
+			- CONFIG_USBD_PRODUCT_NAME "acme usb device"
+
+			CONFIG_USBD_VENDORID
+			Define this as your assigned Vendor ID from the USB
+			Implementors Forum. This *must* be a genuine Vendor ID
+			to avoid polluting the USB namespace.
+			- CONFIG_USBD_VENDORID 0xFFFF
+
+			CONFIG_USBD_PRODUCTID
+			Define this as the unique Product ID
+			for your device
+			- CONFIG_USBD_PRODUCTID 0xFFFF
+
+- ULPI Layer Support:
+		The ULPI (UTMI Low Pin (count) Interface) PHYs are supported via
+		the generic ULPI layer. The generic layer accesses the ULPI PHY
+		via the platform viewport, so you need both the genric layer and
+		the viewport enabled. Currently only Chipidea/ARC based
+		viewport is supported.
+		To enable the ULPI layer support, define CONFIG_USB_ULPI and
+		CONFIG_USB_ULPI_VIEWPORT in your board configuration file.
+		If your ULPI phy needs a different reference clock than the
+		standard 24 MHz then you have to define CONFIG_ULPI_REF_CLK to
+		the appropriate value in Hz.
+
+- MMC Support:
+		The MMC controller on the Intel PXA is supported. To
+		enable this define CONFIG_MMC. The MMC can be
+		accessed from the boot prompt by mapping the device
+		to physical memory similar to flash. Command line is
+		enabled with CONFIG_CMD_MMC. The MMC driver also works with
+		the FAT fs. This is enabled with CONFIG_CMD_FAT.
+
+		CONFIG_SH_MMCIF
+		Support for Renesas on-chip MMCIF controller
+
+			CONFIG_SH_MMCIF_ADDR
+			Define the base address of MMCIF registers
+
+			CONFIG_SH_MMCIF_CLK
+			Define the clock frequency for MMCIF
+
+		CONFIG_SUPPORT_EMMC_BOOT
+		Enable some additional features of the eMMC boot partitions.
+
+- USB Device Firmware Update (DFU) class support:
+		CONFIG_DFU_OVER_USB
+		This enables the USB portion of the DFU USB class
+
+		CONFIG_DFU_MMC
+		This enables support for exposing (e)MMC devices via DFU.
+
+		CONFIG_DFU_NAND
+		This enables support for exposing NAND devices via DFU.
+
+		CONFIG_DFU_RAM
+		This enables support for exposing RAM via DFU.
+		Note: DFU spec refer to non-volatile memory usage, but
+		allow usages beyond the scope of spec - here RAM usage,
+		one that would help mostly the developer.
+
+		CONFIG_SYS_DFU_DATA_BUF_SIZE
+		Dfu transfer uses a buffer before writing data to the
+		raw storage device. Make the size (in bytes) of this buffer
+		configurable. The size of this buffer is also configurable
+		through the "dfu_bufsiz" environment variable.
+
+		CONFIG_SYS_DFU_MAX_FILE_SIZE
+		When updating files rather than the raw storage device,
+		we use a static buffer to copy the file into and then write
+		the buffer once we've been given the whole file.  Define
+		this to the maximum filesize (in bytes) for the buffer.
+		Default is 4 MiB if undefined.
+
+		DFU_DEFAULT_POLL_TIMEOUT
+		Poll timeout [ms], is the timeout a device can send to the
+		host. The host must wait for this timeout before sending
+		a subsequent DFU_GET_STATUS request to the device.
+
+		DFU_MANIFEST_POLL_TIMEOUT
+		Poll timeout [ms], which the device sends to the host when
+		entering dfuMANIFEST state. Host waits this timeout, before
+		sending again an USB request to the device.
+
+- Journaling Flash filesystem support:
+		CONFIG_JFFS2_NAND
+		Define these for a default partition on a NAND device
+
+		CONFIG_SYS_JFFS2_FIRST_SECTOR,
+		CONFIG_SYS_JFFS2_FIRST_BANK, CONFIG_SYS_JFFS2_NUM_BANKS
+		Define these for a default partition on a NOR device
+
+- Keyboard Support:
+		See Kconfig help for available keyboard drivers.
+
+		CONFIG_KEYBOARD
+
+		Define this to enable a custom keyboard support.
+		This simply calls drv_keyboard_init() which must be
+		defined in your board-specific files. This option is deprecated
+		and is only used by novena. For new boards, use driver model
+		instead.
+
+- Video support:
+		CONFIG_FSL_DIU_FB
+		Enable the Freescale DIU video driver.	Reference boards for
+		SOCs that have a DIU should define this macro to enable DIU
+		support, and should also define these other macros:
+
+			CONFIG_SYS_DIU_ADDR
+			CONFIG_VIDEO
+			CONFIG_CFB_CONSOLE
+			CONFIG_VIDEO_SW_CURSOR
+			CONFIG_VGA_AS_SINGLE_DEVICE
+			CONFIG_VIDEO_LOGO
+			CONFIG_VIDEO_BMP_LOGO
+
+		The DIU driver will look for the 'video-mode' environment
+		variable, and if defined, enable the DIU as a console during
+		boot.  See the documentation file doc/README.video for a
+		description of this variable.
+
+- LCD Support:	CONFIG_LCD
+
+		Define this to enable LCD support (for output to LCD
+		display); also select one of the supported displays
+		by defining one of these:
+
+		CONFIG_ATMEL_LCD:
+
+			HITACHI TX09D70VM1CCA, 3.5", 240x320.
+
+		CONFIG_NEC_NL6448AC33:
+
+			NEC NL6448AC33-18. Active, color, single scan.
+
+		CONFIG_NEC_NL6448BC20
+
+			NEC NL6448BC20-08. 6.5", 640x480.
+			Active, color, single scan.
+
+		CONFIG_NEC_NL6448BC33_54
+
+			NEC NL6448BC33-54. 10.4", 640x480.
+			Active, color, single scan.
+
+		CONFIG_SHARP_16x9
+
+			Sharp 320x240. Active, color, single scan.
+			It isn't 16x9, and I am not sure what it is.
+
+		CONFIG_SHARP_LQ64D341
+
+			Sharp LQ64D341 display, 640x480.
+			Active, color, single scan.
+
+		CONFIG_HLD1045
+
+			HLD1045 display, 640x480.
+			Active, color, single scan.
+
+		CONFIG_OPTREX_BW
+
+			Optrex	 CBL50840-2 NF-FW 99 22 M5
+			or
+			Hitachi	 LMG6912RPFC-00T
+			or
+			Hitachi	 SP14Q002
+
+			320x240. Black & white.
+
+		CONFIG_LCD_ALIGNMENT
+
+		Normally the LCD is page-aligned (typically 4KB). If this is
+		defined then the LCD will be aligned to this value instead.
+		For ARM it is sometimes useful to use MMU_SECTION_SIZE
+		here, since it is cheaper to change data cache settings on
+		a per-section basis.
+
+
+		CONFIG_LCD_ROTATION
+
+		Sometimes, for example if the display is mounted in portrait
+		mode or even if it's mounted landscape but rotated by 180degree,
+		we need to rotate our content of the display relative to the
+		framebuffer, so that user can read the messages which are
+		printed out.
+		Once CONFIG_LCD_ROTATION is defined, the lcd_console will be
+		initialized with a given rotation from "vl_rot" out of
+		"vidinfo_t" which is provided by the board specific code.
+		The value for vl_rot is coded as following (matching to
+		fbcon=rotate:<n> linux-kernel commandline):
+		0 = no rotation respectively 0 degree
+		1 = 90 degree rotation
+		2 = 180 degree rotation
+		3 = 270 degree rotation
+
+		If CONFIG_LCD_ROTATION is not defined, the console will be
+		initialized with 0degree rotation.
+
+		CONFIG_LCD_BMP_RLE8
+
+		Support drawing of RLE8-compressed bitmaps on the LCD.
+
+		CONFIG_I2C_EDID
+
+		Enables an 'i2c edid' command which can read EDID
+		information over I2C from an attached LCD display.
+
+- Splash Screen Support: CONFIG_SPLASH_SCREEN
+
+		If this option is set, the environment is checked for
+		a variable "splashimage". If found, the usual display
+		of logo, copyright and system information on the LCD
+		is suppressed and the BMP image at the address
+		specified in "splashimage" is loaded instead. The
+		console is redirected to the "nulldev", too. This
+		allows for a "silent" boot where a splash screen is
+		loaded very quickly after power-on.
+
+		CONFIG_SPLASHIMAGE_GUARD
+
+		If this option is set, then U-Boot will prevent the environment
+		variable "splashimage" from being set to a problematic address
+		(see doc/README.displaying-bmps).
+		This option is useful for targets where, due to alignment
+		restrictions, an improperly aligned BMP image will cause a data
+		abort. If you think you will not have problems with unaligned
+		accesses (for example because your toolchain prevents them)
+		there is no need to set this option.
+
+		CONFIG_SPLASH_SCREEN_ALIGN
+
+		If this option is set the splash image can be freely positioned
+		on the screen. Environment variable "splashpos" specifies the
+		position as "x,y". If a positive number is given it is used as
+		number of pixel from left/top. If a negative number is given it
+		is used as number of pixel from right/bottom. You can also
+		specify 'm' for centering the image.
+
+		Example:
+		setenv splashpos m,m
+			=> image at center of screen
+
+		setenv splashpos 30,20
+			=> image at x = 30 and y = 20
+
+		setenv splashpos -10,m
+			=> vertically centered image
+			   at x = dspWidth - bmpWidth - 9
+
+- Gzip compressed BMP image support: CONFIG_VIDEO_BMP_GZIP
+
+		If this option is set, additionally to standard BMP
+		images, gzipped BMP images can be displayed via the
+		splashscreen support or the bmp command.
+
+- Run length encoded BMP image (RLE8) support: CONFIG_VIDEO_BMP_RLE8
+
+		If this option is set, 8-bit RLE compressed BMP images
+		can be displayed via the splashscreen support or the
+		bmp command.
+
+- Compression support:
+		CONFIG_GZIP
+
+		Enabled by default to support gzip compressed images.
+
+		CONFIG_BZIP2
+
+		If this option is set, support for bzip2 compressed
+		images is included. If not, only uncompressed and gzip
+		compressed images are supported.
+
+		NOTE: the bzip2 algorithm requires a lot of RAM, so
+		the malloc area (as defined by CONFIG_SYS_MALLOC_LEN) should
+		be at least 4MB.
+
+- MII/PHY support:
+		CONFIG_PHY_CLOCK_FREQ (ppc4xx)
+
+		The clock frequency of the MII bus
+
+		CONFIG_PHY_RESET_DELAY
+
+		Some PHY like Intel LXT971A need extra delay after
+		reset before any MII register access is possible.
+		For such PHY, set this option to the usec delay
+		required. (minimum 300usec for LXT971A)
+
+		CONFIG_PHY_CMD_DELAY (ppc4xx)
+
+		Some PHY like Intel LXT971A need extra delay after
+		command issued before MII status register can be read
+
+- IP address:
+		CONFIG_IPADDR
+
+		Define a default value for the IP address to use for
+		the default Ethernet interface, in case this is not
+		determined through e.g. bootp.
+		(Environment variable "ipaddr")
+
+- Server IP address:
+		CONFIG_SERVERIP
+
+		Defines a default value for the IP address of a TFTP
+		server to contact when using the "tftboot" command.
+		(Environment variable "serverip")
+
+		CONFIG_KEEP_SERVERADDR
+
+		Keeps the server's MAC address, in the env 'serveraddr'
+		for passing to bootargs (like Linux's netconsole option)
+
+- Gateway IP address:
+		CONFIG_GATEWAYIP
+
+		Defines a default value for the IP address of the
+		default router where packets to other networks are
+		sent to.
+		(Environment variable "gatewayip")
+
+- Subnet mask:
+		CONFIG_NETMASK
+
+		Defines a default value for the subnet mask (or
+		routing prefix) which is used to determine if an IP
+		address belongs to the local subnet or needs to be
+		forwarded through a router.
+		(Environment variable "netmask")
+
+- Multicast TFTP Mode:
+		CONFIG_MCAST_TFTP
+
+		Defines whether you want to support multicast TFTP as per
+		rfc-2090; for example to work with atftp.  Lets lots of targets
+		tftp down the same boot image concurrently.  Note: the Ethernet
+		driver in use must provide a function: mcast() to join/leave a
+		multicast group.
+
+- BOOTP Recovery Mode:
+		CONFIG_BOOTP_RANDOM_DELAY
+
+		If you have many targets in a network that try to
+		boot using BOOTP, you may want to avoid that all
+		systems send out BOOTP requests at precisely the same
+		moment (which would happen for instance at recovery
+		from a power failure, when all systems will try to
+		boot, thus flooding the BOOTP server. Defining
+		CONFIG_BOOTP_RANDOM_DELAY causes a random delay to be
+		inserted before sending out BOOTP requests. The
+		following delays are inserted then:
+
+		1st BOOTP request:	delay 0 ... 1 sec
+		2nd BOOTP request:	delay 0 ... 2 sec
+		3rd BOOTP request:	delay 0 ... 4 sec
+		4th and following
+		BOOTP requests:		delay 0 ... 8 sec
+
+		CONFIG_BOOTP_ID_CACHE_SIZE
+
+		BOOTP packets are uniquely identified using a 32-bit ID. The
+		server will copy the ID from client requests to responses and
+		U-Boot will use this to determine if it is the destination of
+		an incoming response. Some servers will check that addresses
+		aren't in use before handing them out (usually using an ARP
+		ping) and therefore take up to a few hundred milliseconds to
+		respond. Network congestion may also influence the time it
+		takes for a response to make it back to the client. If that
+		time is too long, U-Boot will retransmit requests. In order
+		to allow earlier responses to still be accepted after these
+		retransmissions, U-Boot's BOOTP client keeps a small cache of
+		IDs. The CONFIG_BOOTP_ID_CACHE_SIZE controls the size of this
+		cache. The default is to keep IDs for up to four outstanding
+		requests. Increasing this will allow U-Boot to accept offers
+		from a BOOTP client in networks with unusually high latency.
+
+- DHCP Advanced Options:
+		You can fine tune the DHCP functionality by defining
+		CONFIG_BOOTP_* symbols:
+
+		CONFIG_BOOTP_NISDOMAIN
+		CONFIG_BOOTP_BOOTFILESIZE
+		CONFIG_BOOTP_SEND_HOSTNAME
+		CONFIG_BOOTP_NTPSERVER
+		CONFIG_BOOTP_TIMEOFFSET
+		CONFIG_BOOTP_VENDOREX
+		CONFIG_BOOTP_MAY_FAIL
+
+		CONFIG_BOOTP_SERVERIP - TFTP server will be the serverip
+		environment variable, not the BOOTP server.
+
+		CONFIG_BOOTP_MAY_FAIL - If the DHCP server is not found
+		after the configured retry count, the call will fail
+		instead of starting over.  This can be used to fail over
+		to Link-local IP address configuration if the DHCP server
+		is not available.
+
+		CONFIG_BOOTP_SEND_HOSTNAME - Some DHCP servers are capable
+		to do a dynamic update of a DNS server. To do this, they
+		need the hostname of the DHCP requester.
+		If CONFIG_BOOTP_SEND_HOSTNAME is defined, the content
+		of the "hostname" environment variable is passed as
+		option 12 to the DHCP server.
+
+		CONFIG_BOOTP_DHCP_REQUEST_DELAY
+
+		A 32bit value in microseconds for a delay between
+		receiving a "DHCP Offer" and sending the "DHCP Request".
+		This fixes a problem with certain DHCP servers that don't
+		respond 100% of the time to a "DHCP request". E.g. On an
+		AT91RM9200 processor running at 180MHz, this delay needed
+		to be *at least* 15,000 usec before a Windows Server 2003
+		DHCP server would reply 100% of the time. I recommend at
+		least 50,000 usec to be safe. The alternative is to hope
+		that one of the retries will be successful but note that
+		the DHCP timeout and retry process takes a longer than
+		this delay.
+
+ - Link-local IP address negotiation:
+		Negotiate with other link-local clients on the local network
+		for an address that doesn't require explicit configuration.
+		This is especially useful if a DHCP server cannot be guaranteed
+		to exist in all environments that the device must operate.
+
+		See doc/README.link-local for more information.
+
+ - MAC address from environment variables
+
+		FDT_SEQ_MACADDR_FROM_ENV
+
+		Fix-up device tree with MAC addresses fetched sequentially from
+		environment variables. This config work on assumption that
+		non-usable ethernet node of device-tree are either not present
+		or their status has been marked as "disabled".
+
+ - CDP Options:
+		CONFIG_CDP_DEVICE_ID
+
+		The device id used in CDP trigger frames.
+
+		CONFIG_CDP_DEVICE_ID_PREFIX
+
+		A two character string which is prefixed to the MAC address
+		of the device.
+
+		CONFIG_CDP_PORT_ID
+
+		A printf format string which contains the ascii name of
+		the port. Normally is set to "eth%d" which sets
+		eth0 for the first Ethernet, eth1 for the second etc.
+
+		CONFIG_CDP_CAPABILITIES
+
+		A 32bit integer which indicates the device capabilities;
+		0x00000010 for a normal host which does not forwards.
+
+		CONFIG_CDP_VERSION
+
+		An ascii string containing the version of the software.
+
+		CONFIG_CDP_PLATFORM
+
+		An ascii string containing the name of the platform.
+
+		CONFIG_CDP_TRIGGER
+
+		A 32bit integer sent on the trigger.
+
+		CONFIG_CDP_POWER_CONSUMPTION
+
+		A 16bit integer containing the power consumption of the
+		device in .1 of milliwatts.
+
+		CONFIG_CDP_APPLIANCE_VLAN_TYPE
+
+		A byte containing the id of the VLAN.
+
+- Status LED:	CONFIG_LED_STATUS
+
+		Several configurations allow to display the current
+		status using a LED. For instance, the LED will blink
+		fast while running U-Boot code, stop blinking as
+		soon as a reply to a BOOTP request was received, and
+		start blinking slow once the Linux kernel is running
+		(supported by a status LED driver in the Linux
+		kernel). Defining CONFIG_LED_STATUS enables this
+		feature in U-Boot.
+
+		Additional options:
+
+		CONFIG_LED_STATUS_GPIO
+		The status LED can be connected to a GPIO pin.
+		In such cases, the gpio_led driver can be used as a
+		status LED backend implementation. Define CONFIG_LED_STATUS_GPIO
+		to include the gpio_led driver in the U-Boot binary.
+
+		CONFIG_GPIO_LED_INVERTED_TABLE
+		Some GPIO connected LEDs may have inverted polarity in which
+		case the GPIO high value corresponds to LED off state and
+		GPIO low value corresponds to LED on state.
+		In such cases CONFIG_GPIO_LED_INVERTED_TABLE may be defined
+		with a list of GPIO LEDs that have inverted polarity.
+
+- I2C Support:	CONFIG_SYS_I2C
+
+		This enable the NEW i2c subsystem, and will allow you to use
+		i2c commands at the u-boot command line (as long as you set
+		CONFIG_CMD_I2C in CONFIG_COMMANDS) and communicate with i2c
+		based realtime clock chips or other i2c devices. See
+		common/cmd_i2c.c for a description of the command line
+		interface.
+
+		ported i2c driver to the new framework:
+		- drivers/i2c/soft_i2c.c:
+		  - activate first bus with CONFIG_SYS_I2C_SOFT define
+		    CONFIG_SYS_I2C_SOFT_SPEED and CONFIG_SYS_I2C_SOFT_SLAVE
+		    for defining speed and slave address
+		  - activate second bus with I2C_SOFT_DECLARATIONS2 define
+		    CONFIG_SYS_I2C_SOFT_SPEED_2 and CONFIG_SYS_I2C_SOFT_SLAVE_2
+		    for defining speed and slave address
+		  - activate third bus with I2C_SOFT_DECLARATIONS3 define
+		    CONFIG_SYS_I2C_SOFT_SPEED_3 and CONFIG_SYS_I2C_SOFT_SLAVE_3
+		    for defining speed and slave address
+		  - activate fourth bus with I2C_SOFT_DECLARATIONS4 define
+		    CONFIG_SYS_I2C_SOFT_SPEED_4 and CONFIG_SYS_I2C_SOFT_SLAVE_4
+		    for defining speed and slave address
+
+		- drivers/i2c/fsl_i2c.c:
+		  - activate i2c driver with CONFIG_SYS_I2C_FSL
+		    define CONFIG_SYS_FSL_I2C_OFFSET for setting the register
+		    offset CONFIG_SYS_FSL_I2C_SPEED for the i2c speed and
+		    CONFIG_SYS_FSL_I2C_SLAVE for the slave addr of the first
+		    bus.
+		  - If your board supports a second fsl i2c bus, define
+		    CONFIG_SYS_FSL_I2C2_OFFSET for the register offset
+		    CONFIG_SYS_FSL_I2C2_SPEED for the speed and
+		    CONFIG_SYS_FSL_I2C2_SLAVE for the slave address of the
+		    second bus.
+
+		- drivers/i2c/tegra_i2c.c:
+		  - activate this driver with CONFIG_SYS_I2C_TEGRA
+		  - This driver adds 4 i2c buses with a fix speed from
+		    100000 and the slave addr 0!
+
+		- drivers/i2c/ppc4xx_i2c.c
+		  - activate this driver with CONFIG_SYS_I2C_PPC4XX
+		  - CONFIG_SYS_I2C_PPC4XX_CH0 activate hardware channel 0
+		  - CONFIG_SYS_I2C_PPC4XX_CH1 activate hardware channel 1
+
+		- drivers/i2c/i2c_mxc.c
+		  - activate this driver with CONFIG_SYS_I2C_MXC
+		  - enable bus 1 with CONFIG_SYS_I2C_MXC_I2C1
+		  - enable bus 2 with CONFIG_SYS_I2C_MXC_I2C2
+		  - enable bus 3 with CONFIG_SYS_I2C_MXC_I2C3
+		  - enable bus 4 with CONFIG_SYS_I2C_MXC_I2C4
+		  - define speed for bus 1 with CONFIG_SYS_MXC_I2C1_SPEED
+		  - define slave for bus 1 with CONFIG_SYS_MXC_I2C1_SLAVE
+		  - define speed for bus 2 with CONFIG_SYS_MXC_I2C2_SPEED
+		  - define slave for bus 2 with CONFIG_SYS_MXC_I2C2_SLAVE
+		  - define speed for bus 3 with CONFIG_SYS_MXC_I2C3_SPEED
+		  - define slave for bus 3 with CONFIG_SYS_MXC_I2C3_SLAVE
+		  - define speed for bus 4 with CONFIG_SYS_MXC_I2C4_SPEED
+		  - define slave for bus 4 with CONFIG_SYS_MXC_I2C4_SLAVE
+		If those defines are not set, default value is 100000
+		for speed, and 0 for slave.
+
+		- drivers/i2c/rcar_i2c.c:
+		  - activate this driver with CONFIG_SYS_I2C_RCAR
+		  - This driver adds 4 i2c buses
+
+		  - CONFIG_SYS_RCAR_I2C0_BASE for setting the register channel 0
+		  - CONFIG_SYS_RCAR_I2C0_SPEED for for the speed channel 0
+		  - CONFIG_SYS_RCAR_I2C1_BASE for setting the register channel 1
+		  - CONFIG_SYS_RCAR_I2C1_SPEED for for the speed channel 1
+		  - CONFIG_SYS_RCAR_I2C2_BASE for setting the register channel 2
+		  - CONFIG_SYS_RCAR_I2C2_SPEED for for the speed channel 2
+		  - CONFIG_SYS_RCAR_I2C3_BASE for setting the register channel 3
+		  - CONFIG_SYS_RCAR_I2C3_SPEED for for the speed channel 3
+		  - CONFIF_SYS_RCAR_I2C_NUM_CONTROLLERS for number of i2c buses
+
+		- drivers/i2c/sh_i2c.c:
+		  - activate this driver with CONFIG_SYS_I2C_SH
+		  - This driver adds from 2 to 5 i2c buses
+
+		  - CONFIG_SYS_I2C_SH_BASE0 for setting the register channel 0
+		  - CONFIG_SYS_I2C_SH_SPEED0 for for the speed channel 0
+		  - CONFIG_SYS_I2C_SH_BASE1 for setting the register channel 1
+		  - CONFIG_SYS_I2C_SH_SPEED1 for for the speed channel 1
+		  - CONFIG_SYS_I2C_SH_BASE2 for setting the register channel 2
+		  - CONFIG_SYS_I2C_SH_SPEED2 for for the speed channel 2
+		  - CONFIG_SYS_I2C_SH_BASE3 for setting the register channel 3
+		  - CONFIG_SYS_I2C_SH_SPEED3 for for the speed channel 3
+		  - CONFIG_SYS_I2C_SH_BASE4 for setting the register channel 4
+		  - CONFIG_SYS_I2C_SH_SPEED4 for for the speed channel 4
+		  - CONFIG_SYS_I2C_SH_NUM_CONTROLLERS for number of i2c buses
+
+		- drivers/i2c/omap24xx_i2c.c
+		  - activate this driver with CONFIG_SYS_I2C_OMAP24XX
+		  - CONFIG_SYS_OMAP24_I2C_SPEED speed channel 0
+		  - CONFIG_SYS_OMAP24_I2C_SLAVE slave addr channel 0
+		  - CONFIG_SYS_OMAP24_I2C_SPEED1 speed channel 1
+		  - CONFIG_SYS_OMAP24_I2C_SLAVE1 slave addr channel 1
+		  - CONFIG_SYS_OMAP24_I2C_SPEED2 speed channel 2
+		  - CONFIG_SYS_OMAP24_I2C_SLAVE2 slave addr channel 2
+		  - CONFIG_SYS_OMAP24_I2C_SPEED3 speed channel 3
+		  - CONFIG_SYS_OMAP24_I2C_SLAVE3 slave addr channel 3
+		  - CONFIG_SYS_OMAP24_I2C_SPEED4 speed channel 4
+		  - CONFIG_SYS_OMAP24_I2C_SLAVE4 slave addr channel 4
+
+		- drivers/i2c/zynq_i2c.c
+		  - activate this driver with CONFIG_SYS_I2C_ZYNQ
+		  - set CONFIG_SYS_I2C_ZYNQ_SPEED for speed setting
+		  - set CONFIG_SYS_I2C_ZYNQ_SLAVE for slave addr
+
+		- drivers/i2c/s3c24x0_i2c.c:
+		  - activate this driver with CONFIG_SYS_I2C_S3C24X0
+		  - This driver adds i2c buses (11 for Exynos5250, Exynos5420
+		    9 i2c buses for Exynos4 and 1 for S3C24X0 SoCs from Samsung)
+		    with a fix speed from 100000 and the slave addr 0!
+
+		- drivers/i2c/ihs_i2c.c
+		  - activate this driver with CONFIG_SYS_I2C_IHS
+		  - CONFIG_SYS_I2C_IHS_CH0 activate hardware channel 0
+		  - CONFIG_SYS_I2C_IHS_SPEED_0 speed channel 0
+		  - CONFIG_SYS_I2C_IHS_SLAVE_0 slave addr channel 0
+		  - CONFIG_SYS_I2C_IHS_CH1 activate hardware channel 1
+		  - CONFIG_SYS_I2C_IHS_SPEED_1 speed channel 1
+		  - CONFIG_SYS_I2C_IHS_SLAVE_1 slave addr channel 1
+		  - CONFIG_SYS_I2C_IHS_CH2 activate hardware channel 2
+		  - CONFIG_SYS_I2C_IHS_SPEED_2 speed channel 2
+		  - CONFIG_SYS_I2C_IHS_SLAVE_2 slave addr channel 2
+		  - CONFIG_SYS_I2C_IHS_CH3 activate hardware channel 3
+		  - CONFIG_SYS_I2C_IHS_SPEED_3 speed channel 3
+		  - CONFIG_SYS_I2C_IHS_SLAVE_3 slave addr channel 3
+		  - activate dual channel with CONFIG_SYS_I2C_IHS_DUAL
+		  - CONFIG_SYS_I2C_IHS_SPEED_0_1 speed channel 0_1
+		  - CONFIG_SYS_I2C_IHS_SLAVE_0_1 slave addr channel 0_1
+		  - CONFIG_SYS_I2C_IHS_SPEED_1_1 speed channel 1_1
+		  - CONFIG_SYS_I2C_IHS_SLAVE_1_1 slave addr channel 1_1
+		  - CONFIG_SYS_I2C_IHS_SPEED_2_1 speed channel 2_1
+		  - CONFIG_SYS_I2C_IHS_SLAVE_2_1 slave addr channel 2_1
+		  - CONFIG_SYS_I2C_IHS_SPEED_3_1 speed channel 3_1
+		  - CONFIG_SYS_I2C_IHS_SLAVE_3_1 slave addr channel 3_1
+
+		additional defines:
+
+		CONFIG_SYS_NUM_I2C_BUSES
+		Hold the number of i2c buses you want to use.
+
+		CONFIG_SYS_I2C_DIRECT_BUS
+		define this, if you don't use i2c muxes on your hardware.
+		if CONFIG_SYS_I2C_MAX_HOPS is not defined or == 0 you can
+		omit this define.
+
+		CONFIG_SYS_I2C_MAX_HOPS
+		define how many muxes are maximal consecutively connected
+		on one i2c bus. If you not use i2c muxes, omit this
+		define.
+
+		CONFIG_SYS_I2C_BUSES
+		hold a list of buses you want to use, only used if
+		CONFIG_SYS_I2C_DIRECT_BUS is not defined, for example
+		a board with CONFIG_SYS_I2C_MAX_HOPS = 1 and
+		CONFIG_SYS_NUM_I2C_BUSES = 9:
+
+		 CONFIG_SYS_I2C_BUSES	{{0, {I2C_NULL_HOP}}, \
+					{0, {{I2C_MUX_PCA9547, 0x70, 1}}}, \
+					{0, {{I2C_MUX_PCA9547, 0x70, 2}}}, \
+					{0, {{I2C_MUX_PCA9547, 0x70, 3}}}, \
+					{0, {{I2C_MUX_PCA9547, 0x70, 4}}}, \
+					{0, {{I2C_MUX_PCA9547, 0x70, 5}}}, \
+					{1, {I2C_NULL_HOP}}, \
+					{1, {{I2C_MUX_PCA9544, 0x72, 1}}}, \
+					{1, {{I2C_MUX_PCA9544, 0x72, 2}}}, \
+					}
+
+		which defines
+			bus 0 on adapter 0 without a mux
+			bus 1 on adapter 0 with a PCA9547 on address 0x70 port 1
+			bus 2 on adapter 0 with a PCA9547 on address 0x70 port 2
+			bus 3 on adapter 0 with a PCA9547 on address 0x70 port 3
+			bus 4 on adapter 0 with a PCA9547 on address 0x70 port 4
+			bus 5 on adapter 0 with a PCA9547 on address 0x70 port 5
+			bus 6 on adapter 1 without a mux
+			bus 7 on adapter 1 with a PCA9544 on address 0x72 port 1
+			bus 8 on adapter 1 with a PCA9544 on address 0x72 port 2
+
+		If you do not have i2c muxes on your board, omit this define.
+
+- Legacy I2C Support:
+		If you use the software i2c interface (CONFIG_SYS_I2C_SOFT)
+		then the following macros need to be defined (examples are
+		from include/configs/lwmon.h):
+
+		I2C_INIT
+
+		(Optional). Any commands necessary to enable the I2C
+		controller or configure ports.
+
+		eg: #define I2C_INIT (immr->im_cpm.cp_pbdir |=	PB_SCL)
+
+		I2C_ACTIVE
+
+		The code necessary to make the I2C data line active
+		(driven).  If the data line is open collector, this
+		define can be null.
+
+		eg: #define I2C_ACTIVE (immr->im_cpm.cp_pbdir |=  PB_SDA)
+
+		I2C_TRISTATE
+
+		The code necessary to make the I2C data line tri-stated
+		(inactive).  If the data line is open collector, this
+		define can be null.
+
+		eg: #define I2C_TRISTATE (immr->im_cpm.cp_pbdir &= ~PB_SDA)
+
+		I2C_READ
+
+		Code that returns true if the I2C data line is high,
+		false if it is low.
+
+		eg: #define I2C_READ ((immr->im_cpm.cp_pbdat & PB_SDA) != 0)
+
+		I2C_SDA(bit)
+
+		If <bit> is true, sets the I2C data line high. If it
+		is false, it clears it (low).
+
+		eg: #define I2C_SDA(bit) \
+			if(bit) immr->im_cpm.cp_pbdat |=  PB_SDA; \
+			else	immr->im_cpm.cp_pbdat &= ~PB_SDA
+
+		I2C_SCL(bit)
+
+		If <bit> is true, sets the I2C clock line high. If it
+		is false, it clears it (low).
+
+		eg: #define I2C_SCL(bit) \
+			if(bit) immr->im_cpm.cp_pbdat |=  PB_SCL; \
+			else	immr->im_cpm.cp_pbdat &= ~PB_SCL
+
+		I2C_DELAY
+
+		This delay is invoked four times per clock cycle so this
+		controls the rate of data transfer.  The data rate thus
+		is 1 / (I2C_DELAY * 4). Often defined to be something
+		like:
+
+		#define I2C_DELAY  udelay(2)
+
+		CONFIG_SOFT_I2C_GPIO_SCL / CONFIG_SOFT_I2C_GPIO_SDA
+
+		If your arch supports the generic GPIO framework (asm/gpio.h),
+		then you may alternatively define the two GPIOs that are to be
+		used as SCL / SDA.  Any of the previous I2C_xxx macros will
+		have GPIO-based defaults assigned to them as appropriate.
+
+		You should define these to the GPIO value as given directly to
+		the generic GPIO functions.
+
+		CONFIG_SYS_I2C_INIT_BOARD
+
+		When a board is reset during an i2c bus transfer
+		chips might think that the current transfer is still
+		in progress. On some boards it is possible to access
+		the i2c SCLK line directly, either by using the
+		processor pin as a GPIO or by having a second pin
+		connected to the bus. If this option is defined a
+		custom i2c_init_board() routine in boards/xxx/board.c
+		is run early in the boot sequence.
+
+		CONFIG_I2C_MULTI_BUS
+
+		This option allows the use of multiple I2C buses, each of which
+		must have a controller.	 At any point in time, only one bus is
+		active.	 To switch to a different bus, use the 'i2c dev' command.
+		Note that bus numbering is zero-based.
+
+		CONFIG_SYS_I2C_NOPROBES
+
+		This option specifies a list of I2C devices that will be skipped
+		when the 'i2c probe' command is issued.	 If CONFIG_I2C_MULTI_BUS
+		is set, specify a list of bus-device pairs.  Otherwise, specify
+		a 1D array of device addresses
+
+		e.g.
+			#undef	CONFIG_I2C_MULTI_BUS
+			#define CONFIG_SYS_I2C_NOPROBES {0x50,0x68}
+
+		will skip addresses 0x50 and 0x68 on a board with one I2C bus
+
+			#define CONFIG_I2C_MULTI_BUS
+			#define CONFIG_SYS_I2C_NOPROBES	{{0,0x50},{0,0x68},{1,0x54}}
+
+		will skip addresses 0x50 and 0x68 on bus 0 and address 0x54 on bus 1
+
+		CONFIG_SYS_SPD_BUS_NUM
+
+		If defined, then this indicates the I2C bus number for DDR SPD.
+		If not defined, then U-Boot assumes that SPD is on I2C bus 0.
+
+		CONFIG_SYS_RTC_BUS_NUM
+
+		If defined, then this indicates the I2C bus number for the RTC.
+		If not defined, then U-Boot assumes that RTC is on I2C bus 0.
+
+		CONFIG_SOFT_I2C_READ_REPEATED_START
+
+		defining this will force the i2c_read() function in
+		the soft_i2c driver to perform an I2C repeated start
+		between writing the address pointer and reading the
+		data.  If this define is omitted the default behaviour
+		of doing a stop-start sequence will be used.  Most I2C
+		devices can use either method, but some require one or
+		the other.
+
+- SPI Support:	CONFIG_SPI
+
+		Enables SPI driver (so far only tested with
+		SPI EEPROM, also an instance works with Crystal A/D and
+		D/As on the SACSng board)
+
+		CONFIG_SOFT_SPI
+
+		Enables a software (bit-bang) SPI driver rather than
+		using hardware support. This is a general purpose
+		driver that only requires three general I/O port pins
+		(two outputs, one input) to function. If this is
+		defined, the board configuration must define several
+		SPI configuration items (port pins to use, etc). For
+		an example, see include/configs/sacsng.h.
+
+		CONFIG_SYS_SPI_MXC_WAIT
+		Timeout for waiting until spi transfer completed.
+		default: (CONFIG_SYS_HZ/100)     /* 10 ms */
+
+- FPGA Support: CONFIG_FPGA
+
+		Enables FPGA subsystem.
+
+		CONFIG_FPGA_<vendor>
+
+		Enables support for specific chip vendors.
+		(ALTERA, XILINX)
+
+		CONFIG_FPGA_<family>
+
+		Enables support for FPGA family.
+		(SPARTAN2, SPARTAN3, VIRTEX2, CYCLONE2, ACEX1K, ACEX)
+
+		CONFIG_FPGA_COUNT
+
+		Specify the number of FPGA devices to support.
+
+		CONFIG_SYS_FPGA_PROG_FEEDBACK
+
+		Enable printing of hash marks during FPGA configuration.
+
+		CONFIG_SYS_FPGA_CHECK_BUSY
+
+		Enable checks on FPGA configuration interface busy
+		status by the configuration function. This option
+		will require a board or device specific function to
+		be written.
+
+		CONFIG_FPGA_DELAY
+
+		If defined, a function that provides delays in the FPGA
+		configuration driver.
+
+		CONFIG_SYS_FPGA_CHECK_CTRLC
+		Allow Control-C to interrupt FPGA configuration
+
+		CONFIG_SYS_FPGA_CHECK_ERROR
+
+		Check for configuration errors during FPGA bitfile
+		loading. For example, abort during Virtex II
+		configuration if the INIT_B line goes low (which
+		indicated a CRC error).
+
+		CONFIG_SYS_FPGA_WAIT_INIT
+
+		Maximum time to wait for the INIT_B line to de-assert
+		after PROB_B has been de-asserted during a Virtex II
+		FPGA configuration sequence. The default time is 500
+		ms.
+
+		CONFIG_SYS_FPGA_WAIT_BUSY
+
+		Maximum time to wait for BUSY to de-assert during
+		Virtex II FPGA configuration. The default is 5 ms.
+
+		CONFIG_SYS_FPGA_WAIT_CONFIG
+
+		Time to wait after FPGA configuration. The default is
+		200 ms.
+
+- Configuration Management:
+		CONFIG_BUILD_TARGET
+
+		Some SoCs need special image types (e.g. U-Boot binary
+		with a special header) as build targets. By defining
+		CONFIG_BUILD_TARGET in the SoC / board header, this
+		special image will be automatically built upon calling
+		make / buildman.
+
+		CONFIG_IDENT_STRING
+
+		If defined, this string will be added to the U-Boot
+		version information (U_BOOT_VERSION)
+
+- Vendor Parameter Protection:
+
+		U-Boot considers the values of the environment
+		variables "serial#" (Board Serial Number) and
+		"ethaddr" (Ethernet Address) to be parameters that
+		are set once by the board vendor / manufacturer, and
+		protects these variables from casual modification by
+		the user. Once set, these variables are read-only,
+		and write or delete attempts are rejected. You can
+		change this behaviour:
+
+		If CONFIG_ENV_OVERWRITE is #defined in your config
+		file, the write protection for vendor parameters is
+		completely disabled. Anybody can change or delete
+		these parameters.
+
+		Alternatively, if you define _both_ an ethaddr in the
+		default env _and_ CONFIG_OVERWRITE_ETHADDR_ONCE, a default
+		Ethernet address is installed in the environment,
+		which can be changed exactly ONCE by the user. [The
+		serial# is unaffected by this, i. e. it remains
+		read-only.]
+
+		The same can be accomplished in a more flexible way
+		for any variable by configuring the type of access
+		to allow for those variables in the ".flags" variable
+		or define CONFIG_ENV_FLAGS_LIST_STATIC.
+
+- Protected RAM:
+		CONFIG_PRAM
+
+		Define this variable to enable the reservation of
+		"protected RAM", i. e. RAM which is not overwritten
+		by U-Boot. Define CONFIG_PRAM to hold the number of
+		kB you want to reserve for pRAM. You can overwrite
+		this default value by defining an environment
+		variable "pram" to the number of kB you want to
+		reserve. Note that the board info structure will
+		still show the full amount of RAM. If pRAM is
+		reserved, a new environment variable "mem" will
+		automatically be defined to hold the amount of
+		remaining RAM in a form that can be passed as boot
+		argument to Linux, for instance like that:
+
+			setenv bootargs ... mem=\${mem}
+			saveenv
+
+		This way you can tell Linux not to use this memory,
+		either, which results in a memory region that will
+		not be affected by reboots.
+
+		*WARNING* If your board configuration uses automatic
+		detection of the RAM size, you must make sure that
+		this memory test is non-destructive. So far, the
+		following board configurations are known to be
+		"pRAM-clean":
+
+			IVMS8, IVML24, SPD8xx,
+			HERMES, IP860, RPXlite, LWMON,
+			FLAGADM
+
+- Access to physical memory region (> 4GB)
+		Some basic support is provided for operations on memory not
+		normally accessible to U-Boot - e.g. some architectures
+		support access to more than 4GB of memory on 32-bit
+		machines using physical address extension or similar.
+		Define CONFIG_PHYSMEM to access this basic support, which
+		currently only supports clearing the memory.
+
+- Error Recovery:
+		CONFIG_NET_RETRY_COUNT
+
+		This variable defines the number of retries for
+		network operations like ARP, RARP, TFTP, or BOOTP
+		before giving up the operation. If not defined, a
+		default value of 5 is used.
+
+		CONFIG_ARP_TIMEOUT
+
+		Timeout waiting for an ARP reply in milliseconds.
+
+		CONFIG_NFS_TIMEOUT
+
+		Timeout in milliseconds used in NFS protocol.
+		If you encounter "ERROR: Cannot umount" in nfs command,
+		try longer timeout such as
+		#define CONFIG_NFS_TIMEOUT 10000UL
+
+- Command Interpreter:
+		CONFIG_SYS_PROMPT_HUSH_PS2
+
+		This defines the secondary prompt string, which is
+		printed when the command interpreter needs more input
+		to complete a command. Usually "> ".
+
+	Note:
+
+		In the current implementation, the local variables
+		space and global environment variables space are
+		separated. Local variables are those you define by
+		simply typing `name=value'. To access a local
+		variable later on, you have write `$name' or
+		`${name}'; to execute the contents of a variable
+		directly type `$name' at the command prompt.
+
+		Global environment variables are those you use
+		setenv/printenv to work with. To run a command stored
+		in such a variable, you need to use the run command,
+		and you must not use the '$' sign to access them.
+
+		To store commands and special characters in a
+		variable, please use double quotation marks
+		surrounding the whole text of the variable, instead
+		of the backslashes before semicolons and special
+		symbols.
+
+- Command Line Editing and History:
+		CONFIG_CMDLINE_PS_SUPPORT
+
+		Enable support for changing the command prompt string
+		at run-time. Only static string is supported so far.
+		The string is obtained from environment variables PS1
+		and PS2.
+
+- Default Environment:
+		CONFIG_EXTRA_ENV_SETTINGS
+
+		Define this to contain any number of null terminated
+		strings (variable = value pairs) that will be part of
+		the default environment compiled into the boot image.
+
+		For example, place something like this in your
+		board's config file:
+
+		#define CONFIG_EXTRA_ENV_SETTINGS \
+			"myvar1=value1\0" \
+			"myvar2=value2\0"
+
+		Warning: This method is based on knowledge about the
+		internal format how the environment is stored by the
+		U-Boot code. This is NOT an official, exported
+		interface! Although it is unlikely that this format
+		will change soon, there is no guarantee either.
+		You better know what you are doing here.
+
+		Note: overly (ab)use of the default environment is
+		discouraged. Make sure to check other ways to preset
+		the environment like the "source" command or the
+		boot command first.
+
+		CONFIG_DELAY_ENVIRONMENT
+
+		Normally the environment is loaded when the board is
+		initialised so that it is available to U-Boot. This inhibits
+		that so that the environment is not available until
+		explicitly loaded later by U-Boot code. With CONFIG_OF_CONTROL
+		this is instead controlled by the value of
+		/config/load-environment.
+
+- Serial Flash support
+		Usage requires an initial 'sf probe' to define the serial
+		flash parameters, followed by read/write/erase/update
+		commands.
+
+		The following defaults may be provided by the platform
+		to handle the common case when only a single serial
+		flash is present on the system.
+
+		CONFIG_SF_DEFAULT_BUS		Bus identifier
+		CONFIG_SF_DEFAULT_CS		Chip-select
+		CONFIG_SF_DEFAULT_MODE 		(see include/spi.h)
+		CONFIG_SF_DEFAULT_SPEED		in Hz
+
+
+- TFTP Fixed UDP Port:
+		CONFIG_TFTP_PORT
+
+		If this is defined, the environment variable tftpsrcp
+		is used to supply the TFTP UDP source port value.
+		If tftpsrcp isn't defined, the normal pseudo-random port
+		number generator is used.
+
+		Also, the environment variable tftpdstp is used to supply
+		the TFTP UDP destination port value.  If tftpdstp isn't
+		defined, the normal port 69 is used.
+
+		The purpose for tftpsrcp is to allow a TFTP server to
+		blindly start the TFTP transfer using the pre-configured
+		target IP address and UDP port. This has the effect of
+		"punching through" the (Windows XP) firewall, allowing
+		the remainder of the TFTP transfer to proceed normally.
+		A better solution is to properly configure the firewall,
+		but sometimes that is not allowed.
+
+- Show boot progress:
+		CONFIG_SHOW_BOOT_PROGRESS
+
+		Defining this option allows to add some board-
+		specific code (calling a user-provided function
+		"show_boot_progress(int)") that enables you to show
+		the system's boot progress on some display (for
+		example, some LED's) on your board. At the moment,
+		the following checkpoints are implemented:
+
+
+Legacy uImage format:
+
+  Arg	Where			When
+    1	common/cmd_bootm.c	before attempting to boot an image
+   -1	common/cmd_bootm.c	Image header has bad	 magic number
+    2	common/cmd_bootm.c	Image header has correct magic number
+   -2	common/cmd_bootm.c	Image header has bad	 checksum
+    3	common/cmd_bootm.c	Image header has correct checksum
+   -3	common/cmd_bootm.c	Image data   has bad	 checksum
+    4	common/cmd_bootm.c	Image data   has correct checksum
+   -4	common/cmd_bootm.c	Image is for unsupported architecture
+    5	common/cmd_bootm.c	Architecture check OK
+   -5	common/cmd_bootm.c	Wrong Image Type (not kernel, multi)
+    6	common/cmd_bootm.c	Image Type check OK
+   -6	common/cmd_bootm.c	gunzip uncompression error
+   -7	common/cmd_bootm.c	Unimplemented compression type
+    7	common/cmd_bootm.c	Uncompression OK
+    8	common/cmd_bootm.c	No uncompress/copy overwrite error
+   -9	common/cmd_bootm.c	Unsupported OS (not Linux, BSD, VxWorks, QNX)
+
+    9	common/image.c		Start initial ramdisk verification
+  -10	common/image.c		Ramdisk header has bad	   magic number
+  -11	common/image.c		Ramdisk header has bad	   checksum
+   10	common/image.c		Ramdisk header is OK
+  -12	common/image.c		Ramdisk data   has bad	   checksum
+   11	common/image.c		Ramdisk data   has correct checksum
+   12	common/image.c		Ramdisk verification complete, start loading
+  -13	common/image.c		Wrong Image Type (not PPC Linux ramdisk)
+   13	common/image.c		Start multifile image verification
+   14	common/image.c		No initial ramdisk, no multifile, continue.
+
+   15	arch/<arch>/lib/bootm.c All preparation done, transferring control to OS
+
+  -30	arch/powerpc/lib/board.c	Fatal error, hang the system
+  -31	post/post.c		POST test failed, detected by post_output_backlog()
+  -32	post/post.c		POST test failed, detected by post_run_single()
+
+   34	common/cmd_doc.c	before loading a Image from a DOC device
+  -35	common/cmd_doc.c	Bad usage of "doc" command
+   35	common/cmd_doc.c	correct usage of "doc" command
+  -36	common/cmd_doc.c	No boot device
+   36	common/cmd_doc.c	correct boot device
+  -37	common/cmd_doc.c	Unknown Chip ID on boot device
+   37	common/cmd_doc.c	correct chip ID found, device available
+  -38	common/cmd_doc.c	Read Error on boot device
+   38	common/cmd_doc.c	reading Image header from DOC device OK
+  -39	common/cmd_doc.c	Image header has bad magic number
+   39	common/cmd_doc.c	Image header has correct magic number
+  -40	common/cmd_doc.c	Error reading Image from DOC device
+   40	common/cmd_doc.c	Image header has correct magic number
+   41	common/cmd_ide.c	before loading a Image from a IDE device
+  -42	common/cmd_ide.c	Bad usage of "ide" command
+   42	common/cmd_ide.c	correct usage of "ide" command
+  -43	common/cmd_ide.c	No boot device
+   43	common/cmd_ide.c	boot device found
+  -44	common/cmd_ide.c	Device not available
+   44	common/cmd_ide.c	Device available
+  -45	common/cmd_ide.c	wrong partition selected
+   45	common/cmd_ide.c	partition selected
+  -46	common/cmd_ide.c	Unknown partition table
+   46	common/cmd_ide.c	valid partition table found
+  -47	common/cmd_ide.c	Invalid partition type
+   47	common/cmd_ide.c	correct partition type
+  -48	common/cmd_ide.c	Error reading Image Header on boot device
+   48	common/cmd_ide.c	reading Image Header from IDE device OK
+  -49	common/cmd_ide.c	Image header has bad magic number
+   49	common/cmd_ide.c	Image header has correct magic number
+  -50	common/cmd_ide.c	Image header has bad	 checksum
+   50	common/cmd_ide.c	Image header has correct checksum
+  -51	common/cmd_ide.c	Error reading Image from IDE device
+   51	common/cmd_ide.c	reading Image from IDE device OK
+   52	common/cmd_nand.c	before loading a Image from a NAND device
+  -53	common/cmd_nand.c	Bad usage of "nand" command
+   53	common/cmd_nand.c	correct usage of "nand" command
+  -54	common/cmd_nand.c	No boot device
+   54	common/cmd_nand.c	boot device found
+  -55	common/cmd_nand.c	Unknown Chip ID on boot device
+   55	common/cmd_nand.c	correct chip ID found, device available
+  -56	common/cmd_nand.c	Error reading Image Header on boot device
+   56	common/cmd_nand.c	reading Image Header from NAND device OK
+  -57	common/cmd_nand.c	Image header has bad magic number
+   57	common/cmd_nand.c	Image header has correct magic number
+  -58	common/cmd_nand.c	Error reading Image from NAND device
+   58	common/cmd_nand.c	reading Image from NAND device OK
+
+  -60	common/env_common.c	Environment has a bad CRC, using default
+
+   64	net/eth.c		starting with Ethernet configuration.
+  -64	net/eth.c		no Ethernet found.
+   65	net/eth.c		Ethernet found.
+
+  -80	common/cmd_net.c	usage wrong
+   80	common/cmd_net.c	before calling net_loop()
+  -81	common/cmd_net.c	some error in net_loop() occurred
+   81	common/cmd_net.c	net_loop() back without error
+  -82	common/cmd_net.c	size == 0 (File with size 0 loaded)
+   82	common/cmd_net.c	trying automatic boot
+   83	common/cmd_net.c	running "source" command
+  -83	common/cmd_net.c	some error in automatic boot or "source" command
+   84	common/cmd_net.c	end without errors
+
+FIT uImage format:
+
+  Arg	Where			When
+  100	common/cmd_bootm.c	Kernel FIT Image has correct format
+ -100	common/cmd_bootm.c	Kernel FIT Image has incorrect format
+  101	common/cmd_bootm.c	No Kernel subimage unit name, using configuration
+ -101	common/cmd_bootm.c	Can't get configuration for kernel subimage
+  102	common/cmd_bootm.c	Kernel unit name specified
+ -103	common/cmd_bootm.c	Can't get kernel subimage node offset
+  103	common/cmd_bootm.c	Found configuration node
+  104	common/cmd_bootm.c	Got kernel subimage node offset
+ -104	common/cmd_bootm.c	Kernel subimage hash verification failed
+  105	common/cmd_bootm.c	Kernel subimage hash verification OK
+ -105	common/cmd_bootm.c	Kernel subimage is for unsupported architecture
+  106	common/cmd_bootm.c	Architecture check OK
+ -106	common/cmd_bootm.c	Kernel subimage has wrong type
+  107	common/cmd_bootm.c	Kernel subimage type OK
+ -107	common/cmd_bootm.c	Can't get kernel subimage data/size
+  108	common/cmd_bootm.c	Got kernel subimage data/size
+ -108	common/cmd_bootm.c	Wrong image type (not legacy, FIT)
+ -109	common/cmd_bootm.c	Can't get kernel subimage type
+ -110	common/cmd_bootm.c	Can't get kernel subimage comp
+ -111	common/cmd_bootm.c	Can't get kernel subimage os
+ -112	common/cmd_bootm.c	Can't get kernel subimage load address
+ -113	common/cmd_bootm.c	Image uncompress/copy overwrite error
+
+  120	common/image.c		Start initial ramdisk verification
+ -120	common/image.c		Ramdisk FIT image has incorrect format
+  121	common/image.c		Ramdisk FIT image has correct format
+  122	common/image.c		No ramdisk subimage unit name, using configuration
+ -122	common/image.c		Can't get configuration for ramdisk subimage
+  123	common/image.c		Ramdisk unit name specified
+ -124	common/image.c		Can't get ramdisk subimage node offset
+  125	common/image.c		Got ramdisk subimage node offset
+ -125	common/image.c		Ramdisk subimage hash verification failed
+  126	common/image.c		Ramdisk subimage hash verification OK
+ -126	common/image.c		Ramdisk subimage for unsupported architecture
+  127	common/image.c		Architecture check OK
+ -127	common/image.c		Can't get ramdisk subimage data/size
+  128	common/image.c		Got ramdisk subimage data/size
+  129	common/image.c		Can't get ramdisk load address
+ -129	common/image.c		Got ramdisk load address
+
+ -130	common/cmd_doc.c	Incorrect FIT image format
+  131	common/cmd_doc.c	FIT image format OK
+
+ -140	common/cmd_ide.c	Incorrect FIT image format
+  141	common/cmd_ide.c	FIT image format OK
+
+ -150	common/cmd_nand.c	Incorrect FIT image format
+  151	common/cmd_nand.c	FIT image format OK
+
+- Standalone program support:
+		CONFIG_STANDALONE_LOAD_ADDR
+
+		This option defines a board specific value for the
+		address where standalone program gets loaded, thus
+		overwriting the architecture dependent default
+		settings.
+
+- Frame Buffer Address:
+		CONFIG_FB_ADDR
+
+		Define CONFIG_FB_ADDR if you want to use specific
+		address for frame buffer.  This is typically the case
+		when using a graphics controller has separate video
+		memory.  U-Boot will then place the frame buffer at
+		the given address instead of dynamically reserving it
+		in system RAM by calling lcd_setmem(), which grabs
+		the memory for the frame buffer depending on the
+		configured panel size.
+
+		Please see board_init_f function.
+
+- Automatic software updates via TFTP server
+		CONFIG_UPDATE_TFTP
+		CONFIG_UPDATE_TFTP_CNT_MAX
+		CONFIG_UPDATE_TFTP_MSEC_MAX
+
+		These options enable and control the auto-update feature;
+		for a more detailed description refer to doc/README.update.
+
+- MTD Support (mtdparts command, UBI support)
+		CONFIG_MTD_UBI_WL_THRESHOLD
+		This parameter defines the maximum difference between the highest
+		erase counter value and the lowest erase counter value of eraseblocks
+		of UBI devices. When this threshold is exceeded, UBI starts performing
+		wear leveling by means of moving data from eraseblock with low erase
+		counter to eraseblocks with high erase counter.
+
+		The default value should be OK for SLC NAND flashes, NOR flashes and
+		other flashes which have eraseblock life-cycle 100000 or more.
+		However, in case of MLC NAND flashes which typically have eraseblock
+		life-cycle less than 10000, the threshold should be lessened (e.g.,
+		to 128 or 256, although it does not have to be power of 2).
+
+		default: 4096
+
+		CONFIG_MTD_UBI_BEB_LIMIT
+		This option specifies the maximum bad physical eraseblocks UBI
+		expects on the MTD device (per 1024 eraseblocks). If the
+		underlying flash does not admit of bad eraseblocks (e.g. NOR
+		flash), this value is ignored.
+
+		NAND datasheets often specify the minimum and maximum NVM
+		(Number of Valid Blocks) for the flashes' endurance lifetime.
+		The maximum expected bad eraseblocks per 1024 eraseblocks
+		then can be calculated as "1024 * (1 - MinNVB / MaxNVB)",
+		which gives 20 for most NANDs (MaxNVB is basically the total
+		count of eraseblocks on the chip).
+
+		To put it differently, if this value is 20, UBI will try to
+		reserve about 1.9% of physical eraseblocks for bad blocks
+		handling. And that will be 1.9% of eraseblocks on the entire
+		NAND chip, not just the MTD partition UBI attaches. This means
+		that if you have, say, a NAND flash chip admits maximum 40 bad
+		eraseblocks, and it is split on two MTD partitions of the same
+		size, UBI will reserve 40 eraseblocks when attaching a
+		partition.
+
+		default: 20
+
+		CONFIG_MTD_UBI_FASTMAP
+		Fastmap is a mechanism which allows attaching an UBI device
+		in nearly constant time. Instead of scanning the whole MTD device it
+		only has to locate a checkpoint (called fastmap) on the device.
+		The on-flash fastmap contains all information needed to attach
+		the device. Using fastmap makes only sense on large devices where
+		attaching by scanning takes long. UBI will not automatically install
+		a fastmap on old images, but you can set the UBI parameter
+		CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT to 1 if you want so. Please note
+		that fastmap-enabled images are still usable with UBI implementations
+		without	fastmap support. On typical flash devices the whole fastmap
+		fits into one PEB. UBI will reserve PEBs to hold two fastmaps.
+
+		CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT
+		Set this parameter to enable fastmap automatically on images
+		without a fastmap.
+		default: 0
+
+		CONFIG_MTD_UBI_FM_DEBUG
+		Enable UBI fastmap debug
+		default: 0
+
+- SPL framework
+		CONFIG_SPL
+		Enable building of SPL globally.
+
+		CONFIG_SPL_LDSCRIPT
+		LDSCRIPT for linking the SPL binary.
+
+		CONFIG_SPL_MAX_FOOTPRINT
+		Maximum size in memory allocated to the SPL, BSS included.
+		When defined, the linker checks that the actual memory
+		used by SPL from _start to __bss_end does not exceed it.
+		CONFIG_SPL_MAX_FOOTPRINT and CONFIG_SPL_BSS_MAX_SIZE
+		must not be both defined at the same time.
+
+		CONFIG_SPL_MAX_SIZE
+		Maximum size of the SPL image (text, data, rodata, and
+		linker lists sections), BSS excluded.
+		When defined, the linker checks that the actual size does
+		not exceed it.
+
+		CONFIG_SPL_TEXT_BASE
+		TEXT_BASE for linking the SPL binary.
+
+		CONFIG_SPL_RELOC_TEXT_BASE
+		Address to relocate to.  If unspecified, this is equal to
+		CONFIG_SPL_TEXT_BASE (i.e. no relocation is done).
+
+		CONFIG_SPL_BSS_START_ADDR
+		Link address for the BSS within the SPL binary.
+
+		CONFIG_SPL_BSS_MAX_SIZE
+		Maximum size in memory allocated to the SPL BSS.
+		When defined, the linker checks that the actual memory used
+		by SPL from __bss_start to __bss_end does not exceed it.
+		CONFIG_SPL_MAX_FOOTPRINT and CONFIG_SPL_BSS_MAX_SIZE
+		must not be both defined at the same time.
+
+		CONFIG_SPL_STACK
+		Adress of the start of the stack SPL will use
+
+		CONFIG_SPL_PANIC_ON_RAW_IMAGE
+		When defined, SPL will panic() if the image it has
+		loaded does not have a signature.
+		Defining this is useful when code which loads images
+		in SPL cannot guarantee that absolutely all read errors
+		will be caught.
+		An example is the LPC32XX MLC NAND driver, which will
+		consider that a completely unreadable NAND block is bad,
+		and thus should be skipped silently.
+
+		CONFIG_SPL_RELOC_STACK
+		Adress of the start of the stack SPL will use after
+		relocation.  If unspecified, this is equal to
+		CONFIG_SPL_STACK.
+
+		CONFIG_SYS_SPL_MALLOC_START
+		Starting address of the malloc pool used in SPL.
+		When this option is set the full malloc is used in SPL and
+		it is set up by spl_init() and before that, the simple malloc()
+		can be used if CONFIG_SYS_MALLOC_F is defined.
+
+		CONFIG_SYS_SPL_MALLOC_SIZE
+		The size of the malloc pool used in SPL.
+
+		CONFIG_SPL_OS_BOOT
+		Enable booting directly to an OS from SPL.
+		See also: doc/README.falcon
+
+		CONFIG_SPL_DISPLAY_PRINT
+		For ARM, enable an optional function to print more information
+		about the running system.
+
+		CONFIG_SPL_INIT_MINIMAL
+		Arch init code should be built for a very small image
+
+		CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
+		Partition on the MMC to load U-Boot from when the MMC is being
+		used in raw mode
+
+		CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR
+		Sector to load kernel uImage from when MMC is being
+		used in raw mode (for Falcon mode)
+
+		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
+		CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS
+		Sector and number of sectors to load kernel argument
+		parameters from when MMC is being used in raw mode
+		(for falcon mode)
+
+		CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
+		Partition on the MMC to load U-Boot from when the MMC is being
+		used in fs mode
+
+		CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
+		Filename to read to load U-Boot when reading from filesystem
+
+		CONFIG_SPL_FS_LOAD_KERNEL_NAME
+		Filename to read to load kernel uImage when reading
+		from filesystem (for Falcon mode)
+
+		CONFIG_SPL_FS_LOAD_ARGS_NAME
+		Filename to read to load kernel argument parameters
+		when reading from filesystem (for Falcon mode)
+
+		CONFIG_SPL_MPC83XX_WAIT_FOR_NAND
+		Set this for NAND SPL on PPC mpc83xx targets, so that
+		start.S waits for the rest of the SPL to load before
+		continuing (the hardware starts execution after just
+		loading the first page rather than the full 4K).
+
+		CONFIG_SPL_SKIP_RELOCATE
+		Avoid SPL relocation
+
+		CONFIG_SPL_NAND_BASE
+		Include nand_base.c in the SPL.  Requires
+		CONFIG_SPL_NAND_DRIVERS.
+
+		CONFIG_SPL_NAND_DRIVERS
+		SPL uses normal NAND drivers, not minimal drivers.
+
+		CONFIG_SPL_NAND_IDENT
+		SPL uses the chip ID list to identify the NAND flash.
+		Requires CONFIG_SPL_NAND_BASE.
+
+		CONFIG_SPL_NAND_ECC
+		Include standard software ECC in the SPL
+
+		CONFIG_SPL_NAND_SIMPLE
+		Support for NAND boot using simple NAND drivers that
+		expose the cmd_ctrl() interface.
+
+		CONFIG_SPL_UBI
+		Support for a lightweight UBI (fastmap) scanner and
+		loader
+
+		CONFIG_SPL_NAND_RAW_ONLY
+		Support to boot only raw u-boot.bin images. Use this only
+		if you need to save space.
+
+		CONFIG_SPL_COMMON_INIT_DDR
+		Set for common ddr init with serial presence detect in
+		SPL binary.
+
+		CONFIG_SYS_NAND_5_ADDR_CYCLE, CONFIG_SYS_NAND_PAGE_COUNT,
+		CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE,
+		CONFIG_SYS_NAND_BLOCK_SIZE, CONFIG_SYS_NAND_BAD_BLOCK_POS,
+		CONFIG_SYS_NAND_ECCPOS, CONFIG_SYS_NAND_ECCSIZE,
+		CONFIG_SYS_NAND_ECCBYTES
+		Defines the size and behavior of the NAND that SPL uses
+		to read U-Boot
+
+		CONFIG_SPL_NAND_BOOT
+		Add support NAND boot
+
+		CONFIG_SYS_NAND_U_BOOT_OFFS
+		Location in NAND to read U-Boot from
+
+		CONFIG_SYS_NAND_U_BOOT_DST
+		Location in memory to load U-Boot to
+
+		CONFIG_SYS_NAND_U_BOOT_SIZE
+		Size of image to load
+
+		CONFIG_SYS_NAND_U_BOOT_START
+		Entry point in loaded image to jump to
+
+		CONFIG_SYS_NAND_HW_ECC_OOBFIRST
+		Define this if you need to first read the OOB and then the
+		data. This is used, for example, on davinci platforms.
+
+		CONFIG_SPL_RAM_DEVICE
+		Support for running image already present in ram, in SPL binary
+
+		CONFIG_SPL_PAD_TO
+		Image offset to which the SPL should be padded before appending
+		the SPL payload. By default, this is defined as
+		CONFIG_SPL_MAX_SIZE, or 0 if CONFIG_SPL_MAX_SIZE is undefined.
+		CONFIG_SPL_PAD_TO must be either 0, meaning to append the SPL
+		payload without any padding, or >= CONFIG_SPL_MAX_SIZE.
+
+		CONFIG_SPL_TARGET
+		Final target image containing SPL and payload.  Some SPLs
+		use an arch-specific makefile fragment instead, for
+		example if more than one image needs to be produced.
+
+		CONFIG_SPL_FIT_PRINT
+		Printing information about a FIT image adds quite a bit of
+		code to SPL. So this is normally disabled in SPL. Use this
+		option to re-enable it. This will affect the output of the
+		bootm command when booting a FIT image.
+
+- TPL framework
+		CONFIG_TPL
+		Enable building of TPL globally.
+
+		CONFIG_TPL_PAD_TO
+		Image offset to which the TPL should be padded before appending
+		the TPL payload. By default, this is defined as
+		CONFIG_SPL_MAX_SIZE, or 0 if CONFIG_SPL_MAX_SIZE is undefined.
+		CONFIG_SPL_PAD_TO must be either 0, meaning to append the SPL
+		payload without any padding, or >= CONFIG_SPL_MAX_SIZE.
+
+- Interrupt support (PPC):
+
+		There are common interrupt_init() and timer_interrupt()
+		for all PPC archs. interrupt_init() calls interrupt_init_cpu()
+		for CPU specific initialization. interrupt_init_cpu()
+		should set decrementer_count to appropriate value. If
+		CPU resets decrementer automatically after interrupt
+		(ppc4xx) it should set decrementer_count to zero.
+		timer_interrupt() calls timer_interrupt_cpu() for CPU
+		specific handling. If board has watchdog / status_led
+		/ other_activity_monitor it works automatically from
+		general timer_interrupt().
+
+
+Board initialization settings:
+------------------------------
+
+During Initialization u-boot calls a number of board specific functions
+to allow the preparation of board specific prerequisites, e.g. pin setup
+before drivers are initialized. To enable these callbacks the
+following configuration macros have to be defined. Currently this is
+architecture specific, so please check arch/your_architecture/lib/board.c
+typically in board_init_f() and board_init_r().
+
+- CONFIG_BOARD_EARLY_INIT_F: Call board_early_init_f()
+- CONFIG_BOARD_EARLY_INIT_R: Call board_early_init_r()
+- CONFIG_BOARD_LATE_INIT: Call board_late_init()
+- CONFIG_BOARD_POSTCLK_INIT: Call board_postclk_init()
+
+Configuration Settings:
+-----------------------
+
+- CONFIG_SYS_SUPPORT_64BIT_DATA: Defined automatically if compiled as 64-bit.
+		Optionally it can be defined to support 64-bit memory commands.
+
+- CONFIG_SYS_LONGHELP: Defined when you want long help messages included;
+		undefine this when you're short of memory.
+
+- CONFIG_SYS_HELP_CMD_WIDTH: Defined when you want to override the default
+		width of the commands listed in the 'help' command output.
+
+- CONFIG_SYS_PROMPT:	This is what U-Boot prints on the console to
+		prompt for user input.
+
+- CONFIG_SYS_CBSIZE:	Buffer size for input from the Console
+
+- CONFIG_SYS_PBSIZE:	Buffer size for Console output
+
+- CONFIG_SYS_MAXARGS:	max. Number of arguments accepted for monitor commands
+
+- CONFIG_SYS_BARGSIZE: Buffer size for Boot Arguments which are passed to
+		the application (usually a Linux kernel) when it is
+		booted
+
+- CONFIG_SYS_BAUDRATE_TABLE:
+		List of legal baudrate settings for this board.
+
+- CONFIG_SYS_MEMTEST_START, CONFIG_SYS_MEMTEST_END:
+		Begin and End addresses of the area used by the
+		simple memory test.
+
+- CONFIG_SYS_MEMTEST_SCRATCH:
+		Scratch address used by the alternate memory test
+		You only need to set this if address zero isn't writeable
+
+- CONFIG_SYS_MEM_RESERVE_SECURE
+		Only implemented for ARMv8 for now.
+		If defined, the size of CONFIG_SYS_MEM_RESERVE_SECURE memory
+		is substracted from total RAM and won't be reported to OS.
+		This memory can be used as secure memory. A variable
+		gd->arch.secure_ram is used to track the location. In systems
+		the RAM base is not zero, or RAM is divided into banks,
+		this variable needs to be recalcuated to get the address.
+
+- CONFIG_SYS_MEM_TOP_HIDE:
+		If CONFIG_SYS_MEM_TOP_HIDE is defined in the board config header,
+		this specified memory area will get subtracted from the top
+		(end) of RAM and won't get "touched" at all by U-Boot. By
+		fixing up gd->ram_size the Linux kernel should gets passed
+		the now "corrected" memory size and won't touch it either.
+		This should work for arch/ppc and arch/powerpc. Only Linux
+		board ports in arch/powerpc with bootwrapper support that
+		recalculate the memory size from the SDRAM controller setup
+		will have to get fixed in Linux additionally.
+
+		This option can be used as a workaround for the 440EPx/GRx
+		CHIP 11 errata where the last 256 bytes in SDRAM shouldn't
+		be touched.
+
+		WARNING: Please make sure that this value is a multiple of
+		the Linux page size (normally 4k). If this is not the case,
+		then the end address of the Linux memory will be located at a
+		non page size aligned address and this could cause major
+		problems.
+
+- CONFIG_SYS_LOADS_BAUD_CHANGE:
+		Enable temporary baudrate change while serial download
+
+- CONFIG_SYS_SDRAM_BASE:
+		Physical start address of SDRAM. _Must_ be 0 here.
+
+- CONFIG_SYS_FLASH_BASE:
+		Physical start address of Flash memory.
+
+- CONFIG_SYS_MONITOR_BASE:
+		Physical start address of boot monitor code (set by
+		make config files to be same as the text base address
+		(CONFIG_SYS_TEXT_BASE) used when linking) - same as
+		CONFIG_SYS_FLASH_BASE when booting from flash.
+
+- CONFIG_SYS_MONITOR_LEN:
+		Size of memory reserved for monitor code, used to
+		determine _at_compile_time_ (!) if the environment is
+		embedded within the U-Boot image, or in a separate
+		flash sector.
+
+- CONFIG_SYS_MALLOC_LEN:
+		Size of DRAM reserved for malloc() use.
+
+- CONFIG_SYS_MALLOC_F_LEN
+		Size of the malloc() pool for use before relocation. If
+		this is defined, then a very simple malloc() implementation
+		will become available before relocation. The address is just
+		below the global data, and the stack is moved down to make
+		space.
+
+		This feature allocates regions with increasing addresses
+		within the region. calloc() is supported, but realloc()
+		is not available. free() is supported but does nothing.
+		The memory will be freed (or in fact just forgotten) when
+		U-Boot relocates itself.
+
+- CONFIG_SYS_MALLOC_SIMPLE
+		Provides a simple and small malloc() and calloc() for those
+		boards which do not use the full malloc in SPL (which is
+		enabled with CONFIG_SYS_SPL_MALLOC_START).
+
+- CONFIG_SYS_NONCACHED_MEMORY:
+		Size of non-cached memory area. This area of memory will be
+		typically located right below the malloc() area and mapped
+		uncached in the MMU. This is useful for drivers that would
+		otherwise require a lot of explicit cache maintenance. For
+		some drivers it's also impossible to properly maintain the
+		cache. For example if the regions that need to be flushed
+		are not a multiple of the cache-line size, *and* padding
+		cannot be allocated between the regions to align them (i.e.
+		if the HW requires a contiguous array of regions, and the
+		size of each region is not cache-aligned), then a flush of
+		one region may result in overwriting data that hardware has
+		written to another region in the same cache-line. This can
+		happen for example in network drivers where descriptors for
+		buffers are typically smaller than the CPU cache-line (e.g.
+		16 bytes vs. 32 or 64 bytes).
+
+		Non-cached memory is only supported on 32-bit ARM at present.
+
+- CONFIG_SYS_BOOTM_LEN:
+		Normally compressed uImages are limited to an
+		uncompressed size of 8 MBytes. If this is not enough,
+		you can define CONFIG_SYS_BOOTM_LEN in your board config file
+		to adjust this setting to your needs.
+
+- CONFIG_SYS_BOOTMAPSZ:
+		Maximum size of memory mapped by the startup code of
+		the Linux kernel; all data that must be processed by
+		the Linux kernel (bd_info, boot arguments, FDT blob if
+		used) must be put below this limit, unless "bootm_low"
+		environment variable is defined and non-zero. In such case
+		all data for the Linux kernel must be between "bootm_low"
+		and "bootm_low" + CONFIG_SYS_BOOTMAPSZ.	 The environment
+		variable "bootm_mapsize" will override the value of
+		CONFIG_SYS_BOOTMAPSZ.  If CONFIG_SYS_BOOTMAPSZ is undefined,
+		then the value in "bootm_size" will be used instead.
+
+- CONFIG_SYS_BOOT_RAMDISK_HIGH:
+		Enable initrd_high functionality.  If defined then the
+		initrd_high feature is enabled and the bootm ramdisk subcommand
+		is enabled.
+
+- CONFIG_SYS_BOOT_GET_CMDLINE:
+		Enables allocating and saving kernel cmdline in space between
+		"bootm_low" and "bootm_low" + BOOTMAPSZ.
+
+- CONFIG_SYS_BOOT_GET_KBD:
+		Enables allocating and saving a kernel copy of the bd_info in
+		space between "bootm_low" and "bootm_low" + BOOTMAPSZ.
+
+- CONFIG_SYS_MAX_FLASH_BANKS:
+		Max number of Flash memory banks
+
+- CONFIG_SYS_MAX_FLASH_SECT:
+		Max number of sectors on a Flash chip
+
+- CONFIG_SYS_FLASH_ERASE_TOUT:
+		Timeout for Flash erase operations (in ms)
+
+- CONFIG_SYS_FLASH_WRITE_TOUT:
+		Timeout for Flash write operations (in ms)
+
+- CONFIG_SYS_FLASH_LOCK_TOUT
+		Timeout for Flash set sector lock bit operation (in ms)
+
+- CONFIG_SYS_FLASH_UNLOCK_TOUT
+		Timeout for Flash clear lock bits operation (in ms)
+
+- CONFIG_SYS_FLASH_PROTECTION
+		If defined, hardware flash sectors protection is used
+		instead of U-Boot software protection.
+
+- CONFIG_SYS_DIRECT_FLASH_TFTP:
+
+		Enable TFTP transfers directly to flash memory;
+		without this option such a download has to be
+		performed in two steps: (1) download to RAM, and (2)
+		copy from RAM to flash.
+
+		The two-step approach is usually more reliable, since
+		you can check if the download worked before you erase
+		the flash, but in some situations (when system RAM is
+		too limited to allow for a temporary copy of the
+		downloaded image) this option may be very useful.
+
+- CONFIG_SYS_FLASH_CFI:
+		Define if the flash driver uses extra elements in the
+		common flash structure for storing flash geometry.
+
+- CONFIG_FLASH_CFI_DRIVER
+		This option also enables the building of the cfi_flash driver
+		in the drivers directory
+
+- CONFIG_FLASH_CFI_MTD
+		This option enables the building of the cfi_mtd driver
+		in the drivers directory. The driver exports CFI flash
+		to the MTD layer.
+
+- CONFIG_SYS_FLASH_USE_BUFFER_WRITE
+		Use buffered writes to flash.
+
+- CONFIG_FLASH_SPANSION_S29WS_N
+		s29ws-n MirrorBit flash has non-standard addresses for buffered
+		write commands.
+
+- CONFIG_SYS_FLASH_QUIET_TEST
+		If this option is defined, the common CFI flash doesn't
+		print it's warning upon not recognized FLASH banks. This
+		is useful, if some of the configured banks are only
+		optionally available.
+
+- CONFIG_FLASH_SHOW_PROGRESS
+		If defined (must be an integer), print out countdown
+		digits and dots.  Recommended value: 45 (9..1) for 80
+		column displays, 15 (3..1) for 40 column displays.
+
+- CONFIG_FLASH_VERIFY
+		If defined, the content of the flash (destination) is compared
+		against the source after the write operation. An error message
+		will be printed when the contents are not identical.
+		Please note that this option is useless in nearly all cases,
+		since such flash programming errors usually are detected earlier
+		while unprotecting/erasing/programming. Please only enable
+		this option if you really know what you are doing.
+
+- CONFIG_SYS_RX_ETH_BUFFER:
+		Defines the number of Ethernet receive buffers. On some
+		Ethernet controllers it is recommended to set this value
+		to 8 or even higher (EEPRO100 or 405 EMAC), since all
+		buffers can be full shortly after enabling the interface
+		on high Ethernet traffic.
+		Defaults to 4 if not defined.
+
+- CONFIG_ENV_MAX_ENTRIES
+
+	Maximum number of entries in the hash table that is used
+	internally to store the environment settings. The default
+	setting is supposed to be generous and should work in most
+	cases. This setting can be used to tune behaviour; see
+	lib/hashtable.c for details.
+
+- CONFIG_ENV_FLAGS_LIST_DEFAULT
+- CONFIG_ENV_FLAGS_LIST_STATIC
+	Enable validation of the values given to environment variables when
+	calling env set.  Variables can be restricted to only decimal,
+	hexadecimal, or boolean.  If CONFIG_CMD_NET is also defined,
+	the variables can also be restricted to IP address or MAC address.
+
+	The format of the list is:
+		type_attribute = [s|d|x|b|i|m]
+		access_attribute = [a|r|o|c]
+		attributes = type_attribute[access_attribute]
+		entry = variable_name[:attributes]
+		list = entry[,list]
+
+	The type attributes are:
+		s - String (default)
+		d - Decimal
+		x - Hexadecimal
+		b - Boolean ([1yYtT|0nNfF])
+		i - IP address
+		m - MAC address
+
+	The access attributes are:
+		a - Any (default)
+		r - Read-only
+		o - Write-once
+		c - Change-default
+
+	- CONFIG_ENV_FLAGS_LIST_DEFAULT
+		Define this to a list (string) to define the ".flags"
+		environment variable in the default or embedded environment.
+
+	- CONFIG_ENV_FLAGS_LIST_STATIC
+		Define this to a list (string) to define validation that
+		should be done if an entry is not found in the ".flags"
+		environment variable.  To override a setting in the static
+		list, simply add an entry for the same variable name to the
+		".flags" variable.
+
+	If CONFIG_REGEX is defined, the variable_name above is evaluated as a
+	regular expression. This allows multiple variables to define the same
+	flags without explicitly listing them for each variable.
+
+- CONFIG_ENV_ACCESS_IGNORE_FORCE
+	If defined, don't allow the -f switch to env set override variable
+	access flags.
+
+The following definitions that deal with the placement and management
+of environment data (variable area); in general, we support the
+following configurations:
+
+- CONFIG_BUILD_ENVCRC:
+
+	Builds up envcrc with the target environment so that external utils
+	may easily extract it and embed it in final U-Boot images.
+
+BE CAREFUL! The first access to the environment happens quite early
+in U-Boot initialization (when we try to get the setting of for the
+console baudrate). You *MUST* have mapped your NVRAM area then, or
+U-Boot will hang.
+
+Please note that even with NVRAM we still use a copy of the
+environment in RAM: we could work on NVRAM directly, but we want to
+keep settings there always unmodified except somebody uses "saveenv"
+to save the current settings.
+
+BE CAREFUL! For some special cases, the local device can not use
+"saveenv" command. For example, the local device will get the
+environment stored in a remote NOR flash by SRIO or PCIE link,
+but it can not erase, write this NOR flash by SRIO or PCIE interface.
+
+- CONFIG_NAND_ENV_DST
+
+	Defines address in RAM to which the nand_spl code should copy the
+	environment. If redundant environment is used, it will be copied to
+	CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE.
+
+Please note that the environment is read-only until the monitor
+has been relocated to RAM and a RAM copy of the environment has been
+created; also, when using EEPROM you will have to use env_get_f()
+until then to read environment variables.
+
+The environment is protected by a CRC32 checksum. Before the monitor
+is relocated into RAM, as a result of a bad CRC you will be working
+with the compiled-in default environment - *silently*!!! [This is
+necessary, because the first environment variable we need is the
+"baudrate" setting for the console - if we have a bad CRC, we don't
+have any device yet where we could complain.]
+
+Note: once the monitor has been relocated, then it will complain if
+the default environment is used; a new CRC is computed as soon as you
+use the "saveenv" command to store a valid environment.
+
+- CONFIG_SYS_FAULT_ECHO_LINK_DOWN:
+		Echo the inverted Ethernet link state to the fault LED.
+
+		Note: If this option is active, then CONFIG_SYS_FAULT_MII_ADDR
+		      also needs to be defined.
+
+- CONFIG_SYS_FAULT_MII_ADDR:
+		MII address of the PHY to check for the Ethernet link state.
+
+- CONFIG_NS16550_MIN_FUNCTIONS:
+		Define this if you desire to only have use of the NS16550_init
+		and NS16550_putc functions for the serial driver located at
+		drivers/serial/ns16550.c.  This option is useful for saving
+		space for already greatly restricted images, including but not
+		limited to NAND_SPL configurations.
+
+- CONFIG_DISPLAY_BOARDINFO
+		Display information about the board that U-Boot is running on
+		when U-Boot starts up. The board function checkboard() is called
+		to do this.
+
+- CONFIG_DISPLAY_BOARDINFO_LATE
+		Similar to the previous option, but display this information
+		later, once stdio is running and output goes to the LCD, if
+		present.
+
+- CONFIG_BOARD_SIZE_LIMIT:
+		Maximum size of the U-Boot image. When defined, the
+		build system checks that the actual size does not
+		exceed it.
+
+Low Level (hardware related) configuration options:
+---------------------------------------------------
+
+- CONFIG_SYS_CACHELINE_SIZE:
+		Cache Line Size of the CPU.
+
+- CONFIG_SYS_CCSRBAR_DEFAULT:
+		Default (power-on reset) physical address of CCSR on Freescale
+		PowerPC SOCs.
+
+- CONFIG_SYS_CCSRBAR:
+		Virtual address of CCSR.  On a 32-bit build, this is typically
+		the same value as CONFIG_SYS_CCSRBAR_DEFAULT.
+
+- CONFIG_SYS_CCSRBAR_PHYS:
+		Physical address of CCSR.  CCSR can be relocated to a new
+		physical address, if desired.  In this case, this macro should
+		be set to that address.	 Otherwise, it should be set to the
+		same value as CONFIG_SYS_CCSRBAR_DEFAULT.  For example, CCSR
+		is typically relocated on 36-bit builds.  It is recommended
+		that this macro be defined via the _HIGH and _LOW macros:
+
+		#define CONFIG_SYS_CCSRBAR_PHYS ((CONFIG_SYS_CCSRBAR_PHYS_HIGH
+			* 1ull) << 32 | CONFIG_SYS_CCSRBAR_PHYS_LOW)
+
+- CONFIG_SYS_CCSRBAR_PHYS_HIGH:
+		Bits 33-36 of CONFIG_SYS_CCSRBAR_PHYS.	This value is typically
+		either 0 (32-bit build) or 0xF (36-bit build).	This macro is
+		used in assembly code, so it must not contain typecasts or
+		integer size suffixes (e.g. "ULL").
+
+- CONFIG_SYS_CCSRBAR_PHYS_LOW:
+		Lower 32-bits of CONFIG_SYS_CCSRBAR_PHYS.  This macro is
+		used in assembly code, so it must not contain typecasts or
+		integer size suffixes (e.g. "ULL").
+
+- CONFIG_SYS_CCSR_DO_NOT_RELOCATE:
+		If this macro is defined, then CONFIG_SYS_CCSRBAR_PHYS will be
+		forced to a value that ensures that CCSR is not relocated.
+
+- Floppy Disk Support:
+		CONFIG_SYS_FDC_DRIVE_NUMBER
+
+		the default drive number (default value 0)
+
+		CONFIG_SYS_ISA_IO_STRIDE
+
+		defines the spacing between FDC chipset registers
+		(default value 1)
+
+		CONFIG_SYS_ISA_IO_OFFSET
+
+		defines the offset of register from address. It
+		depends on which part of the data bus is connected to
+		the FDC chipset. (default value 0)
+
+		If CONFIG_SYS_ISA_IO_STRIDE CONFIG_SYS_ISA_IO_OFFSET and
+		CONFIG_SYS_FDC_DRIVE_NUMBER are undefined, they take their
+		default value.
+
+		if CONFIG_SYS_FDC_HW_INIT is defined, then the function
+		fdc_hw_init() is called at the beginning of the FDC
+		setup. fdc_hw_init() must be provided by the board
+		source code. It is used to make hardware-dependent
+		initializations.
+
+- CONFIG_IDE_AHB:
+		Most IDE controllers were designed to be connected with PCI
+		interface. Only few of them were designed for AHB interface.
+		When software is doing ATA command and data transfer to
+		IDE devices through IDE-AHB controller, some additional
+		registers accessing to these kind of IDE-AHB controller
+		is required.
+
+- CONFIG_SYS_IMMR:	Physical address of the Internal Memory.
+		DO NOT CHANGE unless you know exactly what you're
+		doing! (11-4) [MPC8xx systems only]
+
+- CONFIG_SYS_INIT_RAM_ADDR:
+
+		Start address of memory area that can be used for
+		initial data and stack; please note that this must be
+		writable memory that is working WITHOUT special
+		initialization, i. e. you CANNOT use normal RAM which
+		will become available only after programming the
+		memory controller and running certain initialization
+		sequences.
+
+		U-Boot uses the following memory types:
+		- MPC8xx: IMMR (internal memory of the CPU)
+
+- CONFIG_SYS_GBL_DATA_OFFSET:
+
+		Offset of the initial data structure in the memory
+		area defined by CONFIG_SYS_INIT_RAM_ADDR. Usually
+		CONFIG_SYS_GBL_DATA_OFFSET is chosen such that the initial
+		data is located at the end of the available space
+		(sometimes written as (CONFIG_SYS_INIT_RAM_SIZE -
+		GENERATED_GBL_DATA_SIZE), and the initial stack is just
+		below that area (growing from (CONFIG_SYS_INIT_RAM_ADDR +
+		CONFIG_SYS_GBL_DATA_OFFSET) downward.
+
+	Note:
+		On the MPC824X (or other systems that use the data
+		cache for initial memory) the address chosen for
+		CONFIG_SYS_INIT_RAM_ADDR is basically arbitrary - it must
+		point to an otherwise UNUSED address space between
+		the top of RAM and the start of the PCI space.
+
+- CONFIG_SYS_SCCR:	System Clock and reset Control Register (15-27)
+
+- CONFIG_SYS_OR_TIMING_SDRAM:
+		SDRAM timing
+
+- CONFIG_SYS_MAMR_PTA:
+		periodic timer for refresh
+
+- FLASH_BASE0_PRELIM, FLASH_BASE1_PRELIM, CONFIG_SYS_REMAP_OR_AM,
+  CONFIG_SYS_PRELIM_OR_AM, CONFIG_SYS_OR_TIMING_FLASH, CONFIG_SYS_OR0_REMAP,
+  CONFIG_SYS_OR0_PRELIM, CONFIG_SYS_BR0_PRELIM, CONFIG_SYS_OR1_REMAP, CONFIG_SYS_OR1_PRELIM,
+  CONFIG_SYS_BR1_PRELIM:
+		Memory Controller Definitions: BR0/1 and OR0/1 (FLASH)
+
+- SDRAM_BASE2_PRELIM, SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE,
+  CONFIG_SYS_OR_TIMING_SDRAM, CONFIG_SYS_OR2_PRELIM, CONFIG_SYS_BR2_PRELIM,
+  CONFIG_SYS_OR3_PRELIM, CONFIG_SYS_BR3_PRELIM:
+		Memory Controller Definitions: BR2/3 and OR2/3 (SDRAM)
+
+- CONFIG_PCI_ENUM_ONLY
+		Only scan through and get the devices on the buses.
+		Don't do any setup work, presumably because someone or
+		something has already done it, and we don't need to do it
+		a second time.	Useful for platforms that are pre-booted
+		by coreboot or similar.
+
+- CONFIG_PCI_INDIRECT_BRIDGE:
+		Enable support for indirect PCI bridges.
+
+- CONFIG_SYS_SRIO:
+		Chip has SRIO or not
+
+- CONFIG_SRIO1:
+		Board has SRIO 1 port available
+
+- CONFIG_SRIO2:
+		Board has SRIO 2 port available
+
+- CONFIG_SRIO_PCIE_BOOT_MASTER
+		Board can support master function for Boot from SRIO and PCIE
+
+- CONFIG_SYS_SRIOn_MEM_VIRT:
+		Virtual Address of SRIO port 'n' memory region
+
+- CONFIG_SYS_SRIOn_MEM_PHYS:
+		Physical Address of SRIO port 'n' memory region
+
+- CONFIG_SYS_SRIOn_MEM_SIZE:
+		Size of SRIO port 'n' memory region
+
+- CONFIG_SYS_NAND_BUSWIDTH_16BIT
+		Defined to tell the NAND controller that the NAND chip is using
+		a 16 bit bus.
+		Not all NAND drivers use this symbol.
+		Example of drivers that use it:
+		- drivers/mtd/nand/raw/ndfc.c
+		- drivers/mtd/nand/raw/mxc_nand.c
+
+- CONFIG_SYS_NDFC_EBC0_CFG
+		Sets the EBC0_CFG register for the NDFC. If not defined
+		a default value will be used.
+
+- CONFIG_SPD_EEPROM
+		Get DDR timing information from an I2C EEPROM. Common
+		with pluggable memory modules such as SODIMMs
+
+  SPD_EEPROM_ADDRESS
+		I2C address of the SPD EEPROM
+
+- CONFIG_SYS_SPD_BUS_NUM
+		If SPD EEPROM is on an I2C bus other than the first
+		one, specify here. Note that the value must resolve
+		to something your driver can deal with.
+
+- CONFIG_SYS_DDR_RAW_TIMING
+		Get DDR timing information from other than SPD. Common with
+		soldered DDR chips onboard without SPD. DDR raw timing
+		parameters are extracted from datasheet and hard-coded into
+		header files or board specific files.
+
+- CONFIG_FSL_DDR_INTERACTIVE
+		Enable interactive DDR debugging. See doc/README.fsl-ddr.
+
+- CONFIG_FSL_DDR_SYNC_REFRESH
+		Enable sync of refresh for multiple controllers.
+
+- CONFIG_FSL_DDR_BIST
+		Enable built-in memory test for Freescale DDR controllers.
+
+- CONFIG_SYS_83XX_DDR_USES_CS0
+		Only for 83xx systems. If specified, then DDR should
+		be configured using CS0 and CS1 instead of CS2 and CS3.
+
+- CONFIG_RMII
+		Enable RMII mode for all FECs.
+		Note that this is a global option, we can't
+		have one FEC in standard MII mode and another in RMII mode.
+
+- CONFIG_CRC32_VERIFY
+		Add a verify option to the crc32 command.
+		The syntax is:
+
+		=> crc32 -v <address> <count> <crc32>
+
+		Where address/count indicate a memory area
+		and crc32 is the correct crc32 which the
+		area should have.
+
+- CONFIG_LOOPW
+		Add the "loopw" memory command. This only takes effect if
+		the memory commands are activated globally (CONFIG_CMD_MEMORY).
+
+- CONFIG_MX_CYCLIC
+		Add the "mdc" and "mwc" memory commands. These are cyclic
+		"md/mw" commands.
+		Examples:
+
+		=> mdc.b 10 4 500
+		This command will print 4 bytes (10,11,12,13) each 500 ms.
+
+		=> mwc.l 100 12345678 10
+		This command will write 12345678 to address 100 all 10 ms.
+
+		This only takes effect if the memory commands are activated
+		globally (CONFIG_CMD_MEMORY).
+
+- CONFIG_SKIP_LOWLEVEL_INIT
+		[ARM, NDS32, MIPS, RISC-V only] If this variable is defined, then certain
+		low level initializations (like setting up the memory
+		controller) are omitted and/or U-Boot does not
+		relocate itself into RAM.
+
+		Normally this variable MUST NOT be defined. The only
+		exception is when U-Boot is loaded (to RAM) by some
+		other boot loader or by a debugger which performs
+		these initializations itself.
+
+- CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+		[ARM926EJ-S only] This allows just the call to lowlevel_init()
+		to be skipped. The normal CP15 init (such as enabling the
+		instruction cache) is still performed.
+
+- CONFIG_SPL_BUILD
+		Modifies the behaviour of start.S when compiling a loader
+		that is executed before the actual U-Boot. E.g. when
+		compiling a NAND SPL.
+
+- CONFIG_TPL_BUILD
+		Modifies the behaviour of start.S  when compiling a loader
+		that is executed after the SPL and before the actual U-Boot.
+		It is loaded by the SPL.
+
+- CONFIG_SYS_MPC85XX_NO_RESETVEC
+		Only for 85xx systems. If this variable is specified, the section
+		.resetvec is not kept and the section .bootpg is placed in the
+		previous 4k of the .text section.
+
+- CONFIG_ARCH_MAP_SYSMEM
+		Generally U-Boot (and in particular the md command) uses
+		effective address. It is therefore not necessary to regard
+		U-Boot address as virtual addresses that need to be translated
+		to physical addresses. However, sandbox requires this, since
+		it maintains its own little RAM buffer which contains all
+		addressable memory. This option causes some memory accesses
+		to be mapped through map_sysmem() / unmap_sysmem().
+
+- CONFIG_X86_RESET_VECTOR
+		If defined, the x86 reset vector code is included. This is not
+		needed when U-Boot is running from Coreboot.
+
+- CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
+		Option to disable subpage write in NAND driver
+		driver that uses this:
+		drivers/mtd/nand/raw/davinci_nand.c
+
+Freescale QE/FMAN Firmware Support:
+-----------------------------------
+
+The Freescale QUICCEngine (QE) and Frame Manager (FMAN) both support the
+loading of "firmware", which is encoded in the QE firmware binary format.
+This firmware often needs to be loaded during U-Boot booting, so macros
+are used to identify the storage device (NOR flash, SPI, etc) and the address
+within that device.
+
+- CONFIG_SYS_FMAN_FW_ADDR
+	The address in the storage device where the FMAN microcode is located.  The
+	meaning of this address depends on which CONFIG_SYS_QE_FW_IN_xxx macro
+	is also specified.
+
+- CONFIG_SYS_QE_FW_ADDR
+	The address in the storage device where the QE microcode is located.  The
+	meaning of this address depends on which CONFIG_SYS_QE_FW_IN_xxx macro
+	is also specified.
+
+- CONFIG_SYS_QE_FMAN_FW_LENGTH
+	The maximum possible size of the firmware.  The firmware binary format
+	has a field that specifies the actual size of the firmware, but it
+	might not be possible to read any part of the firmware unless some
+	local storage is allocated to hold the entire firmware first.
+
+- CONFIG_SYS_QE_FMAN_FW_IN_NOR
+	Specifies that QE/FMAN firmware is located in NOR flash, mapped as
+	normal addressable memory via the LBC.  CONFIG_SYS_FMAN_FW_ADDR is the
+	virtual address in NOR flash.
+
+- CONFIG_SYS_QE_FMAN_FW_IN_NAND
+	Specifies that QE/FMAN firmware is located in NAND flash.
+	CONFIG_SYS_FMAN_FW_ADDR is the offset within NAND flash.
+
+- CONFIG_SYS_QE_FMAN_FW_IN_MMC
+	Specifies that QE/FMAN firmware is located on the primary SD/MMC
+	device.  CONFIG_SYS_FMAN_FW_ADDR is the byte offset on that device.
+
+- CONFIG_SYS_QE_FMAN_FW_IN_REMOTE
+	Specifies that QE/FMAN firmware is located in the remote (master)
+	memory space.	CONFIG_SYS_FMAN_FW_ADDR is a virtual address which
+	can be mapped from slave TLB->slave LAW->slave SRIO or PCIE outbound
+	window->master inbound window->master LAW->the ucode address in
+	master's memory space.
+
+Freescale Layerscape Management Complex Firmware Support:
+---------------------------------------------------------
+The Freescale Layerscape Management Complex (MC) supports the loading of
+"firmware".
+This firmware often needs to be loaded during U-Boot booting, so macros
+are used to identify the storage device (NOR flash, SPI, etc) and the address
+within that device.
+
+- CONFIG_FSL_MC_ENET
+	Enable the MC driver for Layerscape SoCs.
+
+Freescale Layerscape Debug Server Support:
+-------------------------------------------
+The Freescale Layerscape Debug Server Support supports the loading of
+"Debug Server firmware" and triggering SP boot-rom.
+This firmware often needs to be loaded during U-Boot booting.
+
+- CONFIG_SYS_MC_RSV_MEM_ALIGN
+	Define alignment of reserved memory MC requires
+
+Reproducible builds
+-------------------
+
+In order to achieve reproducible builds, timestamps used in the U-Boot build
+process have to be set to a fixed value.
+
+This is done using the SOURCE_DATE_EPOCH environment variable.
+SOURCE_DATE_EPOCH is to be set on the build host's shell, not as a configuration
+option for U-Boot or an environment variable in U-Boot.
+
+SOURCE_DATE_EPOCH should be set to a number of seconds since the epoch, in UTC.
+
+Building the Software:
+======================
+
+Building U-Boot has been tested in several native build environments
+and in many different cross environments. Of course we cannot support
+all possibly existing versions of cross development tools in all
+(potentially obsolete) versions. In case of tool chain problems we
+recommend to use the ELDK (see http://www.denx.de/wiki/DULG/ELDK)
+which is extensively used to build and test U-Boot.
+
+If you are not using a native environment, it is assumed that you
+have GNU cross compiling tools available in your path. In this case,
+you must set the environment variable CROSS_COMPILE in your shell.
+Note that no changes to the Makefile or any other source files are
+necessary. For example using the ELDK on a 4xx CPU, please enter:
+
+	$ CROSS_COMPILE=ppc_4xx-
+	$ export CROSS_COMPILE
+
+Note: If you wish to generate Windows versions of the utilities in
+      the tools directory you can use the MinGW toolchain
+      (http://www.mingw.org).  Set your HOST tools to the MinGW
+      toolchain and execute 'make tools'.  For example:
+
+       $ make HOSTCC=i586-mingw32msvc-gcc HOSTSTRIP=i586-mingw32msvc-strip tools
+
+      Binaries such as tools/mkimage.exe will be created which can
+      be executed on computers running Windows.
+
+U-Boot is intended to be simple to build. After installing the
+sources you must configure U-Boot for one specific board type. This
+is done by typing:
+
+	make NAME_defconfig
+
+where "NAME_defconfig" is the name of one of the existing configu-
+rations; see boards.cfg for supported names.
+
+Note: for some board special configuration names may exist; check if
+      additional information is available from the board vendor; for
+      instance, the TQM823L systems are available without (standard)
+      or with LCD support. You can select such additional "features"
+      when choosing the configuration, i. e.
+
+      make TQM823L_defconfig
+	- will configure for a plain TQM823L, i. e. no LCD support
+
+      make TQM823L_LCD_defconfig
+	- will configure for a TQM823L with U-Boot console on LCD
+
+      etc.
+
+
+Finally, type "make all", and you should get some working U-Boot
+images ready for download to / installation on your system:
+
+- "u-boot.bin" is a raw binary image
+- "u-boot" is an image in ELF binary format
+- "u-boot.srec" is in Motorola S-Record format
+
+By default the build is performed locally and the objects are saved
+in the source directory. One of the two methods can be used to change
+this behavior and build U-Boot to some external directory:
+
+1. Add O= to the make command line invocations:
+
+	make O=/tmp/build distclean
+	make O=/tmp/build NAME_defconfig
+	make O=/tmp/build all
+
+2. Set environment variable KBUILD_OUTPUT to point to the desired location:
+
+	export KBUILD_OUTPUT=/tmp/build
+	make distclean
+	make NAME_defconfig
+	make all
+
+Note that the command line "O=" setting overrides the KBUILD_OUTPUT environment
+variable.
+
+User specific CPPFLAGS, AFLAGS and CFLAGS can be passed to the compiler by
+setting the according environment variables KCPPFLAGS, KAFLAGS and KCFLAGS.
+For example to treat all compiler warnings as errors:
+
+	make KCFLAGS=-Werror
+
+Please be aware that the Makefiles assume you are using GNU make, so
+for instance on NetBSD you might need to use "gmake" instead of
+native "make".
+
+
+If the system board that you have is not listed, then you will need
+to port U-Boot to your hardware platform. To do this, follow these
+steps:
+
+1.  Create a new directory to hold your board specific code. Add any
+    files you need. In your board directory, you will need at least
+    the "Makefile" and a "<board>.c".
+2.  Create a new configuration file "include/configs/<board>.h" for
+    your board.
+3.  If you're porting U-Boot to a new CPU, then also create a new
+    directory to hold your CPU specific code. Add any files you need.
+4.  Run "make <board>_defconfig" with your new name.
+5.  Type "make", and you should get a working "u-boot.srec" file
+    to be installed on your target system.
+6.  Debug and solve any problems that might arise.
+    [Of course, this last step is much harder than it sounds.]
+
+
+Testing of U-Boot Modifications, Ports to New Hardware, etc.:
+==============================================================
+
+If you have modified U-Boot sources (for instance added a new board
+or support for new devices, a new CPU, etc.) you are expected to
+provide feedback to the other developers. The feedback normally takes
+the form of a "patch", i. e. a context diff against a certain (latest
+official or latest in the git repository) version of U-Boot sources.
+
+But before you submit such a patch, please verify that your modifi-
+cation did not break existing code. At least make sure that *ALL* of
+the supported boards compile WITHOUT ANY compiler warnings. To do so,
+just run the buildman script (tools/buildman/buildman), which will
+configure and build U-Boot for ALL supported system. Be warned, this
+will take a while. Please see the buildman README, or run 'buildman -H'
+for documentation.
+
+
+See also "U-Boot Porting Guide" below.
+
+
+Monitor Commands - Overview:
+============================
+
+go	- start application at address 'addr'
+run	- run commands in an environment variable
+bootm	- boot application image from memory
+bootp	- boot image via network using BootP/TFTP protocol
+bootz   - boot zImage from memory
+tftpboot- boot image via network using TFTP protocol
+	       and env variables "ipaddr" and "serverip"
+	       (and eventually "gatewayip")
+tftpput - upload a file via network using TFTP protocol
+rarpboot- boot image via network using RARP/TFTP protocol
+diskboot- boot from IDE devicebootd   - boot default, i.e., run 'bootcmd'
+loads	- load S-Record file over serial line
+loadb	- load binary file over serial line (kermit mode)
+md	- memory display
+mm	- memory modify (auto-incrementing)
+nm	- memory modify (constant address)
+mw	- memory write (fill)
+cp	- memory copy
+cmp	- memory compare
+crc32	- checksum calculation
+i2c	- I2C sub-system
+sspi	- SPI utility commands
+base	- print or set address offset
+printenv- print environment variables
+setenv	- set environment variables
+saveenv - save environment variables to persistent storage
+protect - enable or disable FLASH write protection
+erase	- erase FLASH memory
+flinfo	- print FLASH memory information
+nand	- NAND memory operations (see doc/README.nand)
+bdinfo	- print Board Info structure
+iminfo	- print header information for application image
+coninfo - print console devices and informations
+ide	- IDE sub-system
+loop	- infinite loop on address range
+loopw	- infinite write loop on address range
+mtest	- simple RAM test
+icache	- enable or disable instruction cache
+dcache	- enable or disable data cache
+reset	- Perform RESET of the CPU
+echo	- echo args to console
+version - print monitor version
+help	- print online help
+?	- alias for 'help'
+
+
+Monitor Commands - Detailed Description:
+========================================
+
+TODO.
+
+For now: just type "help <command>".
+
+
+Environment Variables:
+======================
+
+U-Boot supports user configuration using Environment Variables which
+can be made persistent by saving to Flash memory.
+
+Environment Variables are set using "setenv", printed using
+"printenv", and saved to Flash using "saveenv". Using "setenv"
+without a value can be used to delete a variable from the
+environment. As long as you don't save the environment you are
+working with an in-memory copy. In case the Flash area containing the
+environment is erased by accident, a default environment is provided.
+
+Some configuration options can be set using Environment Variables.
+
+List of environment variables (most likely not complete):
+
+  baudrate	- see CONFIG_BAUDRATE
+
+  bootdelay	- see CONFIG_BOOTDELAY
+
+  bootcmd	- see CONFIG_BOOTCOMMAND
+
+  bootargs	- Boot arguments when booting an RTOS image
+
+  bootfile	- Name of the image to load with TFTP
+
+  bootm_low	- Memory range available for image processing in the bootm
+		  command can be restricted. This variable is given as
+		  a hexadecimal number and defines lowest address allowed
+		  for use by the bootm command. See also "bootm_size"
+		  environment variable. Address defined by "bootm_low" is
+		  also the base of the initial memory mapping for the Linux
+		  kernel -- see the description of CONFIG_SYS_BOOTMAPSZ and
+		  bootm_mapsize.
+
+  bootm_mapsize - Size of the initial memory mapping for the Linux kernel.
+		  This variable is given as a hexadecimal number and it
+		  defines the size of the memory region starting at base
+		  address bootm_low that is accessible by the Linux kernel
+		  during early boot.  If unset, CONFIG_SYS_BOOTMAPSZ is used
+		  as the default value if it is defined, and bootm_size is
+		  used otherwise.
+
+  bootm_size	- Memory range available for image processing in the bootm
+		  command can be restricted. This variable is given as
+		  a hexadecimal number and defines the size of the region
+		  allowed for use by the bootm command. See also "bootm_low"
+		  environment variable.
+
+  updatefile	- Location of the software update file on a TFTP server, used
+		  by the automatic software update feature. Please refer to
+		  documentation in doc/README.update for more details.
+
+  autoload	- if set to "no" (any string beginning with 'n'),
+		  "bootp" will just load perform a lookup of the
+		  configuration from the BOOTP server, but not try to
+		  load any image using TFTP
+
+  autostart	- if set to "yes", an image loaded using the "bootp",
+		  "rarpboot", "tftpboot" or "diskboot" commands will
+		  be automatically started (by internally calling
+		  "bootm")
+
+		  If set to "no", a standalone image passed to the
+		  "bootm" command will be copied to the load address
+		  (and eventually uncompressed), but NOT be started.
+		  This can be used to load and uncompress arbitrary
+		  data.
+
+  fdt_high	- if set this restricts the maximum address that the
+		  flattened device tree will be copied into upon boot.
+		  For example, if you have a system with 1 GB memory
+		  at physical address 0x10000000, while Linux kernel
+		  only recognizes the first 704 MB as low memory, you
+		  may need to set fdt_high as 0x3C000000 to have the
+		  device tree blob be copied to the maximum address
+		  of the 704 MB low memory, so that Linux kernel can
+		  access it during the boot procedure.
+
+		  If this is set to the special value 0xFFFFFFFF then
+		  the fdt will not be copied at all on boot.  For this
+		  to work it must reside in writable memory, have
+		  sufficient padding on the end of it for u-boot to
+		  add the information it needs into it, and the memory
+		  must be accessible by the kernel.
+
+  fdtcontroladdr- if set this is the address of the control flattened
+		  device tree used by U-Boot when CONFIG_OF_CONTROL is
+		  defined.
+
+  i2cfast	- (PPC405GP|PPC405EP only)
+		  if set to 'y' configures Linux I2C driver for fast
+		  mode (400kHZ). This environment variable is used in
+		  initialization code. So, for changes to be effective
+		  it must be saved and board must be reset.
+
+  initrd_high	- restrict positioning of initrd images:
+		  If this variable is not set, initrd images will be
+		  copied to the highest possible address in RAM; this
+		  is usually what you want since it allows for
+		  maximum initrd size. If for some reason you want to
+		  make sure that the initrd image is loaded below the
+		  CONFIG_SYS_BOOTMAPSZ limit, you can set this environment
+		  variable to a value of "no" or "off" or "0".
+		  Alternatively, you can set it to a maximum upper
+		  address to use (U-Boot will still check that it
+		  does not overwrite the U-Boot stack and data).
+
+		  For instance, when you have a system with 16 MB
+		  RAM, and want to reserve 4 MB from use by Linux,
+		  you can do this by adding "mem=12M" to the value of
+		  the "bootargs" variable. However, now you must make
+		  sure that the initrd image is placed in the first
+		  12 MB as well - this can be done with
+
+		  setenv initrd_high 00c00000
+
+		  If you set initrd_high to 0xFFFFFFFF, this is an
+		  indication to U-Boot that all addresses are legal
+		  for the Linux kernel, including addresses in flash
+		  memory. In this case U-Boot will NOT COPY the
+		  ramdisk at all. This may be useful to reduce the
+		  boot time on your system, but requires that this
+		  feature is supported by your Linux kernel.
+
+  ipaddr	- IP address; needed for tftpboot command
+
+  loadaddr	- Default load address for commands like "bootp",
+		  "rarpboot", "tftpboot", "loadb" or "diskboot"
+
+  loads_echo	- see CONFIG_LOADS_ECHO
+
+  serverip	- TFTP server IP address; needed for tftpboot command
+
+  bootretry	- see CONFIG_BOOT_RETRY_TIME
+
+  bootdelaykey	- see CONFIG_AUTOBOOT_DELAY_STR
+
+  bootstopkey	- see CONFIG_AUTOBOOT_STOP_STR
+
+  ethprime	- controls which interface is used first.
+
+  ethact	- controls which interface is currently active.
+		  For example you can do the following
+
+		  => setenv ethact FEC
+		  => ping 192.168.0.1 # traffic sent on FEC
+		  => setenv ethact SCC
+		  => ping 10.0.0.1 # traffic sent on SCC
+
+  ethrotate	- When set to "no" U-Boot does not go through all
+		  available network interfaces.
+		  It just stays at the currently selected interface.
+
+  netretry	- When set to "no" each network operation will
+		  either succeed or fail without retrying.
+		  When set to "once" the network operation will
+		  fail when all the available network interfaces
+		  are tried once without success.
+		  Useful on scripts which control the retry operation
+		  themselves.
+
+  npe_ucode	- set load address for the NPE microcode
+
+  silent_linux  - If set then Linux will be told to boot silently, by
+		  changing the console to be empty. If "yes" it will be
+		  made silent. If "no" it will not be made silent. If
+		  unset, then it will be made silent if the U-Boot console
+		  is silent.
+
+  tftpsrcp	- If this is set, the value is used for TFTP's
+		  UDP source port.
+
+  tftpdstp	- If this is set, the value is used for TFTP's UDP
+		  destination port instead of the Well Know Port 69.
+
+  tftpblocksize - Block size to use for TFTP transfers; if not set,
+		  we use the TFTP server's default block size
+
+  tftptimeout	- Retransmission timeout for TFTP packets (in milli-
+		  seconds, minimum value is 1000 = 1 second). Defines
+		  when a packet is considered to be lost so it has to
+		  be retransmitted. The default is 5000 = 5 seconds.
+		  Lowering this value may make downloads succeed
+		  faster in networks with high packet loss rates or
+		  with unreliable TFTP servers.
+
+  tftptimeoutcountmax	- maximum count of TFTP timeouts (no
+		  unit, minimum value = 0). Defines how many timeouts
+		  can happen during a single file transfer before that
+		  transfer is aborted. The default is 10, and 0 means
+		  'no timeouts allowed'. Increasing this value may help
+		  downloads succeed with high packet loss rates, or with
+		  unreliable TFTP servers or client hardware.
+
+  vlan		- When set to a value < 4095 the traffic over
+		  Ethernet is encapsulated/received over 802.1q
+		  VLAN tagged frames.
+
+  bootpretryperiod	- Period during which BOOTP/DHCP sends retries.
+		  Unsigned value, in milliseconds. If not set, the period will
+		  be either the default (28000), or a value based on
+		  CONFIG_NET_RETRY_COUNT, if defined. This value has
+		  precedence over the valu based on CONFIG_NET_RETRY_COUNT.
+
+The following image location variables contain the location of images
+used in booting. The "Image" column gives the role of the image and is
+not an environment variable name. The other columns are environment
+variable names. "File Name" gives the name of the file on a TFTP
+server, "RAM Address" gives the location in RAM the image will be
+loaded to, and "Flash Location" gives the image's address in NOR
+flash or offset in NAND flash.
+
+*Note* - these variables don't have to be defined for all boards, some
+boards currently use other variables for these purposes, and some
+boards use these variables for other purposes.
+
+Image		    File Name	     RAM Address       Flash Location
+-----		    ---------	     -----------       --------------
+u-boot		    u-boot	     u-boot_addr_r     u-boot_addr
+Linux kernel	    bootfile	     kernel_addr_r     kernel_addr
+device tree blob    fdtfile	     fdt_addr_r	       fdt_addr
+ramdisk		    ramdiskfile	     ramdisk_addr_r    ramdisk_addr
+
+The following environment variables may be used and automatically
+updated by the network boot commands ("bootp" and "rarpboot"),
+depending the information provided by your boot server:
+
+  bootfile	- see above
+  dnsip		- IP address of your Domain Name Server
+  dnsip2	- IP address of your secondary Domain Name Server
+  gatewayip	- IP address of the Gateway (Router) to use
+  hostname	- Target hostname
+  ipaddr	- see above
+  netmask	- Subnet Mask
+  rootpath	- Pathname of the root filesystem on the NFS server
+  serverip	- see above
+
+
+There are two special Environment Variables:
+
+  serial#	- contains hardware identification information such
+		  as type string and/or serial number
+  ethaddr	- Ethernet address
+
+These variables can be set only once (usually during manufacturing of
+the board). U-Boot refuses to delete or overwrite these variables
+once they have been set once.
+
+
+Further special Environment Variables:
+
+  ver		- Contains the U-Boot version string as printed
+		  with the "version" command. This variable is
+		  readonly (see CONFIG_VERSION_VARIABLE).
+
+
+Please note that changes to some configuration parameters may take
+only effect after the next boot (yes, that's just like Windoze :-).
+
+
+Callback functions for environment variables:
+---------------------------------------------
+
+For some environment variables, the behavior of u-boot needs to change
+when their values are changed.  This functionality allows functions to
+be associated with arbitrary variables.  On creation, overwrite, or
+deletion, the callback will provide the opportunity for some side
+effect to happen or for the change to be rejected.
+
+The callbacks are named and associated with a function using the
+U_BOOT_ENV_CALLBACK macro in your board or driver code.
+
+These callbacks are associated with variables in one of two ways.  The
+static list can be added to by defining CONFIG_ENV_CALLBACK_LIST_STATIC
+in the board configuration to a string that defines a list of
+associations.  The list must be in the following format:
+
+	entry = variable_name[:callback_name]
+	list = entry[,list]
+
+If the callback name is not specified, then the callback is deleted.
+Spaces are also allowed anywhere in the list.
+
+Callbacks can also be associated by defining the ".callbacks" variable
+with the same list format above.  Any association in ".callbacks" will
+override any association in the static list. You can define
+CONFIG_ENV_CALLBACK_LIST_DEFAULT to a list (string) to define the
+".callbacks" environment variable in the default or embedded environment.
+
+If CONFIG_REGEX is defined, the variable_name above is evaluated as a
+regular expression. This allows multiple variables to be connected to
+the same callback without explicitly listing them all out.
+
+The signature of the callback functions is:
+
+    int callback(const char *name, const char *value, enum env_op op, int flags)
+
+* name - changed environment variable
+* value - new value of the environment variable
+* op - operation (create, overwrite, or delete)
+* flags - attributes of the environment variable change, see flags H_* in
+  include/search.h
+
+The return value is 0 if the variable change is accepted and 1 otherwise.
+
+Command Line Parsing:
+=====================
+
+There are two different command line parsers available with U-Boot:
+the old "simple" one, and the much more powerful "hush" shell:
+
+Old, simple command line parser:
+--------------------------------
+
+- supports environment variables (through setenv / saveenv commands)
+- several commands on one line, separated by ';'
+- variable substitution using "... ${name} ..." syntax
+- special characters ('$', ';') can be escaped by prefixing with '\',
+  for example:
+	setenv bootcmd bootm \${address}
+- You can also escape text by enclosing in single apostrophes, for example:
+	setenv addip 'setenv bootargs $bootargs ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname::off'
+
+Hush shell:
+-----------
+
+- similar to Bourne shell, with control structures like
+  if...then...else...fi, for...do...done; while...do...done,
+  until...do...done, ...
+- supports environment ("global") variables (through setenv / saveenv
+  commands) and local shell variables (through standard shell syntax
+  "name=value"); only environment variables can be used with "run"
+  command
+
+General rules:
+--------------
+
+(1) If a command line (or an environment variable executed by a "run"
+    command) contains several commands separated by semicolon, and
+    one of these commands fails, then the remaining commands will be
+    executed anyway.
+
+(2) If you execute several variables with one call to run (i. e.
+    calling run with a list of variables as arguments), any failing
+    command will cause "run" to terminate, i. e. the remaining
+    variables are not executed.
+
+Note for Redundant Ethernet Interfaces:
+=======================================
+
+Some boards come with redundant Ethernet interfaces; U-Boot supports
+such configurations and is capable of automatic selection of a
+"working" interface when needed. MAC assignment works as follows:
+
+Network interfaces are numbered eth0, eth1, eth2, ... Corresponding
+MAC addresses can be stored in the environment as "ethaddr" (=>eth0),
+"eth1addr" (=>eth1), "eth2addr", ...
+
+If the network interface stores some valid MAC address (for instance
+in SROM), this is used as default address if there is NO correspon-
+ding setting in the environment; if the corresponding environment
+variable is set, this overrides the settings in the card; that means:
+
+o If the SROM has a valid MAC address, and there is no address in the
+  environment, the SROM's address is used.
+
+o If there is no valid address in the SROM, and a definition in the
+  environment exists, then the value from the environment variable is
+  used.
+
+o If both the SROM and the environment contain a MAC address, and
+  both addresses are the same, this MAC address is used.
+
+o If both the SROM and the environment contain a MAC address, and the
+  addresses differ, the value from the environment is used and a
+  warning is printed.
+
+o If neither SROM nor the environment contain a MAC address, an error
+  is raised. If CONFIG_NET_RANDOM_ETHADDR is defined, then in this case
+  a random, locally-assigned MAC is used.
+
+If Ethernet drivers implement the 'write_hwaddr' function, valid MAC addresses
+will be programmed into hardware as part of the initialization process.	 This
+may be skipped by setting the appropriate 'ethmacskip' environment variable.
+The naming convention is as follows:
+"ethmacskip" (=>eth0), "eth1macskip" (=>eth1) etc.
+
+Image Formats:
+==============
+
+U-Boot is capable of booting (and performing other auxiliary operations on)
+images in two formats:
+
+New uImage format (FIT)
+-----------------------
+
+Flexible and powerful format based on Flattened Image Tree -- FIT (similar
+to Flattened Device Tree). It allows the use of images with multiple
+components (several kernels, ramdisks, etc.), with contents protected by
+SHA1, MD5 or CRC32. More details are found in the doc/uImage.FIT directory.
+
+
+Old uImage format
+-----------------
+
+Old image format is based on binary files which can be basically anything,
+preceded by a special header; see the definitions in include/image.h for
+details; basically, the header defines the following image properties:
+
+* Target Operating System (Provisions for OpenBSD, NetBSD, FreeBSD,
+  4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks,
+  LynxOS, pSOS, QNX, RTEMS, INTEGRITY;
+  Currently supported: Linux, NetBSD, VxWorks, QNX, RTEMS, LynxOS,
+  INTEGRITY).
+* Target CPU Architecture (Provisions for Alpha, ARM, Intel x86,
+  IA64, MIPS, NDS32, Nios II, PowerPC, IBM S390, SuperH, Sparc, Sparc 64 Bit;
+  Currently supported: ARM, Intel x86, MIPS, NDS32, Nios II, PowerPC).
+* Compression Type (uncompressed, gzip, bzip2)
+* Load Address
+* Entry Point
+* Image Name
+* Image Timestamp
+
+The header is marked by a special Magic Number, and both the header
+and the data portions of the image are secured against corruption by
+CRC32 checksums.
+
+
+Linux Support:
+==============
+
+Although U-Boot should support any OS or standalone application
+easily, the main focus has always been on Linux during the design of
+U-Boot.
+
+U-Boot includes many features that so far have been part of some
+special "boot loader" code within the Linux kernel. Also, any
+"initrd" images to be used are no longer part of one big Linux image;
+instead, kernel and "initrd" are separate images. This implementation
+serves several purposes:
+
+- the same features can be used for other OS or standalone
+  applications (for instance: using compressed images to reduce the
+  Flash memory footprint)
+
+- it becomes much easier to port new Linux kernel versions because
+  lots of low-level, hardware dependent stuff are done by U-Boot
+
+- the same Linux kernel image can now be used with different "initrd"
+  images; of course this also means that different kernel images can
+  be run with the same "initrd". This makes testing easier (you don't
+  have to build a new "zImage.initrd" Linux image when you just
+  change a file in your "initrd"). Also, a field-upgrade of the
+  software is easier now.
+
+
+Linux HOWTO:
+============
+
+Porting Linux to U-Boot based systems:
+---------------------------------------
+
+U-Boot cannot save you from doing all the necessary modifications to
+configure the Linux device drivers for use with your target hardware
+(no, we don't intend to provide a full virtual machine interface to
+Linux :-).
+
+But now you can ignore ALL boot loader code (in arch/powerpc/mbxboot).
+
+Just make sure your machine specific header file (for instance
+include/asm-ppc/tqm8xx.h) includes the same definition of the Board
+Information structure as we define in include/asm-<arch>/u-boot.h,
+and make sure that your definition of IMAP_ADDR uses the same value
+as your U-Boot configuration in CONFIG_SYS_IMMR.
+
+Note that U-Boot now has a driver model, a unified model for drivers.
+If you are adding a new driver, plumb it into driver model. If there
+is no uclass available, you are encouraged to create one. See
+doc/driver-model.
+
+
+Configuring the Linux kernel:
+-----------------------------
+
+No specific requirements for U-Boot. Make sure you have some root
+device (initial ramdisk, NFS) for your target system.
+
+
+Building a Linux Image:
+-----------------------
+
+With U-Boot, "normal" build targets like "zImage" or "bzImage" are
+not used. If you use recent kernel source, a new build target
+"uImage" will exist which automatically builds an image usable by
+U-Boot. Most older kernels also have support for a "pImage" target,
+which was introduced for our predecessor project PPCBoot and uses a
+100% compatible format.
+
+Example:
+
+	make TQM850L_defconfig
+	make oldconfig
+	make dep
+	make uImage
+
+The "uImage" build target uses a special tool (in 'tools/mkimage') to
+encapsulate a compressed Linux kernel image with header	 information,
+CRC32 checksum etc. for use with U-Boot. This is what we are doing:
+
+* build a standard "vmlinux" kernel image (in ELF binary format):
+
+* convert the kernel into a raw binary image:
+
+	${CROSS_COMPILE}-objcopy -O binary \
+				 -R .note -R .comment \
+				 -S vmlinux linux.bin
+
+* compress the binary image:
+
+	gzip -9 linux.bin
+
+* package compressed binary image for U-Boot:
+
+	mkimage -A ppc -O linux -T kernel -C gzip \
+		-a 0 -e 0 -n "Linux Kernel Image" \
+		-d linux.bin.gz uImage
+
+
+The "mkimage" tool can also be used to create ramdisk images for use
+with U-Boot, either separated from the Linux kernel image, or
+combined into one file. "mkimage" encapsulates the images with a 64
+byte header containing information about target architecture,
+operating system, image type, compression method, entry points, time
+stamp, CRC32 checksums, etc.
+
+"mkimage" can be called in two ways: to verify existing images and
+print the header information, or to build new images.
+
+In the first form (with "-l" option) mkimage lists the information
+contained in the header of an existing U-Boot image; this includes
+checksum verification:
+
+	tools/mkimage -l image
+	  -l ==> list image header information
+
+The second form (with "-d" option) is used to build a U-Boot image
+from a "data file" which is used as image payload:
+
+	tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \
+		      -n name -d data_file image
+	  -A ==> set architecture to 'arch'
+	  -O ==> set operating system to 'os'
+	  -T ==> set image type to 'type'
+	  -C ==> set compression type 'comp'
+	  -a ==> set load address to 'addr' (hex)
+	  -e ==> set entry point to 'ep' (hex)
+	  -n ==> set image name to 'name'
+	  -d ==> use image data from 'datafile'
+
+Right now, all Linux kernels for PowerPC systems use the same load
+address (0x00000000), but the entry point address depends on the
+kernel version:
+
+- 2.2.x kernels have the entry point at 0x0000000C,
+- 2.3.x and later kernels have the entry point at 0x00000000.
+
+So a typical call to build a U-Boot image would read:
+
+	-> tools/mkimage -n '2.4.4 kernel for TQM850L' \
+	> -A ppc -O linux -T kernel -C gzip -a 0 -e 0 \
+	> -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz \
+	> examples/uImage.TQM850L
+	Image Name:   2.4.4 kernel for TQM850L
+	Created:      Wed Jul 19 02:34:59 2000
+	Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+	Data Size:    335725 Bytes = 327.86 kB = 0.32 MB
+	Load Address: 0x00000000
+	Entry Point:  0x00000000
+
+To verify the contents of the image (or check for corruption):
+
+	-> tools/mkimage -l examples/uImage.TQM850L
+	Image Name:   2.4.4 kernel for TQM850L
+	Created:      Wed Jul 19 02:34:59 2000
+	Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+	Data Size:    335725 Bytes = 327.86 kB = 0.32 MB
+	Load Address: 0x00000000
+	Entry Point:  0x00000000
+
+NOTE: for embedded systems where boot time is critical you can trade
+speed for memory and install an UNCOMPRESSED image instead: this
+needs more space in Flash, but boots much faster since it does not
+need to be uncompressed:
+
+	-> gunzip /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz
+	-> tools/mkimage -n '2.4.4 kernel for TQM850L' \
+	> -A ppc -O linux -T kernel -C none -a 0 -e 0 \
+	> -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux \
+	> examples/uImage.TQM850L-uncompressed
+	Image Name:   2.4.4 kernel for TQM850L
+	Created:      Wed Jul 19 02:34:59 2000
+	Image Type:   PowerPC Linux Kernel Image (uncompressed)
+	Data Size:    792160 Bytes = 773.59 kB = 0.76 MB
+	Load Address: 0x00000000
+	Entry Point:  0x00000000
+
+
+Similar you can build U-Boot images from a 'ramdisk.image.gz' file
+when your kernel is intended to use an initial ramdisk:
+
+	-> tools/mkimage -n 'Simple Ramdisk Image' \
+	> -A ppc -O linux -T ramdisk -C gzip \
+	> -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd
+	Image Name:   Simple Ramdisk Image
+	Created:      Wed Jan 12 14:01:50 2000
+	Image Type:   PowerPC Linux RAMDisk Image (gzip compressed)
+	Data Size:    566530 Bytes = 553.25 kB = 0.54 MB
+	Load Address: 0x00000000
+	Entry Point:  0x00000000
+
+The "dumpimage" is a tool to disassemble images built by mkimage. Its "-i"
+option performs the converse operation of the mkimage's second form (the "-d"
+option). Given an image built by mkimage, the dumpimage extracts a "data file"
+from the image:
+
+	tools/dumpimage -i image -T type -p position data_file
+	  -i ==> extract from the 'image' a specific 'data_file'
+	  -T ==> set image type to 'type'
+	  -p ==> 'position' (starting at 0) of the 'data_file' inside the 'image'
+
+
+Installing a Linux Image:
+-------------------------
+
+To downloading a U-Boot image over the serial (console) interface,
+you must convert the image to S-Record format:
+
+	objcopy -I binary -O srec examples/image examples/image.srec
+
+The 'objcopy' does not understand the information in the U-Boot
+image header, so the resulting S-Record file will be relative to
+address 0x00000000. To load it to a given address, you need to
+specify the target address as 'offset' parameter with the 'loads'
+command.
+
+Example: install the image to address 0x40100000 (which on the
+TQM8xxL is in the first Flash bank):
+
+	=> erase 40100000 401FFFFF
+
+	.......... done
+	Erased 8 sectors
+
+	=> loads 40100000
+	## Ready for S-Record download ...
+	~>examples/image.srec
+	1 2 3 4 5 6 7 8 9 10 11 12 13 ...
+	...
+	15989 15990 15991 15992
+	[file transfer complete]
+	[connected]
+	## Start Addr = 0x00000000
+
+
+You can check the success of the download using the 'iminfo' command;
+this includes a checksum verification so you can be sure no data
+corruption happened:
+
+	=> imi 40100000
+
+	## Checking Image at 40100000 ...
+	   Image Name:	 2.2.13 for initrd on TQM850L
+	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
+	   Data Size:	 335725 Bytes = 327 kB = 0 MB
+	   Load Address: 00000000
+	   Entry Point:	 0000000c
+	   Verifying Checksum ... OK
+
+
+Boot Linux:
+-----------
+
+The "bootm" command is used to boot an application that is stored in
+memory (RAM or Flash). In case of a Linux kernel image, the contents
+of the "bootargs" environment variable is passed to the kernel as
+parameters. You can check and modify this variable using the
+"printenv" and "setenv" commands:
+
+
+	=> printenv bootargs
+	bootargs=root=/dev/ram
+
+	=> setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+
+	=> printenv bootargs
+	bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+
+	=> bootm 40020000
+	## Booting Linux kernel at 40020000 ...
+	   Image Name:	 2.2.13 for NFS on TQM850L
+	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
+	   Data Size:	 381681 Bytes = 372 kB = 0 MB
+	   Load Address: 00000000
+	   Entry Point:	 0000000c
+	   Verifying Checksum ... OK
+	   Uncompressing Kernel Image ... OK
+	Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000
+	Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+	time_init: decrementer frequency = 187500000/60
+	Calibrating delay loop... 49.77 BogoMIPS
+	Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000]
+	...
+
+If you want to boot a Linux kernel with initial RAM disk, you pass
+the memory addresses of both the kernel and the initrd image (PPBCOOT
+format!) to the "bootm" command:
+
+	=> imi 40100000 40200000
+
+	## Checking Image at 40100000 ...
+	   Image Name:	 2.2.13 for initrd on TQM850L
+	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
+	   Data Size:	 335725 Bytes = 327 kB = 0 MB
+	   Load Address: 00000000
+	   Entry Point:	 0000000c
+	   Verifying Checksum ... OK
+
+	## Checking Image at 40200000 ...
+	   Image Name:	 Simple Ramdisk Image
+	   Image Type:	 PowerPC Linux RAMDisk Image (gzip compressed)
+	   Data Size:	 566530 Bytes = 553 kB = 0 MB
+	   Load Address: 00000000
+	   Entry Point:	 00000000
+	   Verifying Checksum ... OK
+
+	=> bootm 40100000 40200000
+	## Booting Linux kernel at 40100000 ...
+	   Image Name:	 2.2.13 for initrd on TQM850L
+	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
+	   Data Size:	 335725 Bytes = 327 kB = 0 MB
+	   Load Address: 00000000
+	   Entry Point:	 0000000c
+	   Verifying Checksum ... OK
+	   Uncompressing Kernel Image ... OK
+	## Loading RAMDisk Image at 40200000 ...
+	   Image Name:	 Simple Ramdisk Image
+	   Image Type:	 PowerPC Linux RAMDisk Image (gzip compressed)
+	   Data Size:	 566530 Bytes = 553 kB = 0 MB
+	   Load Address: 00000000
+	   Entry Point:	 00000000
+	   Verifying Checksum ... OK
+	   Loading Ramdisk ... OK
+	Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000
+	Boot arguments: root=/dev/ram
+	time_init: decrementer frequency = 187500000/60
+	Calibrating delay loop... 49.77 BogoMIPS
+	...
+	RAMDISK: Compressed image found at block 0
+	VFS: Mounted root (ext2 filesystem).
+
+	bash#
+
+Boot Linux and pass a flat device tree:
+-----------
+
+First, U-Boot must be compiled with the appropriate defines. See the section
+titled "Linux Kernel Interface" above for a more in depth explanation. The
+following is an example of how to start a kernel and pass an updated
+flat device tree:
+
+=> print oftaddr
+oftaddr=0x300000
+=> print oft
+oft=oftrees/mpc8540ads.dtb
+=> tftp $oftaddr $oft
+Speed: 1000, full duplex
+Using TSEC0 device
+TFTP from server 192.168.1.1; our IP address is 192.168.1.101
+Filename 'oftrees/mpc8540ads.dtb'.
+Load address: 0x300000
+Loading: #
+done
+Bytes transferred = 4106 (100a hex)
+=> tftp $loadaddr $bootfile
+Speed: 1000, full duplex
+Using TSEC0 device
+TFTP from server 192.168.1.1; our IP address is 192.168.1.2
+Filename 'uImage'.
+Load address: 0x200000
+Loading:############
+done
+Bytes transferred = 1029407 (fb51f hex)
+=> print loadaddr
+loadaddr=200000
+=> print oftaddr
+oftaddr=0x300000
+=> bootm $loadaddr - $oftaddr
+## Booting image at 00200000 ...
+   Image Name:	 Linux-2.6.17-dirty
+   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
+   Data Size:	 1029343 Bytes = 1005.2 kB
+   Load Address: 00000000
+   Entry Point:	 00000000
+   Verifying Checksum ... OK
+   Uncompressing Kernel Image ... OK
+Booting using flat device tree at 0x300000
+Using MPC85xx ADS machine description
+Memory CAM mapping: CAM0=256Mb, CAM1=256Mb, CAM2=0Mb residual: 0Mb
+[snip]
+
+
+More About U-Boot Image Types:
+------------------------------
+
+U-Boot supports the following image types:
+
+   "Standalone Programs" are directly runnable in the environment
+	provided by U-Boot; it is expected that (if they behave
+	well) you can continue to work in U-Boot after return from
+	the Standalone Program.
+   "OS Kernel Images" are usually images of some Embedded OS which
+	will take over control completely. Usually these programs
+	will install their own set of exception handlers, device
+	drivers, set up the MMU, etc. - this means, that you cannot
+	expect to re-enter U-Boot except by resetting the CPU.
+   "RAMDisk Images" are more or less just data blocks, and their
+	parameters (address, size) are passed to an OS kernel that is
+	being started.
+   "Multi-File Images" contain several images, typically an OS
+	(Linux) kernel image and one or more data images like
+	RAMDisks. This construct is useful for instance when you want
+	to boot over the network using BOOTP etc., where the boot
+	server provides just a single image file, but you want to get
+	for instance an OS kernel and a RAMDisk image.
+
+	"Multi-File Images" start with a list of image sizes, each
+	image size (in bytes) specified by an "uint32_t" in network
+	byte order. This list is terminated by an "(uint32_t)0".
+	Immediately after the terminating 0 follow the images, one by
+	one, all aligned on "uint32_t" boundaries (size rounded up to
+	a multiple of 4 bytes).
+
+   "Firmware Images" are binary images containing firmware (like
+	U-Boot or FPGA images) which usually will be programmed to
+	flash memory.
+
+   "Script files" are command sequences that will be executed by
+	U-Boot's command interpreter; this feature is especially
+	useful when you configure U-Boot to use a real shell (hush)
+	as command interpreter.
+
+Booting the Linux zImage:
+-------------------------
+
+On some platforms, it's possible to boot Linux zImage. This is done
+using the "bootz" command. The syntax of "bootz" command is the same
+as the syntax of "bootm" command.
+
+Note, defining the CONFIG_SUPPORT_RAW_INITRD allows user to supply
+kernel with raw initrd images. The syntax is slightly different, the
+address of the initrd must be augmented by it's size, in the following
+format: "<initrd addres>:<initrd size>".
+
+
+Standalone HOWTO:
+=================
+
+One of the features of U-Boot is that you can dynamically load and
+run "standalone" applications, which can use some resources of
+U-Boot like console I/O functions or interrupt services.
+
+Two simple examples are included with the sources:
+
+"Hello World" Demo:
+-------------------
+
+'examples/hello_world.c' contains a small "Hello World" Demo
+application; it is automatically compiled when you build U-Boot.
+It's configured to run at address 0x00040004, so you can play with it
+like that:
+
+	=> loads
+	## Ready for S-Record download ...
+	~>examples/hello_world.srec
+	1 2 3 4 5 6 7 8 9 10 11 ...
+	[file transfer complete]
+	[connected]
+	## Start Addr = 0x00040004
+
+	=> go 40004 Hello World! This is a test.
+	## Starting application at 0x00040004 ...
+	Hello World
+	argc = 7
+	argv[0] = "40004"
+	argv[1] = "Hello"
+	argv[2] = "World!"
+	argv[3] = "This"
+	argv[4] = "is"
+	argv[5] = "a"
+	argv[6] = "test."
+	argv[7] = "<NULL>"
+	Hit any key to exit ...
+
+	## Application terminated, rc = 0x0
+
+Another example, which demonstrates how to register a CPM interrupt
+handler with the U-Boot code, can be found in 'examples/timer.c'.
+Here, a CPM timer is set up to generate an interrupt every second.
+The interrupt service routine is trivial, just printing a '.'
+character, but this is just a demo program. The application can be
+controlled by the following keys:
+
+	? - print current values og the CPM Timer registers
+	b - enable interrupts and start timer
+	e - stop timer and disable interrupts
+	q - quit application
+
+	=> loads
+	## Ready for S-Record download ...
+	~>examples/timer.srec
+	1 2 3 4 5 6 7 8 9 10 11 ...
+	[file transfer complete]
+	[connected]
+	## Start Addr = 0x00040004
+
+	=> go 40004
+	## Starting application at 0x00040004 ...
+	TIMERS=0xfff00980
+	Using timer 1
+	  tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0
+
+Hit 'b':
+	[q, b, e, ?] Set interval 1000000 us
+	Enabling timer
+Hit '?':
+	[q, b, e, ?] ........
+	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0
+Hit '?':
+	[q, b, e, ?] .
+	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0
+Hit '?':
+	[q, b, e, ?] .
+	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0
+Hit '?':
+	[q, b, e, ?] .
+	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0
+Hit 'e':
+	[q, b, e, ?] ...Stopping timer
+Hit 'q':
+	[q, b, e, ?] ## Application terminated, rc = 0x0
+
+
+Minicom warning:
+================
+
+Over time, many people have reported problems when trying to use the
+"minicom" terminal emulation program for serial download. I (wd)
+consider minicom to be broken, and recommend not to use it. Under
+Unix, I recommend to use C-Kermit for general purpose use (and
+especially for kermit binary protocol download ("loadb" command), and
+use "cu" for S-Record download ("loads" command).  See
+http://www.denx.de/wiki/view/DULG/SystemSetup#Section_4.3.
+for help with kermit.
+
+
+Nevertheless, if you absolutely want to use it try adding this
+configuration to your "File transfer protocols" section:
+
+	   Name	   Program			Name U/D FullScr IO-Red. Multi
+	X  kermit  /usr/bin/kermit -i -l %l -s	 Y    U	   Y	   N	  N
+	Y  kermit  /usr/bin/kermit -i -l %l -r	 N    D	   Y	   N	  N
+
+
+NetBSD Notes:
+=============
+
+Starting at version 0.9.2, U-Boot supports NetBSD both as host
+(build U-Boot) and target system (boots NetBSD/mpc8xx).
+
+Building requires a cross environment; it is known to work on
+NetBSD/i386 with the cross-powerpc-netbsd-1.3 package (you will also
+need gmake since the Makefiles are not compatible with BSD make).
+Note that the cross-powerpc package does not install include files;
+attempting to build U-Boot will fail because <machine/ansi.h> is
+missing.  This file has to be installed and patched manually:
+
+	# cd /usr/pkg/cross/powerpc-netbsd/include
+	# mkdir powerpc
+	# ln -s powerpc machine
+	# cp /usr/src/sys/arch/powerpc/include/ansi.h powerpc/ansi.h
+	# ${EDIT} powerpc/ansi.h	## must remove __va_list, _BSD_VA_LIST
+
+Native builds *don't* work due to incompatibilities between native
+and U-Boot include files.
+
+Booting assumes that (the first part of) the image booted is a
+stage-2 loader which in turn loads and then invokes the kernel
+proper. Loader sources will eventually appear in the NetBSD source
+tree (probably in sys/arc/mpc8xx/stand/u-boot_stage2/); in the
+meantime, see ftp://ftp.denx.de/pub/u-boot/ppcboot_stage2.tar.gz
+
+
+Implementation Internals:
+=========================
+
+The following is not intended to be a complete description of every
+implementation detail. However, it should help to understand the
+inner workings of U-Boot and make it easier to port it to custom
+hardware.
+
+
+Initial Stack, Global Data:
+---------------------------
+
+The implementation of U-Boot is complicated by the fact that U-Boot
+starts running out of ROM (flash memory), usually without access to
+system RAM (because the memory controller is not initialized yet).
+This means that we don't have writable Data or BSS segments, and BSS
+is not initialized as zero. To be able to get a C environment working
+at all, we have to allocate at least a minimal stack. Implementation
+options for this are defined and restricted by the CPU used: Some CPU
+models provide on-chip memory (like the IMMR area on MPC8xx and
+MPC826x processors), on others (parts of) the data cache can be
+locked as (mis-) used as memory, etc.
+
+	Chris Hallinan posted a good summary of these issues to the
+	U-Boot mailing list:
+
+	Subject: RE: [U-Boot-Users] RE: More On Memory Bank x (nothingness)?
+	From: "Chris Hallinan" <clh@net1plus.com>
+	Date: Mon, 10 Feb 2003 16:43:46 -0500 (22:43 MET)
+	...
+
+	Correct me if I'm wrong, folks, but the way I understand it
+	is this: Using DCACHE as initial RAM for Stack, etc, does not
+	require any physical RAM backing up the cache. The cleverness
+	is that the cache is being used as a temporary supply of
+	necessary storage before the SDRAM controller is setup. It's
+	beyond the scope of this list to explain the details, but you
+	can see how this works by studying the cache architecture and
+	operation in the architecture and processor-specific manuals.
+
+	OCM is On Chip Memory, which I believe the 405GP has 4K. It
+	is another option for the system designer to use as an
+	initial stack/RAM area prior to SDRAM being available. Either
+	option should work for you. Using CS 4 should be fine if your
+	board designers haven't used it for something that would
+	cause you grief during the initial boot! It is frequently not
+	used.
+
+	CONFIG_SYS_INIT_RAM_ADDR should be somewhere that won't interfere
+	with your processor/board/system design. The default value
+	you will find in any recent u-boot distribution in
+	walnut.h should work for you. I'd set it to a value larger
+	than your SDRAM module. If you have a 64MB SDRAM module, set
+	it above 400_0000. Just make sure your board has no resources
+	that are supposed to respond to that address! That code in
+	start.S has been around a while and should work as is when
+	you get the config right.
+
+	-Chris Hallinan
+	DS4.COM, Inc.
+
+It is essential to remember this, since it has some impact on the C
+code for the initialization procedures:
+
+* Initialized global data (data segment) is read-only. Do not attempt
+  to write it.
+
+* Do not use any uninitialized global data (or implicitly initialized
+  as zero data - BSS segment) at all - this is undefined, initiali-
+  zation is performed later (when relocating to RAM).
+
+* Stack space is very limited. Avoid big data buffers or things like
+  that.
+
+Having only the stack as writable memory limits means we cannot use
+normal global data to share information between the code. But it
+turned out that the implementation of U-Boot can be greatly
+simplified by making a global data structure (gd_t) available to all
+functions. We could pass a pointer to this data as argument to _all_
+functions, but this would bloat the code. Instead we use a feature of
+the GCC compiler (Global Register Variables) to share the data: we
+place a pointer (gd) to the global data into a register which we
+reserve for this purpose.
+
+When choosing a register for such a purpose we are restricted by the
+relevant  (E)ABI  specifications for the current architecture, and by
+GCC's implementation.
+
+For PowerPC, the following registers have specific use:
+	R1:	stack pointer
+	R2:	reserved for system use
+	R3-R4:	parameter passing and return values
+	R5-R10: parameter passing
+	R13:	small data area pointer
+	R30:	GOT pointer
+	R31:	frame pointer
+
+	(U-Boot also uses R12 as internal GOT pointer. r12
+	is a volatile register so r12 needs to be reset when
+	going back and forth between asm and C)
+
+    ==> U-Boot will use R2 to hold a pointer to the global data
+
+    Note: on PPC, we could use a static initializer (since the
+    address of the global data structure is known at compile time),
+    but it turned out that reserving a register results in somewhat
+    smaller code - although the code savings are not that big (on
+    average for all boards 752 bytes for the whole U-Boot image,
+    624 text + 127 data).
+
+On ARM, the following registers are used:
+
+	R0:	function argument word/integer result
+	R1-R3:	function argument word
+	R9:	platform specific
+	R10:	stack limit (used only if stack checking is enabled)
+	R11:	argument (frame) pointer
+	R12:	temporary workspace
+	R13:	stack pointer
+	R14:	link register
+	R15:	program counter
+
+    ==> U-Boot will use R9 to hold a pointer to the global data
+
+    Note: on ARM, only R_ARM_RELATIVE relocations are supported.
+
+On Nios II, the ABI is documented here:
+	http://www.altera.com/literature/hb/nios2/n2cpu_nii51016.pdf
+
+    ==> U-Boot will use gp to hold a pointer to the global data
+
+    Note: on Nios II, we give "-G0" option to gcc and don't use gp
+    to access small data sections, so gp is free.
+
+On NDS32, the following registers are used:
+
+	R0-R1:	argument/return
+	R2-R5:	argument
+	R15:	temporary register for assembler
+	R16:	trampoline register
+	R28:	frame pointer (FP)
+	R29:	global pointer (GP)
+	R30:	link register (LP)
+	R31:	stack pointer (SP)
+	PC:	program counter (PC)
+
+    ==> U-Boot will use R10 to hold a pointer to the global data
+
+NOTE: DECLARE_GLOBAL_DATA_PTR must be used with file-global scope,
+or current versions of GCC may "optimize" the code too much.
+
+On RISC-V, the following registers are used:
+
+	x0: hard-wired zero (zero)
+	x1: return address (ra)
+	x2:	stack pointer (sp)
+	x3:	global pointer (gp)
+	x4:	thread pointer (tp)
+	x5:	link register (t0)
+	x8:	frame pointer (fp)
+	x10-x11:	arguments/return values (a0-1)
+	x12-x17:	arguments (a2-7)
+	x28-31:	 temporaries (t3-6)
+	pc:	program counter (pc)
+
+    ==> U-Boot will use gp to hold a pointer to the global data
+
+Memory Management:
+------------------
+
+U-Boot runs in system state and uses physical addresses, i.e. the
+MMU is not used either for address mapping nor for memory protection.
+
+The available memory is mapped to fixed addresses using the memory
+controller. In this process, a contiguous block is formed for each
+memory type (Flash, SDRAM, SRAM), even when it consists of several
+physical memory banks.
+
+U-Boot is installed in the first 128 kB of the first Flash bank (on
+TQM8xxL modules this is the range 0x40000000 ... 0x4001FFFF). After
+booting and sizing and initializing DRAM, the code relocates itself
+to the upper end of DRAM. Immediately below the U-Boot code some
+memory is reserved for use by malloc() [see CONFIG_SYS_MALLOC_LEN
+configuration setting]. Below that, a structure with global Board
+Info data is placed, followed by the stack (growing downward).
+
+Additionally, some exception handler code is copied to the low 8 kB
+of DRAM (0x00000000 ... 0x00001FFF).
+
+So a typical memory configuration with 16 MB of DRAM could look like
+this:
+
+	0x0000 0000	Exception Vector code
+	      :
+	0x0000 1FFF
+	0x0000 2000	Free for Application Use
+	      :
+	      :
+
+	      :
+	      :
+	0x00FB FF20	Monitor Stack (Growing downward)
+	0x00FB FFAC	Board Info Data and permanent copy of global data
+	0x00FC 0000	Malloc Arena
+	      :
+	0x00FD FFFF
+	0x00FE 0000	RAM Copy of Monitor Code
+	...		eventually: LCD or video framebuffer
+	...		eventually: pRAM (Protected RAM - unchanged by reset)
+	0x00FF FFFF	[End of RAM]
+
+
+System Initialization:
+----------------------
+
+In the reset configuration, U-Boot starts at the reset entry point
+(on most PowerPC systems at address 0x00000100). Because of the reset
+configuration for CS0# this is a mirror of the on board Flash memory.
+To be able to re-map memory U-Boot then jumps to its link address.
+To be able to implement the initialization code in C, a (small!)
+initial stack is set up in the internal Dual Ported RAM (in case CPUs
+which provide such a feature like), or in a locked part of the data
+cache. After that, U-Boot initializes the CPU core, the caches and
+the SIU.
+
+Next, all (potentially) available memory banks are mapped using a
+preliminary mapping. For example, we put them on 512 MB boundaries
+(multiples of 0x20000000: SDRAM on 0x00000000 and 0x20000000, Flash
+on 0x40000000 and 0x60000000, SRAM on 0x80000000). Then UPM A is
+programmed for SDRAM access. Using the temporary configuration, a
+simple memory test is run that determines the size of the SDRAM
+banks.
+
+When there is more than one SDRAM bank, and the banks are of
+different size, the largest is mapped first. For equal size, the first
+bank (CS2#) is mapped first. The first mapping is always for address
+0x00000000, with any additional banks following immediately to create
+contiguous memory starting from 0.
+
+Then, the monitor installs itself at the upper end of the SDRAM area
+and allocates memory for use by malloc() and for the global Board
+Info data; also, the exception vector code is copied to the low RAM
+pages, and the final stack is set up.
+
+Only after this relocation will you have a "normal" C environment;
+until that you are restricted in several ways, mostly because you are
+running from ROM, and because the code will have to be relocated to a
+new address in RAM.
+
+
+U-Boot Porting Guide:
+----------------------
+
+[Based on messages by Jerry Van Baren in the U-Boot-Users mailing
+list, October 2002]
+
+
+int main(int argc, char *argv[])
+{
+	sighandler_t no_more_time;
+
+	signal(SIGALRM, no_more_time);
+	alarm(PROJECT_DEADLINE - toSec (3 * WEEK));
+
+	if (available_money > available_manpower) {
+		Pay consultant to port U-Boot;
+		return 0;
+	}
+
+	Download latest U-Boot source;
+
+	Subscribe to u-boot mailing list;
+
+	if (clueless)
+		email("Hi, I am new to U-Boot, how do I get started?");
+
+	while (learning) {
+		Read the README file in the top level directory;
+		Read http://www.denx.de/twiki/bin/view/DULG/Manual;
+		Read applicable doc/*.README;
+		Read the source, Luke;
+		/* find . -name "*.[chS]" | xargs grep -i <keyword> */
+	}
+
+	if (available_money > toLocalCurrency ($2500))
+		Buy a BDI3000;
+	else
+		Add a lot of aggravation and time;
+
+	if (a similar board exists) {	/* hopefully... */
+		cp -a board/<similar> board/<myboard>
+		cp include/configs/<similar>.h include/configs/<myboard>.h
+	} else {
+		Create your own board support subdirectory;
+		Create your own board include/configs/<myboard>.h file;
+	}
+	Edit new board/<myboard> files
+	Edit new include/configs/<myboard>.h
+
+	while (!accepted) {
+		while (!running) {
+			do {
+				Add / modify source code;
+			} until (compiles);
+			Debug;
+			if (clueless)
+				email("Hi, I am having problems...");
+		}
+		Send patch file to the U-Boot email list;
+		if (reasonable critiques)
+			Incorporate improvements from email list code review;
+		else
+			Defend code as written;
+	}
+
+	return 0;
+}
+
+void no_more_time (int sig)
+{
+      hire_a_guru();
+}
+
+
+Coding Standards:
+-----------------
+
+All contributions to U-Boot should conform to the Linux kernel
+coding style; see the kernel coding style guide at
+https://www.kernel.org/doc/html/latest/process/coding-style.html, and the
+script "scripts/Lindent" in your Linux kernel source directory.
+
+Source files originating from a different project (for example the
+MTD subsystem) are generally exempt from these guidelines and are not
+reformatted to ease subsequent migration to newer versions of those
+sources.
+
+Please note that U-Boot is implemented in C (and to some small parts in
+Assembler); no C++ is used, so please do not use C++ style comments (//)
+in your code.
+
+Please also stick to the following formatting rules:
+- remove any trailing white space
+- use TAB characters for indentation and vertical alignment, not spaces
+- make sure NOT to use DOS '\r\n' line feeds
+- do not add more than 2 consecutive empty lines to source files
+- do not add trailing empty lines to source files
+
+Submissions which do not conform to the standards may be returned
+with a request to reformat the changes.
+
+
+Submitting Patches:
+-------------------
+
+Since the number of patches for U-Boot is growing, we need to
+establish some rules. Submissions which do not conform to these rules
+may be rejected, even when they contain important and valuable stuff.
+
+Please see http://www.denx.de/wiki/U-Boot/Patches for details.
+
+Patches shall be sent to the u-boot mailing list <u-boot@lists.denx.de>;
+see https://lists.denx.de/listinfo/u-boot
+
+When you send a patch, please include the following information with
+it:
+
+* For bug fixes: a description of the bug and how your patch fixes
+  this bug. Please try to include a way of demonstrating that the
+  patch actually fixes something.
+
+* For new features: a description of the feature and your
+  implementation.
+
+* A CHANGELOG entry as plaintext (separate from the patch)
+
+* For major contributions, add a MAINTAINERS file with your
+  information and associated file and directory references.
+
+* When you add support for a new board, don't forget to add a
+  maintainer e-mail address to the boards.cfg file, too.
+
+* If your patch adds new configuration options, don't forget to
+  document these in the README file.
+
+* The patch itself. If you are using git (which is *strongly*
+  recommended) you can easily generate the patch using the
+  "git format-patch". If you then use "git send-email" to send it to
+  the U-Boot mailing list, you will avoid most of the common problems
+  with some other mail clients.
+
+  If you cannot use git, use "diff -purN OLD NEW". If your version of
+  diff does not support these options, then get the latest version of
+  GNU diff.
+
+  The current directory when running this command shall be the parent
+  directory of the U-Boot source tree (i. e. please make sure that
+  your patch includes sufficient directory information for the
+  affected files).
+
+  We prefer patches as plain text. MIME attachments are discouraged,
+  and compressed attachments must not be used.
+
+* If one logical set of modifications affects or creates several
+  files, all these changes shall be submitted in a SINGLE patch file.
+
+* Changesets that contain different, unrelated modifications shall be
+  submitted as SEPARATE patches, one patch per changeset.
+
+
+Notes:
+
+* Before sending the patch, run the buildman script on your patched
+  source tree and make sure that no errors or warnings are reported
+  for any of the boards.
+
+* Keep your modifications to the necessary minimum: A patch
+  containing several unrelated changes or arbitrary reformats will be
+  returned with a request to re-formatting / split it.
+
+* If you modify existing code, make sure that your new code does not
+  add to the memory footprint of the code ;-) Small is beautiful!
+  When adding new features, these should compile conditionally only
+  (using #ifdef), and the resulting code with the new feature
+  disabled must not need more memory than the old code without your
+  modification.
+
+* Remember that there is a size limit of 100 kB per message on the
+  u-boot mailing list. Bigger patches will be moderated. If they are
+  reasonable and not too big, they will be acknowledged. But patches
+  bigger than the size limit should be avoided.
diff --git a/README.md b/README.md
deleted file mode 100644
index 1779f85..0000000
--- a/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# SPDX-License-Identifier:	GPL-2.0+
-# u-boot
-
-This is a version of u-boot, modified to support Fuchsia on the Khadas vim2,
-vim3, and NXP imx8mevk boards.
-
-The master branch in this repository is empty.
-
-Please check out one of the platform specific branches, like vim2 or imx8mevk
-for access to the source.
-
-u-boot uses the Gerrit code review system to review and accept patches. Our
-instance is located at [https://third-party-mirror-review.googlesource.com/].
-Please take a look at the CONTRIBUTING file and at that link if you're
-interested.
-
-Building vim2 Bootloader
-========================
-
-To build the vim2 bootloader for Fuchsia:
-
-Prerequisites - arm and aarch64 toolchains. On Debian/Ubuntu systems, for example:
-```
-apt-get install gcc-arm-none-eabi gcc-aarch64-linux-gnu
-```
-
-1. Check out the vim2 branch
-```
-git checkout -b vim2 origin/vim2
-```
-2. Configure the target
-```
-make kvim2_defconfig
-```
-3. Build u-boot.bin
-```
-CROSS_COMPILE=aarch64-linux-gnu- make
-```
-
-You now have a u-boot.bin that you can flash to a target with using fastboot.
diff --git a/api/Kconfig b/api/Kconfig
new file mode 100644
index 0000000..e418adc
--- /dev/null
+++ b/api/Kconfig
@@ -0,0 +1,10 @@
+menu "API"
+
+config API
+	bool "Enable U-Boot API"
+	default n
+	help
+	  This option enables the U-Boot API. See api/README for more information.
+
+endmenu
+
diff --git a/api/Makefile b/api/Makefile
new file mode 100644
index 0000000..bd2d035
--- /dev/null
+++ b/api/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2007 Semihalf
+
+obj-y += api.o api_display.o api_net.o api_storage.o
+obj-$(CONFIG_ARM) += api_platform-arm.o
+obj-$(CONFIG_PPC) += api_platform-powerpc.o
+obj-$(CONFIG_MIPS) += api_platform-mips.o
diff --git a/api/README b/api/README
new file mode 100644
index 0000000..6df225f
--- /dev/null
+++ b/api/README
@@ -0,0 +1,55 @@
+U-Boot machine/arch independent API for external apps
+=====================================================
+
+1.  Main assumptions
+
+  - there is a single entry point (syscall) to the API
+
+  - per current design the syscall is a C-callable function in the U-Boot
+    text, which might evolve into a real syscall using machine exception trap
+    once this initial version proves functional
+
+  - the consumer app is responsible for producing appropriate context (call
+    number and arguments)
+
+  - upon entry, the syscall dispatches the call to other (existing) U-Boot
+    functional areas like networking or storage operations
+
+  - consumer application will recognize the API is available by searching
+    a specified (assumed by convention) range of address space for the
+    signature
+
+  - the U-Boot integral part of the API is meant to be thin and non-intrusive,
+    leaving as much processing as possible on the consumer application side,
+    for example it doesn't keep states, but relies on hints from the app and
+    so on
+
+  - optional (CONFIG_API)
+
+
+2. Calls
+
+  - console related (getc, putc, tstc etc.)
+  - system (reset, platform info)
+  - time (delay, current)
+  - env vars (enumerate all, get, set)
+  - devices (enumerate all, open, close, read, write); currently two classes
+    of devices are recognized and supported: network and storage (ide, scsi,
+    usb etc.)
+
+
+3. Structure overview
+
+  - core API, integral part of U-Boot, mandatory
+    - implements the single entry point (mimics UNIX syscall)
+
+  - glue
+    - entry point at the consumer side, allows to make syscall, mandatory
+      part
+
+    - helper conveniency wrappers so that consumer app does not have to use
+      the syscall directly, but in a more friendly manner (a la libc calls),
+      optional part
+
+  - consumer application
+    - calls directly, or leverages the provided glue mid-layer
diff --git a/api/api.c b/api/api.c
new file mode 100644
index 0000000..9f03f1a
--- /dev/null
+++ b/api/api.c
@@ -0,0 +1,693 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ */
+
+#include <config.h>
+#include <command.h>
+#include <common.h>
+#include <malloc.h>
+#include <environment.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include "api_private.h"
+
+#define DEBUG
+#undef DEBUG
+
+/*****************************************************************************
+ *
+ * This is the API core.
+ *
+ * API_ functions are part of U-Boot code and constitute the lowest level
+ * calls:
+ *
+ *  - they know what values they need as arguments
+ *  - their direct return value pertains to the API_ "shell" itself (0 on
+ *    success, some error code otherwise)
+ *  - if the call returns a value it is buried within arguments
+ *
+ ****************************************************************************/
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+typedef	int (*cfp_t)(va_list argp);
+
+static int calls_no;
+
+/*
+ * pseudo signature:
+ *
+ * int API_getc(int *c)
+ */
+static int API_getc(va_list ap)
+{
+	int *c;
+
+	if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+
+	*c = getc();
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_tstc(int *c)
+ */
+static int API_tstc(va_list ap)
+{
+	int *t;
+
+	if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+
+	*t = tstc();
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_putc(char *ch)
+ */
+static int API_putc(va_list ap)
+{
+	char *c;
+
+	if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+
+	putc(*c);
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_puts(char **s)
+ */
+static int API_puts(va_list ap)
+{
+	char *s;
+
+	if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+
+	puts(s);
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_reset(void)
+ */
+static int API_reset(va_list ap)
+{
+	do_reset(NULL, 0, 0, NULL);
+
+	/* NOT REACHED */
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_get_sys_info(struct sys_info *si)
+ *
+ * fill out the sys_info struct containing selected parameters about the
+ * machine
+ */
+static int API_get_sys_info(va_list ap)
+{
+	struct sys_info *si;
+
+	si = (struct sys_info *)va_arg(ap, uintptr_t);
+	if (si == NULL)
+		return API_ENOMEM;
+
+	return (platform_sys_info(si)) ? 0 : API_ENODEV;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_udelay(unsigned long *udelay)
+ */
+static int API_udelay(va_list ap)
+{
+	unsigned long *d;
+
+	if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
+		return API_EINVAL;
+
+	udelay(*d);
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_get_timer(unsigned long *current, unsigned long *base)
+ */
+static int API_get_timer(va_list ap)
+{
+	unsigned long *base, *cur;
+
+	cur = (unsigned long *)va_arg(ap, unsigned long);
+	if (cur == NULL)
+		return API_EINVAL;
+
+	base = (unsigned long *)va_arg(ap, unsigned long);
+	if (base == NULL)
+		return API_EINVAL;
+
+	*cur = get_timer(*base);
+	return 0;
+}
+
+
+/*****************************************************************************
+ *
+ * pseudo signature:
+ *
+ * int API_dev_enum(struct device_info *)
+ *
+ *
+ * cookies uniqely identify the previously enumerated device instance and
+ * provide a hint for what to inspect in current enum iteration:
+ *
+ *   - net: &eth_device struct address from list pointed to by eth_devices
+ *
+ *   - storage: struct blk_desc struct address from &ide_dev_desc[n],
+ *     &scsi_dev_desc[n] and similar tables
+ *
+ ****************************************************************************/
+
+static int API_dev_enum(va_list ap)
+{
+	struct device_info *di;
+
+	/* arg is ptr to the device_info struct we are going to fill out */
+	di = (struct device_info *)va_arg(ap, uintptr_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	if (di->cookie == NULL) {
+		/* start over - clean up enumeration */
+		dev_enum_reset();	/* XXX shouldn't the name contain 'stor'? */
+		debugf("RESTART ENUM\n");
+
+		/* net device enumeration first */
+		if (dev_enum_net(di))
+			return 0;
+	}
+
+	/*
+	 * The hidden assumption is there can only be one active network
+	 * device and it is identified upon enumeration (re)start, so there's
+	 * no point in trying to find network devices in other cases than the
+	 * (re)start and hence the 'next' device can only be storage
+	 */
+	if (!dev_enum_storage(di))
+		/* make sure we mark there are no more devices */
+		di->cookie = NULL;
+
+	return 0;
+}
+
+
+static int API_dev_open(va_list ap)
+{
+	struct device_info *di;
+	int err = 0;
+
+	/* arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, uintptr_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	/* Allow only one consumer of the device at a time */
+	if (di->state == DEV_STA_OPEN)
+		return API_EBUSY;
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	if (di->type & DEV_TYP_STOR)
+		err = dev_open_stor(di->cookie);
+
+	else if (di->type & DEV_TYP_NET)
+		err = dev_open_net(di->cookie);
+	else
+		err = API_ENODEV;
+
+	if (!err)
+		di->state = DEV_STA_OPEN;
+
+	return err;
+}
+
+
+static int API_dev_close(va_list ap)
+{
+	struct device_info *di;
+	int err = 0;
+
+	/* arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, uintptr_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	if (di->state == DEV_STA_CLOSED)
+		return 0;
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	if (di->type & DEV_TYP_STOR)
+		err = dev_close_stor(di->cookie);
+
+	else if (di->type & DEV_TYP_NET)
+		err = dev_close_net(di->cookie);
+	else
+		/*
+		 * In case of unknown device we cannot change its state, so
+		 * only return error code
+		 */
+		err = API_ENODEV;
+
+	if (!err)
+		di->state = DEV_STA_CLOSED;
+
+	return err;
+}
+
+
+/*
+ * Notice: this is for sending network packets only, as U-Boot does not
+ * support writing to storage at the moment (12.2007)
+ *
+ * pseudo signature:
+ *
+ * int API_dev_write(
+ *	struct device_info *di,
+ *	void *buf,
+ *	int *len
+ * )
+ *
+ * buf:	ptr to buffer from where to get the data to send
+ *
+ * len: length of packet to be sent (in bytes)
+ *
+ */
+static int API_dev_write(va_list ap)
+{
+	struct device_info *di;
+	void *buf;
+	int *len;
+	int err = 0;
+
+	/* 1. arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, uintptr_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	/* XXX should we check if device is open? i.e. the ->state ? */
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	/* 2. arg is ptr to buffer from where to get data to write */
+	buf = (void *)va_arg(ap, uintptr_t);
+	if (buf == NULL)
+		return API_EINVAL;
+
+	/* 3. arg is length of buffer */
+	len = (int *)va_arg(ap, uintptr_t);
+	if (len == NULL)
+		return API_EINVAL;
+	if (*len <= 0)
+		return API_EINVAL;
+
+	if (di->type & DEV_TYP_STOR)
+		/*
+		 * write to storage is currently not supported by U-Boot:
+		 * no storage device implements block_write() method
+		 */
+		return API_ENODEV;
+
+	else if (di->type & DEV_TYP_NET)
+		err = dev_write_net(di->cookie, buf, *len);
+	else
+		err = API_ENODEV;
+
+	return err;
+}
+
+
+/*
+ * pseudo signature:
+ *
+ * int API_dev_read(
+ *	struct device_info *di,
+ *	void *buf,
+ *	size_t *len,
+ *	unsigned long *start
+ *	size_t *act_len
+ * )
+ *
+ * buf:	ptr to buffer where to put the read data
+ *
+ * len: ptr to length to be read
+ *      - network: len of packet to read (in bytes)
+ *      - storage: # of blocks to read (can vary in size depending on define)
+ *
+ * start: ptr to start block (only used for storage devices, ignored for
+ *        network)
+ *
+ * act_len: ptr to where to put the len actually read
+ */
+static int API_dev_read(va_list ap)
+{
+	struct device_info *di;
+	void *buf;
+	lbasize_t *len_stor, *act_len_stor;
+	lbastart_t *start;
+	int *len_net, *act_len_net;
+
+	/* 1. arg is ptr to the device_info struct */
+	di = (struct device_info *)va_arg(ap, uintptr_t);
+	if (di == NULL)
+		return API_EINVAL;
+
+	/* XXX should we check if device is open? i.e. the ->state ? */
+
+	if (di->cookie == NULL)
+		return API_ENODEV;
+
+	/* 2. arg is ptr to buffer from where to put the read data */
+	buf = (void *)va_arg(ap, uintptr_t);
+	if (buf == NULL)
+		return API_EINVAL;
+
+	if (di->type & DEV_TYP_STOR) {
+		/* 3. arg - ptr to var with # of blocks to read */
+		len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
+		if (!len_stor)
+			return API_EINVAL;
+		if (*len_stor <= 0)
+			return API_EINVAL;
+
+		/* 4. arg - ptr to var with start block */
+		start = (lbastart_t *)va_arg(ap, uintptr_t);
+
+		/* 5. arg - ptr to var where to put the len actually read */
+		act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
+		if (!act_len_stor)
+			return API_EINVAL;
+
+		*act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
+
+	} else if (di->type & DEV_TYP_NET) {
+
+		/* 3. arg points to the var with length of packet to read */
+		len_net = (int *)va_arg(ap, uintptr_t);
+		if (!len_net)
+			return API_EINVAL;
+		if (*len_net <= 0)
+			return API_EINVAL;
+
+		/* 4. - ptr to var where to put the len actually read */
+		act_len_net = (int *)va_arg(ap, uintptr_t);
+		if (!act_len_net)
+			return API_EINVAL;
+
+		*act_len_net = dev_read_net(di->cookie, buf, *len_net);
+
+	} else
+		return API_ENODEV;
+
+	return 0;
+}
+
+
+/*
+ * pseudo signature:
+ *
+ * int API_env_get(const char *name, char **value)
+ *
+ * name: ptr to name of env var
+ */
+static int API_env_get(va_list ap)
+{
+	char *name, **value;
+
+	if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+	if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+
+	*value = env_get(name);
+
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_env_set(const char *name, const char *value)
+ *
+ * name: ptr to name of env var
+ *
+ * value: ptr to value to be set
+ */
+static int API_env_set(va_list ap)
+{
+	char *name, *value;
+
+	if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+	if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+
+	env_set(name, value);
+
+	return 0;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_env_enum(const char *last, char **next)
+ *
+ * last: ptr to name of env var found in last iteration
+ */
+static int API_env_enum(va_list ap)
+{
+	int i, buflen;
+	char *last, **next, *s;
+	ENTRY *match, search;
+	static char *var;
+
+	last = (char *)va_arg(ap, unsigned long);
+
+	if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
+		return API_EINVAL;
+
+	if (last == NULL) {
+		var = NULL;
+		i = 0;
+	} else {
+		var = strdup(last);
+		s = strchr(var, '=');
+		if (s != NULL)
+			*s = 0;
+		search.key = var;
+		i = hsearch_r(search, FIND, &match, &env_htab, 0);
+		if (i == 0) {
+			i = API_EINVAL;
+			goto done;
+		}
+	}
+
+	/* match the next entry after i */
+	i = hmatch_r("", i, &match, &env_htab);
+	if (i == 0)
+		goto done;
+	buflen = strlen(match->key) + strlen(match->data) + 2;
+	var = realloc(var, buflen);
+	snprintf(var, buflen, "%s=%s", match->key, match->data);
+	*next = var;
+	return 0;
+
+done:
+	free(var);
+	var = NULL;
+	*next = NULL;
+	return i;
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_display_get_info(int type, struct display_info *di)
+ */
+static int API_display_get_info(va_list ap)
+{
+	int type;
+	struct display_info *di;
+
+	type = va_arg(ap, int);
+	di = va_arg(ap, struct display_info *);
+
+	return display_get_info(type, di);
+}
+
+/*
+ * pseudo signature:
+ *
+ * int API_display_draw_bitmap(ulong bitmap, int x, int y)
+ */
+static int API_display_draw_bitmap(va_list ap)
+{
+	ulong bitmap;
+	int x, y;
+
+	bitmap = va_arg(ap, ulong);
+	x = va_arg(ap, int);
+	y = va_arg(ap, int);
+
+	return display_draw_bitmap(bitmap, x, y);
+}
+
+/*
+ * pseudo signature:
+ *
+ * void API_display_clear(void)
+ */
+static int API_display_clear(va_list ap)
+{
+	display_clear();
+	return 0;
+}
+
+static cfp_t calls_table[API_MAXCALL] = { NULL, };
+
+/*
+ * The main syscall entry point - this is not reentrant, only one call is
+ * serviced until finished.
+ *
+ * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
+ *
+ * call:	syscall number
+ *
+ * retval:	points to the return value placeholder, this is the place the
+ *		syscall puts its return value, if NULL the caller does not
+ *		expect a return value
+ *
+ * ...		syscall arguments (variable number)
+ *
+ * returns:	0 if the call not found, 1 if serviced
+ */
+int syscall(int call, int *retval, ...)
+{
+	va_list	ap;
+	int rv;
+
+	if (call < 0 || call >= calls_no) {
+		debugf("invalid call #%d\n", call);
+		return 0;
+	}
+
+	if (calls_table[call] == NULL) {
+		debugf("syscall #%d does not have a handler\n", call);
+		return 0;
+	}
+
+	va_start(ap, retval);
+	rv = calls_table[call](ap);
+	if (retval != NULL)
+		*retval = rv;
+
+	return 1;
+}
+
+void api_init(void)
+{
+	struct api_signature *sig;
+
+	/* TODO put this into linker set one day... */
+	calls_table[API_RSVD] = NULL;
+	calls_table[API_GETC] = &API_getc;
+	calls_table[API_PUTC] = &API_putc;
+	calls_table[API_TSTC] = &API_tstc;
+	calls_table[API_PUTS] = &API_puts;
+	calls_table[API_RESET] = &API_reset;
+	calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
+	calls_table[API_UDELAY] = &API_udelay;
+	calls_table[API_GET_TIMER] = &API_get_timer;
+	calls_table[API_DEV_ENUM] = &API_dev_enum;
+	calls_table[API_DEV_OPEN] = &API_dev_open;
+	calls_table[API_DEV_CLOSE] = &API_dev_close;
+	calls_table[API_DEV_READ] = &API_dev_read;
+	calls_table[API_DEV_WRITE] = &API_dev_write;
+	calls_table[API_ENV_GET] = &API_env_get;
+	calls_table[API_ENV_SET] = &API_env_set;
+	calls_table[API_ENV_ENUM] = &API_env_enum;
+	calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
+	calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
+	calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
+	calls_no = API_MAXCALL;
+
+	debugf("API initialized with %d calls\n", calls_no);
+
+	dev_stor_init();
+
+	/*
+	 * Produce the signature so the API consumers can find it
+	 */
+	sig = malloc(sizeof(struct api_signature));
+	if (sig == NULL) {
+		printf("API: could not allocate memory for the signature!\n");
+		return;
+	}
+
+	env_set_hex("api_address", (unsigned long)sig);
+	debugf("API sig @ 0x%lX\n", (unsigned long)sig);
+	memcpy(sig->magic, API_SIG_MAGIC, 8);
+	sig->version = API_SIG_VERSION;
+	sig->syscall = &syscall;
+	sig->checksum = 0;
+	sig->checksum = crc32(0, (unsigned char *)sig,
+			      sizeof(struct api_signature));
+	debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
+}
+
+void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
+			int flags)
+{
+	int i;
+
+	if (!si->mr || !size || (flags == 0))
+		return;
+
+	/* find free slot */
+	for (i = 0; i < si->mr_no; i++)
+		if (si->mr[i].flags == 0) {
+			/* insert new mem region */
+			si->mr[i].start = start;
+			si->mr[i].size = size;
+			si->mr[i].flags = flags;
+			return;
+		}
+}
diff --git a/api/api_display.c b/api/api_display.c
new file mode 100644
index 0000000..8ae358a
--- /dev/null
+++ b/api/api_display.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <api_public.h>
+#include <lcd.h>
+#include <video_font.h> /* Get font width and height */
+
+/* lcd.h needs BMP_LOGO_HEIGHT to calculate CONSOLE_ROWS */
+#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
+#include <bmp_logo.h>
+#endif
+
+/* TODO(clchiou): add support of video device */
+
+int display_get_info(int type, struct display_info *di)
+{
+	if (!di)
+		return API_EINVAL;
+
+	switch (type) {
+	default:
+		debug("%s: unsupport display device type: %d\n",
+				__FILE__, type);
+		return API_ENODEV;
+#ifdef CONFIG_LCD
+	case DISPLAY_TYPE_LCD:
+		di->pixel_width  = panel_info.vl_col;
+		di->pixel_height = panel_info.vl_row;
+		di->screen_rows = lcd_get_screen_rows();
+		di->screen_cols = lcd_get_screen_columns();
+		break;
+#endif
+	}
+
+	di->type = type;
+	return 0;
+}
+
+int display_draw_bitmap(ulong bitmap, int x, int y)
+{
+	if (!bitmap)
+		return API_EINVAL;
+#ifdef CONFIG_LCD
+	return lcd_display_bitmap(bitmap, x, y);
+#else
+	return API_ENODEV;
+#endif
+}
+
+void display_clear(void)
+{
+#ifdef CONFIG_LCD
+	lcd_clear();
+#endif
+}
diff --git a/api/api_net.c b/api/api_net.c
new file mode 100644
index 0000000..7515c26
--- /dev/null
+++ b/api/api_net.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
+
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
+
+static int dev_valid_net(void *cookie)
+{
+	return ((void *)eth_get_dev() == cookie) ? 1 : 0;
+}
+
+int dev_open_net(void *cookie)
+{
+	if (!dev_valid_net(cookie))
+		return API_ENODEV;
+
+	if (eth_init() < 0)
+		return API_EIO;
+
+	return 0;
+}
+
+int dev_close_net(void *cookie)
+{
+	if (!dev_valid_net(cookie))
+		return API_ENODEV;
+
+	eth_halt();
+	return 0;
+}
+
+/*
+ * There can only be one active eth interface at a time - use what is
+ * currently set to eth_current
+ */
+int dev_enum_net(struct device_info *di)
+{
+	struct eth_device *eth_current = eth_get_dev();
+
+	di->type = DEV_TYP_NET;
+	di->cookie = (void *)eth_current;
+	if (di->cookie == NULL)
+		return 0;
+
+	memcpy(di->di_net.hwaddr, eth_current->enetaddr, 6);
+
+	debugf("device found, returning cookie 0x%08x\n",
+		(u_int32_t)di->cookie);
+
+	return 1;
+}
+
+int dev_write_net(void *cookie, void *buf, int len)
+{
+	/* XXX verify that cookie points to a valid net device??? */
+
+	return eth_send(buf, len);
+}
+
+int dev_read_net(void *cookie, void *buf, int len)
+{
+	/* XXX verify that cookie points to a valid net device??? */
+
+	return eth_receive(buf, len);
+}
+
+#else
+
+int dev_open_net(void *cookie)
+{
+	return API_ENODEV;
+}
+
+int dev_close_net(void *cookie)
+{
+	return API_ENODEV;
+}
+
+int dev_enum_net(struct device_info *di)
+{
+	return 0;
+}
+
+int dev_write_net(void *cookie, void *buf, int len)
+{
+	return API_ENODEV;
+}
+
+int dev_read_net(void *cookie, void *buf, int len)
+{
+	return API_ENODEV;
+}
+
+#endif
diff --git a/api/api_platform-arm.c b/api/api_platform-arm.c
new file mode 100644
index 0000000..6cfd9e6
--- /dev/null
+++ b/api/api_platform-arm.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * This file contains routines that fetch data from ARM-dependent sources
+ * (bd_info etc.)
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include <asm/u-boot.h>
+#include <asm/global_data.h>
+
+#include "api_private.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Important notice: handling of individual fields MUST be kept in sync with
+ * include/asm-arm/u-boot.h and include/asm-arm/global_data.h, so any changes
+ * need to reflect their current state and layout of structures involved!
+ */
+int platform_sys_info(struct sys_info *si)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
+		platform_set_mr(si, gd->bd->bi_dram[i].start,
+				gd->bd->bi_dram[i].size, MR_ATTR_DRAM);
+
+	return 1;
+}
diff --git a/api/api_platform-mips.c b/api/api_platform-mips.c
new file mode 100644
index 0000000..51cd328
--- /dev/null
+++ b/api/api_platform-mips.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 Stanislav Galabov <sgalabov@gmail.com>
+ *
+ * This file contains routines that fetch data from bd_info sources
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include <asm/u-boot.h>
+#include <asm/global_data.h>
+
+#include "api_private.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Important notice: handling of individual fields MUST be kept in sync with
+ * include/asm-generic/u-boot.h, so any changes
+ * need to reflect their current state and layout of structures involved!
+ */
+int platform_sys_info(struct sys_info *si)
+{
+
+	platform_set_mr(si, gd->bd->bi_memstart,
+			gd->bd->bi_memsize, MR_ATTR_DRAM);
+
+	return 1;
+}
diff --git a/api/api_platform-powerpc.c b/api/api_platform-powerpc.c
new file mode 100644
index 0000000..15930cf
--- /dev/null
+++ b/api/api_platform-powerpc.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * This file contains routines that fetch data from PowerPC-dependent sources
+ * (bd_info etc.)
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <api_public.h>
+
+#include <asm/u-boot.h>
+#include <asm/global_data.h>
+
+#include "api_private.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Important notice: handling of individual fields MUST be kept in sync with
+ * include/asm-ppc/u-boot.h and include/asm-ppc/global_data.h, so any changes
+ * need to reflect their current state and layout of structures involved!
+ */
+int platform_sys_info(struct sys_info *si)
+{
+	si->clk_bus = gd->bus_clk;
+	si->clk_cpu = gd->cpu_clk;
+
+#if defined(CONFIG_MPC8xx) || defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+#define bi_bar	bi_immr_base
+#elif defined(CONFIG_MPC83xx)
+#define bi_bar	bi_immrbar
+#endif
+
+#if defined(bi_bar)
+	si->bar = gd->bd->bi_bar;
+#undef bi_bar
+#else
+	si->bar = 0;
+#endif
+
+	platform_set_mr(si, gd->bd->bi_memstart, gd->bd->bi_memsize, MR_ATTR_DRAM);
+	platform_set_mr(si, gd->bd->bi_flashstart, gd->bd->bi_flashsize, MR_ATTR_FLASH);
+	platform_set_mr(si, gd->bd->bi_sramstart, gd->bd->bi_sramsize, MR_ATTR_SRAM);
+
+	return 1;
+}
diff --git a/api/api_private.h b/api/api_private.h
new file mode 100644
index 0000000..8d97ca9
--- /dev/null
+++ b/api/api_private.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2007 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ */
+
+#ifndef _API_PRIVATE_H_
+#define _API_PRIVATE_H_
+
+void	api_init(void);
+void	platform_set_mr(struct sys_info *, unsigned long, unsigned long, int);
+int	platform_sys_info(struct sys_info *);
+
+void	dev_enum_reset(void);
+int	dev_enum_storage(struct device_info *);
+int	dev_enum_net(struct device_info *);
+
+int	dev_open_stor(void *);
+int	dev_open_net(void *);
+int	dev_close_stor(void *);
+int	dev_close_net(void *);
+
+lbasize_t	dev_read_stor(void *, void *, lbasize_t, lbastart_t);
+int		dev_read_net(void *, void *, int);
+int		dev_write_net(void *, void *, int);
+
+void dev_stor_init(void);
+
+int display_get_info(int type, struct display_info *di);
+int display_draw_bitmap(ulong bitmap, int x, int y);
+void display_clear(void);
+
+#endif /* _API_PRIVATE_H_ */
diff --git a/api/api_storage.c b/api/api_storage.c
new file mode 100644
index 0000000..2b90c18
--- /dev/null
+++ b/api/api_storage.c
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007-2008 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <api_public.h>
+
+#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
+#include <usb.h>
+#endif
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
+
+
+#define ENUM_IDE	0
+#define ENUM_USB	1
+#define ENUM_SCSI	2
+#define ENUM_MMC	3
+#define ENUM_SATA	4
+#define ENUM_MAX	5
+
+struct stor_spec {
+	int		max_dev;
+	int		enum_started;
+	int		enum_ended;
+	int		type;	/* "external" type: DT_STOR_{IDE,USB,etc} */
+	char		*name;
+};
+
+static struct stor_spec specs[ENUM_MAX] = { { 0, 0, 0, 0, NULL }, };
+
+#ifndef CONFIG_SYS_MMC_MAX_DEVICE
+#define CONFIG_SYS_MMC_MAX_DEVICE	1
+#endif
+
+void dev_stor_init(void)
+{
+#if defined(CONFIG_IDE)
+	specs[ENUM_IDE].max_dev = CONFIG_SYS_IDE_MAXDEVICE;
+	specs[ENUM_IDE].enum_started = 0;
+	specs[ENUM_IDE].enum_ended = 0;
+	specs[ENUM_IDE].type = DEV_TYP_STOR | DT_STOR_IDE;
+	specs[ENUM_IDE].name = "ide";
+#endif
+#if defined(CONFIG_CMD_MMC)
+	specs[ENUM_MMC].max_dev = CONFIG_SYS_MMC_MAX_DEVICE;
+	specs[ENUM_MMC].enum_started = 0;
+	specs[ENUM_MMC].enum_ended = 0;
+	specs[ENUM_MMC].type = DEV_TYP_STOR | DT_STOR_MMC;
+	specs[ENUM_MMC].name = "mmc";
+#endif
+#if defined(CONFIG_SATA)
+	specs[ENUM_SATA].max_dev = CONFIG_SYS_SATA_MAX_DEVICE;
+	specs[ENUM_SATA].enum_started = 0;
+	specs[ENUM_SATA].enum_ended = 0;
+	specs[ENUM_SATA].type = DEV_TYP_STOR | DT_STOR_SATA;
+	specs[ENUM_SATA].name = "sata";
+#endif
+#if defined(CONFIG_SCSI)
+	specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE;
+	specs[ENUM_SCSI].enum_started = 0;
+	specs[ENUM_SCSI].enum_ended = 0;
+	specs[ENUM_SCSI].type = DEV_TYP_STOR | DT_STOR_SCSI;
+	specs[ENUM_SCSI].name = "scsi";
+#endif
+#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
+	specs[ENUM_USB].max_dev = USB_MAX_STOR_DEV;
+	specs[ENUM_USB].enum_started = 0;
+	specs[ENUM_USB].enum_ended = 0;
+	specs[ENUM_USB].type = DEV_TYP_STOR | DT_STOR_USB;
+	specs[ENUM_USB].name = "usb";
+#endif
+}
+
+/*
+ * Finds next available device in the storage group
+ *
+ * type:	storage group type - ENUM_IDE, ENUM_SCSI etc.
+ *
+ * more:	returns 0/1 depending if there are more devices in this group
+ *		available (for future iterations)
+ *
+ * returns:	0/1 depending if device found in this iteration
+ */
+static int dev_stor_get(int type, int *more, struct device_info *di)
+{
+	struct blk_desc *dd;
+	int found = 0;
+	int found_last = 0;
+	int i = 0;
+
+	/* Wasn't configured for this type, return 0 directly */
+	if (specs[type].name == NULL)
+		return 0;
+
+	if (di->cookie != NULL) {
+		/* Find the last device we've returned  */
+		for (i = 0; i < specs[type].max_dev; i++) {
+			if (di->cookie ==
+			    (void *)blk_get_dev(specs[type].name, i)) {
+				i += 1;
+				found_last = 1;
+				break;
+			}
+		}
+
+		if (!found_last)
+			i = 0;
+	}
+
+	for (; i < specs[type].max_dev; i++) {
+		di->cookie = (void *)blk_get_dev(specs[type].name, i);
+
+		if (di->cookie != NULL) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (i == specs[type].max_dev)
+		*more = 0;
+	else
+		*more = 1;
+
+	if (found) {
+		di->type = specs[type].type;
+
+		dd = (struct blk_desc *)di->cookie;
+		if (dd->type == DEV_TYPE_UNKNOWN) {
+			debugf("device instance exists, but is not active..");
+			found = 0;
+		} else {
+			di->di_stor.block_count = dd->lba;
+			di->di_stor.block_size = dd->blksz;
+		}
+	} else {
+		di->cookie = NULL;
+	}
+
+	return found;
+}
+
+
+/* returns: ENUM_IDE, ENUM_USB etc. based on struct blk_desc */
+
+static int dev_stor_type(struct blk_desc *dd)
+{
+	int i, j;
+
+	for (i = ENUM_IDE; i < ENUM_MAX; i++)
+		for (j = 0; j < specs[i].max_dev; j++)
+			if (dd == blk_get_dev(specs[i].name, j))
+				return i;
+
+	return ENUM_MAX;
+}
+
+
+/* returns: 0/1 whether cookie points to some device in this group */
+
+static int dev_is_stor(int type, struct device_info *di)
+{
+	return (dev_stor_type(di->cookie) == type) ? 1 : 0;
+}
+
+
+static int dev_enum_stor(int type, struct device_info *di)
+{
+	int found = 0, more = 0;
+
+	debugf("called, type %d\n", type);
+
+	/*
+	 * Formulae for enumerating storage devices:
+	 * 1. if cookie (hint from previous enum call) is NULL we start again
+	 *    with enumeration, so return the first available device, done.
+	 *
+	 * 2. if cookie is not NULL, check if it identifies some device in
+	 *    this group:
+	 *
+	 * 2a. if cookie is a storage device from our group (IDE, USB etc.),
+	 *     return next available (if exists) in this group
+	 *
+	 * 2b. if it isn't device from our group, check if such devices were
+	 *     ever enumerated before:
+	 *     - if not, return the first available device from this group
+	 *     - else return 0
+	 */
+
+	if (di->cookie == NULL) {
+		debugf("group%d - enum restart\n", type);
+
+		/*
+		 * 1. Enumeration (re-)started: take the first available
+		 * device, if exists
+		 */
+		found = dev_stor_get(type, &more, di);
+		specs[type].enum_started = 1;
+
+	} else if (dev_is_stor(type, di)) {
+		debugf("group%d - enum continued for the next device\n", type);
+
+		if (specs[type].enum_ended) {
+			debugf("group%d - nothing more to enum!\n", type);
+			return 0;
+		}
+
+		/* 2a. Attempt to take a next available device in the group */
+		found = dev_stor_get(type, &more, di);
+
+	} else {
+		if (specs[type].enum_ended) {
+			debugf("group %d - already enumerated, skipping\n", type);
+			return 0;
+		}
+
+		debugf("group%d - first time enum\n", type);
+
+		if (specs[type].enum_started == 0) {
+			/*
+			 * 2b.  If enumerating devices in this group did not
+			 * happen before, it means the cookie pointed to a
+			 * device from some other group (another storage
+			 * group, or network); in this case try to take the
+			 * first available device from our group
+			 */
+			specs[type].enum_started = 1;
+
+			/*
+			 * Attempt to take the first device in this group:
+			 *'first element' flag is set
+			 */
+			found = dev_stor_get(type, &more, di);
+
+		} else {
+			errf("group%d - out of order iteration\n", type);
+			found = 0;
+			more = 0;
+		}
+	}
+
+	/*
+	 * If there are no more devices in this group, consider its
+	 * enumeration finished
+	 */
+	specs[type].enum_ended = (!more) ? 1 : 0;
+
+	if (found)
+		debugf("device found, returning cookie 0x%08x\n",
+		       (u_int32_t)di->cookie);
+	else
+		debugf("no device found\n");
+
+	return found;
+}
+
+void dev_enum_reset(void)
+{
+	int i;
+
+	for (i = 0; i < ENUM_MAX; i ++) {
+		specs[i].enum_started = 0;
+		specs[i].enum_ended = 0;
+	}
+}
+
+int dev_enum_storage(struct device_info *di)
+{
+	int i;
+
+	/* check: ide, usb, scsi, mmc */
+	for (i = ENUM_IDE; i < ENUM_MAX; i ++) {
+		if (dev_enum_stor(i, di))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int dev_stor_is_valid(int type, struct blk_desc *dd)
+{
+	int i;
+
+	for (i = 0; i < specs[type].max_dev; i++)
+		if (dd == blk_get_dev(specs[type].name, i))
+			if (dd->type != DEV_TYPE_UNKNOWN)
+				return 1;
+
+	return 0;
+}
+
+
+int dev_open_stor(void *cookie)
+{
+	int type = dev_stor_type(cookie);
+
+	if (type == ENUM_MAX)
+		return API_ENODEV;
+
+	if (dev_stor_is_valid(type, (struct blk_desc *)cookie))
+		return 0;
+
+	return API_ENODEV;
+}
+
+
+int dev_close_stor(void *cookie)
+{
+	/*
+	 * Not much to do as we actually do not alter storage devices upon
+	 * close
+	 */
+	return 0;
+}
+
+
+lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start)
+{
+	int type;
+	struct blk_desc *dd = (struct blk_desc *)cookie;
+
+	if ((type = dev_stor_type(dd)) == ENUM_MAX)
+		return 0;
+
+	if (!dev_stor_is_valid(type, dd))
+		return 0;
+
+#ifdef CONFIG_BLK
+	return blk_dread(dd, start, len, buf);
+#else
+	if ((dd->block_read) == NULL) {
+		debugf("no block_read() for device 0x%08x\n", cookie);
+		return 0;
+	}
+
+	return dd->block_read(dd, start, len, buf);
+#endif	/* defined(CONFIG_BLK) */
+}
diff --git a/arch/.gitignore b/arch/.gitignore
new file mode 100644
index 0000000..2714b86
--- /dev/null
+++ b/arch/.gitignore
@@ -0,0 +1 @@
+/*/include/asm/arch
diff --git a/arch/Kconfig b/arch/Kconfig
new file mode 100644
index 0000000..11e7713
--- /dev/null
+++ b/arch/Kconfig
@@ -0,0 +1,240 @@
+config CREATE_ARCH_SYMLINK
+	bool
+
+config HAVE_ARCH_IOREMAP
+	bool
+
+choice
+	prompt "Architecture select"
+	default SANDBOX
+
+config ARC
+	bool "ARC architecture"
+	select ARCH_EARLY_INIT_R
+	select ARC_TIMER
+	select CLK
+	select HAVE_PRIVATE_LIBGCC
+	select SUPPORT_OF_CONTROL
+	select TIMER
+
+config ARM
+	bool "ARM architecture"
+	select CREATE_ARCH_SYMLINK
+	select HAVE_PRIVATE_LIBGCC if !ARM64
+	select SUPPORT_OF_CONTROL
+
+config M68K
+	bool "M68000 architecture"
+	select HAVE_PRIVATE_LIBGCC
+	select SYS_BOOT_GET_CMDLINE
+	select SYS_BOOT_GET_KBD
+
+config MICROBLAZE
+	bool "MicroBlaze architecture"
+	select SUPPORT_OF_CONTROL
+	imply CMD_IRQ
+
+config MIPS
+	bool "MIPS architecture"
+	select HAVE_ARCH_IOREMAP
+	select HAVE_PRIVATE_LIBGCC
+	select SUPPORT_OF_CONTROL
+
+config NDS32
+	bool "NDS32 architecture"
+	select SUPPORT_OF_CONTROL
+
+config NIOS2
+	bool "Nios II architecture"
+	select CPU
+	select DM
+	select OF_CONTROL
+	select SUPPORT_OF_CONTROL
+	imply CMD_DM
+
+config PPC
+	bool "PowerPC architecture"
+	select HAVE_PRIVATE_LIBGCC
+	select SUPPORT_OF_CONTROL
+	select SYS_BOOT_GET_CMDLINE
+	select SYS_BOOT_GET_KBD
+
+config RISCV
+	bool "RISC-V architecture"
+	select SUPPORT_OF_CONTROL
+	select OF_CONTROL
+	select DM
+	imply DM_SERIAL
+	imply DM_ETH
+	imply DM_MMC
+	imply DM_SPI
+	imply DM_SPI_FLASH
+	imply BLK
+	imply CLK
+	imply MTD
+	imply TIMER
+	imply CMD_DM
+
+config SANDBOX
+	bool "Sandbox"
+	select BOARD_LATE_INIT
+	select DM
+	select DM_GPIO
+	select DM_I2C
+	select DM_KEYBOARD
+	select DM_MMC
+	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
+	select HAVE_BLOCK_DEVICE
+	select LZO
+	select SPI
+	select SUPPORT_OF_CONTROL
+	imply BITREVERSE
+	select BLOBLIST
+	imply CMD_DM
+	imply CMD_GETTIME
+	imply CMD_HASH
+	imply CMD_IO
+	imply CMD_IOTRACE
+	imply CMD_LZMADEC
+	imply CMD_SATA
+	imply CMD_SF_TEST
+	imply CRC32_VERIFY
+	imply FAT_WRITE
+	imply FIRMWARE
+	imply HASH_VERIFY
+	imply LZMA
+	imply SCSI
+	imply TEE
+	imply AVB_VERIFY
+	imply LIBAVB
+	imply CMD_AVB
+	imply UDP_FUNCTION_FASTBOOT
+	imply VIRTIO_MMIO
+	imply VIRTIO_PCI
+	imply VIRTIO_SANDBOX
+	imply VIRTIO_BLK
+	imply VIRTIO_NET
+	imply DM_SOUND
+
+config SH
+	bool "SuperH architecture"
+	select HAVE_PRIVATE_LIBGCC
+
+config X86
+	bool "x86 architecture"
+	select CREATE_ARCH_SYMLINK
+	select DM
+	select DM_PCI
+	select HAVE_ARCH_IOMAP
+	select HAVE_PRIVATE_LIBGCC
+	select OF_CONTROL
+	select PCI
+	select SUPPORT_OF_CONTROL
+	select TIMER
+	select USE_PRIVATE_LIBGCC
+	select X86_TSC_TIMER
+	imply BLK
+	imply CMD_DM
+	imply CMD_FPGA_LOADMK
+	imply CMD_GETTIME
+	imply CMD_IO
+	imply CMD_IRQ
+	imply CMD_PCI
+	imply CMD_SF_TEST
+	imply CMD_ZBOOT
+	imply DM_ETH
+	imply DM_GPIO
+	imply DM_KEYBOARD
+	imply DM_MMC
+	imply DM_RTC
+	imply DM_SCSI
+	imply DM_SERIAL
+	imply DM_SPI
+	imply DM_SPI_FLASH
+	imply DM_USB
+	imply DM_VIDEO
+	imply SYSRESET
+	imply SYSRESET_X86
+	imply USB_ETHER_ASIX
+	imply USB_ETHER_SMSC95XX
+	imply USB_HOST_ETHER
+
+config XTENSA
+	bool "Xtensa architecture"
+	select CREATE_ARCH_SYMLINK
+	select SUPPORT_OF_CONTROL
+
+endchoice
+
+config SYS_ARCH
+	string
+	help
+	  This option should contain the architecture name to build the
+	  appropriate arch/<CONFIG_SYS_ARCH> directory.
+	  All the architectures should specify this option correctly.
+
+config SYS_CPU
+	string
+	help
+	  This option should contain the CPU name to build the correct
+	  arch/<CONFIG_SYS_ARCH>/cpu/<CONFIG_SYS_CPU> directory.
+
+	  This is optional.  For those targets without the CPU directory,
+	  leave this option empty.
+
+config SYS_SOC
+	string
+	help
+	  This option should contain the SoC name to build the directory
+	  arch/<CONFIG_SYS_ARCH>/cpu/<CONFIG_SYS_CPU>/<CONFIG_SYS_SOC>.
+
+	  This is optional.  For those targets without the SoC directory,
+	  leave this option empty.
+
+config SYS_VENDOR
+	string
+	help
+	  This option should contain the vendor name of the target board.
+	  If it is set and
+	  board/<CONFIG_SYS_VENDOR>/common/Makefile exists, the vendor common
+	  directory is compiled.
+	  If CONFIG_SYS_BOARD is also set, the sources under
+	  board/<CONFIG_SYS_VENDOR>/<CONFIG_SYS_BOARD> directory are compiled.
+
+	  This is optional.  For those targets without the vendor directory,
+	  leave this option empty.
+
+config SYS_BOARD
+	string
+	help
+	  This option should contain the name of the target board.
+	  If it is set, either board/<CONFIG_SYS_VENDOR>/<CONFIG_SYS_BOARD>
+	  or board/<CONFIG_SYS_BOARD> directory is compiled depending on
+	  whether CONFIG_SYS_VENDOR is set or not.
+
+	  This is optional.  For those targets without the board directory,
+	  leave this option empty.
+
+config SYS_CONFIG_NAME
+	string
+	help
+	  This option should contain the base name of board header file.
+	  The header file include/configs/<CONFIG_SYS_CONFIG_NAME>.h
+	  should be included from include/config.h.
+
+source "arch/arc/Kconfig"
+source "arch/arm/Kconfig"
+source "arch/m68k/Kconfig"
+source "arch/microblaze/Kconfig"
+source "arch/mips/Kconfig"
+source "arch/nds32/Kconfig"
+source "arch/nios2/Kconfig"
+source "arch/powerpc/Kconfig"
+source "arch/sandbox/Kconfig"
+source "arch/sh/Kconfig"
+source "arch/x86/Kconfig"
+source "arch/xtensa/Kconfig"
+source "arch/riscv/Kconfig"
+
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
new file mode 100644
index 0000000..38b6ffe
--- /dev/null
+++ b/arch/arc/Kconfig
@@ -0,0 +1,174 @@
+menu "ARC architecture"
+	depends on ARC
+
+config SYS_ARCH
+	default "arc"
+
+config SYS_CPU
+	default "arcv1" if ISA_ARCOMPACT
+	default "arcv2" if ISA_ARCV2
+
+choice
+	prompt "ARC Instruction Set"
+	default ISA_ARCOMPACT
+
+config ISA_ARCOMPACT
+	bool "ARCompact ISA"
+	help
+	  The original ARC ISA of ARC600/700 cores
+
+config ISA_ARCV2
+	bool "ARC ISA v2"
+	help
+	  ISA for the Next Generation ARC-HS cores
+
+endchoice
+
+choice
+	prompt "CPU selection"
+	default CPU_ARC770D if ISA_ARCOMPACT
+	default CPU_ARCHS38 if ISA_ARCV2
+
+config CPU_ARC750D
+	bool "ARC 750D"
+	depends on ISA_ARCOMPACT
+	select ARC_MMU_V2
+	help
+	  Choose this option to build an U-Boot for ARC750D CPU.
+
+config CPU_ARC770D
+	bool "ARC 770D"
+	depends on ISA_ARCOMPACT
+	select ARC_MMU_V3
+	help
+	  Choose this option to build an U-Boot for ARC770D CPU.
+
+config CPU_ARCEM6
+	bool "ARC EM6"
+	depends on ISA_ARCV2
+	select ARC_MMU_ABSENT
+	help
+	  Next Generation ARC Core based on ISA-v2 ISA without MMU.
+
+config CPU_ARCHS36
+	bool "ARC HS36"
+	depends on ISA_ARCV2
+	select ARC_MMU_ABSENT
+	help
+	  Next Generation ARC Core based on ISA-v2 ISA without MMU.
+
+config CPU_ARCHS38
+	bool "ARC HS38"
+	depends on ISA_ARCV2
+	select ARC_MMU_V4
+	help
+	  Next Generation ARC Core based on ISA-v2 ISA with MMU.
+
+endchoice
+
+choice
+	prompt "MMU Version"
+	default ARC_MMU_V3 if CPU_ARC770D
+	default ARC_MMU_V2 if CPU_ARC750D
+	default ARC_MMU_ABSENT if CPU_ARCEM6
+	default ARC_MMU_ABSENT if CPU_ARCHS36
+	default ARC_MMU_V4 if CPU_ARCHS38
+
+config ARC_MMU_ABSENT
+	bool "No MMU"
+	help
+	  No MMU
+
+config ARC_MMU_V2
+	bool "MMU v2"
+	depends on CPU_ARC750D
+	help
+	  Fixed the deficiency of v1 - possible thrashing in memcpy sceanrio
+	  when 2 D-TLB and 1 I-TLB entries index into same 2way set.
+
+config ARC_MMU_V3
+	bool "MMU v3"
+	depends on CPU_ARC770D
+	help
+	  Introduced with ARC700 4.10: New Features
+	  Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
+	  Shared Address Spaces (SASID)
+
+config ARC_MMU_V4
+	bool "MMU v4"
+	depends on CPU_ARCHS38
+	help
+	  Introduced as a part of ARC HS38 release.
+
+endchoice
+
+config CPU_BIG_ENDIAN
+	bool "Enable Big Endian Mode"
+	default n
+	help
+	  Build kernel for Big Endian Mode of ARC CPU
+
+config SYS_ICACHE_OFF
+	bool "Do not use Instruction Cache"
+	default n
+
+config SYS_DCACHE_OFF
+	bool "Do not use Data Cache"
+	default n
+
+menuconfig ARC_DBG
+	bool "ARC debugging"
+	default n
+
+if ARC_DBG
+
+config ARC_DBG_IOC_ENABLE
+	bool "Enable IO coherency unit"
+	depends on CPU_ARCHS38
+	default n
+	help
+	  Enable IO coherency unit to debug problems with caches and
+	  DMA peripherals.
+	  NOTE: as of today linux will not work properly if this option
+	  is enabled in u-boot!
+
+endif
+
+choice
+	prompt "Target select"
+	default TARGET_AXS103
+
+config TARGET_TB100
+	bool "Support tb100"
+
+config TARGET_NSIM
+	bool "Support standalone nSIM & Free nSIM"
+
+config TARGET_AXS101
+	bool "Support Synopsys Designware SDP board AXS101"
+
+config TARGET_AXS103
+	bool "Support Synopsys Designware SDP board AXS103"
+
+config TARGET_EMSDP
+	bool "Synopsys EM Software Development Platform"
+	select CPU_ARCEM6
+
+config TARGET_HSDK
+	bool "Support Synpsys HS DevelopmentKit board"
+
+config TARGET_IOT_DEVKIT
+	bool "Synopsys Brite IoT Development kit"
+	select CPU_ARCEM6
+
+endchoice
+
+source "board/abilis/tb100/Kconfig"
+source "board/synopsys/Kconfig"
+source "board/synopsys/axs10x/Kconfig"
+source "board/synopsys/emsdp/Kconfig"
+source "board/synopsys/hsdk/Kconfig"
+source "board/synopsys/iot_devkit/Kconfig"
+
+endmenu
+
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
new file mode 100644
index 0000000..44568f8
--- /dev/null
+++ b/arch/arc/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+libs-y += arch/arc/cpu/$(CPU)/
+libs-y += arch/arc/lib/
+
+# MetaWare debugger doesn't support PIE (position-independent executable)
+# so the only way to load U-Boot in MDB is to fake it by:
+#   1. Reset PIE flag in ELF header
+#   2. Strip all debug information from elf
+ifdef CONFIG_SYS_LITTLE_ENDIAN
+	EXEC_TYPE_OFFSET=16
+else
+	EXEC_TYPE_OFFSET=17
+endif
+
+mdbtrick: u-boot
+	$(Q)printf '\x02' | dd of=u-boot bs=1 seek=$(EXEC_TYPE_OFFSET) count=1 \
+		conv=notrunc &> /dev/null
+	$(Q)$(CROSS_COMPILE)strip -g u-boot
diff --git a/arch/arc/config.mk b/arch/arc/config.mk
new file mode 100644
index 0000000..18005d9
--- /dev/null
+++ b/arch/arc/config.mk
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+
+ifndef CONFIG_CPU_BIG_ENDIAN
+CONFIG_SYS_LITTLE_ENDIAN = 1
+else
+CONFIG_SYS_BIG_ENDIAN = 1
+endif
+
+ifdef CONFIG_SYS_LITTLE_ENDIAN
+PLATFORM_LDFLAGS += -EL
+PLATFORM_CPPFLAGS += -mlittle-endian
+endif
+
+ifdef CONFIG_SYS_BIG_ENDIAN
+PLATFORM_LDFLAGS += -EB
+PLATFORM_CPPFLAGS += -mbig-endian
+endif
+
+ifdef CONFIG_ARC_MMU_VER
+CONFIG_MMU = 1
+endif
+
+ifdef CONFIG_CPU_ARC750D
+PLATFORM_CPPFLAGS += -mcpu=arc700
+endif
+
+ifdef CONFIG_CPU_ARC770D
+PLATFORM_CPPFLAGS += -mcpu=arc700 -mlock -mswape
+endif
+
+ifdef CONFIG_CPU_ARCEM6
+PLATFORM_CPPFLAGS += -mcpu=arcem
+endif
+
+ifdef CONFIG_CPU_ARCHS34
+PLATFORM_CPPFLAGS += -mcpu=archs
+endif
+
+ifdef CONFIG_CPU_ARCHS38
+PLATFORM_CPPFLAGS += -mcpu=archs
+endif
+
+PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 -mno-sdata
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections -fno-common
+
+# Needed for relocation
+LDFLAGS_FINAL += -pie --gc-sections
+
+# Load address for standalone apps
+CONFIG_STANDALONE_LOAD_ADDR ?= 0x82000000
diff --git a/arch/arc/cpu/arcv1/Makefile b/arch/arc/cpu/arcv1/Makefile
new file mode 100644
index 0000000..4d42ac6
--- /dev/null
+++ b/arch/arc/cpu/arcv1/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+
+obj-y += ivt.o
diff --git a/arch/arc/cpu/arcv1/ivt.S b/arch/arc/cpu/arcv1/ivt.S
new file mode 100644
index 0000000..3d63430
--- /dev/null
+++ b/arch/arc/cpu/arcv1/ivt.S
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+.section .ivt, "ax",@progbits
+.align 4
+_ivt:
+	/* Critical system events */
+	j	_start			/* 0 - 0x000 */
+	j	memory_error		/* 1 - 0x008 */
+	j	instruction_error	/* 2 - 0x010 */
+
+	/* Device interrupts */
+.rept	29
+	j	interrupt_handler	/* 3:31 - 0x018:0xF8 */
+.endr
+	/* Exceptions */
+	j	EV_MachineCheck		/* 0x100, Fatal Machine check  (0x20) */
+	j	EV_TLBMissI		/* 0x108, Intruction TLB miss  (0x21) */
+	j	EV_TLBMissD		/* 0x110, Data TLB miss        (0x22) */
+	j	EV_TLBProtV		/* 0x118, Protection Violation (0x23)
+							or Misaligned Access  */
+	j	EV_PrivilegeV		/* 0x120, Privilege Violation  (0x24) */
+	j	EV_Trap			/* 0x128, Trap exception       (0x25) */
+	j	EV_Extension		/* 0x130, Extn Intruction Excp (0x26) */
diff --git a/arch/arc/cpu/arcv2/Makefile b/arch/arc/cpu/arcv2/Makefile
new file mode 100644
index 0000000..ab74026
--- /dev/null
+++ b/arch/arc/cpu/arcv2/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+
+obj-y += ivt.o
diff --git a/arch/arc/cpu/arcv2/ivt.S b/arch/arc/cpu/arcv2/ivt.S
new file mode 100644
index 0000000..3f5b409
--- /dev/null
+++ b/arch/arc/cpu/arcv2/ivt.S
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+ */
+
+.section .ivt, "a",@progbits
+.align 4
+	/* Critical system events */
+.word	_start			/* 0x00 - Reset */
+.word	memory_error		/* 0x01 - Memory Error */
+.word	instruction_error	/* 0x02 - Instruction Error */
+
+	/* Exceptions */
+.word	EV_MachineCheck		/* 0x03 - Fatal Machine check */
+.word	EV_TLBMissI		/* 0x04 - Intruction TLB miss */
+.word	EV_TLBMissD		/* 0x05 - Data TLB miss */
+.word	EV_TLBProtV		/* 0x06 - Protection Violation or Misaligned Access */
+.word	EV_PrivilegeV		/* 0x07 - Privilege Violation */
+.word	EV_SWI			/* 0x08 - Software Interrupt */
+.word	EV_Trap			/* 0x09 - Trap */
+.word	EV_Extension		/* 0x0A - Extension Intruction Exception */
+.word	EV_DivZero		/* 0x0B - Division by Zero */
+.word	EV_DCError		/* 0x0C - Data cache consistency error */
+.word	EV_Maligned		/* 0x0D - Misaligned data access */
+.word	0			/* 0x0E - Unused */
+.word	0			/* 0x0F - Unused */
+
+	/* Device interrupts */
+.rept	240
+.word	interrupt_handler	/* 0x10 - 0xFF */
+.endr
diff --git a/arch/arc/cpu/u-boot.lds b/arch/arc/cpu/u-boot.lds
new file mode 100644
index 0000000..e12145c
--- /dev/null
+++ b/arch/arc/cpu/u-boot.lds
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#include <config.h>
+
+OUTPUT_FORMAT("elf32-littlearc", "elf32-bigarc", "elf32-littlearc")
+OUTPUT_ARCH(arc)
+ENTRY(_start)
+SECTIONS
+{
+	. = CONFIG_SYS_TEXT_BASE;
+	__image_copy_start = .;
+	. = ALIGN(1024);
+	__ivt_start = .;
+	.ivt :
+	{
+		KEEP(*(.ivt))
+	}
+	__ivt_end = .;
+
+	. = ALIGN(1024);
+	__text_start = .;
+	.text :	{
+		arch/arc/lib/start.o (.text*)
+		*(.text*)
+	}
+	__text_end = .;
+
+	. = ALIGN(4);
+	.rodata : {
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+	}
+
+	. = ALIGN(4);
+	.data : {
+		*(.data*)
+	}
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+
+	. = ALIGN(4);
+	__rel_dyn_start = .;
+	.rela.dyn : {
+		*(.rela.dyn)
+	}
+	__rel_dyn_end = .;
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : {
+		*(.bss*)
+	}
+	__bss_end = .;
+
+	. = ALIGN(4);
+	__image_copy_end = .;
+	__init_end = .;
+}
diff --git a/arch/arc/dts/Makefile b/arch/arc/dts/Makefile
new file mode 100644
index 0000000..4f1e463
--- /dev/null
+++ b/arch/arc/dts/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+dtb-$(CONFIG_TARGET_AXS101) +=  axs101.dtb
+dtb-$(CONFIG_TARGET_AXS103) +=  axs103.dtb
+dtb-$(CONFIG_TARGET_NSIM) +=  nsim.dtb
+dtb-$(CONFIG_TARGET_TB100) +=  abilis_tb100.dtb
+dtb-$(CONFIG_TARGET_EMSDP) +=  emsdp.dtb
+dtb-$(CONFIG_TARGET_HSDK) +=  hsdk.dtb
+dtb-$(CONFIG_TARGET_IOT_DEVKIT) +=  iot_devkit.dtb
+
+targets += $(dtb-y)
+
+DTC_FLAGS += -R 4 -p 0x1000
+
+PHONY += dtbs
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+	@:
+
+clean-files := *.dtb
diff --git a/arch/arc/dts/abilis_tb100.dts b/arch/arc/dts/abilis_tb100.dts
new file mode 100644
index 0000000..19e45b9
--- /dev/null
+++ b/arch/arc/dts/abilis_tb100.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.com)
+ */
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+/ {
+	model = "abilis,tb100";
+
+	aliases {
+		console = &uart0;
+	};
+
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <500000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	uart0: serial@ff100000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0xff100000 0x1000>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+	};
+};
diff --git a/arch/arc/dts/axc001.dtsi b/arch/arc/dts/axc001.dtsi
new file mode 100644
index 0000000..412580a
--- /dev/null
+++ b/arch/arc/dts/axc001.dtsi
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Synopsys, Inc. All rights reserved.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <750000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+};
+
diff --git a/arch/arc/dts/axc003.dtsi b/arch/arc/dts/axc003.dtsi
new file mode 100644
index 0000000..75a9de6
--- /dev/null
+++ b/arch/arc/dts/axc003.dtsi
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Synopsys, Inc. All rights reserved.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <100000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+};
+
diff --git a/arch/arc/dts/axs101.dts b/arch/arc/dts/axs101.dts
new file mode 100644
index 0000000..fc9fa93
--- /dev/null
+++ b/arch/arc/dts/axs101.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Synopsys, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+/include/ "axc001.dtsi"
+/include/ "axs10x_mb.dtsi"
+
+
+/ {
+	model = "snps,axs101";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+};
+
diff --git a/arch/arc/dts/axs103.dts b/arch/arc/dts/axs103.dts
new file mode 100644
index 0000000..6e2dd00
--- /dev/null
+++ b/arch/arc/dts/axs103.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Synopsys, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+/include/ "axc003.dtsi"
+/include/ "axs10x_mb.dtsi"
+
+
+/ {
+	model = "snps,axs103";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+};
+
diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi
new file mode 100644
index 0000000..dfc0381
--- /dev/null
+++ b/arch/arc/dts/axs10x_mb.dtsi
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Synopsys, Inc. All rights reserved.
+ */
+
+/ {
+	aliases {
+		spi0 = &spi0;
+	};
+
+	axs10x_mb@e0000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00000000 0xe0000000 0x10000000>;
+		u-boot,dm-pre-reloc;
+
+		clocks {
+			compatible = "simple-bus";
+			u-boot,dm-pre-reloc;
+
+			apbclk: apbclk {
+				compatible = "fixed-clock";
+				clock-frequency = <50000000>;
+				#clock-cells = <0>;
+			};
+
+			uartclk: uartclk {
+				compatible = "fixed-clock";
+				clock-frequency = <33333333>;
+				#clock-cells = <0>;
+				u-boot,dm-pre-reloc;
+			};
+		};
+
+		ethernet@18000 {
+			compatible = "altr,socfpga-stmmac";
+			reg = < 0x18000 0x2000 >;
+			phy-mode = "gmii";
+			snps,pbl = < 32 >;
+			clocks = <&apbclk>;
+			clock-names = "stmmaceth";
+			max-speed = <100>;
+		};
+
+		ehci@0x40000 {
+			compatible = "generic-ehci";
+			reg = < 0x40000 0x100 >;
+		};
+
+		ohci@0x60000 {
+			compatible = "generic-ohci";
+			reg = < 0x60000 0x100 >;
+		};
+
+		uart0: serial0@22000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x22000 0x100>;
+			clocks = <&uartclk>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+		};
+
+		spi0: spi@0 {
+			compatible = "snps,dw-apb-ssi";
+			reg = <0x0 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			spi-max-frequency = <4000000>;
+			clocks = <&apbclk>;
+			clock-names = "spi_clk";
+			cs-gpio = <&cs_gpio 0>;
+			spi_flash@0 {
+				compatible = "spi-flash";
+				reg = <0>;
+				spi-max-frequency = <4000000>;
+			};
+		};
+
+		cs_gpio: gpio@11218 {
+			compatible = "snps,creg-gpio";
+			reg = <0x11218 0x4>;
+			gpio-controller;
+			#gpio-cells = <1>;
+			gpio-bank-name = "axs-spi-cs";
+			gpio-count = <1>;
+			gpio-first-shift = <0>;
+			gpio-bit-per-line = <2>;
+			gpio-activate-val = <1>;
+			gpio-deactivate-val = <3>;
+			gpio-default-val = <1>;
+		};
+	};
+};
diff --git a/arch/arc/dts/emsdp.dts b/arch/arc/dts/emsdp.dts
new file mode 100644
index 0000000..d307b95
--- /dev/null
+++ b/arch/arc/dts/emsdp.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+/ {
+	model = "snps,emsdp";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		console = &uart0;
+	};
+
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <40000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	uart0: serial0@f0004000 {
+		compatible = "snps,dw-apb-uart";
+		clock-frequency = <100000000>;
+		reg = <0xf0004000 0x1000>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+};
diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts
new file mode 100644
index 0000000..f024b96
--- /dev/null
+++ b/arch/arc/dts/hsdk.dts
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Synopsys, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+#include "skeleton.dtsi"
+#include "dt-bindings/clock/snps,hsdk-cgu.h"
+
+/ {
+	model = "snps,hsdk";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		console = &uart0;
+		spi0 = &spi0;
+	};
+
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <500000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	clk-fmeas {
+		clocks = <&cgu_clk CLK_ARC_PLL>, <&cgu_clk CLK_SYS_PLL>,
+			 <&cgu_clk CLK_TUN_PLL>, <&cgu_clk CLK_DDR_PLL>,
+			 <&cgu_clk CLK_ARC>, <&cgu_clk CLK_HDMI_PLL>,
+			 <&cgu_clk CLK_TUN_TUN>, <&cgu_clk CLK_HDMI>,
+			 <&cgu_clk CLK_SYS_APB>, <&cgu_clk CLK_SYS_AXI>,
+			 <&cgu_clk CLK_SYS_ETH>, <&cgu_clk CLK_SYS_USB>,
+			 <&cgu_clk CLK_SYS_SDIO>, <&cgu_clk CLK_SYS_HDMI>,
+			 <&cgu_clk CLK_SYS_GFX_CORE>, <&cgu_clk CLK_SYS_GFX_DMA>,
+			 <&cgu_clk CLK_SYS_GFX_CFG>, <&cgu_clk CLK_SYS_DMAC_CORE>,
+			 <&cgu_clk CLK_SYS_DMAC_CFG>, <&cgu_clk CLK_SYS_SDIO_REF>,
+			 <&cgu_clk CLK_SYS_SPI_REF>, <&cgu_clk CLK_SYS_I2C_REF>,
+			 <&cgu_clk CLK_SYS_UART_REF>, <&cgu_clk CLK_SYS_EBI_REF>,
+			 <&cgu_clk CLK_TUN_ROM>, <&cgu_clk CLK_TUN_PWM>;
+		clock-names = "cpu-pll", "sys-pll",
+			      "tun-pll", "ddr-clk",
+			      "cpu-clk", "hdmi-pll",
+			      "tun-clk", "hdmi-clk",
+			      "apb-clk", "axi-clk",
+			      "eth-clk", "usb-clk",
+			      "sdio-clk", "hdmi-sys-clk",
+			      "gfx-core-clk", "gfx-dma-clk",
+			      "gfx-cfg-clk", "dmac-core-clk",
+			      "dmac-cfg-clk", "sdio-ref-clk",
+			      "spi-clk", "i2c-clk",
+			      "uart-clk", "ebi-clk",
+			      "rom-clk", "pwm-clk";
+	};
+
+	cgu_clk: cgu-clk@f0000000 {
+		compatible = "snps,hsdk-cgu-clock";
+		reg = <0xf0000000 0x10>, <0xf00014B8 0x4>;
+		#clock-cells = <1>;
+	};
+
+	uart0: serial0@f0005000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0xf0005000 0x1000>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+	ethernet@f0008000 {
+		#interrupt-cells = <1>;
+		compatible = "altr,socfpga-stmmac";
+		reg = <0xf0008000 0x2000>;
+		phy-mode = "gmii";
+	};
+
+	ehci@0xf0040000 {
+		compatible = "generic-ehci";
+		reg = <0xf0040000 0x100>;
+	};
+
+	ohci@0xf0060000 {
+		compatible = "generic-ohci";
+		reg = <0xf0060000 0x100>;
+	};
+
+	spi0: spi@f0020000 {
+		compatible = "snps,dw-apb-ssi";
+		reg = <0xf0020000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		spi-max-frequency = <4000000>;
+		clocks = <&cgu_clk CLK_SYS_SPI_REF>;
+		clock-names = "spi_clk";
+		cs-gpio = <&cs_gpio 0>;
+		spi_flash@0 {
+			compatible = "spi-flash";
+			reg = <0>;
+			spi-max-frequency = <4000000>;
+		};
+	};
+
+	cs_gpio: gpio@f00014b0 {
+		compatible = "snps,creg-gpio";
+		reg = <0xf00014b0 0x4>;
+		gpio-controller;
+		#gpio-cells = <1>;
+		gpio-bank-name = "hsdk-spi-cs";
+		gpio-count = <1>;
+		gpio-first-shift = <0>;
+		gpio-bit-per-line = <2>;
+		gpio-activate-val = <2>;
+		gpio-deactivate-val = <3>;
+		gpio-default-val = <1>;
+	};
+};
diff --git a/arch/arc/dts/iot_devkit.dts b/arch/arc/dts/iot_devkit.dts
new file mode 100644
index 0000000..ebf5a95
--- /dev/null
+++ b/arch/arc/dts/iot_devkit.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		console = &uart0;
+	};
+
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <144000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	uart0: serial0@80014000 {
+		compatible = "snps,dw-apb-uart";
+		clock-frequency = <16000000>;
+		reg = <0x80014000 0x1000>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+	usb: usb@f0040000 {
+		compatible = "snps,dwc2";
+		reg = <0xf0040000 0x10000>;
+		phys = <&usbphy>;
+		phy-names = "usb2-phy";
+	};
+
+	usbphy: phy {
+		compatible = "nop-phy";
+		#phy-cells = <0>;
+	};
+};
diff --git a/arch/arc/dts/nsim.dts b/arch/arc/dts/nsim.dts
new file mode 100644
index 0000000..243ecb1
--- /dev/null
+++ b/arch/arc/dts/nsim.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ */
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+/ {
+	model = "snps,nsim";
+
+	aliases {
+		console = &arcuart0;
+	};
+
+	cpu_card {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <70000000>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	arcuart0: serial@0xc0fc1000 {
+		compatible = "snps,arc-uart";
+		reg = <0xc0fc1000 0x100>;
+		clock-frequency = <70000000>;
+	};
+
+};
diff --git a/arch/arc/dts/skeleton.dtsi b/arch/arc/dts/skeleton.dtsi
new file mode 100644
index 0000000..279fc6c
--- /dev/null
+++ b/arch/arc/dts/skeleton.dtsi
@@ -0,0 +1,30 @@
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value.  The bootloader will typically populate the memory
+ * node.
+ */
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	chosen { };
+	aliases { };
+
+	cpu_card {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		u-boot,dm-pre-reloc;
+
+		timer@0 {
+			compatible = "snps,arc-timer";
+			clocks = <&core_clk>;
+			reg = <0 1>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256M */
+	};
+};
diff --git a/arch/arc/include/asm/arc-bcr.h b/arch/arc/include/asm/arc-bcr.h
new file mode 100644
index 0000000..823906d
--- /dev/null
+++ b/arch/arc/include/asm/arc-bcr.h
@@ -0,0 +1,77 @@
+/*
+ * ARC Build Configuration Registers, with encoded hardware config
+ *
+ * Copyright (C) 2018 Synopsys
+ * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ARC_BCR_H
+#define __ARC_BCR_H
+#ifndef __ASSEMBLY__
+
+#include <config.h>
+
+union bcr_di_cache {
+	struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+		unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
+#else
+		unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
+#endif
+	} fields;
+	unsigned int word;
+};
+
+union bcr_slc_cfg {
+	struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+		unsigned int pad:24, way:2, lsz:2, sz:4;
+#else
+		unsigned int sz:4, lsz:2, way:2, pad:24;
+#endif
+	} fields;
+	unsigned int word;
+};
+
+union bcr_generic {
+	struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+		unsigned int pad:24, ver:8;
+#else
+		unsigned int ver:8, pad:24;
+#endif
+	} fields;
+	unsigned int word;
+};
+
+union bcr_clust_cfg {
+	struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+		unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8;
+#else
+		unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7;
+#endif
+	} fields;
+	unsigned int word;
+};
+
+union bcr_mmu_4 {
+	struct {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1,
+		     n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3;
+#else
+	/*           DTLB      ITLB      JES        JE         JA      */
+	unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2,
+		     pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8;
+#endif
+	} fields;
+	unsigned int word;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARC_BCR_H */
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
new file mode 100644
index 0000000..fff6591
--- /dev/null
+++ b/arch/arc/include/asm/arcregs.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_ARC_ARCREGS_H
+#define _ASM_ARC_ARCREGS_H
+
+#include <asm/cache.h>
+#include <config.h>
+
+/*
+ * ARC architecture has additional address space - auxiliary registers.
+ * These registers are mostly used for configuration purposes.
+ * These registers are not memory mapped and special commands are used for
+ * access: "lr"/"sr".
+ */
+
+/*
+ * Typically 8 least significant bits of Build Configuration Register (BCR)
+ * describe version of the HW block in question. Moreover if decoded version
+ * is 0 this means given HW block is absent - this is especially useful because
+ * we may safely read BRC regardless HW block existence while an attempt to
+ * access any other AUX regs associated with this HW block lead to imediate
+ * "instruction error" exception.
+ *
+ * I.e. before using any cofigurable HW block it's required to make sure it
+ * exists at all, and for that we introduce a special macro below.
+ */
+#define ARC_BCR_VERSION_MASK	GENMASK(7, 0)
+#define ARC_FEATURE_EXISTS(bcr)	!!(__builtin_arc_lr(bcr) & ARC_BCR_VERSION_MASK)
+
+#define ARC_AUX_IDENTITY	0x04
+#define ARC_AUX_STATUS32	0x0a
+
+/* STATUS32 Bits Positions */
+#define STATUS_AD_BIT		19	/* Enable unaligned access */
+
+/* Instruction cache related auxiliary registers */
+#define ARC_AUX_IC_IVIC		0x10
+#define ARC_AUX_IC_CTRL		0x11
+#define ARC_AUX_IC_IVIL		0x19
+#if (CONFIG_ARC_MMU_VER == 3)
+#define ARC_AUX_IC_PTAG		0x1E
+#endif
+#define ARC_BCR_IC_BUILD	0x77
+#define AUX_AUX_CACHE_LIMIT		0x5D
+#define ARC_AUX_NON_VOLATILE_LIMIT	0x5E
+
+/* ICCM and DCCM auxiliary registers */
+#define ARC_AUX_DCCM_BASE	0x18	/* DCCM Base Addr ARCv2 */
+#define ARC_AUX_ICCM_BASE	0x208	/* ICCM Base Addr ARCv2 */
+
+/* Timer related auxiliary registers */
+#define ARC_AUX_TIMER0_CNT	0x21	/* Timer 0 count */
+#define ARC_AUX_TIMER0_CTRL	0x22	/* Timer 0 control */
+#define ARC_AUX_TIMER0_LIMIT	0x23	/* Timer 0 limit */
+
+#define ARC_AUX_TIMER1_CNT	0x100	/* Timer 1 count */
+#define ARC_AUX_TIMER1_CTRL	0x101	/* Timer 1 control */
+#define ARC_AUX_TIMER1_LIMIT	0x102	/* Timer 1 limit */
+
+#define ARC_AUX_INTR_VEC_BASE	0x25
+
+/* Data cache related auxiliary registers */
+#define ARC_AUX_DC_IVDC		0x47
+#define ARC_AUX_DC_CTRL		0x48
+
+#define ARC_AUX_DC_IVDL		0x4A
+#define ARC_AUX_DC_FLSH		0x4B
+#define ARC_AUX_DC_FLDL		0x4C
+#if (CONFIG_ARC_MMU_VER == 3)
+#define ARC_AUX_DC_PTAG		0x5C
+#endif
+#define ARC_BCR_DC_BUILD	0x72
+#define ARC_BCR_SLC		0xce
+#define ARC_AUX_SLC_CONFIG	0x901
+#define ARC_AUX_SLC_CTRL	0x903
+#define ARC_AUX_SLC_FLUSH	0x904
+#define ARC_AUX_SLC_INVALIDATE	0x905
+#define ARC_AUX_SLC_IVDL	0x910
+#define ARC_AUX_SLC_FLDL	0x912
+#define ARC_AUX_SLC_RGN_START	0x914
+#define ARC_AUX_SLC_RGN_START1	0x915
+#define ARC_AUX_SLC_RGN_END	0x916
+#define ARC_AUX_SLC_RGN_END1	0x917
+#define ARC_BCR_CLUSTER		0xcf
+
+/* MMU Management regs */
+#define ARC_AUX_MMU_BCR		0x6f
+
+/* IO coherency related auxiliary registers */
+#define ARC_AUX_IO_COH_ENABLE	0x500
+#define ARC_AUX_IO_COH_PARTIAL	0x501
+#define ARC_AUX_IO_COH_AP0_BASE	0x508
+#define ARC_AUX_IO_COH_AP0_SIZE	0x509
+
+/* XY-memory related */
+#define ARC_AUX_XY_BUILD	0x79
+
+/* DSP-extensions related auxiliary registers */
+#define ARC_AUX_DSP_BUILD	0x7A
+
+/* ARC Subsystems related auxiliary registers */
+#define ARC_AUX_SUBSYS_BUILD	0xF0
+
+#ifndef __ASSEMBLY__
+/* Accessors for auxiliary registers */
+#define read_aux_reg(reg)	__builtin_arc_lr(reg)
+
+/* gcc builtin sr needs reg param to be long immediate */
+#define write_aux_reg(reg_immed, val)		\
+		__builtin_arc_sr((unsigned int)val, reg_immed)
+
+/* ARCNUM [15:8] - field to identify each core in a multi-core system */
+#define CPU_ID_GET()	((read_aux_reg(ARC_AUX_IDENTITY) & 0xFF00) >> 8)
+
+static const inline int is_isa_arcv2(void)
+{
+	return IS_ENABLED(CONFIG_ISA_ARCV2);
+}
+
+static const inline int is_isa_arcompact(void)
+{
+	return IS_ENABLED(CONFIG_ISA_ARCOMPACT);
+}
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_ARC_ARCREGS_H */
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
new file mode 100644
index 0000000..c6dd28e
--- /dev/null
+++ b/arch/arc/include/asm/bitops.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_BITOPS_H
+#define __ASM_ARC_BITOPS_H
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/__ffs.h>
+
+#endif /* __ASM_ARC_BITOPS_H */
diff --git a/arch/arc/include/asm/byteorder.h b/arch/arc/include/asm/byteorder.h
new file mode 100644
index 0000000..8c171bb
--- /dev/null
+++ b/arch/arc/include/asm/byteorder.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_BYTEORDER_H
+#define __ASM_ARC_BYTEORDER_H
+
+#include <asm/types.h>
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+	#define __BYTEORDER_HAS_U64__
+	#define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __LITTLE_ENDIAN__
+	#include <linux/byteorder/little_endian.h>
+#else
+	#include <linux/byteorder/big_endian.h>
+#endif	/* CONFIG_SYS_BIG_ENDIAN */
+
+#endif	/* ASM_ARC_BYTEORDER_H */
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
new file mode 100644
index 0000000..1604cd0
--- /dev/null
+++ b/arch/arc/include/asm/cache.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_CACHE_H
+#define __ASM_ARC_CACHE_H
+
+#include <config.h>
+
+/*
+ * As of today we may handle any L1 cache line length right in software.
+ * For that essentially cache line length is a variable not constant.
+ * And to satisfy users of ARCH_DMA_MINALIGN we just use largest line length
+ * that may exist in either L1 or L2 (AKA SLC) caches on ARC.
+ */
+#define ARCH_DMA_MINALIGN	128
+
+#if defined(ARC_MMU_ABSENT)
+#define CONFIG_ARC_MMU_VER 0
+#elif defined(CONFIG_ARC_MMU_V2)
+#define CONFIG_ARC_MMU_VER 2
+#elif defined(CONFIG_ARC_MMU_V3)
+#define CONFIG_ARC_MMU_VER 3
+#elif defined(CONFIG_ARC_MMU_V4)
+#define CONFIG_ARC_MMU_VER 4
+#endif
+
+#ifndef __ASSEMBLY__
+
+void cache_init(void);
+void flush_n_invalidate_dcache_all(void);
+void sync_n_cleanup_cache_all(void);
+
+static const inline int is_ioc_enabled(void)
+{
+	return IS_ENABLED(CONFIG_ARC_DBG_IOC_ENABLE);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARC_CACHE_H */
diff --git a/arch/arc/include/asm/config.h b/arch/arc/include/asm/config.h
new file mode 100644
index 0000000..d88c361
--- /dev/null
+++ b/arch/arc/include/asm/config.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_CONFIG_H_
+#define __ASM_ARC_CONFIG_H_
+
+#define CONFIG_SYS_BOOT_RAMDISK_HIGH
+
+#define CONFIG_LMB
+
+#endif /*__ASM_ARC_CONFIG_H_ */
diff --git a/arch/arc/include/asm/global_data.h b/arch/arc/include/asm/global_data.h
new file mode 100644
index 0000000..8f9c83d
--- /dev/null
+++ b/arch/arc/include/asm/global_data.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef	__ASM_ARC_GLOBAL_DATA_H
+#define __ASM_ARC_GLOBAL_DATA_H
+
+#include <config.h>
+
+#ifndef __ASSEMBLY__
+/* Architecture-specific global data */
+struct arch_global_data {
+	int l1_line_sz;
+#if defined(CONFIG_ISA_ARCV2)
+	int slc_line_sz;
+#endif
+};
+#endif /* __ASSEMBLY__ */
+
+#include <asm-generic/global_data.h>
+
+#define DECLARE_GLOBAL_DATA_PTR		register volatile gd_t *gd asm ("r25")
+
+#endif /* __ASM_ARC_GLOBAL_DATA_H */
diff --git a/arch/arc/include/asm/gpio.h b/arch/arc/include/asm/gpio.h
new file mode 100644
index 0000000..306ab4c
--- /dev/null
+++ b/arch/arc/include/asm/gpio.h
@@ -0,0 +1 @@
+#include <asm-generic/gpio.h>
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
new file mode 100644
index 0000000..fa844b5
--- /dev/null
+++ b/arch/arc/include/asm/io.h
@@ -0,0 +1,282 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_IO_H
+#define __ASM_ARC_IO_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#ifdef __ARCHS__
+
+/*
+ * ARCv2 based HS38 cores are in-order issue, but still weakly ordered
+ * due to micro-arch buffering/queuing of load/store, cache hit vs. miss ...
+ *
+ * Explicit barrier provided by DMB instruction
+ *  - Operand supports fine grained load/store/load+store semantics
+ *  - Ensures that selected memory operation issued before it will complete
+ *    before any subsequent memory operation of same type
+ *  - DMB guarantees SMP as well as local barrier semantics
+ *    (asm-generic/barrier.h ensures sane smp_*mb if not defined here, i.e.
+ *    UP: barrier(), SMP: smp_*mb == *mb)
+ *  - DSYNC provides DMB+completion_of_cache_bpu_maintenance_ops hence not needed
+ *    in the general case. Plus it only provides full barrier.
+ */
+
+#define mb()	asm volatile("dmb 3\n" : : : "memory")
+#define rmb()	asm volatile("dmb 1\n" : : : "memory")
+#define wmb()	asm volatile("dmb 2\n" : : : "memory")
+
+#else
+
+/*
+ * ARCompact based cores (ARC700) only have SYNC instruction which is super
+ * heavy weight as it flushes the pipeline as well.
+ * There are no real SMP implementations of such cores.
+ */
+
+#define mb()	asm volatile("sync\n" : : : "memory")
+#endif
+
+#ifdef __ARCHS__
+#define __iormb()		rmb()
+#define __iowmb()		wmb()
+#else
+#define __iormb()		asm volatile("" : : : "memory")
+#define __iowmb()		asm volatile("" : : : "memory")
+#endif
+
+static inline void sync(void)
+{
+	/* Not yet implemented */
+}
+
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	u8 b;
+
+	__asm__ __volatile__("ldb%U1	%0, %1\n"
+			     : "=r" (b)
+			     : "m" (*(volatile u8 __force *)addr)
+			     : "memory");
+	return b;
+}
+
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	u16 s;
+
+	__asm__ __volatile__("ldw%U1	%0, %1\n"
+			     : "=r" (s)
+			     : "m" (*(volatile u16 __force *)addr)
+			     : "memory");
+	return s;
+}
+
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	u32 w;
+
+	__asm__ __volatile__("ld%U1	%0, %1\n"
+			     : "=r" (w)
+			     : "m" (*(volatile u32 __force *)addr)
+			     : "memory");
+	return w;
+}
+
+static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stb%U1	%0, %1\n"
+			     :
+			     : "r" (b), "m" (*(volatile u8 __force *)addr)
+			     : "memory");
+}
+
+static inline void __raw_writew(u16 s, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stw%U1	%0, %1\n"
+			     :
+			     : "r" (s), "m" (*(volatile u16 __force *)addr)
+			     : "memory");
+}
+
+static inline void __raw_writel(u32 w, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("st%U1	%0, %1\n"
+			     :
+			     : "r" (w), "m" (*(volatile u32 __force *)addr)
+			     : "memory");
+}
+
+static inline int __raw_readsb(unsigned int addr, void *data, int bytelen)
+{
+	__asm__ __volatile__ ("1:ld.di	r8, [r0]\n"
+			      "sub.f	r2, r2, 1\n"
+			      "bnz.d	1b\n"
+			      "stb.ab	r8, [r1, 1]\n"
+			      :
+			      : "r" (addr), "r" (data), "r" (bytelen)
+			      : "r8");
+	return bytelen;
+}
+
+static inline int __raw_readsw(unsigned int addr, void *data, int wordlen)
+{
+	__asm__ __volatile__ ("1:ld.di	r8, [r0]\n"
+			      "sub.f	r2, r2, 1\n"
+			      "bnz.d	1b\n"
+			      "stw.ab	r8, [r1, 2]\n"
+			      :
+			      : "r" (addr), "r" (data), "r" (wordlen)
+			      : "r8");
+	return wordlen;
+}
+
+static inline int __raw_readsl(unsigned int addr, void *data, int longlen)
+{
+	__asm__ __volatile__ ("1:ld.di	r8, [r0]\n"
+			      "sub.f	r2, r2, 1\n"
+			      "bnz.d	1b\n"
+			      "st.ab	r8, [r1, 4]\n"
+			      :
+			      : "r" (addr), "r" (data), "r" (longlen)
+			      : "r8");
+	return longlen;
+}
+
+static inline int __raw_writesb(unsigned int addr, void *data, int bytelen)
+{
+	__asm__ __volatile__ ("1:ldb.ab	r8, [r1, 1]\n"
+			      "sub.f	r2, r2, 1\n"
+			      "bnz.d	1b\n"
+			      "st.di	r8, [r0, 0]\n"
+			      :
+			      : "r" (addr), "r" (data), "r" (bytelen)
+			      : "r8");
+	return bytelen;
+}
+
+static inline int __raw_writesw(unsigned int addr, void *data, int wordlen)
+{
+	__asm__ __volatile__ ("1:ldw.ab	r8, [r1, 2]\n"
+			      "sub.f	r2, r2, 1\n"
+			      "bnz.d	1b\n"
+			      "st.ab.di	r8, [r0, 0]\n"
+			      :
+			      : "r" (addr), "r" (data), "r" (wordlen)
+			      : "r8");
+	return wordlen;
+}
+
+static inline int __raw_writesl(unsigned int addr, void *data, int longlen)
+{
+	__asm__ __volatile__ ("1:ld.ab	r8, [r1, 4]\n"
+			      "sub.f	r2, r2, 1\n"
+			      "bnz.d	1b\n"
+			      "st.ab.di	r8, [r0, 0]\n"
+			      :
+			      : "r" (addr), "r" (data), "r" (longlen)
+			      : "r8");
+	return longlen;
+}
+
+/*
+ * MMIO can also get buffered/optimized in micro-arch, so barriers needed
+ * Based on ARM model for the typical use case
+ *
+ *	<ST [DMA buffer]>
+ *	<writel MMIO "go" reg>
+ *  or:
+ *	<readl MMIO "status" reg>
+ *	<LD [DMA buffer]>
+ *
+ * http://lkml.kernel.org/r/20150622133656.GG1583@arm.com
+ */
+#define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
+#define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
+#define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+
+#define writeb(v,c)		({ __iowmb(); writeb_relaxed(v,c); })
+#define writew(v,c)		({ __iowmb(); writew_relaxed(v,c); })
+#define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })
+
+/*
+ * Relaxed API for drivers which can handle barrier ordering themselves
+ *
+ * Also these are defined to perform little endian accesses.
+ * To provide the typical device register semantics of fixed endian,
+ * swap the byte order for Big Endian
+ *
+ * http://lkml.kernel.org/r/201603100845.30602.arnd@arndb.de
+ */
+#define readb_relaxed(c)	__raw_readb(c)
+#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
+					__raw_readw(c)); __r; })
+#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl(c)); __r; })
+
+#define writeb_relaxed(v,c)	__raw_writeb(v,c)
+#define writew_relaxed(v,c)	__raw_writew((__force u16) cpu_to_le16(v),c)
+#define writel_relaxed(v,c)	__raw_writel((__force u32) cpu_to_le32(v),c)
+
+#define out_arch(type, endian, a, v)	__raw_write##type(cpu_to_##endian(v), a)
+#define in_arch(type, endian, a)	endian##_to_cpu(__raw_read##type(a))
+
+#define out_le32(a, v)	out_arch(l, le32, a, v)
+#define out_le16(a, v)	out_arch(w, le16, a, v)
+
+#define in_le32(a)	in_arch(l, le32, a)
+#define in_le16(a)	in_arch(w, le16, a)
+
+#define out_be32(a, v)	out_arch(l, be32, a, v)
+#define out_be16(a, v)	out_arch(w, be16, a, v)
+
+#define in_be32(a)	in_arch(l, be32, a)
+#define in_be16(a)	in_arch(w, be16, a)
+
+#define out_8(a, v)	__raw_writeb(v, a)
+#define in_8(a)		__raw_readb(a)
+
+/*
+ * Clear and set bits in one shot. These macros can be used to clear and
+ * set multiple bits in a register using a single call. These macros can
+ * also be used to set a multiple-bit bit pattern using a mask, by
+ * specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+
+#define clrbits(type, addr, clear) \
+	out_##type((addr), in_##type(addr) & ~(clear))
+
+#define setbits(type, addr, set) \
+	out_##type((addr), in_##type(addr) | (set))
+
+#define clrsetbits(type, addr, clear, set) \
+	out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrbits_be32(addr, clear) clrbits(be32, addr, clear)
+#define setbits_be32(addr, set) setbits(be32, addr, set)
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+
+#define clrbits_le32(addr, clear) clrbits(le32, addr, clear)
+#define setbits_le32(addr, set) setbits(le32, addr, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrbits_be16(addr, clear) clrbits(be16, addr, clear)
+#define setbits_be16(addr, set) setbits(be16, addr, set)
+#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
+
+#define clrbits_le16(addr, clear) clrbits(le16, addr, clear)
+#define setbits_le16(addr, set) setbits(le16, addr, set)
+#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set)
+
+#define clrbits_8(addr, clear) clrbits(8, addr, clear)
+#define setbits_8(addr, set) setbits(8, addr, set)
+#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+
+#include <asm-generic/io.h>
+
+#endif	/* __ASM_ARC_IO_H */
diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h
new file mode 100644
index 0000000..2d42ed4
--- /dev/null
+++ b/arch/arc/include/asm/linkage.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2015 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_LINKAGE_H
+#define __ASM_ARC_LINKAGE_H
+
+#define ASM_NL		 `	/* use '`' to mark new line in macro */
+
+#endif /* __ASM_ARC_LINKAGE_H */
diff --git a/arch/arc/include/asm/posix_types.h b/arch/arc/include/asm/posix_types.h
new file mode 100644
index 0000000..13838cb
--- /dev/null
+++ b/arch/arc/include/asm/posix_types.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_POSIX_TYPES_H
+#define __ASM_ARC_POSIX_TYPES_H
+
+typedef unsigned short		__kernel_dev_t;
+typedef unsigned long		__kernel_ino_t;
+typedef unsigned short		__kernel_mode_t;
+typedef unsigned short		__kernel_nlink_t;
+typedef long			__kernel_off_t;
+typedef int			__kernel_pid_t;
+typedef unsigned short		__kernel_ipc_pid_t;
+typedef unsigned short		__kernel_uid_t;
+typedef unsigned short		__kernel_gid_t;
+#ifdef __GNUC__
+typedef __SIZE_TYPE__		__kernel_size_t;
+#else
+typedef unsigned int		__kernel_size_t;
+#endif
+typedef int			__kernel_ssize_t;
+typedef int			__kernel_ptrdiff_t;
+typedef long			__kernel_time_t;
+typedef long			__kernel_suseconds_t;
+typedef long			__kernel_clock_t;
+typedef int			__kernel_daddr_t;
+typedef char			*__kernel_caddr_t;
+typedef unsigned short		__kernel_uid16_t;
+typedef unsigned short		__kernel_gid16_t;
+typedef unsigned int		__kernel_uid32_t;
+typedef unsigned int		__kernel_gid32_t;
+
+typedef unsigned short		__kernel_old_uid_t;
+typedef unsigned short		__kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long		__kernel_loff_t;
+#endif
+
+#endif	/* __ASM_ARC_POSIX_TYPES_H */
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
new file mode 100644
index 0000000..03e31fb
--- /dev/null
+++ b/arch/arc/include/asm/processor.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_ARC_PROCESSOR_H
+#define _ASM_ARC_PROCESSOR_H
+
+/* This file is required by some generic code like USB etc */
+
+#endif /* _ASM_ARC_PROCESSOR_H */
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
new file mode 100644
index 0000000..6965e89
--- /dev/null
+++ b/arch/arc/include/asm/ptrace.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_PTRACE_H
+#define __ASM_ARC_PTRACE_H
+
+struct pt_regs {
+	long bta;
+	long lp_start;
+	long lp_end;
+	long lp_count;
+	long status32;
+	long ret;
+	long blink;
+	long fp;
+	long r26;	/* gp */
+	long r25;
+	long r24;
+	long r23;
+	long r22;
+	long r21;
+	long r20;
+	long r19;
+	long r18;
+	long r17;
+	long r16;
+	long r15;
+	long r14;
+	long r13;
+	long r12;
+	long r11;
+	long r10;
+	long r9;
+	long r8;
+	long r7;
+	long r6;
+	long r5;
+	long r4;
+	long r3;
+	long r2;
+	long r1;
+	long r0;
+	long sp;
+	long ecr;
+};
+
+#endif /* __ASM_ARC_PTRACE_H */
diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h
new file mode 100644
index 0000000..1c9c9db
--- /dev/null
+++ b/arch/arc/include/asm/sections.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_SECTIONS_H
+#define __ASM_ARC_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+extern ulong __ivt_start;
+extern ulong __ivt_end;
+
+#endif /* __ASM_ARC_SECTIONS_H */
diff --git a/arch/arc/include/asm/string.h b/arch/arc/include/asm/string.h
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/arch/arc/include/asm/string.h
@@ -0,0 +1 @@
+
diff --git a/arch/arc/include/asm/types.h b/arch/arc/include/asm/types.h
new file mode 100644
index 0000000..f31dcdf
--- /dev/null
+++ b/arch/arc/include/asm/types.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_TYPES_H
+#define __ASM_ARC_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+typedef unsigned short umode_t;
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide. */
+
+typedef u32 dma_addr_t;
+
+typedef unsigned long phys_addr_t;
+typedef unsigned long phys_size_t;
+
+#endif /* __ASM_ARC_TYPES_H */
diff --git a/arch/arc/include/asm/u-boot-arc.h b/arch/arc/include/asm/u-boot-arc.h
new file mode 100644
index 0000000..dd2c094
--- /dev/null
+++ b/arch/arc/include/asm/u-boot-arc.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_U_BOOT_ARC_H__
+#define __ASM_ARC_U_BOOT_ARC_H__
+
+int arch_early_init_r(void);
+
+void	board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
+void	board_init_f_r(void) __attribute__ ((noreturn));
+
+#endif	/* __ASM_ARC_U_BOOT_ARC_H__ */
diff --git a/arch/arc/include/asm/u-boot.h b/arch/arc/include/asm/u-boot.h
new file mode 100644
index 0000000..36c2207
--- /dev/null
+++ b/arch/arc/include/asm/u-boot.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef __ASM_ARC_U_BOOT_H__
+#define __ASM_ARC_U_BOOT_H__
+
+#include <asm-generic/u-boot.h>
+#include <asm/u-boot-arc.h>
+
+/* For image.h:image_check_target_arch() */
+#define IH_ARCH_DEFAULT IH_ARCH_ARC
+
+#endif	/* __ASM_ARC_U_BOOT_H__ */
diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h
new file mode 100644
index 0000000..6cecbbb
--- /dev/null
+++ b/arch/arc/include/asm/unaligned.h
@@ -0,0 +1 @@
+#include <asm-generic/unaligned.h>
diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile
new file mode 100644
index 0000000..0eb44bc
--- /dev/null
+++ b/arch/arc/lib/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+
+extra-y	= start.o
+head-y := start.o
+obj-y += cache.o
+obj-y += cpu.o
+obj-y += interrupts.o
+obj-y += relocate.o
+obj-y += reset.o
+obj-y += ints_low.o
+obj-y += init_helpers.o
+
+obj-$(CONFIG_CMD_BOOTM) += bootm.o
+
+lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _millicodethunk.o libgcc2.o
diff --git a/arch/arc/lib/_millicodethunk.S b/arch/arc/lib/_millicodethunk.S
new file mode 100644
index 0000000..4ad16ae
--- /dev/null
+++ b/arch/arc/lib/_millicodethunk.S
@@ -0,0 +1,225 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 1995, 1997, 2007-2013 Free Software Foundation, Inc.
+ */
+
+ /* ANSI concatenation macros.  */
+
+ #define CONCAT1(a, b) CONCAT2(a, b)
+ #define CONCAT2(a, b) a ## b
+
+ /* Use the right prefix for global labels.  */
+
+ #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+#ifndef WORKING_ASSEMBLER
+#define abs_l abs
+#define asl_l asl
+#define mov_l mov
+#endif
+
+#define FUNC(X)         .type SYM(X),@function
+#define HIDDEN_FUNC(X)	FUNC(X)` .hidden X
+#define ENDFUNC0(X)     .Lfe_##X: .size X,.Lfe_##X-X
+#define ENDFUNC(X)      ENDFUNC0(X)
+
+	.section .text
+	.align 4
+	.global SYM(__st_r13_to_r15)
+	.global SYM(__st_r13_to_r16)
+	.global SYM(__st_r13_to_r17)
+	.global SYM(__st_r13_to_r18)
+	.global SYM(__st_r13_to_r19)
+	.global SYM(__st_r13_to_r20)
+	.global SYM(__st_r13_to_r21)
+	.global SYM(__st_r13_to_r22)
+	.global SYM(__st_r13_to_r23)
+	.global SYM(__st_r13_to_r24)
+	.global SYM(__st_r13_to_r25)
+	HIDDEN_FUNC(__st_r13_to_r15)
+	HIDDEN_FUNC(__st_r13_to_r16)
+	HIDDEN_FUNC(__st_r13_to_r17)
+	HIDDEN_FUNC(__st_r13_to_r18)
+	HIDDEN_FUNC(__st_r13_to_r19)
+	HIDDEN_FUNC(__st_r13_to_r20)
+	HIDDEN_FUNC(__st_r13_to_r21)
+	HIDDEN_FUNC(__st_r13_to_r22)
+	HIDDEN_FUNC(__st_r13_to_r23)
+	HIDDEN_FUNC(__st_r13_to_r24)
+	HIDDEN_FUNC(__st_r13_to_r25)
+	.align 4
+SYM(__st_r13_to_r25):
+	st r25, [sp,48]
+SYM(__st_r13_to_r24):
+	st r24, [sp,44]
+SYM(__st_r13_to_r23):
+	st r23, [sp,40]
+SYM(__st_r13_to_r22):
+	st r22, [sp,36]
+SYM(__st_r13_to_r21):
+	st r21, [sp,32]
+SYM(__st_r13_to_r20):
+	st r20, [sp,28]
+SYM(__st_r13_to_r19):
+	st r19, [sp,24]
+SYM(__st_r13_to_r18):
+	st r18, [sp,20]
+SYM(__st_r13_to_r17):
+	st r17, [sp,16]
+SYM(__st_r13_to_r16):
+	st r16, [sp,12]
+SYM(__st_r13_to_r15):
+#ifdef __ARC700__
+	st r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+	st_s r15, [sp,8]
+#endif
+	st_s r14, [sp,4]
+	j_s.d [%blink]
+	st_s r13, [sp,0]
+	ENDFUNC(__st_r13_to_r15)
+	ENDFUNC(__st_r13_to_r16)
+	ENDFUNC(__st_r13_to_r17)
+	ENDFUNC(__st_r13_to_r18)
+	ENDFUNC(__st_r13_to_r19)
+	ENDFUNC(__st_r13_to_r20)
+	ENDFUNC(__st_r13_to_r21)
+	ENDFUNC(__st_r13_to_r22)
+	ENDFUNC(__st_r13_to_r23)
+	ENDFUNC(__st_r13_to_r24)
+	ENDFUNC(__st_r13_to_r25)
+
+	.section .text
+	.align 4
+;	==================================
+;	the loads
+
+	.global SYM(__ld_r13_to_r15)
+	.global SYM(__ld_r13_to_r16)
+	.global SYM(__ld_r13_to_r17)
+	.global SYM(__ld_r13_to_r18)
+	.global SYM(__ld_r13_to_r19)
+	.global SYM(__ld_r13_to_r20)
+	.global SYM(__ld_r13_to_r21)
+	.global SYM(__ld_r13_to_r22)
+	.global SYM(__ld_r13_to_r23)
+	.global SYM(__ld_r13_to_r24)
+	.global SYM(__ld_r13_to_r25)
+	HIDDEN_FUNC(__ld_r13_to_r15)
+	HIDDEN_FUNC(__ld_r13_to_r16)
+	HIDDEN_FUNC(__ld_r13_to_r17)
+	HIDDEN_FUNC(__ld_r13_to_r18)
+	HIDDEN_FUNC(__ld_r13_to_r19)
+	HIDDEN_FUNC(__ld_r13_to_r20)
+	HIDDEN_FUNC(__ld_r13_to_r21)
+	HIDDEN_FUNC(__ld_r13_to_r22)
+	HIDDEN_FUNC(__ld_r13_to_r23)
+	HIDDEN_FUNC(__ld_r13_to_r24)
+	HIDDEN_FUNC(__ld_r13_to_r25)
+SYM(__ld_r13_to_r25):
+	ld r25, [sp,48]
+SYM(__ld_r13_to_r24):
+	ld r24, [sp,44]
+SYM(__ld_r13_to_r23):
+	ld r23, [sp,40]
+SYM(__ld_r13_to_r22):
+	ld r22, [sp,36]
+SYM(__ld_r13_to_r21):
+	ld r21, [sp,32]
+SYM(__ld_r13_to_r20):
+	ld r20, [sp,28]
+SYM(__ld_r13_to_r19):
+	ld r19, [sp,24]
+SYM(__ld_r13_to_r18):
+	ld r18, [sp,20]
+SYM(__ld_r13_to_r17):
+	ld r17, [sp,16]
+SYM(__ld_r13_to_r16):
+	ld r16, [sp,12]
+SYM(__ld_r13_to_r15):
+#ifdef __ARC700__
+	ld r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+	ld_s r15, [sp,8]
+#endif
+	ld_s r14, [sp,4]
+	j_s.d [%blink]
+	ld_s r13, [sp,0]
+	ENDFUNC(__ld_r13_to_r15)
+	ENDFUNC(__ld_r13_to_r16)
+	ENDFUNC(__ld_r13_to_r17)
+	ENDFUNC(__ld_r13_to_r18)
+	ENDFUNC(__ld_r13_to_r19)
+	ENDFUNC(__ld_r13_to_r20)
+	ENDFUNC(__ld_r13_to_r21)
+	ENDFUNC(__ld_r13_to_r22)
+	ENDFUNC(__ld_r13_to_r23)
+	ENDFUNC(__ld_r13_to_r24)
+	ENDFUNC(__ld_r13_to_r25)
+
+	.global SYM(__ld_r13_to_r14_ret)
+	.global SYM(__ld_r13_to_r15_ret)
+	.global SYM(__ld_r13_to_r16_ret)
+	.global SYM(__ld_r13_to_r17_ret)
+	.global SYM(__ld_r13_to_r18_ret)
+	.global SYM(__ld_r13_to_r19_ret)
+	.global SYM(__ld_r13_to_r20_ret)
+	.global SYM(__ld_r13_to_r21_ret)
+	.global SYM(__ld_r13_to_r22_ret)
+	.global SYM(__ld_r13_to_r23_ret)
+	.global SYM(__ld_r13_to_r24_ret)
+	.global SYM(__ld_r13_to_r25_ret)
+	HIDDEN_FUNC(__ld_r13_to_r14_ret)
+	HIDDEN_FUNC(__ld_r13_to_r15_ret)
+	HIDDEN_FUNC(__ld_r13_to_r16_ret)
+	HIDDEN_FUNC(__ld_r13_to_r17_ret)
+	HIDDEN_FUNC(__ld_r13_to_r18_ret)
+	HIDDEN_FUNC(__ld_r13_to_r19_ret)
+	HIDDEN_FUNC(__ld_r13_to_r20_ret)
+	HIDDEN_FUNC(__ld_r13_to_r21_ret)
+	HIDDEN_FUNC(__ld_r13_to_r22_ret)
+	HIDDEN_FUNC(__ld_r13_to_r23_ret)
+	HIDDEN_FUNC(__ld_r13_to_r24_ret)
+	HIDDEN_FUNC(__ld_r13_to_r25_ret)
+	.section .text
+	.align 4
+SYM(__ld_r13_to_r25_ret):
+	ld r25, [sp,48]
+SYM(__ld_r13_to_r24_ret):
+	ld r24, [sp,44]
+SYM(__ld_r13_to_r23_ret):
+	ld r23, [sp,40]
+SYM(__ld_r13_to_r22_ret):
+	ld r22, [sp,36]
+SYM(__ld_r13_to_r21_ret):
+	ld r21, [sp,32]
+SYM(__ld_r13_to_r20_ret):
+	ld r20, [sp,28]
+SYM(__ld_r13_to_r19_ret):
+	ld r19, [sp,24]
+SYM(__ld_r13_to_r18_ret):
+	ld r18, [sp,20]
+SYM(__ld_r13_to_r17_ret):
+	ld r17, [sp,16]
+SYM(__ld_r13_to_r16_ret):
+	ld r16, [sp,12]
+SYM(__ld_r13_to_r15_ret):
+	ld r15, [sp,8]
+SYM(__ld_r13_to_r14_ret):
+	ld blink,[sp,r12]
+	ld_s r14, [sp,4]
+	ld.ab r13, [sp,r12]
+	j_s.d [%blink]
+	add_s sp,sp,4
+	ENDFUNC(__ld_r13_to_r14_ret)
+	ENDFUNC(__ld_r13_to_r15_ret)
+	ENDFUNC(__ld_r13_to_r16_ret)
+	ENDFUNC(__ld_r13_to_r17_ret)
+	ENDFUNC(__ld_r13_to_r18_ret)
+	ENDFUNC(__ld_r13_to_r19_ret)
+	ENDFUNC(__ld_r13_to_r20_ret)
+	ENDFUNC(__ld_r13_to_r21_ret)
+	ENDFUNC(__ld_r13_to_r22_ret)
+	ENDFUNC(__ld_r13_to_r23_ret)
+	ENDFUNC(__ld_r13_to_r24_ret)
+	ENDFUNC(__ld_r13_to_r25_ret)
diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c
new file mode 100644
index 0000000..254e028
--- /dev/null
+++ b/arch/arc/lib/bootm.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#include <asm/cache.h>
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong get_sp(void)
+{
+	ulong ret;
+
+	asm("mov %0, sp" : "=r"(ret) : );
+	return ret;
+}
+
+void arch_lmb_reserve(struct lmb *lmb)
+{
+	ulong sp;
+
+	/*
+	 * Booting a (Linux) kernel image
+	 *
+	 * Allocate space for command line and board info - the
+	 * address should be as high as possible within the reach of
+	 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
+	 * memory, which means far enough below the current stack
+	 * pointer.
+	 */
+	sp = get_sp();
+	debug("## Current stack ends at 0x%08lx ", sp);
+
+	/* adjust sp by 4K to be safe */
+	sp -= 4096;
+	lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp));
+}
+
+static int cleanup_before_linux(void)
+{
+	disable_interrupts();
+	sync_n_cleanup_cache_all();
+
+	return 0;
+}
+
+__weak int board_prep_linux(bootm_headers_t *images) { return 0; }
+
+/* Subcommand: PREP */
+static int boot_prep_linux(bootm_headers_t *images)
+{
+	int ret;
+
+	ret = image_setup_linux(images);
+	if (ret)
+		return ret;
+
+	return board_prep_linux(images);
+}
+
+/* Generic implementation for single core CPU */
+__weak void board_jump_and_run(ulong entry, int zero, int arch, uint params)
+{
+	void (*kernel_entry)(int zero, int arch, uint params);
+
+	kernel_entry = (void (*)(int, int, uint))entry;
+
+	kernel_entry(zero, arch, params);
+}
+
+/* Subcommand: GO */
+static void boot_jump_linux(bootm_headers_t *images, int flag)
+{
+	ulong kernel_entry;
+	unsigned int r0, r2;
+	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
+
+	kernel_entry = images->ep;
+
+	debug("## Transferring control to Linux (at address %08lx)...\n",
+	      kernel_entry);
+	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+	printf("\nStarting kernel ...%s\n\n", fake ?
+	       "(fake run for tracing)" : "");
+	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+
+	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
+		r0 = 2;
+		r2 = (unsigned int)images->ft_addr;
+	} else {
+		r0 = 1;
+		r2 = (unsigned int)env_get("bootargs");
+	}
+
+	cleanup_before_linux();
+
+	if (!fake)
+		board_jump_and_run(kernel_entry, r0, 0, r2);
+}
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	/* No need for those on ARC */
+	if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE))
+		return -1;
+
+	if (flag & BOOTM_STATE_OS_PREP)
+		return boot_prep_linux(images);
+
+	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
+		boot_jump_linux(images, flag);
+		return 0;
+	}
+
+	return -1;
+}
diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c
new file mode 100644
index 0000000..8c1cb6e
--- /dev/null
+++ b/arch/arc/lib/cache.c
@@ -0,0 +1,719 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <asm/arcregs.h>
+#include <asm/arc-bcr.h>
+#include <asm/cache.h>
+
+/*
+ * [ NOTE 1 ]:
+ * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable
+ * operation may result in unexpected behavior and data loss even if we flush
+ * data cache right before invalidation. That may happens if we store any context
+ * on stack (like we store BLINK register on stack before function call).
+ * BLINK register is the register where return address is automatically saved
+ * when we do function call with instructions like 'bl'.
+ *
+ * There is the real example:
+ * We may hang in the next code as we store any BLINK register on stack in
+ * invalidate_dcache_all() function.
+ *
+ * void flush_dcache_all() {
+ *     __dc_entire_op(OP_FLUSH);
+ *     // Other code //
+ * }
+ *
+ * void invalidate_dcache_all() {
+ *     __dc_entire_op(OP_INV);
+ *     // Other code //
+ * }
+ *
+ * void foo(void) {
+ *     flush_dcache_all();
+ *     invalidate_dcache_all();
+ * }
+ *
+ * Now let's see what really happens during that code execution:
+ *
+ * foo()
+ *   |->> call flush_dcache_all
+ *     [return address is saved to BLINK register]
+ *     [push BLINK] (save to stack)              ![point 1]
+ *     |->> call __dc_entire_op(OP_FLUSH)
+ *         [return address is saved to BLINK register]
+ *         [flush L1 D$]
+ *         return [jump to BLINK]
+ *     <<------
+ *     [other flush_dcache_all code]
+ *     [pop BLINK] (get from stack)
+ *     return [jump to BLINK]
+ *   <<------
+ *   |->> call invalidate_dcache_all
+ *     [return address is saved to BLINK register]
+ *     [push BLINK] (save to stack)               ![point 2]
+ *     |->> call __dc_entire_op(OP_FLUSH)
+ *         [return address is saved to BLINK register]
+ *         [invalidate L1 D$]                 ![point 3]
+ *         // Oops!!!
+ *         // We lose return address from invalidate_dcache_all function:
+ *         // we save it to stack and invalidate L1 D$ after that!
+ *         return [jump to BLINK]
+ *     <<------
+ *     [other invalidate_dcache_all code]
+ *     [pop BLINK] (get from stack)
+ *     // we don't have this data in L1 dcache as we invalidated it in [point 3]
+ *     // so we get it from next memory level (for example DDR memory)
+ *     // but in the memory we have value which we save in [point 1], which
+ *     // is return address from flush_dcache_all function (instead of
+ *     // address from current invalidate_dcache_all function which we
+ *     // saved in [point 2] !)
+ *     return [jump to BLINK]
+ *   <<------
+ *   // As BLINK points to invalidate_dcache_all, we call it again and
+ *   // loop forever.
+ *
+ * Fortunately we may fix that by using flush & invalidation of D$ with a single
+ * one instruction (instead of flush and invalidation instructions pair) and
+ * enabling force function inline with '__attribute__((always_inline))' gcc
+ * attribute to avoid any function call (and BLINK store) between cache flush
+ * and disable.
+ *
+ *
+ * [ NOTE 2 ]:
+ * As of today we only support the following cache configurations on ARC.
+ * Other configurations may exist in HW (for example, since version 3.0 HS
+ * supports SL$ (L2 system level cache) disable) but we don't support it in SW.
+ * Configuration 1:
+ *        ______________________
+ *       |                      |
+ *       |   ARC CPU            |
+ *       |______________________|
+ *        ___|___        ___|___
+ *       |       |      |       |
+ *       | L1 I$ |      | L1 D$ |
+ *       |_______|      |_______|
+ *        on/off         on/off
+ *        ___|______________|____
+ *       |                      |
+ *       |   main memory        |
+ *       |______________________|
+ *
+ * Configuration 2:
+ *        ______________________
+ *       |                      |
+ *       |   ARC CPU            |
+ *       |______________________|
+ *        ___|___        ___|___
+ *       |       |      |       |
+ *       | L1 I$ |      | L1 D$ |
+ *       |_______|      |_______|
+ *        on/off         on/off
+ *        ___|______________|____
+ *       |                      |
+ *       |   L2 (SL$)           |
+ *       |______________________|
+ *          always must be on
+ *        ___|______________|____
+ *       |                      |
+ *       |   main memory        |
+ *       |______________________|
+ *
+ * Configuration 3:
+ *        ______________________
+ *       |                      |
+ *       |   ARC CPU            |
+ *       |______________________|
+ *        ___|___        ___|___
+ *       |       |      |       |
+ *       | L1 I$ |      | L1 D$ |
+ *       |_______|      |_______|
+ *        on/off        must be on
+ *        ___|______________|____      _______
+ *       |                      |     |       |
+ *       |   L2 (SL$)           |-----|  IOC  |
+ *       |______________________|     |_______|
+ *          always must be on          on/off
+ *        ___|______________|____
+ *       |                      |
+ *       |   main memory        |
+ *       |______________________|
+ */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Bit values in IC_CTRL */
+#define IC_CTRL_CACHE_DISABLE	BIT(0)
+
+/* Bit values in DC_CTRL */
+#define DC_CTRL_CACHE_DISABLE	BIT(0)
+#define DC_CTRL_INV_MODE_FLUSH	BIT(6)
+#define DC_CTRL_FLUSH_STATUS	BIT(8)
+
+#define OP_INV			BIT(0)
+#define OP_FLUSH		BIT(1)
+#define OP_FLUSH_N_INV		(OP_FLUSH | OP_INV)
+
+/* Bit val in SLC_CONTROL */
+#define SLC_CTRL_DIS		0x001
+#define SLC_CTRL_IM		0x040
+#define SLC_CTRL_BUSY		0x100
+#define SLC_CTRL_RGN_OP_INV	0x200
+
+#define CACHE_LINE_MASK		(~(gd->arch.l1_line_sz - 1))
+
+/*
+ * We don't want to use '__always_inline' macro here as it can be redefined
+ * to simple 'inline' in some cases which breaks stuff. See [ NOTE 1 ] for more
+ * details about the reasons we need to use always_inline functions.
+ */
+#define inlined_cachefunc	 inline __attribute__((always_inline))
+
+static inlined_cachefunc void __ic_entire_invalidate(void);
+static inlined_cachefunc void __dc_entire_op(const int cacheop);
+
+static inline bool pae_exists(void)
+{
+	/* TODO: should we compare mmu version from BCR and from CONFIG? */
+#if (CONFIG_ARC_MMU_VER >= 4)
+	union bcr_mmu_4 mmu4;
+
+	mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR);
+
+	if (mmu4.fields.pae)
+		return true;
+#endif /* (CONFIG_ARC_MMU_VER >= 4) */
+
+	return false;
+}
+
+static inlined_cachefunc bool icache_exists(void)
+{
+	union bcr_di_cache ibcr;
+
+	ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
+	return !!ibcr.fields.ver;
+}
+
+static inlined_cachefunc bool icache_enabled(void)
+{
+	if (!icache_exists())
+		return false;
+
+	return !(read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE);
+}
+
+static inlined_cachefunc bool dcache_exists(void)
+{
+	union bcr_di_cache dbcr;
+
+	dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
+	return !!dbcr.fields.ver;
+}
+
+static inlined_cachefunc bool dcache_enabled(void)
+{
+	if (!dcache_exists())
+		return false;
+
+	return !(read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE);
+}
+
+static inlined_cachefunc bool slc_exists(void)
+{
+	if (is_isa_arcv2()) {
+		union bcr_generic sbcr;
+
+		sbcr.word = read_aux_reg(ARC_BCR_SLC);
+		return !!sbcr.fields.ver;
+	}
+
+	return false;
+}
+
+static inlined_cachefunc bool slc_data_bypass(void)
+{
+	/*
+	 * If L1 data cache is disabled SL$ is bypassed and all load/store
+	 * requests are sent directly to main memory.
+	 */
+	return !dcache_enabled();
+}
+
+static inline bool ioc_exists(void)
+{
+	if (is_isa_arcv2()) {
+		union bcr_clust_cfg cbcr;
+
+		cbcr.word = read_aux_reg(ARC_BCR_CLUSTER);
+		return cbcr.fields.c;
+	}
+
+	return false;
+}
+
+static inline bool ioc_enabled(void)
+{
+	/*
+	 * We check only CONFIG option instead of IOC HW state check as IOC
+	 * must be disabled by default.
+	 */
+	if (is_ioc_enabled())
+		return ioc_exists();
+
+	return false;
+}
+
+static inlined_cachefunc void __slc_entire_op(const int op)
+{
+	unsigned int ctrl;
+
+	if (!slc_exists())
+		return;
+
+	ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
+
+	if (!(op & OP_FLUSH))		/* i.e. OP_INV */
+		ctrl &= ~SLC_CTRL_IM;	/* clear IM: Disable flush before Inv */
+	else
+		ctrl |= SLC_CTRL_IM;
+
+	write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
+
+	if (op & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
+		write_aux_reg(ARC_AUX_SLC_INVALIDATE, 0x1);
+	else
+		write_aux_reg(ARC_AUX_SLC_FLUSH, 0x1);
+
+	/* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
+	read_aux_reg(ARC_AUX_SLC_CTRL);
+
+	/* Important to wait for flush to complete */
+	while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY);
+}
+
+static void slc_upper_region_init(void)
+{
+	/*
+	 * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist
+	 * only if PAE exists in current HW. So we had to check pae_exist
+	 * before using them.
+	 */
+	if (!pae_exists())
+		return;
+
+	/*
+	 * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0
+	 * as we don't use PAE40.
+	 */
+	write_aux_reg(ARC_AUX_SLC_RGN_END1, 0);
+	write_aux_reg(ARC_AUX_SLC_RGN_START1, 0);
+}
+
+static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op)
+{
+#ifdef CONFIG_ISA_ARCV2
+
+	unsigned int ctrl;
+	unsigned long end;
+
+	if (!slc_exists())
+		return;
+
+	/*
+	 * The Region Flush operation is specified by CTRL.RGN_OP[11..9]
+	 *  - b'000 (default) is Flush,
+	 *  - b'001 is Invalidate if CTRL.IM == 0
+	 *  - b'001 is Flush-n-Invalidate if CTRL.IM == 1
+	 */
+	ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
+
+	/* Don't rely on default value of IM bit */
+	if (!(op & OP_FLUSH))		/* i.e. OP_INV */
+		ctrl &= ~SLC_CTRL_IM;	/* clear IM: Disable flush before Inv */
+	else
+		ctrl |= SLC_CTRL_IM;
+
+	if (op & OP_INV)
+		ctrl |= SLC_CTRL_RGN_OP_INV;	/* Inv or flush-n-inv */
+	else
+		ctrl &= ~SLC_CTRL_RGN_OP_INV;
+
+	write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
+
+	/*
+	 * Lower bits are ignored, no need to clip
+	 * END needs to be setup before START (latter triggers the operation)
+	 * END can't be same as START, so add (l2_line_sz - 1) to sz
+	 */
+	end = paddr + sz + gd->arch.slc_line_sz - 1;
+
+	/*
+	 * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1)
+	 * are always == 0 as we don't use PAE40, so we only setup lower ones
+	 * (ARC_AUX_SLC_RGN_END and ARC_AUX_SLC_RGN_START)
+	 */
+	write_aux_reg(ARC_AUX_SLC_RGN_END, end);
+	write_aux_reg(ARC_AUX_SLC_RGN_START, paddr);
+
+	/* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
+	read_aux_reg(ARC_AUX_SLC_CTRL);
+
+	while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY);
+
+#endif /* CONFIG_ISA_ARCV2 */
+}
+
+static void arc_ioc_setup(void)
+{
+	/* IOC Aperture start is equal to DDR start */
+	unsigned int ap_base = CONFIG_SYS_SDRAM_BASE;
+	/* IOC Aperture size is equal to DDR size */
+	long ap_size = CONFIG_SYS_SDRAM_SIZE;
+
+	/* Unsupported configuration. See [ NOTE 2 ] for more details. */
+	if (!slc_exists())
+		panic("Try to enable IOC but SLC is not present");
+
+	/* Unsupported configuration. See [ NOTE 2 ] for more details. */
+	if (!dcache_enabled())
+		panic("Try to enable IOC but L1 D$ is disabled");
+
+	if (!is_power_of_2(ap_size) || ap_size < 4096)
+		panic("IOC Aperture size must be power of 2 and bigger 4Kib");
+
+	/* IOC Aperture start must be aligned to the size of the aperture */
+	if (ap_base % ap_size != 0)
+		panic("IOC Aperture start must be aligned to the size of the aperture");
+
+	flush_n_invalidate_dcache_all();
+
+	/*
+	 * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB,
+	 * so setting 0x11 implies 512M, 0x12 implies 1G...
+	 */
+	write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE,
+		      order_base_2(ap_size / 1024) - 2);
+
+	write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12);
+	write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1);
+	write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1);
+}
+
+static void read_decode_cache_bcr_arcv2(void)
+{
+#ifdef CONFIG_ISA_ARCV2
+
+	union bcr_slc_cfg slc_cfg;
+
+	if (slc_exists()) {
+		slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG);
+		gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
+
+		/*
+		 * We don't support configuration where L1 I$ or L1 D$ is
+		 * absent but SL$ exists. See [ NOTE 2 ] for more details.
+		 */
+		if (!icache_exists() || !dcache_exists())
+			panic("Unsupported cache configuration: SLC exists but one of L1 caches is absent");
+	}
+
+#endif /* CONFIG_ISA_ARCV2 */
+}
+
+void read_decode_cache_bcr(void)
+{
+	int dc_line_sz = 0, ic_line_sz = 0;
+	union bcr_di_cache ibcr, dbcr;
+
+	/*
+	 * We don't care much about I$ line length really as there're
+	 * no per-line ops on I$ instead we only do full invalidation of it
+	 * on occasion of relocation and right before jumping to the OS.
+	 * Still we check insane config with zero-encoded line length in
+	 * presense of version field in I$ BCR. Just in case.
+	 */
+	ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
+	if (ibcr.fields.ver) {
+		ic_line_sz = 8 << ibcr.fields.line_len;
+		if (!ic_line_sz)
+			panic("Instruction exists but line length is 0\n");
+	}
+
+	dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
+	if (dbcr.fields.ver) {
+		gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len;
+		if (!dc_line_sz)
+			panic("Data cache exists but line length is 0\n");
+	}
+}
+
+void cache_init(void)
+{
+	read_decode_cache_bcr();
+
+	if (is_isa_arcv2())
+		read_decode_cache_bcr_arcv2();
+
+	if (is_isa_arcv2() && ioc_enabled())
+		arc_ioc_setup();
+
+	if (is_isa_arcv2() && slc_exists())
+		slc_upper_region_init();
+}
+
+int icache_status(void)
+{
+	return icache_enabled();
+}
+
+void icache_enable(void)
+{
+	if (icache_exists())
+		write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
+			      ~IC_CTRL_CACHE_DISABLE);
+}
+
+void icache_disable(void)
+{
+	if (!icache_exists())
+		return;
+
+	__ic_entire_invalidate();
+
+	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
+		      IC_CTRL_CACHE_DISABLE);
+}
+
+/* IC supports only invalidation */
+static inlined_cachefunc void __ic_entire_invalidate(void)
+{
+	if (!icache_enabled())
+		return;
+
+	/* Any write to IC_IVIC register triggers invalidation of entire I$ */
+	write_aux_reg(ARC_AUX_IC_IVIC, 1);
+	/*
+	 * As per ARC HS databook (see chapter 5.3.3.2)
+	 * it is required to add 3 NOPs after each write to IC_IVIC.
+	 */
+	__builtin_arc_nop();
+	__builtin_arc_nop();
+	__builtin_arc_nop();
+	read_aux_reg(ARC_AUX_IC_CTRL);  /* blocks */
+}
+
+void invalidate_icache_all(void)
+{
+	__ic_entire_invalidate();
+
+	/*
+	 * If SL$ is bypassed for data it is used only for instructions,
+	 * so we need to invalidate it too.
+	 * TODO: HS 3.0 supports SLC disable so we need to check slc
+	 * enable/disable status here.
+	 */
+	if (is_isa_arcv2() && slc_data_bypass())
+		__slc_entire_op(OP_INV);
+}
+
+int dcache_status(void)
+{
+	return dcache_enabled();
+}
+
+void dcache_enable(void)
+{
+	if (!dcache_exists())
+		return;
+
+	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
+		      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
+}
+
+void dcache_disable(void)
+{
+	if (!dcache_exists())
+		return;
+
+	__dc_entire_op(OP_FLUSH_N_INV);
+
+	/*
+	 * As SLC will be bypassed for data after L1 D$ disable we need to
+	 * flush it first before L1 D$ disable. Also we invalidate SLC to
+	 * avoid any inconsistent data problems after enabling L1 D$ again with
+	 * dcache_enable function.
+	 */
+	if (is_isa_arcv2())
+		__slc_entire_op(OP_FLUSH_N_INV);
+
+	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
+		      DC_CTRL_CACHE_DISABLE);
+}
+
+/* Common Helper for Line Operations on D-cache */
+static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz,
+				      const int cacheop)
+{
+	unsigned int aux_cmd;
+	int num_lines;
+
+	/* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
+	aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL;
+
+	sz += paddr & ~CACHE_LINE_MASK;
+	paddr &= CACHE_LINE_MASK;
+
+	num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz);
+
+	while (num_lines-- > 0) {
+#if (CONFIG_ARC_MMU_VER == 3)
+		write_aux_reg(ARC_AUX_DC_PTAG, paddr);
+#endif
+		write_aux_reg(aux_cmd, paddr);
+		paddr += gd->arch.l1_line_sz;
+	}
+}
+
+static inlined_cachefunc void __before_dc_op(const int op)
+{
+	unsigned int ctrl;
+
+	ctrl = read_aux_reg(ARC_AUX_DC_CTRL);
+
+	/* IM bit implies flush-n-inv, instead of vanilla inv */
+	if (op == OP_INV)
+		ctrl &= ~DC_CTRL_INV_MODE_FLUSH;
+	else
+		ctrl |= DC_CTRL_INV_MODE_FLUSH;
+
+	write_aux_reg(ARC_AUX_DC_CTRL, ctrl);
+}
+
+static inlined_cachefunc void __after_dc_op(const int op)
+{
+	if (op & OP_FLUSH)	/* flush / flush-n-inv both wait */
+		while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
+}
+
+static inlined_cachefunc void __dc_entire_op(const int cacheop)
+{
+	int aux;
+
+	if (!dcache_enabled())
+		return;
+
+	__before_dc_op(cacheop);
+
+	if (cacheop & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
+		aux = ARC_AUX_DC_IVDC;
+	else
+		aux = ARC_AUX_DC_FLSH;
+
+	write_aux_reg(aux, 0x1);
+
+	__after_dc_op(cacheop);
+}
+
+static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
+				const int cacheop)
+{
+	if (!dcache_enabled())
+		return;
+
+	__before_dc_op(cacheop);
+	__dcache_line_loop(paddr, sz, cacheop);
+	__after_dc_op(cacheop);
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+	if (start >= end)
+		return;
+
+	/*
+	 * ARCv1                                 -> call __dc_line_op
+	 * ARCv2 && L1 D$ disabled               -> nothing
+	 * ARCv2 && L1 D$ enabled && IOC enabled -> nothing
+	 * ARCv2 && L1 D$ enabled && no IOC      -> call __dc_line_op; call __slc_rgn_op
+	 */
+	if (!is_isa_arcv2() || !ioc_enabled())
+		__dc_line_op(start, end - start, OP_INV);
+
+	if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass())
+		__slc_rgn_op(start, end - start, OP_INV);
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+	if (start >= end)
+		return;
+
+	/*
+	 * ARCv1                                 -> call __dc_line_op
+	 * ARCv2 && L1 D$ disabled               -> nothing
+	 * ARCv2 && L1 D$ enabled && IOC enabled -> nothing
+	 * ARCv2 && L1 D$ enabled && no IOC      -> call __dc_line_op; call __slc_rgn_op
+	 */
+	if (!is_isa_arcv2() || !ioc_enabled())
+		__dc_line_op(start, end - start, OP_FLUSH);
+
+	if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass())
+		__slc_rgn_op(start, end - start, OP_FLUSH);
+}
+
+void flush_cache(unsigned long start, unsigned long size)
+{
+	flush_dcache_range(start, start + size);
+}
+
+/*
+ * As invalidate_dcache_all() is not used in generic U-Boot code and as we
+ * don't need it in arch/arc code alone (invalidate without flush) we implement
+ * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because
+ * it's much safer. See [ NOTE 1 ] for more details.
+ */
+void flush_n_invalidate_dcache_all(void)
+{
+	__dc_entire_op(OP_FLUSH_N_INV);
+
+	if (is_isa_arcv2() && !slc_data_bypass())
+		__slc_entire_op(OP_FLUSH_N_INV);
+}
+
+void flush_dcache_all(void)
+{
+	__dc_entire_op(OP_FLUSH);
+
+	if (is_isa_arcv2() && !slc_data_bypass())
+		__slc_entire_op(OP_FLUSH);
+}
+
+/*
+ * This is function to cleanup all caches (and therefore sync I/D caches) which
+ * can be used for cleanup before linux launch or to sync caches during
+ * relocation.
+ */
+void sync_n_cleanup_cache_all(void)
+{
+	__dc_entire_op(OP_FLUSH_N_INV);
+
+	/*
+	 * If SL$ is bypassed for data it is used only for instructions,
+	 * and we shouldn't flush it. So invalidate it instead of flush_n_inv.
+	 */
+	if (is_isa_arcv2()) {
+		if (slc_data_bypass())
+			__slc_entire_op(OP_INV);
+		else
+			__slc_entire_op(OP_FLUSH_N_INV);
+	}
+
+	__ic_entire_invalidate();
+}
diff --git a/arch/arc/lib/cpu.c b/arch/arc/lib/cpu.c
new file mode 100644
index 0000000..07daaa8
--- /dev/null
+++ b/arch/arc/lib/cpu.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013-2014, 2018 Synopsys, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/arcregs.h>
+#include <asm/cache.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_cpu_init(void)
+{
+	timer_init();
+
+	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	cache_init();
+
+	return 0;
+}
+
+int arch_early_init_r(void)
+{
+	gd->bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
+	gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
+	return 0;
+}
+
+/* This is a dummy function on arc */
+int dram_init(void)
+{
+	return 0;
+}
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+const char *arc_700_version(int arcver, char *name, int name_len)
+{
+	const char *arc_ver;
+
+	switch (arcver) {
+	case 0x32:
+		arc_ver = "v4.4-4.5";
+		break;
+	case 0x33:
+		arc_ver = "v4.6-v4.9";
+		break;
+	case 0x34:
+		arc_ver = "v4.10";
+		break;
+	case 0x35:
+		arc_ver = "v4.11";
+		break;
+	default:
+		arc_ver = "unknown version";
+	}
+
+	snprintf(name, name_len, "ARC 700 %s", arc_ver);
+
+	return name;
+}
+
+struct em_template_t {
+	const bool cache;
+	const bool dsp;
+	const bool xymem;
+	const char name[8];
+};
+
+static const struct em_template_t em_versions[] = {
+	{false,	false,	false,	"EM4"},
+	{true,	false,	false,	"EM6"},
+	{false,	true,	false,	"EM5D"},
+	{true,	true,	false,	"EM7D"},
+	{false,	true,	true,	"EM9D"},
+	{true,	true,	true,	"EM11D"},
+};
+
+const char *arc_em_version(int arcver, char *name, int name_len)
+{
+	const char *arc_name = "EM";
+	const char *arc_ver;
+	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
+	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
+	bool xymem = ARC_FEATURE_EXISTS(ARC_AUX_XY_BUILD);
+	int i;
+
+	for (i = 0; i++ < sizeof(em_versions) / sizeof(struct em_template_t);) {
+		if (em_versions[i].cache == cache &&
+		    em_versions[i].dsp == dsp &&
+		    em_versions[i].xymem == xymem) {
+			arc_name = em_versions[i].name;
+			break;
+		}
+	}
+
+	switch (arcver) {
+	case 0x41:
+		arc_ver = "v1.1a";
+		break;
+	case 0x42:
+		arc_ver = "v3.0";
+		break;
+	case 0x43:
+		arc_ver = "v4.0";
+		break;
+	case 0x44:
+		arc_ver = "v5.0";
+		break;
+	default:
+		arc_ver = "unknown version";
+	}
+
+	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
+
+	return name;
+}
+
+struct hs_template_t {
+	const bool cache;
+	const bool mmu;
+	const bool dual_issue;
+	const bool dsp;
+	const char name[8];
+};
+
+static const struct hs_template_t hs_versions[] = {
+	{false,	false,	false,	false,	"HS34"},
+	{true,	false,	false,	false,	"HS36"},
+	{true,	true,	false,	false,	"HS38"},
+	{false,	false,	true,	false,	"HS44"},
+	{true,	false,	true,	false,	"HS46"},
+	{true,	true,	true,	false,	"HS48"},
+	{false,	false,	true,	true,	"HS45D"},
+	{true,	false,	true,	true,	"HS47D"},
+};
+
+const char *arc_hs_version(int arcver, char *name, int name_len)
+{
+	const char *arc_name = "HS";
+	const char *arc_ver;
+	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
+	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
+	bool mmu = !!read_aux_reg(ARC_AUX_MMU_BCR);
+	bool dual_issue = arcver == 0x54 ? true : false;
+	int i;
+
+	for (i = 0; i++ < sizeof(hs_versions) / sizeof(struct hs_template_t);) {
+		if (hs_versions[i].cache == cache &&
+		    hs_versions[i].mmu == mmu &&
+		    hs_versions[i].dual_issue == dual_issue &&
+		    hs_versions[i].dsp == dsp) {
+			arc_name = hs_versions[i].name;
+			break;
+		}
+	}
+
+	switch (arcver) {
+	case 0x50:
+		arc_ver = "v1.0";
+		break;
+	case 0x51:
+		arc_ver = "v2.0";
+		break;
+	case 0x52:
+		arc_ver = "v2.1c";
+		break;
+	case 0x53:
+		arc_ver = "v3.0";
+		break;
+	case 0x54:
+		arc_ver = "v4.0";
+		break;
+	default:
+		arc_ver = "unknown version";
+	}
+
+	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
+
+	return name;
+}
+
+const char *decode_identity(void)
+{
+#define MAX_CPU_NAME_LEN	64
+
+	int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff;
+	char *name = malloc(MAX_CPU_NAME_LEN);
+
+	if (arcver >= 0x50)
+		return arc_hs_version(arcver, name, MAX_CPU_NAME_LEN);
+	else if (arcver >= 0x40)
+		return arc_em_version(arcver, name, MAX_CPU_NAME_LEN);
+	else if (arcver >= 0x30)
+		return arc_700_version(arcver, name, MAX_CPU_NAME_LEN);
+	else
+		return "Unknown ARC core";
+}
+
+const char *decode_subsystem(void)
+{
+	int subsys_type = read_aux_reg(ARC_AUX_SUBSYS_BUILD) & GENMASK(3, 0);
+
+	switch (subsys_type) {
+	case 0: return NULL;
+	case 2: return "ARC Sensor & Control IP Subsystem";
+	case 3: return "ARC Data Fusion IP Subsystem";
+	case 4: return "ARC Secure Subsystem";
+	default: return "Unknown subsystem";
+	};
+}
+
+__weak int print_cpuinfo(void)
+{
+	const char *subsys_name = decode_subsystem();
+	char mhz[8];
+
+	printf("CPU:   %s at %s MHz\n", decode_identity(),
+	       strmhz(mhz, gd->cpu_clk));
+
+	if (subsys_name)
+		printf("Subsys:%s\n", subsys_name);
+
+	return 0;
+}
+#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arc/lib/init_helpers.c b/arch/arc/lib/init_helpers.c
new file mode 100644
index 0000000..c853f25
--- /dev/null
+++ b/arch/arc/lib/init_helpers.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+ */
+
+#include <asm/cache.h>
+#include <common.h>
+
+int init_cache_f_r(void)
+{
+	sync_n_cleanup_cache_all();
+
+	return 0;
+}
diff --git a/arch/arc/lib/interrupts.c b/arch/arc/lib/interrupts.c
new file mode 100644
index 0000000..24ff751
--- /dev/null
+++ b/arch/arc/lib/interrupts.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <asm/arcregs.h>
+#include <asm/ptrace.h>
+
+/* Bit values in STATUS32 */
+#define E1_MASK		(1 << 1)	/* Level 1 interrupts enable */
+#define E2_MASK		(1 << 2)	/* Level 2 interrupts enable */
+
+int interrupt_init(void)
+{
+	return 0;
+}
+
+/*
+ * returns true if interrupts had been enabled before we disabled them
+ */
+int disable_interrupts(void)
+{
+	int status = read_aux_reg(ARC_AUX_STATUS32);
+	int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0;
+
+	status &= ~(E1_MASK | E2_MASK);
+	/* STATUS32 register is updated indirectly with "FLAG" instruction */
+	__asm__("flag %0" : : "r" (status));
+	return state;
+}
+
+void enable_interrupts(void)
+{
+	unsigned int status = read_aux_reg(ARC_AUX_STATUS32);
+
+	status |= E1_MASK | E2_MASK;
+	/* STATUS32 register is updated indirectly with "FLAG" instruction */
+	__asm__("flag %0" : : "r" (status));
+}
+
+static void print_reg_file(long *reg_rev, int start_num)
+{
+	unsigned int i;
+
+	/* Print 3 registers per line */
+	for (i = start_num; i < start_num + 25; i++) {
+		printf("r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev);
+		if (((i + 1) % 3) == 0)
+			printf("\n");
+
+		/* Because pt_regs has registers reversed */
+		reg_rev--;
+	}
+
+	/* Add new-line if none was inserted in the end of loop above */
+	if (((i + 1) % 3) != 0)
+		printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	printf("ECR:\t0x%08lx\n", regs->ecr);
+	printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n",
+	       regs->ret, regs->blink, regs->status32);
+	printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25);
+	printf("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", regs->bta,
+	       regs->sp, regs->fp);
+	printf("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start,
+	       regs->lp_end, regs->lp_count);
+
+	print_reg_file(&(regs->r0), 0);
+}
+
+void bad_mode(struct pt_regs *regs)
+{
+	if (regs)
+		show_regs(regs);
+
+	panic("Resetting CPU ...\n");
+}
+
+void do_memory_error(unsigned long address, struct pt_regs *regs)
+{
+	printf("Memory error exception @ 0x%lx\n", address);
+	bad_mode(regs);
+}
+
+void do_instruction_error(unsigned long address, struct pt_regs *regs)
+{
+	printf("Instruction error exception @ 0x%lx\n", address);
+	bad_mode(regs);
+}
+
+void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
+{
+	printf("Machine check exception @ 0x%lx\n", address);
+	bad_mode(regs);
+}
+
+void do_interrupt_handler(void)
+{
+	printf("Interrupt fired\n");
+	bad_mode(0);
+}
+
+void do_itlb_miss(struct pt_regs *regs)
+{
+	printf("I TLB miss exception\n");
+	bad_mode(regs);
+}
+
+void do_dtlb_miss(struct pt_regs *regs)
+{
+	printf("D TLB miss exception\n");
+	bad_mode(regs);
+}
+
+void do_tlb_prot_violation(unsigned long address, struct pt_regs *regs)
+{
+	printf("TLB protection violation or misaligned access @ 0x%lx\n",
+	       address);
+	bad_mode(regs);
+}
+
+void do_privilege_violation(struct pt_regs *regs)
+{
+	printf("Privilege violation exception\n");
+	bad_mode(regs);
+}
+
+void do_trap(struct pt_regs *regs)
+{
+	printf("Trap exception\n");
+	bad_mode(regs);
+}
+
+void do_extension(struct pt_regs *regs)
+{
+	printf("Extension instruction exception\n");
+	bad_mode(regs);
+}
+
+#ifdef CONFIG_ISA_ARCV2
+void do_swi(struct pt_regs *regs)
+{
+	printf("Software Interrupt exception\n");
+	bad_mode(regs);
+}
+
+void do_divzero(unsigned long address, struct pt_regs *regs)
+{
+	printf("Division by zero exception @ 0x%lx\n", address);
+	bad_mode(regs);
+}
+
+void do_dcerror(struct pt_regs *regs)
+{
+	printf("Data cache consistency error exception\n");
+	bad_mode(regs);
+}
+
+void do_maligned(unsigned long address, struct pt_regs *regs)
+{
+	printf("Misaligned data access exception @ 0x%lx\n", address);
+	bad_mode(regs);
+}
+#endif
diff --git a/arch/arc/lib/ints_low.S b/arch/arc/lib/ints_low.S
new file mode 100644
index 0000000..38c45c6
--- /dev/null
+++ b/arch/arc/lib/ints_low.S
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * Note on the LD/ST addressing modes with address register write-back
+ *
+ * LD.a same as LD.aw
+ *
+ * LD.a    reg1, [reg2, x]  => Pre Incr
+ *      Eff Addr for load = [reg2 + x]
+ *
+ * LD.ab   reg1, [reg2, x]  => Post Incr
+ *      Eff Addr for load = [reg2]
+ */
+
+.macro PUSH reg
+	st.a	\reg, [%sp, -4]
+.endm
+
+.macro PUSHAX aux
+	lr	%r9, [\aux]
+	PUSH	%r9
+.endm
+
+.macro  SAVE_R1_TO_R24
+	PUSH	%r1
+	PUSH	%r2
+	PUSH	%r3
+	PUSH	%r4
+	PUSH	%r5
+	PUSH	%r6
+	PUSH	%r7
+	PUSH	%r8
+	PUSH	%r9
+	PUSH	%r10
+	PUSH	%r11
+	PUSH	%r12
+	PUSH	%r13
+	PUSH	%r14
+	PUSH	%r15
+	PUSH	%r16
+	PUSH	%r17
+	PUSH	%r18
+	PUSH	%r19
+	PUSH	%r20
+	PUSH	%r21
+	PUSH	%r22
+	PUSH	%r23
+	PUSH	%r24
+.endm
+
+.macro SAVE_ALL_SYS
+	/* saving %r0 to reg->r0 in advance since we read %ecr into it */
+	st	%r0, [%sp, -8]
+	lr	%r0, [%ecr]	/* all stack addressing is manual so far */
+	st	%r0, [%sp]
+	st	%sp, [%sp, -4]
+	/* now move %sp to reg->r0 position so we can do "push" automatically */
+	sub	%sp, %sp, 8
+
+	SAVE_R1_TO_R24
+	PUSH	%r25
+	PUSH	%gp
+	PUSH	%fp
+	PUSH	%blink
+	PUSHAX	%eret
+	PUSHAX	%erstatus
+	PUSH	%lp_count
+	PUSHAX	%lp_end
+	PUSHAX	%lp_start
+	PUSHAX	%erbta
+.endm
+
+.macro SAVE_EXCEPTION_SOURCE
+#ifdef CONFIG_MMU
+	/* If MMU exists exception faulting address is loaded in EFA reg */
+	lr	%r0, [%efa]
+#else
+	/* Otherwise in ERET (exception return) reg */
+	lr	%r0, [%eret]
+#endif
+.endm
+
+ENTRY(memory_error)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_memory_error
+ENDPROC(memory_error)
+
+ENTRY(instruction_error)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_instruction_error
+ENDPROC(instruction_error)
+
+ENTRY(interrupt_handler)
+	/* Todo - save and restore CPU context when interrupts will be in use */
+	bl	do_interrupt_handler
+	rtie
+ENDPROC(interrupt_handler)
+
+ENTRY(EV_MachineCheck)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_machine_check_fault
+ENDPROC(EV_MachineCheck)
+
+ENTRY(EV_TLBMissI)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_itlb_miss
+ENDPROC(EV_TLBMissI)
+
+ENTRY(EV_TLBMissD)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_dtlb_miss
+ENDPROC(EV_TLBMissD)
+
+ENTRY(EV_TLBProtV)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_tlb_prot_violation
+ENDPROC(EV_TLBProtV)
+
+ENTRY(EV_PrivilegeV)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_privilege_violation
+ENDPROC(EV_PrivilegeV)
+
+ENTRY(EV_Trap)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_trap
+ENDPROC(EV_Trap)
+
+ENTRY(EV_Extension)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_extension
+ENDPROC(EV_Extension)
+
+#ifdef CONFIG_ISA_ARCV2
+ENTRY(EV_SWI)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_swi
+ENDPROC(EV_SWI)
+
+ENTRY(EV_DivZero)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_divzero
+ENDPROC(EV_DivZero)
+
+ENTRY(EV_DCError)
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_dcerror
+ENDPROC(EV_DCError)
+
+ENTRY(EV_Maligned)
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_maligned
+ENDPROC(EV_Maligned)
+#endif
diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c
new file mode 100644
index 0000000..b92a841
--- /dev/null
+++ b/arch/arc/lib/libgcc2.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ */
+
+#include "libgcc2.h"
+
+DWtype
+__ashldi3(DWtype u, shift_count_type b)
+{
+	if (b == 0)
+		return u;
+
+	const DWunion uu = {.ll = u};
+	const shift_count_type bm = W_TYPE_SIZE - b;
+	DWunion w;
+
+	if (bm <= 0) {
+		w.s.low = 0;
+		w.s.high = (UWtype)uu.s.low << -bm;
+	} else {
+		const UWtype carries = (UWtype) uu.s.low >> bm;
+
+		w.s.low = (UWtype)uu.s.low << b;
+		w.s.high = ((UWtype)uu.s.high << b) | carries;
+	}
+
+	return w.ll;
+}
+
+DWtype
+__ashrdi3(DWtype u, shift_count_type b)
+{
+	if (b == 0)
+		return u;
+
+	const DWunion uu = {.ll = u};
+	const shift_count_type bm = W_TYPE_SIZE - b;
+	DWunion w;
+
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		const UWtype carries = (UWtype) uu.s.high << bm;
+
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((UWtype)uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+DWtype
+__lshrdi3(DWtype u, shift_count_type b)
+{
+	if (b == 0)
+		return u;
+
+	const DWunion uu = {.ll = u};
+	const shift_count_type bm = W_TYPE_SIZE - b;
+	DWunion w;
+
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (UWtype)uu.s.high >> -bm;
+	} else {
+		const UWtype carries = (UWtype)uu.s.high << bm;
+
+		w.s.high = (UWtype)uu.s.high >> b;
+		w.s.low = ((UWtype)uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+unsigned long
+udivmodsi4(unsigned long num, unsigned long den, int modwanted)
+{
+	unsigned long bit = 1;
+	unsigned long res = 0;
+
+	while (den < num && bit && !(den & (1L<<31))) {
+		den <<= 1;
+		bit <<= 1;
+	}
+
+	while (bit) {
+		if (num >= den) {
+			num -= den;
+			res |= bit;
+		}
+		bit >>= 1;
+		den >>= 1;
+	}
+
+	if (modwanted)
+		return num;
+
+	return res;
+}
+
+long
+__divsi3(long a, long b)
+{
+	int neg = 0;
+	long res;
+
+	if (a < 0) {
+		a = -a;
+		neg = !neg;
+	}
+
+	if (b < 0) {
+		b = -b;
+		neg = !neg;
+	}
+
+	res = udivmodsi4(a, b, 0);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+long
+__modsi3(long a, long b)
+{
+	int neg = 0;
+	long res;
+
+	if (a < 0) {
+		a = -a;
+		neg = 1;
+	}
+
+	if (b < 0)
+		b = -b;
+
+	res = udivmodsi4(a, b, 1);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+long
+__udivsi3(long a, long b)
+{
+	return udivmodsi4(a, b, 0);
+}
+
+long
+__umodsi3(long a, long b)
+{
+	return udivmodsi4(a, b, 1);
+}
diff --git a/arch/arc/lib/libgcc2.h b/arch/arc/lib/libgcc2.h
new file mode 100644
index 0000000..9c3ce99
--- /dev/null
+++ b/arch/arc/lib/libgcc2.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ */
+
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#define UNITS_PER_WORD 4	/* for ARC */
+#define BITS_PER_UNIT 8		/* for ARC */
+
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+
+/* Work out the largest "word" size that we can deal with on this target.  */
+#if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_MAX_UNITS_PER_WORD 8
+#elif (MIN_UNITS_PER_WORD > 2 \
+       || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
+# define LIBGCC2_MAX_UNITS_PER_WORD 4
+#else
+# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
+#endif
+
+/* Work out what word size we are using for this compilation.
+   The value can be set on the command line.  */
+#ifndef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
+#endif
+
+typedef		 int QItype	__attribute__ ((mode (QI)));
+typedef unsigned int UQItype	__attribute__ ((mode (QI)));
+typedef		 int HItype	__attribute__ ((mode (HI)));
+typedef unsigned int UHItype	__attribute__ ((mode (HI)));
+#if MIN_UNITS_PER_WORD > 1
+/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1.  */
+typedef 	 int SItype	__attribute__ ((mode (SI)));
+typedef unsigned int USItype	__attribute__ ((mode (SI)));
+#if __SIZEOF_LONG_LONG__ > 4
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2.  */
+typedef		 int DItype	__attribute__ ((mode (DI)));
+typedef unsigned int UDItype	__attribute__ ((mode (DI)));
+#if MIN_UNITS_PER_WORD > 4
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4.  */
+typedef		 int TItype	__attribute__ ((mode (TI)));
+typedef unsigned int UTItype	__attribute__ ((mode (TI)));
+#endif
+#endif
+#endif
+
+#if LIBGCC2_UNITS_PER_WORD == 8
+#define W_TYPE_SIZE (8 * BITS_PER_UNIT)
+#define Wtype	DItype
+#define UWtype	UDItype
+#define HWtype	DItype
+#define UHWtype	UDItype
+#define DWtype	TItype
+#define UDWtype	UTItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## di ## b
+#define __NDW(a,b)	__gnu_ ## a ## ti ## b
+#else
+#define __NW(a,b)	__ ## a ## di ## b
+#define __NDW(a,b)	__ ## a ## ti ## b
+#endif
+#elif LIBGCC2_UNITS_PER_WORD == 4
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+#define Wtype	SItype
+#define UWtype	USItype
+#define HWtype	SItype
+#define UHWtype	USItype
+#define DWtype	DItype
+#define UDWtype	UDItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## si ## b
+#define __NDW(a,b)	__gnu_ ## a ## di ## b
+#else
+#define __NW(a,b)	__ ## a ## si ## b
+#define __NDW(a,b)	__ ## a ## di ## b
+#endif
+#elif LIBGCC2_UNITS_PER_WORD == 2
+#define W_TYPE_SIZE (2 * BITS_PER_UNIT)
+#define Wtype	HItype
+#define UWtype	UHItype
+#define HWtype	HItype
+#define UHWtype	UHItype
+#define DWtype	SItype
+#define UDWtype	USItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## hi ## b
+#define __NDW(a,b)	__gnu_ ## a ## si ## b
+#else
+#define __NW(a,b)	__ ## a ## hi ## b
+#define __NDW(a,b)	__ ## a ## si ## b
+#endif
+#else
+#define W_TYPE_SIZE BITS_PER_UNIT
+#define Wtype	QItype
+#define UWtype  UQItype
+#define HWtype	QItype
+#define UHWtype	UQItype
+#define DWtype	HItype
+#define UDWtype	UHItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## qi ## b
+#define __NDW(a,b)	__gnu_ ## a ## hi ## b
+#else
+#define __NW(a,b)	__ ## a ## qi ## b
+#define __NDW(a,b)	__ ## a ## hi ## b
+#endif
+#endif
+
+typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
+
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+	struct DWstruct {Wtype high, low;};
+#else
+	struct DWstruct {Wtype low, high;};
+#endif
+
+/* We need this union to unpack/pack DImode values, since we don't have
+   any arithmetic yet.  Incoming DImode parameters are stored into the
+   `ll' field, and the unpacked result is read from the struct `s'.  */
+
+typedef union {
+	struct DWstruct s;
+	DWtype ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c
new file mode 100644
index 0000000..4ffba84
--- /dev/null
+++ b/arch/arc/lib/relocate.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <elf.h>
+#include <asm-generic/sections.h>
+
+extern ulong __image_copy_start;
+extern ulong __ivt_start;
+extern ulong __ivt_end;
+extern ulong __text_end;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int copy_uboot_to_ram(void)
+{
+	size_t len = (size_t)&__image_copy_end - (size_t)&__image_copy_start;
+
+	if (gd->flags & GD_FLG_SKIP_RELOC)
+		return 0;
+
+	memcpy((void *)gd->relocaddr, (void *)&__image_copy_start, len);
+
+	return 0;
+}
+
+int clear_bss(void)
+{
+	ulong dst_addr = (ulong)&__bss_start + gd->reloc_off;
+	size_t len = (size_t)&__bss_end - (size_t)&__bss_start;
+
+	memset((void *)dst_addr, 0x00, len);
+
+	return 0;
+}
+
+/*
+ * Base functionality is taken from x86 version with added ARC-specifics
+ */
+int do_elf_reloc_fixups(void)
+{
+	Elf32_Rela *re_src = (Elf32_Rela *)(&__rel_dyn_start);
+	Elf32_Rela *re_end = (Elf32_Rela *)(&__rel_dyn_end);
+
+	if (gd->flags & GD_FLG_SKIP_RELOC)
+		return 0;
+
+	debug("Section .rela.dyn is located at %08x-%08x\n",
+	      (unsigned int)re_src, (unsigned int)re_end);
+
+	Elf32_Addr *offset_ptr_rom;
+	Elf32_Addr *offset_ptr_ram;
+
+	do {
+		/* Get the location from the relocation entry */
+		offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
+
+		/* Check that the location of the relocation is in .text */
+		if (offset_ptr_rom >= (Elf32_Addr *)&__image_copy_start &&
+		    offset_ptr_rom < (Elf32_Addr *)&__image_copy_end) {
+			unsigned int val, do_swap = 0;
+			/* Switch to the in-RAM version */
+			offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
+							gd->reloc_off);
+
+#ifdef __LITTLE_ENDIAN__
+			/* If location in ".text" section swap value */
+			if (((u32)offset_ptr_rom >= (u32)&__text_start &&
+			     (u32)offset_ptr_rom <= (u32)&__text_end)
+#if defined(__ARC700__) || defined(__ARC600__)
+			    || ((u32)offset_ptr_rom >= (u32)&__ivt_start &&
+				(u32)offset_ptr_rom <= (u32)&__ivt_end)
+#endif
+			   )
+				do_swap = 1;
+#endif
+
+			debug("Patching value @ %08x (relocated to %08x)%s\n",
+			      (unsigned int)offset_ptr_rom,
+			      (unsigned int)offset_ptr_ram,
+			      do_swap ? ", middle-endian encoded" : "");
+
+			/*
+			 * Use "memcpy" because target location might be
+			 * 16-bit aligned on ARC so we may need to read
+			 * byte-by-byte. On attempt to read entire word by
+			 * CPU throws an exception
+			 */
+			memcpy(&val, offset_ptr_ram, sizeof(int));
+
+			if (do_swap)
+				val = (val << 16) | (val >> 16);
+
+			/* Check that the target points into executable */
+			if (val < (unsigned int)&__image_copy_start ||
+			    val > (unsigned int)&__image_copy_end) {
+				/* TODO: Use panic() instead of debug()
+				 *
+				 * For some reason GCC might generate
+				 * fake relocation even for LD/SC of constant
+				 * inderectly. See an example below:
+				 * ----------------------->8--------------------
+				 * static int setup_mon_len(void)
+				 * {
+				 *         gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
+				 *         return 0;
+				 * }
+				 * ----------------------->8--------------------
+				 *
+				 * And that's what we get in the binary:
+				 * ----------------------->8--------------------
+				 * 10005cb4 <setup_mon_len>:
+				 * 10005cb4:       193c 3f80 0003 2f80     st      0x32f80,[r25,60]
+				 *                         10005cb8: R_ARC_RELATIVE        *ABS*-0x10000000
+				 * 10005cbc:       7fe0                    j_s.d   [blink]
+				 * 10005cbe:       700c                    mov_s   r0,0
+				 * ----------------------->8--------------------
+				 */
+				debug("Relocation target %08x points outside of image\n",
+				      val);
+			}
+
+			val += gd->reloc_off;
+
+			if (do_swap)
+				val = (val << 16) | (val >> 16);
+
+			memcpy(offset_ptr_ram, &val, sizeof(int));
+		}
+	} while (++re_src < re_end);
+
+	return 0;
+}
diff --git a/arch/arc/lib/reset.c b/arch/arc/lib/reset.c
new file mode 100644
index 0000000..02e08df
--- /dev/null
+++ b/arch/arc/lib/reset.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#include <command.h>
+#include <common.h>
+
+__weak void reset_cpu(ulong addr)
+{
+	/* Stop debug session here */
+	__builtin_arc_brk();
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	printf("Resetting the board...\n");
+
+	reset_cpu(0);
+
+	return 0;
+}
diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S
new file mode 100644
index 0000000..84959b4
--- /dev/null
+++ b/arch/arc/lib/start.S
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/arcregs.h>
+
+ENTRY(_start)
+	/* Setup interrupt vector base that matches "__text_start" */
+	sr	__ivt_start, [ARC_AUX_INTR_VEC_BASE]
+
+	; Disable/enable I-cache according to configuration
+	lr	r5, [ARC_BCR_IC_BUILD]
+	breq	r5, 0, 1f		; I$ doesn't exist
+	lr	r5, [ARC_AUX_IC_CTRL]
+#ifndef CONFIG_SYS_ICACHE_OFF
+	bclr	r5, r5, 0		; 0 - Enable, 1 is Disable
+#else
+	bset	r5, r5, 0		; I$ exists, but is not used
+#endif
+	sr	r5, [ARC_AUX_IC_CTRL]
+
+	mov	r5, 1
+	sr	r5, [ARC_AUX_IC_IVIC]
+	; As per ARC HS databook (see chapter 5.3.3.2)
+	; it is required to add 3 NOPs after each write to IC_IVIC.
+	nop
+	nop
+	nop
+
+1:
+	; Disable/enable D-cache according to configuration
+	lr	r5, [ARC_BCR_DC_BUILD]
+	breq	r5, 0, 1f		; D$ doesn't exist
+	lr	r5, [ARC_AUX_DC_CTRL]
+	bclr	r5, r5, 6		; Invalidate (discard w/o wback)
+#ifndef CONFIG_SYS_DCACHE_OFF
+	bclr	r5, r5, 0		; Enable (+Inv)
+#else
+	bset	r5, r5, 0		; Disable (+Inv)
+#endif
+	sr	r5, [ARC_AUX_DC_CTRL]
+
+	mov	r5, 1
+	sr	r5, [ARC_AUX_DC_IVDC]
+
+
+1:
+#ifdef CONFIG_ISA_ARCV2
+	; Disable System-Level Cache (SLC)
+	lr	r5, [ARC_BCR_SLC]
+	breq	r5, 0, 1f		; SLC doesn't exist
+	lr	r5, [ARC_AUX_SLC_CTRL]
+	bclr	r5, r5, 6		; Invalidate (discard w/o wback)
+	bclr	r5, r5, 0		; Enable (+Inv)
+	sr	r5, [ARC_AUX_SLC_CTRL]
+
+1:
+#endif
+
+#ifdef __ARC_UNALIGNED__
+	/*
+	 * Enable handling of unaligned access in the CPU as by default
+	 * this HW feature is disabled while GCC starting from 8.1.0
+	 * unconditionally uses it for ARC HS cores.
+	 */
+	flag	1 << STATUS_AD_BIT
+#endif
+
+	/* Establish C runtime stack and frame */
+	mov	%sp, CONFIG_SYS_INIT_SP_ADDR
+	mov	%fp, %sp
+
+	/* Allocate reserved area from current top of stack */
+	mov	%r0, %sp
+	bl	board_init_f_alloc_reserve
+	/* Set stack below reserved area, adjust frame pointer accordingly */
+	mov	%sp, %r0
+	mov	%fp, %sp
+
+	/* Initialize reserved area - note: r0 already contains address */
+	bl	board_init_f_init_reserve
+
+#ifdef CONFIG_DEBUG_UART
+	/* Earliest point to set up early debug uart */
+	bl	debug_uart_init
+#endif
+
+	/* Zero the one and only argument of "board_init_f" */
+	mov_s	%r0, 0
+	bl	board_init_f
+
+	/* We only get here if relocation is disabled by GD_FLG_SKIP_RELOC */
+	/* Make sure we don't lose GD overwritten by zero new GD */
+	mov	%r0, %r25
+	mov	%r1, 0
+	bl	board_init_r
+ENDPROC(_start)
+
+/*
+ * void board_init_f_r_trampoline(stack-pointer address)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r0 = new stack-pointer
+ */
+ENTRY(board_init_f_r_trampoline)
+	/* Set up the stack- and frame-pointers */
+	mov	%sp, %r0
+	mov	%fp, %sp
+
+	/* Update position of intterupt vector table */
+	lr	%r0, [ARC_AUX_INTR_VEC_BASE]
+	ld	%r1, [%r25, GD_RELOC_OFF]
+	add	%r0, %r0, %r1
+	sr	%r0, [ARC_AUX_INTR_VEC_BASE]
+
+	/* Re-enter U-Boot by calling board_init_f_r */
+	j	board_init_f_r
+ENDPROC(board_init_f_r_trampoline)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
new file mode 100644
index 0000000..d6b1629
--- /dev/null
+++ b/arch/arm/Kconfig
@@ -0,0 +1,1577 @@
+menu "ARM architecture"
+	depends on ARM
+
+config SYS_ARCH
+	default "arm"
+
+config ARM64
+	bool
+	select PHYS_64BIT
+	select SYS_CACHE_SHIFT_6
+
+if ARM64
+config POSITION_INDEPENDENT
+	bool "Generate position-independent pre-relocation code"
+	help
+	  U-Boot expects to be linked to a specific hard-coded address, and to
+	  be loaded to and run from that address. This option lifts that
+	  restriction, thus allowing the code to be loaded to and executed
+	  from almost any address. This logic relies on the relocation
+	  information that is embedded into the binary to support U-Boot
+	  relocating itself to the top-of-RAM later during execution.
+
+config SYS_INIT_SP_BSS_OFFSET
+	int
+	help
+	  U-Boot typically uses a hard-coded value for the stack pointer
+	  before relocation. Define this option to instead calculate the
+	  initial SP at run-time. This is useful to avoid hard-coding addresses
+	  into U-Boot, so that can be loaded and executed at arbitrary
+	  addresses and thus avoid using arbitrary addresses at runtime. This
+	  option's value is the offset added to &_bss_start in order to
+	  calculate the stack pointer. This offset should be large enough so
+	  that the early malloc region, global data (gd), and early stack usage
+	  do not overlap any appended DTB.
+
+config LINUX_KERNEL_IMAGE_HEADER
+	bool
+	help
+	  Place a Linux kernel image header at the start of the U-Boot binary.
+	  The format of the header is described in the Linux kernel source at
+	  Documentation/arm64/booting.txt. This feature is useful since the
+	  image header reports the amount of memory (BSS and similar) that
+	  U-Boot needs to use, but which isn't part of the binary.
+
+if LINUX_KERNEL_IMAGE_HEADER
+config LNX_KRNL_IMG_TEXT_OFFSET_BASE
+	hex
+	help
+	  The value subtracted from CONFIG_SYS_TEXT_BASE to calculate the
+	  TEXT_OFFSET value written in to the Linux kernel image header.
+endif
+endif
+
+config STATIC_RELA
+	bool
+	default y if ARM64 && !POSITION_INDEPENDENT
+
+config DMA_ADDR_T_64BIT
+	bool
+	default y if ARM64
+
+config HAS_VBAR
+	bool
+
+config HAS_THUMB2
+	bool
+
+# Used for compatibility with asm files copied from the kernel
+config ARM_ASM_UNIFIED
+	bool
+	default y
+
+# Used for compatibility with asm files copied from the kernel
+config THUMB2_KERNEL
+	bool
+
+config SYS_ARM_CACHE_CP15
+	bool "CP15 based cache enabling support"
+	help
+	  Select this if your processor suports enabling caches by using
+	  CP15 registers.
+
+config SYS_ARM_MMU
+	bool "MMU-based Paged Memory Management Support"
+	select SYS_ARM_CACHE_CP15
+	help
+	  Select if you want MMU-based virtualised addressing space
+	  support by paged memory management.
+
+config SYS_ARM_MPU
+	bool 'Use the ARM v7 PMSA Compliant MPU'
+	help
+	  Some ARM systems without an MMU have instead a Memory Protection
+	  Unit (MPU) that defines the type and permissions for regions of
+	  memory.
+	  If your CPU has an MPU then you should choose 'y' here unless you
+	  know that you do not want to use the MPU.
+
+# If set, the workarounds for these ARM errata are applied early during U-Boot
+# startup. Note that in general these options force the workarounds to be
+# applied; no CPU-type/version detection exists, unlike the similar options in
+# the Linux kernel. Do not set these options unless they apply!  Also note that
+# the following can be machine specific errata. These do have ability to
+# provide rudimentary version and machine specific checks, but expect no
+# product checks:
+# CONFIG_ARM_ERRATA_430973
+# CONFIG_ARM_ERRATA_454179
+# CONFIG_ARM_ERRATA_621766
+# CONFIG_ARM_ERRATA_798870
+# CONFIG_ARM_ERRATA_801819
+# CONFIG_ARM_CORTEX_A8_CVE_2017_5715
+# CONFIG_ARM_CORTEX_A15_CVE_2017_5715
+
+config ARM_ERRATA_430973
+	bool
+
+config ARM_ERRATA_454179
+	bool
+
+config ARM_ERRATA_621766
+	bool
+
+config ARM_ERRATA_716044
+	bool
+
+config ARM_ERRATA_725233
+	bool
+
+config ARM_ERRATA_742230
+	bool
+
+config ARM_ERRATA_743622
+	bool
+
+config ARM_ERRATA_751472
+	bool
+
+config ARM_ERRATA_761320
+	bool
+
+config ARM_ERRATA_773022
+	bool
+
+config ARM_ERRATA_774769
+	bool
+
+config ARM_ERRATA_794072
+	bool
+
+config ARM_ERRATA_798870
+	bool
+
+config ARM_ERRATA_801819
+	bool
+
+config ARM_ERRATA_826974
+	bool
+
+config ARM_ERRATA_828024
+	bool
+
+config ARM_ERRATA_829520
+	bool
+
+config ARM_ERRATA_833069
+	bool
+
+config ARM_ERRATA_833471
+	bool
+
+config ARM_ERRATA_845369
+	bool
+
+config ARM_ERRATA_852421
+	bool
+
+config ARM_ERRATA_852423
+	bool
+
+config ARM_ERRATA_855873
+	bool
+
+config ARM_CORTEX_A8_CVE_2017_5715
+	bool
+
+config ARM_CORTEX_A15_CVE_2017_5715
+	bool
+
+config CPU_ARM720T
+	bool
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config CPU_ARM920T
+	bool
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config CPU_ARM926EJS
+	bool
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config CPU_ARM946ES
+	bool
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config CPU_ARM1136
+	bool
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config CPU_ARM1176
+	bool
+	select HAS_VBAR
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config CPU_V7A
+	bool
+	select HAS_THUMB2
+	select HAS_VBAR
+	select SYS_CACHE_SHIFT_6
+	imply SYS_ARM_MMU
+
+config CPU_V7M
+	bool
+	select HAS_THUMB2
+	select SYS_ARM_MPU
+	select SYS_CACHE_SHIFT_5
+	select SYS_THUMB_BUILD
+	select THUMB2_KERNEL
+
+config CPU_V7R
+	bool
+	select HAS_THUMB2
+	select SYS_ARM_CACHE_CP15
+	select SYS_ARM_MPU
+	select SYS_CACHE_SHIFT_6
+
+config CPU_PXA
+	bool
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config CPU_SA1100
+	bool
+	select SYS_CACHE_SHIFT_5
+	imply SYS_ARM_MMU
+
+config SYS_CPU
+	default "arm720t" if CPU_ARM720T
+	default "arm920t" if CPU_ARM920T
+	default "arm926ejs" if CPU_ARM926EJS
+	default "arm946es" if CPU_ARM946ES
+	default "arm1136" if CPU_ARM1136
+	default "arm1176" if CPU_ARM1176
+	default "armv7" if CPU_V7A
+	default "armv7" if CPU_V7R
+	default "armv7m" if CPU_V7M
+	default "pxa" if CPU_PXA
+	default "sa1100" if CPU_SA1100
+	default "armv8" if ARM64
+
+config SYS_ARM_ARCH
+	int
+	default 4 if CPU_ARM720T
+	default 4 if CPU_ARM920T
+	default 5 if CPU_ARM926EJS
+	default 5 if CPU_ARM946ES
+	default 6 if CPU_ARM1136
+	default 6 if CPU_ARM1176
+	default 7 if CPU_V7A
+	default 7 if CPU_V7M
+	default 7 if CPU_V7R
+	default 5 if CPU_PXA
+	default 4 if CPU_SA1100
+	default 8 if ARM64
+
+config SYS_CACHE_SHIFT_5
+	bool
+
+config SYS_CACHE_SHIFT_6
+	bool
+
+config SYS_CACHE_SHIFT_7
+	bool
+
+config SYS_CACHELINE_SIZE
+	int
+	default 128 if SYS_CACHE_SHIFT_7
+	default 64 if SYS_CACHE_SHIFT_6
+	default 32 if SYS_CACHE_SHIFT_5
+
+config SYS_ARCH_TIMER
+	bool "ARM Generic Timer support"
+	depends on CPU_V7A || ARM64
+	default y if ARM64
+	help
+	  The ARM Generic Timer (aka arch-timer) provides an architected
+	  interface to a timer source on an SoC.
+	  It is mandantory for ARMv8 implementation and widely available
+	  on ARMv7 systems.
+
+config ARM_SMCCC
+	bool "Support for ARM SMC Calling Convention (SMCCC)"
+	depends on CPU_V7A || ARM64
+	select ARM_PSCI_FW
+	help
+	  Say Y here if you want to enable ARM SMC Calling Convention.
+	  This should be enabled if U-Boot needs to communicate with system
+	  firmware (for example, PSCI) according to SMCCC.
+
+config SEMIHOSTING
+	bool "support boot from semihosting"
+	help
+	  In emulated environments, semihosting is a way for
+	  the hosted environment to call out to the emulator to
+	  retrieve files from the host machine.
+
+config SYS_THUMB_BUILD
+	bool "Build U-Boot using the Thumb instruction set"
+	depends on !ARM64
+	help
+	   Use this flag to build U-Boot using the Thumb instruction set for
+	   ARM architectures. Thumb instruction set provides better code
+	   density. For ARM architectures that support Thumb2 this flag will
+	   result in Thumb2 code generated by GCC.
+
+config SPL_SYS_THUMB_BUILD
+	bool "Build SPL using the Thumb instruction set"
+	default y if SYS_THUMB_BUILD
+	depends on !ARM64
+	help
+	   Use this flag to build SPL using the Thumb instruction set for
+	   ARM architectures. Thumb instruction set provides better code
+	   density. For ARM architectures that support Thumb2 this flag will
+	   result in Thumb2 code generated by GCC.
+
+config SYS_L2CACHE_OFF
+	bool "L2cache off"
+	help
+	  If SoC does not support L2CACHE or one do not want to enable
+	  L2CACHE, choose this option.
+
+config ENABLE_ARM_SOC_BOOT0_HOOK
+	bool "prepare BOOT0 header"
+	help
+	  If the SoC's BOOT0 requires a header area filled with (magic)
+	  values, then choose this option, and create a file included as
+	  <asm/arch/boot0.h> which contains the required assembler code.
+
+config ARM_CORTEX_CPU_IS_UP
+	bool
+	default n
+
+config USE_ARCH_MEMCPY
+	bool "Use an assembly optimized implementation of memcpy"
+	default y
+	depends on !ARM64
+	help
+	  Enable the generation of an optimized version of memcpy.
+	  Such implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config SPL_USE_ARCH_MEMCPY
+	bool "Use an assembly optimized implementation of memcpy for SPL"
+	default y if USE_ARCH_MEMCPY
+	depends on !ARM64
+	help
+	  Enable the generation of an optimized version of memcpy.
+	  Such implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config USE_ARCH_MEMSET
+	bool "Use an assembly optimized implementation of memset"
+	default y
+	depends on !ARM64
+	help
+	  Enable the generation of an optimized version of memset.
+	  Such implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config SPL_USE_ARCH_MEMSET
+	bool "Use an assembly optimized implementation of memset for SPL"
+	default y if USE_ARCH_MEMSET
+	depends on !ARM64
+	help
+	  Enable the generation of an optimized version of memset.
+	  Such implementation may be faster under some conditions
+	  but may increase the binary size.
+
+config ARM64_SUPPORT_AARCH32
+	bool "ARM64 system support AArch32 execution state"
+	default y if ARM64 && !TARGET_THUNDERX_88XX
+	help
+	  This ARM64 system supports AArch32 execution state.
+
+choice
+	prompt "Target select"
+	default TARGET_HIKEY
+
+config ARCH_AT91
+	bool "Atmel AT91"
+	select SPL_BOARD_INIT if SPL && !TARGET_SMARTWEB
+
+config TARGET_EDB93XX
+	bool "Support edb93xx"
+	select CPU_ARM920T
+	select PL010_SERIAL
+
+config TARGET_ASPENITE
+	bool "Support aspenite"
+	select CPU_ARM926EJS
+
+config TARGET_GPLUGD
+	bool "Support gplugd"
+	select CPU_ARM926EJS
+
+config ARCH_DAVINCI
+	bool "TI DaVinci"
+	select CPU_ARM926EJS
+	imply CMD_SAVES
+	help
+	  Support for TI's DaVinci platform.
+
+config KIRKWOOD
+	bool "Marvell Kirkwood"
+	select ARCH_MISC_INIT
+	select BOARD_EARLY_INIT_F
+	select CPU_ARM926EJS
+
+config ARCH_MVEBU
+	bool "Marvell MVEBU family (Armada XP/375/38x/3700/7K/8K)"
+	select DM
+	select DM_ETH
+	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
+	select OF_CONTROL
+	select OF_SEPARATE
+	select SPI
+	imply CMD_DM
+
+config TARGET_APF27
+	bool "Support apf27"
+	select CPU_ARM926EJS
+	select SUPPORT_SPL
+
+config ORION5X
+	bool "Marvell Orion"
+	select CPU_ARM926EJS
+
+config TARGET_SPEAR300
+	bool "Support spear300"
+	select BOARD_EARLY_INIT_F
+	select CPU_ARM926EJS
+	select PL011_SERIAL
+	imply CMD_SAVES
+
+config TARGET_SPEAR310
+	bool "Support spear310"
+	select BOARD_EARLY_INIT_F
+	select CPU_ARM926EJS
+	select PL011_SERIAL
+	imply CMD_SAVES
+
+config TARGET_SPEAR320
+	bool "Support spear320"
+	select BOARD_EARLY_INIT_F
+	select CPU_ARM926EJS
+	select PL011_SERIAL
+	imply CMD_SAVES
+
+config TARGET_SPEAR600
+	bool "Support spear600"
+	select BOARD_EARLY_INIT_F
+	select CPU_ARM926EJS
+	select PL011_SERIAL
+	imply CMD_SAVES
+
+config TARGET_STV0991
+	bool "Support stv0991"
+	select CPU_V7A
+	select DM
+	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
+	select PL01X_SERIAL
+	select SPI
+	select SPI_FLASH
+	imply CMD_DM
+
+config TARGET_X600
+	bool "Support x600"
+	select BOARD_LATE_INIT
+	select CPU_ARM926EJS
+	select PL011_SERIAL
+	select SUPPORT_SPL
+
+config TARGET_WOODBURN
+	bool "Support woodburn"
+	select CPU_ARM1136
+
+config TARGET_WOODBURN_SD
+	bool "Support woodburn_sd"
+	select CPU_ARM1136
+	select SUPPORT_SPL
+
+config TARGET_FLEA3
+	bool "Support flea3"
+	select CPU_ARM1136
+
+config TARGET_MX35PDK
+	bool "Support mx35pdk"
+	select BOARD_LATE_INIT
+	select CPU_ARM1136
+
+config ARCH_BCM283X
+	bool "Broadcom BCM283X family"
+	select DM
+	select DM_GPIO
+	select DM_SERIAL
+	select OF_CONTROL
+	select PL01X_SERIAL
+	select SERIAL_SEARCH_ALL
+	imply CMD_DM
+	imply FAT_WRITE
+
+config ARCH_BCM6858
+	bool "Broadcom BCM6858 family"
+	select DM
+	select OF_CONTROL
+	imply CMD_DM
+
+config TARGET_VEXPRESS_CA15_TC2
+	bool "Support vexpress_ca15_tc2"
+	select CPU_V7A
+	select CPU_V7_HAS_NONSEC
+	select CPU_V7_HAS_VIRT
+	select PL011_SERIAL
+
+config ARCH_BCMSTB
+	bool "Broadcom BCM7XXX family"
+	select CPU_V7A
+	select DM
+	select OF_CONTROL
+	select OF_PRIOR_STAGE
+	imply CMD_DM
+	help
+	  This enables support for Broadcom ARM-based set-top box
+	  chipsets, including the 7445 family of chips.
+
+config TARGET_VEXPRESS_CA5X2
+	bool "Support vexpress_ca5x2"
+	select CPU_V7A
+	select PL011_SERIAL
+
+config TARGET_VEXPRESS_CA9X4
+	bool "Support vexpress_ca9x4"
+	select CPU_V7A
+	select PL011_SERIAL
+
+config TARGET_BCM23550_W1D
+	bool "Support bcm23550_w1d"
+	select CPU_V7A
+	imply CRC32_VERIFY
+	imply FAT_WRITE
+
+config TARGET_BCM28155_AP
+	bool "Support bcm28155_ap"
+	select CPU_V7A
+	imply CRC32_VERIFY
+	imply FAT_WRITE
+
+config TARGET_BCMCYGNUS
+	bool "Support bcmcygnus"
+	select CPU_V7A
+	imply BCM_SF2_ETH
+	imply BCM_SF2_ETH_GMAC
+	imply CMD_HASH
+	imply CRC32_VERIFY
+	imply FAT_WRITE
+	imply HASH_VERIFY
+	imply NETDEVICES
+
+config TARGET_BCMNSP
+	bool "Support bcmnsp"
+	select CPU_V7A
+
+config TARGET_BCMNS2
+	bool "Support Broadcom Northstar2"
+	select ARM64
+	help
+	  Support for Broadcom Northstar 2 SoCs.  NS2 is a quad-core 64-bit
+	  ARMv8 Cortex-A57 processors targeting a broad range of networking
+	  applications
+
+config ARCH_EXYNOS
+	bool "Samsung EXYNOS"
+	select DM
+	select DM_GPIO
+	select DM_I2C
+	select DM_KEYBOARD
+	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
+	select SPI
+	imply SYS_THUMB_BUILD
+	imply CMD_DM
+	imply FAT_WRITE
+
+config ARCH_S5PC1XX
+	bool "Samsung S5PC1XX"
+	select CPU_V7A
+	select DM
+	select DM_GPIO
+	select DM_I2C
+	select DM_SERIAL
+	imply CMD_DM
+
+config ARCH_HIGHBANK
+	bool "Calxeda Highbank"
+	select CPU_V7A
+	select PL011_SERIAL
+
+config ARCH_INTEGRATOR
+	bool "ARM Ltd. Integrator family"
+	select DM
+	select DM_SERIAL
+	select PL01X_SERIAL
+	imply CMD_DM
+
+config ARCH_KEYSTONE
+	bool "TI Keystone"
+	select CMD_POWEROFF
+	select CPU_V7A
+	select SUPPORT_SPL
+	select SYS_ARCH_TIMER
+	select SYS_THUMB_BUILD
+	imply CMD_MTDPARTS
+	imply CMD_SAVES
+	imply FIT
+
+config ARCH_K3
+	bool "Texas Instruments' K3 Architecture"
+	select SPL
+	select SUPPORT_SPL
+	select FIT
+
+config ARCH_OMAP2PLUS
+	bool "TI OMAP2+"
+	select CPU_V7A
+	select SPL_BOARD_INIT if SPL
+	select SPL_STACK_R if SPL
+	select SUPPORT_SPL
+	imply FIT
+
+config ARCH_MESON
+	bool "Amlogic Meson"
+	imply DISTRO_DEFAULTS
+	help
+	  Support for the Meson SoC family developed by Amlogic Inc.,
+	  targeted at media players and tablet computers. We currently
+	  support the S905 (GXBaby) 64-bit SoC.
+
+config ARCH_MEDIATEK
+	bool "MediaTek SoCs"
+	select BINMAN
+	select DM
+	select OF_CONTROL
+	select SPL_DM if SPL
+	select SPL_LIBCOMMON_SUPPORT if SPL
+	select SPL_LIBGENERIC_SUPPORT if SPL
+	select SPL_OF_CONTROL if SPL
+	select SUPPORT_SPL
+	help
+	  Support for the MediaTek SoCs family developed by MediaTek Inc.
+	  Please refer to doc/README.mediatek for more information.
+
+config ARCH_LPC32XX
+	bool "NXP LPC32xx platform"
+	select CPU_ARM926EJS
+	select DM
+	select DM_GPIO
+	select DM_SERIAL
+	select SPL_DM if SPL
+	select SUPPORT_SPL
+	imply CMD_DM
+
+config ARCH_IMX8
+	bool "NXP i.MX8 platform"
+	select ARM64
+	select DM
+	select OF_CONTROL
+
+config ARCH_IMX8M
+	bool "NXP i.MX8M platform"
+	select ARM64
+	select DM
+	select SUPPORT_SPL
+	imply CMD_DM
+
+config ARCH_MX23
+	bool "NXP i.MX23 family"
+	select CPU_ARM926EJS
+	select PL011_SERIAL
+	select SUPPORT_SPL
+
+config ARCH_MX25
+	bool "NXP MX25"
+	select CPU_ARM926EJS
+	imply MXC_GPIO
+
+config ARCH_MX28
+	bool "NXP i.MX28 family"
+	select CPU_ARM926EJS
+	select PL011_SERIAL
+	select SUPPORT_SPL
+
+config ARCH_MX31
+	bool "NXP i.MX31 family"
+	select CPU_ARM1136
+
+config ARCH_MX7ULP
+	bool "NXP MX7ULP"
+	select CPU_V7A
+	select ROM_UNIFIED_SECTIONS
+	imply MXC_GPIO
+
+config ARCH_MX7
+	bool "Freescale MX7"
+	select ARCH_MISC_INIT
+	select BOARD_EARLY_INIT_F
+	select CPU_V7A
+	select SYS_FSL_HAS_SEC if SECURE_BOOT
+	select SYS_FSL_SEC_COMPAT_4
+	select SYS_FSL_SEC_LE
+	imply MXC_GPIO
+
+config ARCH_MX6
+	bool "Freescale MX6"
+	select CPU_V7A
+	select SYS_FSL_HAS_SEC if SECURE_BOOT
+	select SYS_FSL_SEC_COMPAT_4
+	select SYS_FSL_SEC_LE
+	select SYS_THUMB_BUILD if SPL
+	imply MXC_GPIO
+
+if ARCH_MX6
+config SPL_LDSCRIPT
+	default "arch/arm/mach-omap2/u-boot-spl.lds"
+endif
+
+config ARCH_MX5
+	bool "Freescale MX5"
+	select BOARD_EARLY_INIT_F
+	select CPU_V7A
+	imply MXC_GPIO
+
+config ARCH_OWL
+	bool "Actions Semi OWL SoCs"
+	select ARM64
+	select DM
+	select DM_SERIAL
+	select OF_CONTROL
+	imply CMD_DM
+
+config ARCH_QEMU
+	bool "QEMU Virtual Platform"
+	select DM
+	select DM_SERIAL
+	select OF_CONTROL
+	select PL01X_SERIAL
+	imply CMD_DM
+	imply DM_RTC
+	imply RTC_PL031
+
+config ARCH_RMOBILE
+	bool "Renesas ARM SoCs"
+	select BOARD_EARLY_INIT_F
+	select DM
+	select DM_SERIAL
+	imply CMD_DM
+	imply FAT_WRITE
+	imply SYS_THUMB_BUILD
+	imply ARCH_MISC_INIT if DISPLAY_CPUINFO
+
+config TARGET_S32V234EVB
+	bool "Support s32v234evb"
+	select ARM64
+	select SYS_FSL_ERRATUM_ESDHC111
+
+config ARCH_SNAPDRAGON
+	bool "Qualcomm Snapdragon SoCs"
+	select ARM64
+	select DM
+	select DM_GPIO
+	select DM_SERIAL
+	select MSM_SMEM
+	select OF_CONTROL
+	select OF_SEPARATE
+	select SMEM
+	select SPMI
+	imply CMD_DM
+
+config ARCH_SOCFPGA
+	bool "Altera SOCFPGA family"
+	select ARCH_EARLY_INIT_R
+	select ARCH_MISC_INIT if !TARGET_SOCFPGA_ARRIA10
+	select ARM64 if TARGET_SOCFPGA_STRATIX10
+	select CPU_V7A if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10
+	select DM
+	select DM_SERIAL
+	select ENABLE_ARM_SOC_BOOT0_HOOK if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10
+	select OF_CONTROL
+	select SPL_DM_RESET if DM_RESET
+	select SPL_DM_SERIAL
+	select SPL_LIBCOMMON_SUPPORT
+	select SPL_LIBGENERIC_SUPPORT
+	select SPL_NAND_SUPPORT if SPL_NAND_DENALI
+	select SPL_OF_CONTROL
+	select SPL_SEPARATE_BSS if TARGET_SOCFPGA_STRATIX10
+	select SPL_SERIAL_SUPPORT
+	select SPL_WATCHDOG_SUPPORT
+	select SUPPORT_SPL
+	select SYS_NS16550
+	select SYS_THUMB_BUILD if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10
+	imply CMD_DM
+	imply CMD_MTDPARTS
+	imply CRC32_VERIFY
+	imply DM_SPI
+	imply DM_SPI_FLASH
+	imply FAT_WRITE
+	imply SPL_LIBDISK_SUPPORT
+	imply SPL_MMC_SUPPORT
+	imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
+	imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE
+	imply SPL_SPI_FLASH_SUPPORT
+	imply SPL_SPI_SUPPORT
+
+config ARCH_SUNXI
+	bool "Support sunxi (Allwinner) SoCs"
+	select BINMAN
+	select CMD_GPIO
+	select CMD_MMC if MMC
+	select CMD_USB if DISTRO_DEFAULTS
+	select DM
+	select DM_ETH
+	select DM_GPIO
+	select DM_KEYBOARD
+	select DM_SERIAL
+	select DM_USB if DISTRO_DEFAULTS
+	select OF_BOARD_SETUP
+	select OF_CONTROL
+	select OF_SEPARATE
+	select SPECIFY_CONSOLE_INDEX
+	select SPL_STACK_R if SPL
+	select SPL_SYS_MALLOC_SIMPLE if SPL
+	select SPL_SYS_THUMB_BUILD if !ARM64
+	select SYS_NS16550
+	select SYS_THUMB_BUILD if !ARM64
+	select USB if DISTRO_DEFAULTS
+	select USB_KEYBOARD if DISTRO_DEFAULTS
+	select USB_STORAGE if DISTRO_DEFAULTS
+	select USE_TINY_PRINTF
+	imply CMD_DM
+	imply CMD_GPT
+	imply CMD_UBI if NAND
+	imply DISTRO_DEFAULTS
+	imply FAT_WRITE
+	imply FIT
+	imply OF_LIBFDT_OVERLAY
+	imply PRE_CONSOLE_BUFFER
+	imply SPL_GPIO_SUPPORT
+	imply SPL_LIBCOMMON_SUPPORT
+	imply SPL_LIBGENERIC_SUPPORT
+	imply SPL_MMC_SUPPORT if MMC
+	imply SPL_POWER_SUPPORT
+	imply SPL_SERIAL_SUPPORT
+	imply USB_GADGET
+
+config ARCH_VERSAL
+	bool "Support Xilinx Versal Platform"
+	select ARM64
+	select CLK
+	select DM
+	select DM_SERIAL
+	select OF_CONTROL
+
+config ARCH_VF610
+	bool "Freescale Vybrid"
+	select CPU_V7A
+	select SYS_FSL_ERRATUM_ESDHC111
+	imply CMD_MTDPARTS
+	imply NAND
+
+config ARCH_ZYNQ
+	bool "Xilinx Zynq based platform"
+	select BOARD_EARLY_INIT_F if WDT
+	select CLK
+	select CLK_ZYNQ
+	select CPU_V7A
+	select DM
+	select DM_ETH if NET
+	select DM_MMC if MMC
+	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
+	select DM_USB if USB
+	select OF_CONTROL
+	select SPI
+	select SPL_BOARD_INIT if SPL
+	select SPL_CLK if SPL
+	select SPL_DM if SPL
+	select SPL_OF_CONTROL if SPL
+	select SPL_SEPARATE_BSS if SPL
+	select SUPPORT_SPL
+	imply ARCH_EARLY_INIT_R
+	imply BOARD_LATE_INIT
+	imply CMD_CLK
+	imply CMD_DM
+	imply CMD_SPL
+	imply FAT_WRITE
+
+config ARCH_ZYNQMP_R5
+	bool "Xilinx ZynqMP R5 based platform"
+	select CLK
+	select CPU_V7R
+	select DM
+	select DM_SERIAL
+	select OF_CONTROL
+	imply CMD_DM
+	imply DM_USB_GADGET
+
+config ARCH_ZYNQMP
+	bool "Xilinx ZynqMP based platform"
+	select ARM64
+	select CLK
+	select DM
+	select DM_SERIAL
+	select DM_USB if USB
+	select OF_CONTROL
+	select SPL_BOARD_INIT if SPL
+	select SPL_CLK if SPL
+	select SPL_SEPARATE_BSS if SPL
+	select SUPPORT_SPL
+	imply BOARD_LATE_INIT
+	imply CMD_DM
+	imply FAT_WRITE
+	imply MP
+	imply DM_USB_GADGET
+
+config TEGRA
+	bool "NVIDIA Tegra"
+	imply DISTRO_DEFAULTS
+	imply FAT_WRITE
+
+config TARGET_VEXPRESS64_AEMV8A
+	bool "Support vexpress_aemv8a"
+	select ARM64
+	select PL01X_SERIAL
+
+config TARGET_VEXPRESS64_BASE_FVP
+	bool "Support Versatile Express ARMv8a FVP BASE model"
+	select ARM64
+	select PL01X_SERIAL
+	select SEMIHOSTING
+
+config TARGET_VEXPRESS64_BASE_FVP_DRAM
+	bool "Support Versatile Express ARMv8a FVP BASE model booting from DRAM"
+	select ARM64
+	select PL01X_SERIAL
+	help
+	  This target is derived from TARGET_VEXPRESS64_BASE_FVP and over-rides
+	  the default config to allow the user to load the images directly into
+	  DRAM using model parameters rather than by using semi-hosting to load
+	  the files from the host filesystem.
+
+config TARGET_VEXPRESS64_JUNO
+	bool "Support Versatile Express Juno Development Platform"
+	select ARM64
+	select PL01X_SERIAL
+
+config TARGET_LS2080A_EMU
+	bool "Support ls2080a_emu"
+	select ARCH_LS2080A
+	select ARCH_MISC_INIT
+	select ARM64
+	select ARMV8_MULTIENTRY
+	help
+	  Support for Freescale LS2080A_EMU platform
+	  The LS2080A Development System (EMULATOR) is a pre silicon
+	  development platform that supports the QorIQ LS2080A
+	  Layerscape Architecture processor.
+
+config TARGET_LS2080A_SIMU
+	bool "Support ls2080a_simu"
+	select ARCH_LS2080A
+	select ARCH_MISC_INIT
+	select ARM64
+	select ARMV8_MULTIENTRY
+	help
+	  Support for Freescale LS2080A_SIMU platform
+	  The LS2080A Development System (QDS) is a pre silicon
+	  development platform that supports the QorIQ LS2080A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1088AQDS
+	bool "Support ls1088aqds"
+	select ARCH_LS1088A
+	select ARCH_MISC_INIT
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_LATE_INIT
+	select SUPPORT_SPL
+	help
+	  Support for NXP LS1088AQDS platform
+	  The LS1088A Development System (QDS) is a high-performance
+	  development platform that supports the QorIQ LS1088A
+	  Layerscape Architecture processor.
+
+config TARGET_LS2080AQDS
+	bool "Support ls2080aqds"
+	select ARCH_LS2080A
+	select ARCH_MISC_INIT
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_LATE_INIT
+	select SUPPORT_SPL
+	imply SCSI
+	imply SCSI_AHCI
+	help
+	  Support for Freescale LS2080AQDS platform
+	  The LS2080A Development System (QDS) is a high-performance
+	  development platform that supports the QorIQ LS2080A
+	  Layerscape Architecture processor.
+
+config TARGET_LS2080ARDB
+	bool "Support ls2080ardb"
+	select ARCH_LS2080A
+	select ARCH_MISC_INIT
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_LATE_INIT
+	select SUPPORT_SPL
+	imply SCSI
+	imply SCSI_AHCI
+	help
+	  Support for Freescale LS2080ARDB platform.
+	  The LS2080A Reference design board (RDB) is a high-performance
+	  development platform that supports the QorIQ LS2080A
+	  Layerscape Architecture processor.
+
+config TARGET_LS2081ARDB
+	bool "Support ls2081ardb"
+	select ARCH_LS2080A
+	select ARCH_MISC_INIT
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_LATE_INIT
+	select SUPPORT_SPL
+	help
+	  Support for Freescale LS2081ARDB platform.
+	  The LS2081A Reference design board (RDB) is a high-performance
+	  development platform that supports the QorIQ LS2081A/LS2041A
+	  Layerscape Architecture processor.
+
+config TARGET_HIKEY
+	bool "Support HiKey 96boards Consumer Edition Platform"
+	select ARM64
+	select DM
+	select DM_GPIO
+	select DM_SERIAL
+	select OF_CONTROL
+	select PL01X_SERIAL
+	select SPECIFY_CONSOLE_INDEX
+	imply CMD_DM
+	  help
+	  Support for HiKey 96boards platform. It features a HI6220
+	  SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM.
+
+config TARGET_POPLAR
+	bool "Support Poplar 96boards Enterprise Edition Platform"
+	select ARM64
+	select DM
+	select DM_SERIAL
+	select DM_USB
+	select OF_CONTROL
+	select PL01X_SERIAL
+	imply CMD_DM
+	  help
+	  Support for Poplar 96boards EE platform. It features a HI3798cv200
+	  SoC, with 4xA53 CPU, 1GB RAM and the high performance Mali T720 GPU
+	  making it capable of running any commercial set-top solution based on
+	  Linux or Android.
+
+config TARGET_LS1012AQDS
+	bool "Support ls1012aqds"
+	select ARCH_LS1012A
+	select ARM64
+	select BOARD_LATE_INIT
+	help
+	  Support for Freescale LS1012AQDS platform.
+	  The LS1012A Development System (QDS) is a high-performance
+	  development platform that supports the QorIQ LS1012A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1012ARDB
+	bool "Support ls1012ardb"
+	select ARCH_LS1012A
+	select ARM64
+	select BOARD_LATE_INIT
+	imply SCSI
+	imply SCSI_AHCI
+	help
+	  Support for Freescale LS1012ARDB platform.
+	  The LS1012A Reference design board (RDB) is a high-performance
+	  development platform that supports the QorIQ LS1012A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1012A2G5RDB
+	bool "Support ls1012a2g5rdb"
+	select ARCH_LS1012A
+	select ARM64
+	select BOARD_LATE_INIT
+	imply SCSI
+	help
+	  Support for Freescale LS1012A2G5RDB platform.
+	  The LS1012A 2G5 Reference design board (RDB) is a high-performance
+	  development platform that supports the QorIQ LS1012A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1012AFRWY
+	bool "Support ls1012afrwy"
+	select ARCH_LS1012A
+	select ARM64
+	select BOARD_LATE_INIT
+	imply SCSI
+	imply SCSI_AHCI
+	help
+	 Support for Freescale LS1012AFRWY platform.
+	 The LS1012A FRWY board (FRWY) is a high-performance
+	 development platform that supports the QorIQ LS1012A
+	 Layerscape Architecture processor.
+
+config TARGET_LS1012AFRDM
+	bool "Support ls1012afrdm"
+	select ARCH_LS1012A
+	select ARM64
+	help
+	  Support for Freescale LS1012AFRDM platform.
+	  The LS1012A Freedom  board (FRDM) is a high-performance
+	  development platform that supports the QorIQ LS1012A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1088ARDB
+	bool "Support ls1088ardb"
+	select ARCH_LS1088A
+	select ARCH_MISC_INIT
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_LATE_INIT
+	select SUPPORT_SPL
+	help
+	  Support for NXP LS1088ARDB platform.
+	  The LS1088A Reference design board (RDB) is a high-performance
+	  development platform that supports the QorIQ LS1088A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1021AQDS
+	bool "Support ls1021aqds"
+	select ARCH_LS1021A
+	select ARCH_SUPPORT_PSCI
+	select BOARD_EARLY_INIT_F
+	select BOARD_LATE_INIT
+	select CPU_V7A
+	select CPU_V7_HAS_NONSEC
+	select CPU_V7_HAS_VIRT
+	select LS1_DEEP_SLEEP
+	select SUPPORT_SPL
+	select SYS_FSL_DDR
+	imply SCSI
+
+config TARGET_LS1021ATWR
+	bool "Support ls1021atwr"
+	select ARCH_LS1021A
+	select ARCH_SUPPORT_PSCI
+	select BOARD_EARLY_INIT_F
+	select BOARD_LATE_INIT
+	select CPU_V7A
+	select CPU_V7_HAS_NONSEC
+	select CPU_V7_HAS_VIRT
+	select LS1_DEEP_SLEEP
+	select SUPPORT_SPL
+	imply SCSI
+
+config TARGET_LS1021AIOT
+	bool "Support ls1021aiot"
+	select ARCH_LS1021A
+	select ARCH_SUPPORT_PSCI
+	select BOARD_LATE_INIT
+	select CPU_V7A
+	select CPU_V7_HAS_NONSEC
+	select CPU_V7_HAS_VIRT
+	select SUPPORT_SPL
+	imply SCSI
+	help
+	  Support for Freescale LS1021AIOT platform.
+	  The LS1021A Freescale board (IOT) is a high-performance
+	  development platform that supports the QorIQ LS1021A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1043AQDS
+	bool "Support ls1043aqds"
+	select ARCH_LS1043A
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_EARLY_INIT_F
+	select BOARD_LATE_INIT
+	select SUPPORT_SPL
+	imply SCSI
+	help
+	  Support for Freescale LS1043AQDS platform.
+
+config TARGET_LS1043ARDB
+	bool "Support ls1043ardb"
+	select ARCH_LS1043A
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_EARLY_INIT_F
+	select BOARD_LATE_INIT
+	select SUPPORT_SPL
+	imply SCSI
+	help
+	  Support for Freescale LS1043ARDB platform.
+
+config TARGET_LS1046AQDS
+	bool "Support ls1046aqds"
+	select ARCH_LS1046A
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_EARLY_INIT_F
+	select BOARD_LATE_INIT
+	select DM_SPI_FLASH if DM_SPI
+	select SUPPORT_SPL
+	imply SCSI
+	help
+	  Support for Freescale LS1046AQDS platform.
+	  The LS1046A Development System (QDS) is a high-performance
+	  development platform that supports the QorIQ LS1046A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1046ARDB
+	bool "Support ls1046ardb"
+	select ARCH_LS1046A
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select BOARD_EARLY_INIT_F
+	select BOARD_LATE_INIT
+	select DM_SPI_FLASH if DM_SPI
+	select POWER_MC34VR500
+	select SUPPORT_SPL
+	imply SCSI
+	help
+	  Support for Freescale LS1046ARDB platform.
+	  The LS1046A Reference Design Board (RDB) is a high-performance
+	  development platform that supports the QorIQ LS1046A
+	  Layerscape Architecture processor.
+
+config TARGET_H2200
+	bool "Support h2200"
+	select CPU_PXA
+
+config TARGET_ZIPITZ2
+	bool "Support zipitz2"
+	select CPU_PXA
+
+config TARGET_COLIBRI_PXA270
+	bool "Support colibri_pxa270"
+	select CPU_PXA
+
+config ARCH_UNIPHIER
+	bool "Socionext UniPhier SoCs"
+	select BOARD_LATE_INIT
+	select DM
+	select DM_GPIO
+	select DM_I2C
+	select DM_MMC
+	select DM_RESET
+	select DM_SERIAL
+	select DM_USB
+	select OF_BOARD_SETUP
+	select OF_CONTROL
+	select OF_LIBFDT
+	select PINCTRL
+	select SPL_BOARD_INIT if SPL
+	select SPL_DM if SPL
+	select SPL_LIBCOMMON_SUPPORT if SPL
+	select SPL_LIBGENERIC_SUPPORT if SPL
+	select SPL_OF_CONTROL if SPL
+	select SPL_PINCTRL if SPL
+	select SUPPORT_SPL
+	imply CMD_DM
+	imply DISTRO_DEFAULTS
+	imply FAT_WRITE
+	help
+	  Support for UniPhier SoC family developed by Socionext Inc.
+	  (formerly, System LSI Business Division of Panasonic Corporation)
+
+config STM32
+	bool "Support STMicroelectronics STM32 MCU with cortex M"
+	select CPU_V7M
+	select DM
+	select DM_SERIAL
+	imply CMD_DM
+
+config ARCH_STI
+	bool "Support STMicrolectronics SoCs"
+	select BLK
+	select CPU_V7A
+	select DM
+	select DM_MMC
+	select DM_RESET
+	select DM_SERIAL
+	imply CMD_DM
+	help
+	  Support for STMicroelectronics STiH407/10 SoC family.
+	  This SoC is used on Linaro 96Board STiH410-B2260
+
+config ARCH_STM32MP
+	bool "Support STMicroelectronics STM32MP Socs with cortex A"
+	select ARCH_MISC_INIT
+	select BOARD_LATE_INIT
+	select CLK
+	select DM
+	select DM_GPIO
+	select DM_RESET
+	select DM_SERIAL
+	select MISC
+	select OF_CONTROL
+	select OF_LIBFDT
+	select PINCTRL
+	select REGMAP
+	select SUPPORT_SPL
+	select SYSCON
+	select SYSRESET
+	select SYS_THUMB_BUILD
+	imply CMD_DM
+	help
+	  Support for STM32MP SoC family developed by STMicroelectronics,
+	  MPUs based on ARM cortex A core
+	  U-BOOT is running in DDR and SPL support is the unsecure First Stage
+	  BootLoader (FSBL)
+
+config ARCH_ROCKCHIP
+	bool "Support Rockchip SoCs"
+	select BLK
+	select DM
+	select DM_GPIO
+	select DM_I2C
+	select DM_MMC
+	select DM_PWM
+	select DM_REGULATOR
+	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
+	select DM_USB if USB
+	select ENABLE_ARM_SOC_BOOT0_HOOK
+	select OF_CONTROL
+	select SPI
+	select SPL_DM if SPL
+	select SPL_SYS_MALLOC_SIMPLE if SPL
+	select SYS_MALLOC_F
+	select SYS_THUMB_BUILD if !ARM64
+	imply ADC
+	imply CMD_DM
+	imply DISTRO_DEFAULTS
+	imply FAT_WRITE
+	imply SARADC_ROCKCHIP
+	imply SPL_SYSRESET
+	imply SYS_NS16550
+	imply TPL_SYSRESET
+	imply USB_FUNCTION_FASTBOOT
+
+config TARGET_THUNDERX_88XX
+	bool "Support ThunderX 88xx"
+	select ARM64
+	select OF_CONTROL
+	select PL01X_SERIAL
+	select SYS_CACHE_SHIFT_7
+
+config ARCH_ASPEED
+	bool "Support Aspeed SoCs"
+	select DM
+	select OF_CONTROL
+	imply CMD_DM
+
+endchoice
+
+config TI_SECURE_DEVICE
+	bool "HS Device Type Support"
+	depends on ARCH_KEYSTONE || ARCH_OMAP2PLUS
+	help
+	  If a high secure (HS) device type is being used, this config
+	  must be set. This option impacts various aspects of the
+	  build system (to create signed boot images that can be
+	  authenticated) and the code. See the doc/README.ti-secure
+	  file for further details.
+
+source "arch/arm/mach-aspeed/Kconfig"
+
+source "arch/arm/mach-at91/Kconfig"
+
+source "arch/arm/mach-bcm283x/Kconfig"
+
+source "arch/arm/mach-bcmstb/Kconfig"
+
+source "arch/arm/mach-davinci/Kconfig"
+
+source "arch/arm/mach-exynos/Kconfig"
+
+source "arch/arm/mach-highbank/Kconfig"
+
+source "arch/arm/mach-integrator/Kconfig"
+
+source "arch/arm/mach-k3/Kconfig"
+
+source "arch/arm/mach-keystone/Kconfig"
+
+source "arch/arm/mach-kirkwood/Kconfig"
+
+source "arch/arm/cpu/arm926ejs/lpc32xx/Kconfig"
+
+source "arch/arm/mach-mvebu/Kconfig"
+
+source "arch/arm/cpu/armv7/ls102xa/Kconfig"
+
+source "arch/arm/mach-imx/mx2/Kconfig"
+
+source "arch/arm/mach-imx/mx3/Kconfig"
+
+source "arch/arm/mach-imx/mx5/Kconfig"
+
+source "arch/arm/mach-imx/mx6/Kconfig"
+
+source "arch/arm/mach-imx/mx7/Kconfig"
+
+source "arch/arm/mach-imx/mx7ulp/Kconfig"
+
+source "arch/arm/mach-imx/imx8/Kconfig"
+
+source "arch/arm/mach-imx/imx8m/Kconfig"
+
+source "arch/arm/mach-imx/mxs/Kconfig"
+
+source "arch/arm/mach-omap2/Kconfig"
+
+source "arch/arm/cpu/armv8/fsl-layerscape/Kconfig"
+
+source "arch/arm/mach-orion5x/Kconfig"
+
+source "arch/arm/mach-owl/Kconfig"
+
+source "arch/arm/mach-rmobile/Kconfig"
+
+source "arch/arm/mach-meson/Kconfig"
+
+source "arch/arm/mach-mediatek/Kconfig"
+
+source "arch/arm/mach-qemu/Kconfig"
+
+source "arch/arm/mach-rockchip/Kconfig"
+
+source "arch/arm/mach-s5pc1xx/Kconfig"
+
+source "arch/arm/mach-snapdragon/Kconfig"
+
+source "arch/arm/mach-socfpga/Kconfig"
+
+source "arch/arm/mach-sti/Kconfig"
+
+source "arch/arm/mach-stm32/Kconfig"
+
+source "arch/arm/mach-stm32mp/Kconfig"
+
+source "arch/arm/mach-sunxi/Kconfig"
+
+source "arch/arm/mach-tegra/Kconfig"
+
+source "arch/arm/mach-uniphier/Kconfig"
+
+source "arch/arm/cpu/armv7/vf610/Kconfig"
+
+source "arch/arm/mach-zynq/Kconfig"
+
+source "arch/arm/mach-versal/Kconfig"
+
+source "arch/arm/mach-zynqmp-r5/Kconfig"
+
+source "arch/arm/cpu/armv7/Kconfig"
+
+source "arch/arm/cpu/armv8/zynqmp/Kconfig"
+
+source "arch/arm/cpu/armv8/Kconfig"
+
+source "arch/arm/mach-imx/Kconfig"
+
+source "board/bosch/shc/Kconfig"
+source "board/CarMediaLab/flea3/Kconfig"
+source "board/Marvell/aspenite/Kconfig"
+source "board/Marvell/gplugd/Kconfig"
+source "board/armadeus/apf27/Kconfig"
+source "board/armltd/vexpress/Kconfig"
+source "board/armltd/vexpress64/Kconfig"
+source "board/broadcom/bcm23550_w1d/Kconfig"
+source "board/broadcom/bcm28155_ap/Kconfig"
+source "board/broadcom/bcm968580xref/Kconfig"
+source "board/broadcom/bcmcygnus/Kconfig"
+source "board/broadcom/bcmnsp/Kconfig"
+source "board/broadcom/bcmns2/Kconfig"
+source "board/cavium/thunderx/Kconfig"
+source "board/cirrus/edb93xx/Kconfig"
+source "board/eets/pdu001/Kconfig"
+source "board/emulation/qemu-arm/Kconfig"
+source "board/freescale/ls2080a/Kconfig"
+source "board/freescale/ls2080aqds/Kconfig"
+source "board/freescale/ls2080ardb/Kconfig"
+source "board/freescale/ls1088a/Kconfig"
+source "board/freescale/ls1021aqds/Kconfig"
+source "board/freescale/ls1043aqds/Kconfig"
+source "board/freescale/ls1021atwr/Kconfig"
+source "board/freescale/ls1021aiot/Kconfig"
+source "board/freescale/ls1046aqds/Kconfig"
+source "board/freescale/ls1043ardb/Kconfig"
+source "board/freescale/ls1046ardb/Kconfig"
+source "board/freescale/ls1012aqds/Kconfig"
+source "board/freescale/ls1012ardb/Kconfig"
+source "board/freescale/ls1012afrdm/Kconfig"
+source "board/freescale/mx35pdk/Kconfig"
+source "board/freescale/s32v234evb/Kconfig"
+source "board/grinn/chiliboard/Kconfig"
+source "board/gumstix/pepper/Kconfig"
+source "board/h2200/Kconfig"
+source "board/hisilicon/hikey/Kconfig"
+source "board/hisilicon/poplar/Kconfig"
+source "board/isee/igep003x/Kconfig"
+source "board/phytec/pcm051/Kconfig"
+source "board/silica/pengwyn/Kconfig"
+source "board/spear/spear300/Kconfig"
+source "board/spear/spear310/Kconfig"
+source "board/spear/spear320/Kconfig"
+source "board/spear/spear600/Kconfig"
+source "board/spear/x600/Kconfig"
+source "board/st/stv0991/Kconfig"
+source "board/tcl/sl50/Kconfig"
+source "board/ucRobotics/bubblegum_96/Kconfig"
+source "board/birdland/bav335x/Kconfig"
+source "board/toradex/colibri_pxa270/Kconfig"
+source "board/vscom/baltos/Kconfig"
+source "board/woodburn/Kconfig"
+source "board/xilinx/Kconfig"
+source "board/xilinx/zynq/Kconfig"
+source "board/xilinx/zynqmp/Kconfig"
+source "board/zipitz2/Kconfig"
+
+source "arch/arm/Kconfig.debug"
+
+endmenu
+
+config SPL_LDSCRIPT
+	default "arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds" if (ARCH_MX23 || ARCH_MX28) && !SPL_FRAMEWORK
+	default "arch/arm/cpu/arm1136/u-boot-spl.lds" if CPU_ARM1136
+	default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARM64
+
+
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
new file mode 100644
index 0000000..624bcf4
--- /dev/null
+++ b/arch/arm/Kconfig.debug
@@ -0,0 +1,64 @@
+menu "ARM debug"
+
+config DEBUG_LL
+	bool "Low-level debugging functions"
+	depends on !ARM64
+	help
+	  Say Y here to include definitions of printascii, printch, printhex
+	  in U-Boot.  This is helpful if you are debugging code that
+	  executes before the console is initialized.
+
+choice
+	prompt "Low-level debugging port"
+	depends on DEBUG_LL
+
+	config DEBUG_LL_UART_8250
+		bool "Low-level debugging via 8250 UART"
+		help
+		  Say Y here if you wish the debug print routes to direct
+		  their output to an 8250 UART.  You can use this option
+		  to provide the parameters for the 8250 UART rather than
+		  selecting one of the platform specific options above if
+		  you know the parameters for the port.
+
+		  This option is preferred over the platform specific
+		  options; the platform specific options are deprecated
+		  and will be soon removed.
+
+endchoice
+
+config DEBUG_LL_INCLUDE
+	string
+	depends on DEBUG_LL
+	default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	default "mach/debug-macro.S"
+
+# Compatibility options for 8250
+config DEBUG_UART_8250
+	bool
+
+config DEBUG_UART_PHYS
+	hex "Physical base address of debug UART"
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+
+# This is not used in U-Boot
+config DEBUG_UART_VIRT
+	hex
+	default DEBUG_UART_PHYS
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+
+config DEBUG_UART_8250_SHIFT
+	int "Register offset shift for the 8250 debug UART"
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	default 2
+
+config DEBUG_UART_8250_WORD
+	bool "Use 32-bit accesses for 8250 UART"
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+	depends on DEBUG_UART_8250_SHIFT >= 2
+
+config DEBUG_UART_8250_FLOW_CONTROL
+	bool "Enable flow control for 8250 UART"
+	depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+
+endmenu
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
new file mode 100644
index 0000000..87d9d4b
--- /dev/null
+++ b/arch/arm/Makefile
@@ -0,0 +1,120 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TEGRA),yy)
+CONFIG_CPU_V7A=
+CONFIG_CPU_ARM720T=y
+endif
+
+# This selects which instruction set is used.
+arch-$(CONFIG_CPU_ARM720T)	=-march=armv4
+arch-$(CONFIG_CPU_ARM920T)	=-march=armv4t
+arch-$(CONFIG_CPU_ARM926EJS)	=-march=armv5te
+arch-$(CONFIG_CPU_ARM946ES)	=-march=armv5te
+arch-$(CONFIG_CPU_SA1100)	=-march=armv4
+arch-$(CONFIG_CPU_PXA)		=
+arch-$(CONFIG_CPU_ARM1136)	=-march=armv5
+arch-$(CONFIG_CPU_ARM1176)	=-march=armv5t
+arch-$(CONFIG_CPU_V7A)		=$(call cc-option, -march=armv7-a, \
+				 $(call cc-option, -march=armv7))
+arch-$(CONFIG_CPU_V7M)		=-march=armv7-m
+arch-$(CONFIG_CPU_V7R)		=-march=armv7-r
+arch-$(CONFIG_ARM64)		=-march=armv8-a
+
+# On Tegra systems we must build SPL for the armv4 core on the device
+# but otherwise we can use the value in CONFIG_SYS_ARM_ARCH
+ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TEGRA),yy)
+arch-y += -D__LINUX_ARM_ARCH__=4
+else
+arch-y += -D__LINUX_ARM_ARCH__=$(CONFIG_SYS_ARM_ARCH)
+endif
+
+# Evaluate arch cc-option calls now
+arch-y := $(arch-y)
+
+# This selects how we optimise for the processor.
+tune-$(CONFIG_CPU_ARM720T)	=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM920T)	=
+tune-$(CONFIG_CPU_ARM926EJS)	=
+tune-$(CONFIG_CPU_ARM946ES)	=
+tune-$(CONFIG_CPU_SA1100)	=-mtune=strongarm1100
+tune-$(CONFIG_CPU_PXA)		=-mcpu=xscale
+tune-$(CONFIG_CPU_ARM1136)	=
+tune-$(CONFIG_CPU_ARM1176)	=
+tune-$(CONFIG_CPU_V7A)		=-mtune=generic-armv7-a
+tune-$(CONFIG_CPU_V7R)		=
+tune-$(CONFIG_ARM64)		=
+
+# Evaluate tune cc-option calls now
+tune-y := $(tune-y)
+
+PLATFORM_CPPFLAGS += $(arch-y) $(tune-y)
+
+# Machine directory name.  This list is sorted alphanumerically
+# by CONFIG_* macro name.
+machine-$(CONFIG_ARCH_ASPEED)		+= aspeed
+machine-$(CONFIG_ARCH_AT91)		+= at91
+machine-$(CONFIG_ARCH_BCM283X)		+= bcm283x
+machine-$(CONFIG_ARCH_BCMSTB)		+= bcmstb
+machine-$(CONFIG_ARCH_DAVINCI)		+= davinci
+machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
+machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
+machine-$(CONFIG_ARCH_K3)		+= k3
+machine-$(CONFIG_ARCH_KEYSTONE)		+= keystone
+# TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD
+machine-$(CONFIG_KIRKWOOD)		+= kirkwood
+machine-$(CONFIG_ARCH_MEDIATEK)		+= mediatek
+machine-$(CONFIG_ARCH_MESON)		+= meson
+machine-$(CONFIG_ARCH_MVEBU)		+= mvebu
+# TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA
+# TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X
+machine-$(CONFIG_ORION5X)		+= orion5x
+machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
+machine-$(CONFIG_ARCH_OWL)		+= owl
+machine-$(CONFIG_ARCH_S5PC1XX)		+= s5pc1xx
+machine-$(CONFIG_ARCH_SUNXI)		+= sunxi
+machine-$(CONFIG_ARCH_SNAPDRAGON)	+= snapdragon
+machine-$(CONFIG_ARCH_SOCFPGA)		+= socfpga
+machine-$(CONFIG_ARCH_RMOBILE)		+= rmobile
+machine-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip
+machine-$(CONFIG_STM32)			+= stm32
+machine-$(CONFIG_ARCH_STM32MP)		+= stm32mp
+machine-$(CONFIG_TEGRA)			+= tegra
+machine-$(CONFIG_ARCH_UNIPHIER)		+= uniphier
+machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
+machine-$(CONFIG_ARCH_VERSAL)		+= versal
+machine-$(CONFIG_ARCH_ZYNQMP_R5)	+= zynqmp-r5
+
+machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
+
+PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+
+libs-y += $(machdirs)
+
+head-y := arch/arm/cpu/$(CPU)/start.o
+
+ifeq ($(CONFIG_SPL_BUILD),y)
+ifneq ($(CONFIG_SPL_START_S_PATH),)
+head-y := $(CONFIG_SPL_START_S_PATH:"%"=%)/start.o
+endif
+endif
+
+libs-y += arch/arm/cpu/$(CPU)/
+libs-y += arch/arm/cpu/
+libs-y += arch/arm/lib/
+
+ifeq ($(CONFIG_SPL_BUILD),y)
+ifneq (,$(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_MX35)$(filter $(SOC), mx25 mx5 mx6 mx7 mx35 imx8m))
+libs-y += arch/arm/mach-imx/
+endif
+else
+ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx7ulp mx31 mx35 mxs imx8m imx8 vf610))
+libs-y += arch/arm/mach-imx/
+endif
+endif
+
+ifneq (,$(filter $(SOC), kirkwood))
+libs-y += arch/arm/mach-mvebu/
+endif
+
+# deprecated
+-include $(machdirs)/config.mk
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
new file mode 100644
index 0000000..f256031
--- /dev/null
+++ b/arch/arm/config.mk
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2002
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+ifndef CONFIG_STANDALONE_LOAD_ADDR
+ifneq ($(CONFIG_ARCH_OMAP2PLUS),)
+CONFIG_STANDALONE_LOAD_ADDR = 0x80300000
+else
+CONFIG_STANDALONE_LOAD_ADDR = 0xc100000
+endif
+endif
+
+CFLAGS_NON_EFI := -fno-pic -ffixed-r9 -ffunction-sections -fdata-sections
+CFLAGS_EFI := -fpic -fshort-wchar
+
+LDFLAGS_FINAL += --gc-sections
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \
+		     -fno-common -ffixed-r9
+PLATFORM_RELFLAGS += $(call cc-option, -msoft-float) \
+      $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
+
+# LLVM support
+LLVM_RELFLAGS		:= $(call cc-option,-mllvm,) \
+			$(call cc-option,-mno-movt,)
+PLATFORM_RELFLAGS	+= $(LLVM_RELFLAGS)
+
+PLATFORM_CPPFLAGS += -D__ARM__
+
+ifdef CONFIG_ARM64
+PLATFORM_ELFFLAGS += -B aarch64 -O elf64-littleaarch64
+else
+PLATFORM_ELFFLAGS += -B arm -O elf32-littlearm
+endif
+
+# Choose between ARM/Thumb instruction sets
+ifeq ($(CONFIG_$(SPL_)SYS_THUMB_BUILD),y)
+AFLAGS_IMPLICIT_IT	:= $(call as-option,-Wa$(comma)-mimplicit-it=always)
+PF_CPPFLAGS_ARM		:= $(AFLAGS_IMPLICIT_IT) \
+			$(call cc-option, -mthumb -mthumb-interwork,\
+			$(call cc-option,-marm,)\
+			$(call cc-option,-mno-thumb-interwork,)\
+		)
+else
+PF_CPPFLAGS_ARM := $(call cc-option,-marm,) \
+		$(call cc-option,-mno-thumb-interwork,)
+endif
+
+# Only test once
+ifeq ($(CONFIG_$(SPL_)SYS_THUMB_BUILD),y)
+archprepare: checkthumb checkgcc6
+
+checkthumb:
+	@if test "$(call cc-name)" = "gcc" -a \
+			"$(call cc-version)" -lt "0404"; then \
+		echo -n '*** Your GCC does not produce working '; \
+		echo 'binaries in THUMB mode.'; \
+		echo '*** Your board is configured for THUMB mode.'; \
+		false; \
+	fi
+else
+archprepare: checkgcc6
+endif
+
+checkgcc6:
+	@if test "$(call cc-name)" = "gcc" -a \
+			"$(call cc-version)" -lt "0600"; then \
+		echo '*** Your GCC is older than 6.0 and is not supported'; \
+		false; \
+	fi
+
+
+# Try if EABI is supported, else fall back to old API,
+# i. e. for example:
+# - with ELDK 4.2 (EABI supported), use:
+#	-mabi=aapcs-linux
+# - with ELDK 4.1 (gcc 4.x, no EABI), use:
+#	-mabi=apcs-gnu
+# - with ELDK 3.1 (gcc 3.x), use:
+#	-mapcs-32
+PF_CPPFLAGS_ABI := $(call cc-option,\
+			-mabi=aapcs-linux,\
+			$(call cc-option,\
+				-mapcs-32,\
+				$(call cc-option,\
+					-mabi=apcs-gnu,\
+				)\
+			)\
+		)
+PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARM) $(PF_CPPFLAGS_ABI)
+
+# For EABI, make sure to provide raise()
+ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
+# This file is parsed many times, so the string may get added multiple
+# times. Also, the prefix needs to be different based on whether
+# CONFIG_SPL_BUILD is defined or not. 'filter-out' the existing entry
+# before adding the correct one.
+PLATFORM_LIBS := arch/arm/lib/eabi_compat.o \
+	$(filter-out arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS))
+endif
+
+# needed for relocation
+LDFLAGS_u-boot += -pie
+
+#
+# FIXME: binutils versions < 2.22 have a bug in the assembler where
+# branches to weak symbols can be incorrectly optimized in thumb mode
+# to a short branch (b.n instruction) that won't reach when the symbol
+# gets preempted
+#
+# http://sourceware.org/bugzilla/show_bug.cgi?id=12532
+#
+ifeq ($(CONFIG_$(SPL_)SYS_THUMB_BUILD),y)
+ifeq ($(GAS_BUG_12532),)
+export GAS_BUG_12532:=$(shell if [ $(call binutils-version) -lt 0222 ] ; \
+	then echo y; else echo n; fi)
+endif
+ifeq ($(GAS_BUG_12532),y)
+PLATFORM_RELFLAGS += -fno-optimize-sibling-calls
+endif
+endif
+
+ifneq ($(CONFIG_SPL_BUILD),y)
+# Check that only R_ARM_RELATIVE relocations are generated.
+ALL-y += checkarmreloc
+# The movt / movw can hardcode 16 bit parts of the addresses in the
+# instruction. Relocation is not supported for that case, so disable
+# such usage by requiring word relocations.
+PLATFORM_CPPFLAGS += $(call cc-option, -mword-relocations)
+PLATFORM_CPPFLAGS += $(call cc-option, -fno-pic)
+endif
+
+# limit ourselves to the sections we want in the .bin.
+ifdef CONFIG_ARM64
+OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .data \
+		-j .u_boot_list -j .rela.dyn -j .got -j .got.plt \
+		-j .binman_sym_table -j .text_rest
+else
+OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
+		-j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \
+		-j .binman_sym_table -j .text_rest
+endif
+
+# if a dtb section exists we always have to include it
+# there are only two cases where it is generated
+# 1) OF_EMBEDED is turned on
+# 2) unit tests include device tree blobs
+OBJCOPYFLAGS += -j .dtb.init.rodata
+
+ifdef CONFIG_EFI_LOADER
+OBJCOPYFLAGS += -j .efi_runtime -j .efi_runtime_rel
+endif
+
+ifneq ($(CONFIG_IMX_CONFIG),)
+ifdef CONFIG_SPL
+ifndef CONFIG_SPL_BUILD
+ALL-y += SPL
+endif
+else
+ifeq ($(CONFIG_OF_SEPARATE),y)
+ALL-y += u-boot-dtb.imx
+else
+ALL-y += u-boot.imx
+endif
+endif
+ifneq ($(CONFIG_VF610),)
+ALL-y += u-boot.vyb
+endif
+endif
+
+EFI_LDS := elf_arm_efi.lds
+EFI_CRT0 := crt0_arm_efi.o
+EFI_RELOC := reloc_arm_efi.o
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
new file mode 100644
index 0000000..a0e1c2a
--- /dev/null
+++ b/arch/arm/cpu/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj- += dummy.o
diff --git a/arch/arm/cpu/arm11/Makefile b/arch/arm/cpu/arm11/Makefile
new file mode 100644
index 0000000..5d721fc
--- /dev/null
+++ b/arch/arm/cpu/arm11/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y	= cpu.o
diff --git a/arch/arm/cpu/arm11/cpu.c b/arch/arm/cpu/arm11/cpu.c
new file mode 100644
index 0000000..41feeef
--- /dev/null
+++ b/arch/arm/cpu/arm11/cpu.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2004 Texas Insturments
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+
+static void cache_flush(void);
+
+int cleanup_before_linux (void)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * we turn off caches etc ...
+	 */
+
+	disable_interrupts ();
+
+	/* turn off I/D-cache */
+	icache_disable();
+	dcache_disable();
+	/* flush I/D-cache */
+	cache_flush();
+
+	return 0;
+}
+
+static void cache_flush(void)
+{
+	unsigned long i = 0;
+	/* clean entire data cache */
+	asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (i));
+	/* invalidate both caches and flush btb */
+	asm volatile("mcr p15, 0, %0, c7, c7, 0" : : "r" (i));
+	/* mem barrier to sync things */
+	asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (i));
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void invalidate_dcache_all(void)
+{
+	asm volatile("mcr p15, 0, %0, c7, c6, 0" : : "r" (0));
+}
+
+void flush_dcache_all(void)
+{
+	asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (0));
+	asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+	if (!check_cache_range(start, stop))
+		return;
+
+	while (start < stop) {
+		asm volatile("mcr p15, 0, %0, c7, c6, 1" : : "r" (start));
+		start += CONFIG_SYS_CACHELINE_SIZE;
+	}
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+	if (!check_cache_range(start, stop))
+		return;
+
+	while (start < stop) {
+		asm volatile("mcr p15, 0, %0, c7, c14, 1" : : "r" (start));
+		start += CONFIG_SYS_CACHELINE_SIZE;
+	}
+
+	asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+}
+
+#else /* #ifndef CONFIG_SYS_DCACHE_OFF */
+void invalidate_dcache_all(void)
+{
+}
+
+void flush_dcache_all(void)
+{
+}
+#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
+
+#if !defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF)
+void enable_caches(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+	icache_enable();
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+	dcache_enable();
+#endif
+}
+#endif
diff --git a/arch/arm/cpu/arm1136/Makefile b/arch/arm/cpu/arm1136/Makefile
new file mode 100644
index 0000000..24c3386
--- /dev/null
+++ b/arch/arm/cpu/arm1136/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	= start.o
+
+obj-y += ../arm11/
+obj-$(CONFIG_MX31) += mx31/
+obj-$(CONFIG_MX35) += mx35/
diff --git a/arch/arm/cpu/arm1136/mx31/Makefile b/arch/arm/cpu/arm1136/mx31/Makefile
new file mode 100644
index 0000000..67799ee
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx31/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y	+= generic.o
+obj-y	+= timer.o
+obj-y	+= devices.o
+obj-y	+= relocate.o
diff --git a/arch/arm/cpu/arm1136/mx31/devices.c b/arch/arm/cpu/arm1136/mx31/devices.c
new file mode 100644
index 0000000..9997e8f
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx31/devices.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *
+ * (C) Copyright 2009 Magnus Lilja <lilja.magnus@gmail.com>
+ *
+ * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ */
+
+#include <common.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+void mx31_uart1_hw_init(void)
+{
+	/* setup pins for UART1 */
+	mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX);
+	mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX);
+	mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
+	mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
+}
+
+void mx31_uart2_hw_init(void)
+{
+	/* setup pins for UART2 */
+	mx31_gpio_mux(MUX_RXD2__UART2_RXD_MUX);
+	mx31_gpio_mux(MUX_TXD2__UART2_TXD_MUX);
+	mx31_gpio_mux(MUX_RTS2__UART2_RTS_B);
+	mx31_gpio_mux(MUX_CTS2__UART2_CTS_B);
+}
+
+#ifdef CONFIG_MXC_SPI
+/*
+ * Note: putting several spi setups here makes no sense as they may differ
+ * at board level (physical pin SS0 of CSPI2 may aswell be used as SS0 of CSPI3)
+ */
+void mx31_spi2_hw_init(void)
+{
+	/* SPI2 */
+	mx31_gpio_mux(MUX_CSPI2_SS2__CSPI2_SS2_B);
+	mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);
+	mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B);
+	mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI);
+	mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO);
+	mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B);
+	mx31_gpio_mux(MUX_CSPI2_SS1__CSPI2_SS1_B);
+
+	/* start SPI2 clock */
+	__REG(CCM_CGR2) = __REG(CCM_CGR2) | (3 << 4);
+}
+#endif
diff --git a/arch/arm/cpu/arm1136/mx31/generic.c b/arch/arm/cpu/arm1136/mx31/generic.c
new file mode 100644
index 0000000..3f6af6f
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx31/generic.c
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007
+ * Sascha Hauer, Pengutronix
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+
+static u32 mx31_decode_pll(u32 reg, u32 infreq)
+{
+	u32 mfi = GET_PLL_MFI(reg);
+	s32 mfn = GET_PLL_MFN(reg);
+	u32 mfd = GET_PLL_MFD(reg);
+	u32 pd =  GET_PLL_PD(reg);
+
+	mfi = mfi <= 5 ? 5 : mfi;
+	mfn = mfn >= 512 ? mfn - 1024 : mfn;
+	mfd += 1;
+	pd += 1;
+
+	return lldiv(2 * (u64)infreq * (mfi * mfd + mfn),
+		mfd * pd);
+}
+
+static u32 mx31_get_mpl_dpdgck_clk(void)
+{
+	u32 infreq;
+
+	if ((readl(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM)
+		infreq = MXC_CLK32 * 1024;
+	else
+		infreq = MXC_HCLK;
+
+	return mx31_decode_pll(readl(CCM_MPCTL), infreq);
+}
+
+static u32 mx31_get_mcu_main_clk(void)
+{
+	/* For now we assume mpl_dpdgck_clk == mcu_main_clk
+	 * which should be correct for most boards
+	 */
+	return mx31_get_mpl_dpdgck_clk();
+}
+
+static u32 mx31_get_ipg_clk(void)
+{
+	u32 freq = mx31_get_mcu_main_clk();
+	u32 pdr0 = readl(CCM_PDR0);
+
+	freq /= GET_PDR0_MAX_PODF(pdr0) + 1;
+	freq /= GET_PDR0_IPG_PODF(pdr0) + 1;
+
+	return freq;
+}
+
+/* hsp is the clock for the ipu */
+static u32 mx31_get_hsp_clk(void)
+{
+	u32 freq = mx31_get_mcu_main_clk();
+	u32 pdr0 = readl(CCM_PDR0);
+
+	freq /= GET_PDR0_HSP_PODF(pdr0) + 1;
+
+	return freq;
+}
+
+void mx31_dump_clocks(void)
+{
+	u32 cpufreq = mx31_get_mcu_main_clk();
+	printf("mx31 cpu clock: %dMHz\n", cpufreq / 1000000);
+	printf("ipg clock     : %dHz\n", mx31_get_ipg_clk());
+	printf("hsp clock     : %dHz\n", mx31_get_hsp_clk());
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx31_get_mcu_main_clk();
+	case MXC_IPG_CLK:
+	case MXC_IPG_PERCLK:
+	case MXC_CSPI_CLK:
+	case MXC_UART_CLK:
+	case MXC_ESDHC_CLK:
+	case MXC_I2C_CLK:
+		return mx31_get_ipg_clk();
+	case MXC_IPU_CLK:
+		return mx31_get_hsp_clk();
+	}
+	return -1;
+}
+
+u32 imx_get_uartclk(void)
+{
+	return mxc_get_clock(MXC_UART_CLK);
+}
+
+void mx31_gpio_mux(unsigned long mode)
+{
+	unsigned long reg, shift, tmp;
+
+	reg = IOMUXC_BASE + (mode & 0x1fc);
+	shift = (~mode & 0x3) * 8;
+
+	tmp = readl(reg);
+	tmp &= ~(0xff << shift);
+	tmp |= ((mode >> IOMUX_MODE_POS) & 0xff) << shift;
+	writel(tmp, reg);
+}
+
+void mx31_set_pad(enum iomux_pins pin, u32 config)
+{
+	u32 field, l, reg;
+
+	pin &= IOMUX_PADNUM_MASK;
+	reg = (IOMUXC_BASE + 0x154) + (pin + 2) / 3 * 4;
+	field = (pin + 2) % 3;
+
+	l = readl(reg);
+	l &= ~(0x1ff << (field * 10));
+	l |= config << (field * 10);
+	writel(l, reg);
+
+}
+
+void mx31_set_gpr(enum iomux_gp_func gp, char en)
+{
+	u32 l;
+	struct iomuxc_regs *iomuxc = (struct iomuxc_regs *)IOMUXC_BASE;
+
+	l = readl(&iomuxc->gpr);
+	if (en)
+		l |= gp;
+	else
+		l &= ~gp;
+
+	writel(l, &iomuxc->gpr);
+}
+
+void mxc_setup_weimcs(int cs, const struct mxc_weimcs *weimcs)
+{
+	struct mx31_weim *weim = (struct mx31_weim *) WEIM_BASE;
+	struct mx31_weim_cscr *cscr = &weim->cscr[cs];
+
+	writel(weimcs->upper, &cscr->upper);
+	writel(weimcs->lower, &cscr->lower);
+	writel(weimcs->additional, &cscr->additional);
+}
+
+struct mx3_cpu_type mx31_cpu_type[] = {
+	{ .srev = 0x00, .v = 0x10 },
+	{ .srev = 0x10, .v = 0x11 },
+	{ .srev = 0x11, .v = 0x11 },
+	{ .srev = 0x12, .v = 0x1F },
+	{ .srev = 0x13, .v = 0x1F },
+	{ .srev = 0x14, .v = 0x12 },
+	{ .srev = 0x15, .v = 0x12 },
+	{ .srev = 0x28, .v = 0x20 },
+	{ .srev = 0x29, .v = 0x20 },
+};
+
+u32 get_cpu_rev(void)
+{
+	u32 i, srev;
+
+	/* read SREV register from IIM module */
+	struct iim_regs *iim = (struct iim_regs *)MX31_IIM_BASE_ADDR;
+	srev = readl(&iim->iim_srev);
+
+	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
+		if (srev == mx31_cpu_type[i].srev)
+			return mx31_cpu_type[i].v | (MXC_CPU_MX31 << 12);
+
+	return srev | 0x8000;
+}
+
+static char *get_reset_cause(void)
+{
+	/* read RCSR register from CCM module */
+	struct clock_control_regs *ccm =
+		(struct clock_control_regs *)CCM_BASE;
+
+	u32 cause = readl(&ccm->rcsr) & 0x07;
+
+	switch (cause) {
+	case 0x0000:
+		return "POR";
+	case 0x0001:
+		return "RST";
+	case 0x0002:
+		return "WDOG";
+	case 0x0006:
+		return "JTAG";
+	case 0x0007:
+		return "ARM11P power gating";
+	default:
+		return "unknown reset";
+	}
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	u32 srev = get_cpu_rev();
+
+	printf("CPU:   Freescale i.MX31 rev %d.%d%s at %d MHz.\n",
+			(srev & 0xF0) >> 4, (srev & 0x0F),
+			((srev & 0x8000) ? " unknown" : ""),
+			mx31_get_mcu_main_clk() / 1000000);
+	printf("Reset cause: %s\n", get_reset_cause());
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/arm1136/mx31/relocate.S b/arch/arm/cpu/arm1136/mx31/relocate.S
new file mode 100644
index 0000000..225e528
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx31/relocate.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  relocate - i.MX31-specific vector relocation
+ *
+ *  Copyright (c) 2013  Albert ARIBAUD <albert.u.boot@aribaud.net>
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * The i.MX31 SoC is very specific with respect to exceptions: it
+ * does not provide RAM at the high vectors address (0xFFFF0000),
+ * thus only the low address (0x00000000) is useable; but that is
+ * in ROM, so let's avoid relocating the vectors.
+ */
+	.section	.text.relocate_vectors,"ax",%progbits
+
+ENTRY(relocate_vectors)
+
+	bx	lr
+
+ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm1136/mx31/timer.c b/arch/arm/cpu/arm1136/mx31/timer.c
new file mode 100644
index 0000000..3d07ee6
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx31/timer.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007
+ * Sascha Hauer, Pengutronix
+ */
+
+#include <common.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+
+#define TIMER_BASE 0x53f90000 /* General purpose timer 1 */
+
+/* General purpose timers registers */
+#define GPTCR	__REG(TIMER_BASE)		/* Control register	*/
+#define GPTPR	__REG(TIMER_BASE + 0x4)		/* Prescaler register	*/
+#define GPTSR	__REG(TIMER_BASE + 0x8)		/* Status register	*/
+#define GPTCNT	__REG(TIMER_BASE + 0x24)	/* Counter register	*/
+
+/* General purpose timers bitfields */
+#define GPTCR_SWR		(1 << 15)	/* Software reset	*/
+#define GPTCR_FRR		(1 << 9)	/* Freerun / restart	*/
+#define GPTCR_CLKSOURCE_32	(4 << 6)	/* Clock source		*/
+#define GPTCR_TEN		1		/* Timer enable		*/
+
+/* The 32768Hz 32-bit timer overruns in 131072 seconds */
+int timer_init(void)
+{
+	int i;
+
+	/* setup GP Timer 1 */
+	GPTCR = GPTCR_SWR;
+	for (i = 0; i < 100; i++)
+		GPTCR = 0; /* We have no udelay by now */
+	GPTPR = 0; /* 32Khz */
+	/* Freerun Mode, PERCLK1 input */
+	GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN;
+
+	return 0;
+}
+
+unsigned long timer_read_counter(void)
+{
+	return GPTCNT;
+}
diff --git a/arch/arm/cpu/arm1136/mx35/Makefile b/arch/arm/cpu/arm1136/mx35/Makefile
new file mode 100644
index 0000000..36568f9
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx35/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
+
+obj-y	+= generic.o
+obj-y	+= timer.o
+obj-y	+= mx35_sdram.o
+obj-y	+= relocate.o
diff --git a/arch/arm/cpu/arm1136/mx35/generic.c b/arch/arm/cpu/arm1136/mx35/generic.c
new file mode 100644
index 0000000..cbc4364
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx35/generic.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007
+ * Sascha Hauer, Pengutronix
+ *
+ * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+#include <netdev.h>
+#include <spl.h>
+
+#define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel))
+#define CLK_CODE_ARM(c)		(((c) >> 16) & 0xFF)
+#define CLK_CODE_AHB(c)		(((c) >>  8) & 0xFF)
+#define CLK_CODE_PATH(c)	((c) & 0xFF)
+
+#define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o))
+
+#ifdef CONFIG_FSL_ESDHC
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+static int g_clk_mux_auto[8] = {
+	CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1,
+	CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1,
+};
+
+static int g_clk_mux_consumer[16] = {
+	CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1,
+	-1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0),
+	CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1,
+	-1, -1, CLK_CODE(4, 2, 0), -1,
+};
+
+static int hsp_div_table[3][16] = {
+	{4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1},
+	{-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1},
+	{3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1},
+};
+
+u32 get_cpu_rev(void)
+{
+	int reg;
+	struct iim_regs *iim =
+		(struct iim_regs *)IIM_BASE_ADDR;
+	reg = readl(&iim->iim_srev);
+	if (!reg) {
+		reg = readw(ROMPATCH_REV);
+		reg <<= 4;
+	} else {
+		reg += CHIP_REV_1_0;
+	}
+
+	return 0x35000 + (reg & 0xFF);
+}
+
+static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd)
+{
+	int *pclk_mux;
+	if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
+		pclk_mux = g_clk_mux_consumer +
+			((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
+			MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
+	} else {
+		pclk_mux = g_clk_mux_auto +
+			((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >>
+			MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET);
+	}
+
+	if ((*pclk_mux) == -1)
+		return -1;
+
+	if (fi && fd) {
+		if (!CLK_CODE_PATH(*pclk_mux)) {
+			*fi = *fd = 1;
+			return CLK_CODE_ARM(*pclk_mux);
+		}
+		if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
+			*fi = 3;
+			*fd = 4;
+		} else {
+			*fi = 2;
+			*fd = 3;
+		}
+	}
+	return CLK_CODE_ARM(*pclk_mux);
+}
+
+static int get_ahb_div(u32 pdr0)
+{
+	int *pclk_mux;
+
+	pclk_mux = g_clk_mux_consumer +
+		((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
+		MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
+
+	if ((*pclk_mux) == -1)
+		return -1;
+
+	return CLK_CODE_AHB(*pclk_mux);
+}
+
+static u32 decode_pll(u32 reg, u32 infreq)
+{
+	u32 mfi = (reg >> 10) & 0xf;
+	s32 mfn = reg & 0x3ff;
+	u32 mfd = (reg >> 16) & 0x3ff;
+	u32 pd = (reg >> 26) & 0xf;
+
+	mfi = mfi <= 5 ? 5 : mfi;
+	mfn = mfn >= 512 ? mfn - 1024 : mfn;
+	mfd += 1;
+	pd += 1;
+
+	return lldiv(2 * (u64)infreq * (mfi * mfd + mfn),
+		mfd * pd);
+}
+
+static u32 get_mcu_main_clk(void)
+{
+	u32 arm_div = 0, fi = 0, fd = 0;
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+	arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd);
+	fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK);
+	return fi / (arm_div * fd);
+}
+
+static u32 get_ipg_clk(void)
+{
+	u32 freq = get_mcu_main_clk();
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+	u32 pdr0 = readl(&ccm->pdr0);
+
+	return freq / (get_ahb_div(pdr0) * 2);
+}
+
+static u32 get_ipg_per_clk(void)
+{
+	u32 freq = get_mcu_main_clk();
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+	u32 pdr0 = readl(&ccm->pdr0);
+	u32 pdr4 = readl(&ccm->pdr4);
+	u32 div;
+	if (pdr0 & MXC_CCM_PDR0_PER_SEL) {
+		div = CCM_GET_DIVIDER(pdr4,
+			MXC_CCM_PDR4_PER0_PODF_MASK,
+			MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1;
+	} else {
+		div = CCM_GET_DIVIDER(pdr0,
+			MXC_CCM_PDR0_PER_PODF_MASK,
+			MXC_CCM_PDR0_PER_PODF_OFFSET) + 1;
+		div *= get_ahb_div(pdr0);
+	}
+	return freq / div;
+}
+
+u32 imx_get_uartclk(void)
+{
+	u32 freq;
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+	u32 pdr4 = readl(&ccm->pdr4);
+
+	if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U)
+		freq = get_mcu_main_clk();
+	else
+		freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK);
+	freq /= CCM_GET_DIVIDER(pdr4,
+			MXC_CCM_PDR4_UART_PODF_MASK,
+			MXC_CCM_PDR4_UART_PODF_OFFSET) + 1;
+	return freq;
+}
+
+unsigned int mxc_get_main_clock(enum mxc_main_clock clk)
+{
+	u32 nfc_pdf, hsp_podf;
+	u32 pll, ret_val = 0, usb_podf;
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+
+	u32 reg = readl(&ccm->pdr0);
+	u32 reg4 = readl(&ccm->pdr4);
+
+	reg |= 0x1;
+
+	switch (clk) {
+	case CPU_CLK:
+		ret_val = get_mcu_main_clk();
+		break;
+	case AHB_CLK:
+		ret_val = get_mcu_main_clk();
+		break;
+	case HSP_CLK:
+		if (reg & CLKMODE_CONSUMER) {
+			hsp_podf = (reg >> 20) & 0x3;
+			pll = get_mcu_main_clk();
+			hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF];
+			if (hsp_podf > 0) {
+				ret_val = pll / hsp_podf;
+			} else {
+				puts("mismatch HSP with ARM clock setting\n");
+				ret_val = 0;
+			}
+		} else {
+			ret_val = get_mcu_main_clk();
+		}
+		break;
+	case IPG_CLK:
+		ret_val = get_ipg_clk();
+		break;
+	case IPG_PER_CLK:
+		ret_val = get_ipg_per_clk();
+		break;
+	case NFC_CLK:
+		nfc_pdf = (reg4 >> 28) & 0xF;
+		pll = get_mcu_main_clk();
+		/* AHB/nfc_pdf */
+		ret_val = pll / (nfc_pdf + 1);
+		break;
+	case USB_CLK:
+		usb_podf = (reg4 >> 22) & 0x3F;
+		if (reg4 & 0x200)
+			pll = get_mcu_main_clk();
+		else
+			pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK);
+
+		ret_val = pll / (usb_podf + 1);
+		break;
+	default:
+		printf("Unknown clock: %d\n", clk);
+		break;
+	}
+
+	return ret_val;
+}
+unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk)
+{
+	u32 ret_val = 0, pdf, pre_pdf, clk_sel;
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+	u32 mpdr2 = readl(&ccm->pdr2);
+	u32 mpdr3 = readl(&ccm->pdr3);
+	u32 mpdr4 = readl(&ccm->pdr4);
+
+	switch (clk) {
+	case UART1_BAUD:
+	case UART2_BAUD:
+	case UART3_BAUD:
+		clk_sel = mpdr3 & (1 << 14);
+		pdf = (mpdr4 >> 10) & 0x3F;
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
+		break;
+	case SSI1_BAUD:
+		pre_pdf = (mpdr2 >> 24) & 0x7;
+		pdf = mpdr2 & 0x3F;
+		clk_sel = mpdr2 & (1 << 6);
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
+				((pre_pdf + 1) * (pdf + 1));
+		break;
+	case SSI2_BAUD:
+		pre_pdf = (mpdr2 >> 27) & 0x7;
+		pdf = (mpdr2 >> 8) & 0x3F;
+		clk_sel = mpdr2 & (1 << 6);
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
+				((pre_pdf + 1) * (pdf + 1));
+		break;
+	case CSI_BAUD:
+		clk_sel = mpdr2 & (1 << 7);
+		pdf = (mpdr2 >> 16) & 0x3F;
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
+		break;
+	case MSHC_CLK:
+		pre_pdf = readl(&ccm->pdr1);
+		clk_sel = (pre_pdf & 0x80);
+		pdf = (pre_pdf >> 22) & 0x3F;
+		pre_pdf = (pre_pdf >> 28) & 0x7;
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
+				((pre_pdf + 1) * (pdf + 1));
+		break;
+	case ESDHC1_CLK:
+		clk_sel = mpdr3 & 0x40;
+		pdf = mpdr3 & 0x3F;
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
+		break;
+	case ESDHC2_CLK:
+		clk_sel = mpdr3 & 0x40;
+		pdf = (mpdr3 >> 8) & 0x3F;
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
+		break;
+	case ESDHC3_CLK:
+		clk_sel = mpdr3 & 0x40;
+		pdf = (mpdr3 >> 16) & 0x3F;
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1);
+		break;
+	case SPDIF_CLK:
+		clk_sel = mpdr3 & 0x400000;
+		pre_pdf = (mpdr3 >> 29) & 0x7;
+		pdf = (mpdr3 >> 23) & 0x3F;
+		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
+			decode_pll(readl(&ccm->ppctl), MXC_HCLK)) /
+				((pre_pdf + 1) * (pdf + 1));
+		break;
+	default:
+		printf("%s(): This clock: %d not supported yet\n",
+				__func__, clk);
+		break;
+	}
+
+	return ret_val;
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return get_mcu_main_clk();
+	case MXC_AHB_CLK:
+		break;
+	case MXC_IPG_CLK:
+		return get_ipg_clk();
+	case MXC_IPG_PERCLK:
+	case MXC_I2C_CLK:
+		return get_ipg_per_clk();
+	case MXC_UART_CLK:
+		return imx_get_uartclk();
+	case MXC_ESDHC1_CLK:
+		return mxc_get_peri_clock(ESDHC1_CLK);
+	case MXC_ESDHC2_CLK:
+		return mxc_get_peri_clock(ESDHC2_CLK);
+	case MXC_ESDHC3_CLK:
+		return mxc_get_peri_clock(ESDHC3_CLK);
+	case MXC_USB_CLK:
+		return mxc_get_main_clock(USB_CLK);
+	case MXC_FEC_CLK:
+		return get_ipg_clk();
+	case MXC_CSPI_CLK:
+		return get_ipg_clk();
+	}
+	return -1;
+}
+
+#ifdef CONFIG_FEC_MXC
+/*
+ * The MX35 has no fuse for MAC, return a NULL MAC
+ */
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+	memset(mac, 0, 6);
+}
+
+u32 imx_get_fecclk(void)
+{
+	return mxc_get_clock(MXC_IPG_CLK);
+}
+#endif
+
+int do_mx35_showclocks(cmd_tbl_t *cmdtp,
+	int flag, int argc, char * const argv[])
+{
+	u32 cpufreq = get_mcu_main_clk();
+	printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000);
+	printf("ipg clock     : %dHz\n", get_ipg_clk());
+	printf("ipg per clock : %dHz\n", get_ipg_per_clk());
+	printf("uart clock    : %dHz\n", mxc_get_clock(MXC_UART_CLK));
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks,
+	"display clocks",
+	""
+);
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+static char *get_reset_cause(void)
+{
+	/* read RCSR register from CCM module */
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+
+	u32 cause = readl(&ccm->rcsr) & 0x0F;
+
+	switch (cause) {
+	case 0x0000:
+		return "POR";
+	case 0x0002:
+		return "JTAG";
+	case 0x0004:
+		return "RST";
+	case 0x0008:
+		return "WDOG";
+	default:
+		return "unknown reset";
+	}
+}
+
+int print_cpuinfo(void)
+{
+	u32 srev = get_cpu_rev();
+
+	printf("CPU:   Freescale i.MX35 rev %d.%d at %d MHz.\n",
+		(srev & 0xF0) >> 4, (srev & 0x0F),
+		get_mcu_main_clk() / 1000000);
+
+	printf("Reset cause: %s\n", get_reset_cause());
+
+	return 0;
+}
+#endif
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+	int rc = -ENODEV;
+
+#if defined(CONFIG_FEC_MXC)
+	rc = fecmxc_initialize(bis);
+#endif
+
+	return rc;
+}
+
+#ifdef CONFIG_FSL_ESDHC
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+	return fsl_esdhc_mmc_init(bis);
+}
+#endif
+
+int get_clocks(void)
+{
+#ifdef CONFIG_FSL_ESDHC
+#if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR
+	gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR
+	gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+#else
+	gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK);
+#endif
+#endif
+	return 0;
+}
+
+#define RCSR_MEM_CTL_WEIM	0
+#define RCSR_MEM_CTL_NAND	1
+#define RCSR_MEM_CTL_ATA	2
+#define RCSR_MEM_CTL_EXPANSION	3
+#define RCSR_MEM_TYPE_NOR	0
+#define RCSR_MEM_TYPE_ONENAND	2
+#define RCSR_MEM_TYPE_SD	0
+#define RCSR_MEM_TYPE_I2C	2
+#define RCSR_MEM_TYPE_SPI	3
+
+u32 spl_boot_device(void)
+{
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+
+	u32 rcsr = readl(&ccm->rcsr);
+	u32 mem_type, mem_ctl;
+
+	/* In external mode, no boot device is returned */
+	if ((rcsr >> 10) & 0x03)
+		return BOOT_DEVICE_NONE;
+
+	mem_ctl = (rcsr >> 25) & 0x03;
+	mem_type = (rcsr >> 23) & 0x03;
+
+	switch (mem_ctl) {
+	case RCSR_MEM_CTL_WEIM:
+		switch (mem_type) {
+		case RCSR_MEM_TYPE_NOR:
+			return BOOT_DEVICE_NOR;
+		case RCSR_MEM_TYPE_ONENAND:
+			return BOOT_DEVICE_ONENAND;
+		default:
+			return BOOT_DEVICE_NONE;
+		}
+	case RCSR_MEM_CTL_NAND:
+		return BOOT_DEVICE_NAND;
+	case RCSR_MEM_CTL_EXPANSION:
+		switch (mem_type) {
+		case RCSR_MEM_TYPE_SD:
+			return BOOT_DEVICE_MMC1;
+		case RCSR_MEM_TYPE_I2C:
+			return BOOT_DEVICE_I2C;
+		case RCSR_MEM_TYPE_SPI:
+			return BOOT_DEVICE_SPI;
+		default:
+			return BOOT_DEVICE_NONE;
+		}
+	}
+
+	return BOOT_DEVICE_NONE;
+}
diff --git a/arch/arm/cpu/arm1136/mx35/mx35_sdram.c b/arch/arm/cpu/arm1136/mx35/mx35_sdram.c
new file mode 100644
index 0000000..f120e84
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx35/mx35_sdram.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2012, Stefano Babic <sbabic@denx.de>
+ */
+
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/imx-regs.h>
+#include <linux/types.h>
+#include <asm/arch/sys_proto.h>
+
+#define ESDCTL_DDR2_EMR2	0x04000000
+#define ESDCTL_DDR2_EMR3	0x06000000
+#define ESDCTL_PRECHARGE	0x00000400
+#define ESDCTL_DDR2_EN_DLL	0x02000400
+#define ESDCTL_DDR2_RESET_DLL	0x00000333
+#define ESDCTL_DDR2_MR		0x00000233
+#define ESDCTL_DDR2_OCD_DEFAULT 0x02000780
+
+enum {
+	SMODE_NORMAL =	0,
+	SMODE_PRECHARGE,
+	SMODE_AUTO_REFRESH,
+	SMODE_LOAD_REG,
+	SMODE_MANUAL_REFRESH
+};
+
+#define set_mode(x, en, m)	(x | (en << 31) | (m << 28))
+
+static inline void dram_wait(unsigned int count)
+{
+	volatile unsigned int wait = count;
+
+	while (wait--)
+		;
+
+}
+
+void mx3_setup_sdram_bank(u32 start_address, u32 ddr2_config,
+	u32 row, u32 col, u32 dsize, u32 refresh)
+{
+	struct esdc_regs *esdc = (struct esdc_regs *)ESDCTL_BASE_ADDR;
+	u32 *cfg_reg, *ctl_reg;
+	u32 val;
+	u32 ctlval;
+
+	switch (start_address) {
+	case CSD0_BASE_ADDR:
+		cfg_reg = &esdc->esdcfg0;
+		ctl_reg = &esdc->esdctl0;
+		break;
+	case CSD1_BASE_ADDR:
+		cfg_reg = &esdc->esdcfg1;
+		ctl_reg = &esdc->esdctl1;
+		break;
+	default:
+		return;
+	}
+
+	/* The MX35 supports 11 up to 14 rows */
+	if (row < 11 || row > 14 || col < 8 || col > 10)
+		return;
+	ctlval = (row - 11) << 24 | (col - 8) << 20 | (dsize << 16);
+
+	/* Initialize MISC register for DDR2 */
+	val = ESDC_MISC_RST | ESDC_MISC_MDDR_EN | ESDC_MISC_MDDR_DL_RST |
+		ESDC_MISC_DDR_EN | ESDC_MISC_DDR2_EN;
+	writel(val, &esdc->esdmisc);
+	val &= ~(ESDC_MISC_RST | ESDC_MISC_MDDR_DL_RST);
+	writel(val, &esdc->esdmisc);
+
+	/*
+	 * according to DDR2 specs, wait a while before
+	 * the PRECHARGE_ALL command
+	 */
+	dram_wait(0x20000);
+
+	/* Load DDR2 config and timing */
+	writel(ddr2_config, cfg_reg);
+
+	/* Precharge ALL */
+	writel(set_mode(ctlval, 1, SMODE_PRECHARGE),
+		ctl_reg);
+	writel(0xda, start_address + ESDCTL_PRECHARGE);
+
+	/* Load mode */
+	writel(set_mode(ctlval, 1, SMODE_LOAD_REG),
+		ctl_reg);
+	writeb(0xda, start_address + ESDCTL_DDR2_EMR2); /* EMRS2 */
+	writeb(0xda, start_address + ESDCTL_DDR2_EMR3); /* EMRS3 */
+	writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */
+	writeb(0xda, start_address + ESDCTL_DDR2_RESET_DLL); /* Reset DLL */
+
+	/* Precharge ALL */
+	writel(set_mode(ctlval, 1, SMODE_PRECHARGE),
+		ctl_reg);
+	writel(0xda, start_address + ESDCTL_PRECHARGE);
+
+	/* Set mode auto refresh : at least two refresh are required */
+	writel(set_mode(ctlval, 1, SMODE_AUTO_REFRESH),
+		ctl_reg);
+	writel(0xda, start_address);
+	writel(0xda, start_address);
+
+	writel(set_mode(ctlval, 1, SMODE_LOAD_REG),
+		ctl_reg);
+	writeb(0xda, start_address + ESDCTL_DDR2_MR);
+	writeb(0xda, start_address + ESDCTL_DDR2_OCD_DEFAULT);
+
+	/* OCD mode exit */
+	writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */
+
+	/* Set normal mode */
+	writel(set_mode(ctlval, 1, SMODE_NORMAL) | refresh,
+		ctl_reg);
+
+	dram_wait(0x20000);
+
+	/* Do not set delay lines, only for MDDR */
+}
diff --git a/arch/arm/cpu/arm1136/mx35/relocate.S b/arch/arm/cpu/arm1136/mx35/relocate.S
new file mode 100644
index 0000000..e41e5a5
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx35/relocate.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  relocate - i.MX35-specific vector relocation
+ *
+ *  Copyright (c) 2013  Albert ARIBAUD <albert.u.boot@aribaud.net>
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * The i.MX35 SoC is very specific with respect to exceptions: it
+ * does not provide RAM at the high vectors address (0xFFFF0000),
+ * thus only the low address (0x00000000) is useable; but that is
+ * in ROM, so let's avoid relocating the vectors.
+ */
+	.section	.text.relocate_vectors,"ax",%progbits
+
+ENTRY(relocate_vectors)
+
+	bx	lr
+
+ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm1136/mx35/timer.c b/arch/arm/cpu/arm1136/mx35/timer.c
new file mode 100644
index 0000000..c1cdf35
--- /dev/null
+++ b/arch/arm/cpu/arm1136/mx35/timer.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007
+ * Sascha Hauer, Pengutronix
+ *
+ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/crm_regs.h>
+
+/* General purpose timers bitfields */
+#define GPTCR_SWR       (1<<15)	/* Software reset */
+#define GPTCR_FRR       (1<<9)	/* Freerun / restart */
+#define GPTCR_CLKSOURCE_32   (4<<6)	/* Clock source */
+#define GPTCR_TEN       (1)	/* Timer enable */
+
+/*
+ * nothing really to do with interrupts, just starts up a counter.
+ * The 32KHz 32-bit timer overruns in 134217 seconds
+ */
+int timer_init(void)
+{
+	int i;
+	struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR;
+	struct ccm_regs *ccm = (struct ccm_regs *)CCM_BASE_ADDR;
+
+	/* setup GP Timer 1 */
+	writel(GPTCR_SWR, &gpt->ctrl);
+
+	writel(readl(&ccm->cgr1) | 3 << MXC_CCM_CGR1_GPT_OFFSET, &ccm->cgr1);
+
+	for (i = 0; i < 100; i++)
+		writel(0, &gpt->ctrl); /* We have no udelay by now */
+	writel(0, &gpt->pre); /* prescaler = 1 */
+	/* Freerun Mode, 32KHz input */
+	writel(readl(&gpt->ctrl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
+			&gpt->ctrl);
+	writel(readl(&gpt->ctrl) | GPTCR_TEN, &gpt->ctrl);
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm1136/start.S b/arch/arm/cpu/arm1136/start.S
new file mode 100644
index 0000000..da7278e
--- /dev/null
+++ b/arch/arm/cpu/arm1136/start.S
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for OMP2420/ARM1136 CPU-core
+ *
+ *  Copyright (c) 2004	Texas Instruments <r-woodruff2@ti.com>
+ *
+ *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/* the mask ROM code should have PLL and others stable */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl  cpu_init_crit
+#endif
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+	bx	lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
+	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
+	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
+	orr	r0, r0, #0x00000002	@ set bit 1 (A) Align
+	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
+	mcr	p15, 0, r0, c1, c0, 0
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+	/*
+	 * Jump to board specific initialization... The Mask ROM will have already initialized
+	 * basic memory.  Go here to bump up clock rate and handle wake up conditions.
+	 */
+	mov	ip, lr		/* persevere link reg across call */
+	bl	lowlevel_init	/* go setup pll,mux,memory */
+	mov	lr, ip		/* restore link */
+#endif
+	mov	pc, lr		/* back to my caller */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm1136/u-boot-spl.lds b/arch/arm/cpu/arm1136/u-boot-spl.lds
new file mode 100644
index 0000000..881275a
--- /dev/null
+++ b/arch/arm/cpu/arm1136/u-boot-spl.lds
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *	Aneesh V <aneesh@ti.com>
+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+		LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	.text      :
+	{
+	__start = .;
+	  *(.vectors)
+	  arch/arm/cpu/arm1136/start.o	(.text*)
+	  *(.text*)
+	} >.sram
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+	. = ALIGN(4);
+	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+	. = ALIGN(4);
+	__image_copy_end = .;
+
+	.end :
+	{
+		*(.__end)
+	}
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} >.sdram
+}
diff --git a/arch/arm/cpu/arm1176/Makefile b/arch/arm/cpu/arm1176/Makefile
new file mode 100644
index 0000000..3233247
--- /dev/null
+++ b/arch/arm/cpu/arm1176/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2008
+# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
+
+obj- += dummy.o
+extra-y	= start.o
+
+obj-y += ../arm11/
diff --git a/arch/arm/cpu/arm1176/start.S b/arch/arm/cpu/arm1176/start.S
new file mode 100644
index 0000000..1402924
--- /dev/null
+++ b/arch/arm/cpu/arm1176/start.S
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for ARM1176 CPU-core
+ *
+ * Copyright (c) 2007	Samsung Electronics
+ *
+ * Copyright (C) 2008
+ * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
+ *
+ * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com)
+ * 2007-09-21 - Added MoviNAND and OneNAND boot codes by
+ * jsgood (jsgood.yang@samsung.com)
+ * Base codes by scsuh (sc.suh)
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+#ifndef CONFIG_SYS_PHY_UBOOT_BASE
+#define CONFIG_SYS_PHY_UBOOT_BASE	CONFIG_SYS_UBOOT_BASE
+#endif
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+	.globl reset
+
+reset:
+	/* Allow the board to save important registers */
+	b	save_boot_params
+.globl	save_boot_params_ret
+save_boot_params_ret:
+
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0, cpsr
+	bic	r0, r0, #0x3f
+	orr	r0, r0, #0xd3
+	msr	cpsr, r0
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+cpu_init_crit:
+	/*
+	 * When booting from NAND - it has definitely been a reset, so, no need
+	 * to flush caches and disable the MMU
+	 */
+#ifndef CONFIG_SPL_BUILD
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
+	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
+	orr	r0, r0, #0x00000002	@ set bit 1 (A) Align
+	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
+
+	/* Prepare to disable the MMU */
+	adr	r2, mmu_disable_phys
+	sub	r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE)
+	b	mmu_disable
+
+	.align 5
+	/* Run in a single cache-line */
+mmu_disable:
+	mcr	p15, 0, r0, c1, c0, 0
+	nop
+	nop
+	mov	pc, r2
+mmu_disable_phys:
+
+#endif
+
+	/*
+	 * Go setup Memory and board specific bits prior to relocation.
+	 */
+	bl	lowlevel_init		/* go setup pll,mux,memory */
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+	mov	pc, lr
+
+WEAK(save_boot_params)
+	b	save_boot_params_ret	/* back to my caller */
+ENDPROC(save_boot_params)
diff --git a/arch/arm/cpu/arm720t/Makefile b/arch/arm/cpu/arm720t/Makefile
new file mode 100644
index 0000000..e70b590
--- /dev/null
+++ b/arch/arm/cpu/arm720t/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	= start.o
+obj-y	= interrupts.o cpu.o
diff --git a/arch/arm/cpu/arm720t/cpu.c b/arch/arm/cpu/arm720t/cpu.c
new file mode 100644
index 0000000..ece09c8
--- /dev/null
+++ b/arch/arm/cpu/arm720t/cpu.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ */
+
+/*
+ * cleanup_before_linux() - Prepare the CPU to jump to Linux
+ *
+ * This function is called just before we call Linux, it
+ * prepares the processor for linux
+ */
+int cleanup_before_linux(void)
+{
+	return 0;
+}
diff --git a/arch/arm/cpu/arm720t/interrupts.c b/arch/arm/cpu/arm720t/interrupts.c
new file mode 100644
index 0000000..8437717
--- /dev/null
+++ b/arch/arm/cpu/arm720t/interrupts.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_TEGRA)
+static ulong timestamp;
+static ulong lastdec;
+
+int timer_init (void)
+{
+	/* No timer routines for tegra as yet */
+	lastdec = 0;
+	timestamp = 0;
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/arm720t/start.S b/arch/arm/cpu/arm720t/start.S
new file mode 100644
index 0000000..ecb4e44
--- /dev/null
+++ b/arch/arm/cpu/arm720t/start.S
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for ARM720 CPU-core
+ *
+ *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from RAM!
+ * relocate armboot to ram
+ * setup stack
+ * jump to second stage
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && \
+		!defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY)
+	bl	cpu_init_crit
+#endif
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+	mov	pc, lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+
+#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && \
+		!defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY)
+cpu_init_crit:
+
+	mov	ip, lr
+	/*
+	 * before relocating, we have to setup RAM timing
+	 * because memory timing is board-dependent, you will
+	 * find a lowlevel_init.S in your board directory.
+	 */
+	bl	lowlevel_init
+	mov	lr, ip
+
+	mov	pc, lr
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm920t/Makefile b/arch/arm/cpu/arm920t/Makefile
new file mode 100644
index 0000000..c63f578
--- /dev/null
+++ b/arch/arm/cpu/arm920t/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	= start.o
+
+obj-y	+= cpu.o
+
+obj-$(CONFIG_EP93XX) += ep93xx/
+obj-$(CONFIG_IMX) += imx/
+
+# some files can only build in ARM mode
+
+ifdef CONFIG_$(SPL_)SYS_THUMB_BUILD
+CFLAGS_cpu.o := -marm
+endif
diff --git a/arch/arm/cpu/arm920t/cpu.c b/arch/arm/cpu/arm920t/cpu.c
new file mode 100644
index 0000000..2ef133f
--- /dev/null
+++ b/arch/arm/cpu/arm920t/cpu.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+
+static void cache_flush(void);
+
+int cleanup_before_linux (void)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * we turn off caches etc ...
+	 */
+
+	disable_interrupts ();
+
+	/* turn off I/D-cache */
+	icache_disable();
+	dcache_disable();
+	/* flush I/D-cache */
+	cache_flush();
+
+	return 0;
+}
+
+/* flush I/D-cache */
+static void cache_flush (void)
+{
+	unsigned long i = 0;
+
+	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
+}
diff --git a/arch/arm/cpu/arm920t/ep93xx/Makefile b/arch/arm/cpu/arm920t/ep93xx/Makefile
new file mode 100644
index 0000000..152b5e7
--- /dev/null
+++ b/arch/arm/cpu/arm920t/ep93xx/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Cirrus Logic EP93xx CPU-specific Makefile
+#
+# Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+#
+# Copyright (C) 2004, 2005
+# Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
+#
+# Copyright (C) 2006
+# Dominic Rath <Dominic.Rath@gmx.de>
+#
+# Based on an original Makefile, which is
+#
+# (C) Copyright 2000, 2001, 2002
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y   = cpu.o led.o speed.o timer.o
+obj-y   += lowlevel_init.o
diff --git a/arch/arm/cpu/arm920t/ep93xx/cpu.c b/arch/arm/cpu/arm920t/ep93xx/cpu.c
new file mode 100644
index 0000000..3aae12f
--- /dev/null
+++ b/arch/arm/cpu/arm920t/ep93xx/cpu.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cirrus Logic EP93xx CPU-specific support.
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2004, 2005
+ * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
+ */
+
+#include <common.h>
+#include <asm/arch/ep93xx.h>
+#include <asm/io.h>
+
+/* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */
+extern void reset_cpu(ulong addr)
+{
+	struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+	uint32_t value;
+
+	/* Unlock DeviceCfg and set SWRST */
+	writel(0xAA, &syscon->sysswlock);
+	value = readl(&syscon->devicecfg);
+	value |= SYSCON_DEVICECFG_SWRST;
+	writel(value, &syscon->devicecfg);
+
+	/* Unlock DeviceCfg and clear SWRST */
+	writel(0xAA, &syscon->sysswlock);
+	value = readl(&syscon->devicecfg);
+	value &= ~SYSCON_DEVICECFG_SWRST;
+	writel(value, &syscon->devicecfg);
+
+	/* Dying... */
+	while (1)
+		; /* noop */
+}
diff --git a/arch/arm/cpu/arm920t/ep93xx/led.c b/arch/arm/cpu/arm920t/ep93xx/led.c
new file mode 100644
index 0000000..862663a
--- /dev/null
+++ b/arch/arm/cpu/arm920t/ep93xx/led.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2010, 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ */
+
+#include <asm/io.h>
+#include <asm/arch/ep93xx.h>
+#include <config.h>
+#include <status_led.h>
+
+static uint8_t saved_state[2] = {CONFIG_LED_STATUS_OFF, CONFIG_LED_STATUS_OFF};
+static uint32_t gpio_pin[2] = {1 << CONFIG_LED_STATUS_GREEN,
+			       1 << CONFIG_LED_STATUS_RED};
+
+static inline void switch_LED_on(uint8_t led)
+{
+	register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE;
+
+	writel(readl(&gpio->pedr) | gpio_pin[led], &gpio->pedr);
+	saved_state[led] = CONFIG_LED_STATUS_ON;
+}
+
+static inline void switch_LED_off(uint8_t led)
+{
+	register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE;
+
+	writel(readl(&gpio->pedr) & ~gpio_pin[led], &gpio->pedr);
+	saved_state[led] = CONFIG_LED_STATUS_OFF;
+}
+
+void red_led_on(void)
+{
+	switch_LED_on(CONFIG_LED_STATUS_RED);
+}
+
+void red_led_off(void)
+{
+	switch_LED_off(CONFIG_LED_STATUS_RED);
+}
+
+void green_led_on(void)
+{
+	switch_LED_on(CONFIG_LED_STATUS_GREEN);
+}
+
+void green_led_off(void)
+{
+	switch_LED_off(CONFIG_LED_STATUS_GREEN);
+}
+
+void __led_init(led_id_t mask, int state)
+{
+	__led_set(mask, state);
+}
+
+void __led_toggle(led_id_t mask)
+{
+	if (CONFIG_LED_STATUS_RED == mask) {
+		if (CONFIG_LED_STATUS_ON == saved_state[CONFIG_LED_STATUS_RED])
+			red_led_off();
+		else
+			red_led_on();
+	} else if (CONFIG_LED_STATUS_GREEN == mask) {
+		if (CONFIG_LED_STATUS_ON ==
+		    saved_state[CONFIG_LED_STATUS_GREEN])
+			green_led_off();
+		else
+			green_led_on();
+	}
+}
+
+void __led_set(led_id_t mask, int state)
+{
+	if (CONFIG_LED_STATUS_RED == mask) {
+		if (CONFIG_LED_STATUS_ON == state)
+			red_led_on();
+		else
+			red_led_off();
+	} else if (CONFIG_LED_STATUS_GREEN == mask) {
+		if (CONFIG_LED_STATUS_ON == state)
+			green_led_on();
+		else
+			green_led_off();
+	}
+}
diff --git a/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S
new file mode 100644
index 0000000..5239b10
--- /dev/null
+++ b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S
@@ -0,0 +1,457 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Low-level initialization for EP93xx
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ * Copyright (C) 2013
+ * Sergey Kostanabev <sergey.kostanbaev <at> fairwaves.ru>
+ *
+ * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de>
+ * Copyright (C) 2006 Cirrus Logic Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ */
+
+#include <config.h>
+#include <asm/arch-ep93xx/ep93xx.h>
+
+/*
+/* Configure the SDRAM based on the supplied settings.
+ *
+ * Input:	r0 - SDRAM DEVCFG register
+ *		r2 - configuration for SDRAM chips
+ * Output:	none
+ * Modifies:	r3, r4
+ */
+ep93xx_sdram_config:
+	/* Program the SDRAM device configuration register. */
+	ldr	r3, =SDRAM_BASE
+#ifdef CONFIG_EDB93XX_SDCS0
+	str	r0, [r3, #SDRAM_OFF_DEVCFG0]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS1
+	str	r0, [r3, #SDRAM_OFF_DEVCFG1]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS2
+	str	r0, [r3, #SDRAM_OFF_DEVCFG2]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS3
+	str	r0, [r3, #SDRAM_OFF_DEVCFG3]
+#endif
+
+	/* Set the Initialize and MRS bits (issue continuous NOP commands
+	 * (INIT & MRS set))
+	 */
+	ldr	r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_MRS | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_CKE)
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Delay for 200us. */
+	mov	r4, #0x3000
+delay1:
+	subs	r4, r4, #1
+	bne	delay1
+
+	/* Clear the MRS bit to issue a precharge all. */
+	ldr	r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_CKE)
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Temporarily set the refresh timer to 0x10. Make it really low so
+	 * that refresh cycles are generated.
+	 */
+	ldr	r4, =0x10
+	str	r4, [r3, #SDRAM_OFF_REFRSHTIMR]
+
+	/* Delay for at least 80 SDRAM clock cycles. */
+	mov	r4, #80
+delay2:
+	subs	r4, r4, #1
+	bne	delay2
+
+	/* Set the refresh timer to the fastest required for any device
+	 * that might be used. Set 9.6 ms refresh time.
+	 */
+	ldr	r4, =0x01e0
+	str	r4, [r3, #SDRAM_OFF_REFRSHTIMR]
+
+	/* Select mode register update mode. */
+	ldr	r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_CKE | \
+			EP93XX_SDRAMCTRL_GLOBALCFG_MRS)
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Program the mode register on the SDRAM by performing fake read */
+	ldr	r4, [r2]
+
+	/* Select normal operating mode. */
+	ldr	r4, =EP93XX_SDRAMCTRL_GLOBALCFG_CKE
+	str	r4, [r3, #SDRAM_OFF_GLCONFIG]
+
+	/* Return to the caller. */
+	mov	pc, lr
+
+/*
+ * Test to see if the SDRAM has been configured in a usable mode.
+ *
+ * Input:	r0 - Test address of SDRAM
+ * Output:	r0 - 0 -- Test OK, -1 -- Failed
+ * Modifies:	r0-r5
+ */
+ep93xx_sdram_test:
+	/* Load the test patterns to be written to SDRAM. */
+	ldr	r1, =0xf00dface
+	ldr	r2, =0xdeadbeef
+	ldr	r3, =0x08675309
+	ldr	r4, =0xdeafc0ed
+
+	/* Store the test patterns to SDRAM. */
+	stmia	r0, {r1-r4}
+
+	/* Load the test patterns from SDRAM one at a time and compare them
+	 * to the actual pattern.
+	 */
+	ldr	r5, [r0]
+	cmp	r5, r1
+	ldreq	r5, [r0, #0x0004]
+	cmpeq	r5, r2
+	ldreq	r5, [r0, #0x0008]
+	cmpeq	r5, r3
+	ldreq	r5, [r0, #0x000c]
+	cmpeq	r5, r4
+
+	/* Return -1 if a mismatch was encountered, 0 otherwise. */
+	mvnne	r0, #0xffffffff
+	moveq	r0, #0x00000000
+
+	/* Return to the caller. */
+	mov	pc, lr
+
+/*
+ * Determine the size of the SDRAM. Use data=address for the scan.
+ *
+ * Input:	r0 - Start SDRAM address
+ * Return:	r0 - Single block size
+ *		r1 - Valid block mask
+ *		r2 - Total block count
+ * Modifies:	r0-r5
+ */
+ep93xx_sdram_size:
+	/* Store zero at offset zero. */
+	str	r0, [r0]
+
+	/* Start checking for an alias at 1MB into SDRAM. */
+	ldr	r1, =0x00100000
+
+	/* Store the offset at the current offset. */
+check_block_size:
+	str	r1, [r0, r1]
+
+	/* Read back from zero. */
+	ldr	r2, [r0]
+
+	/* Stop searching of an alias was found. */
+	cmp	r1, r2
+	beq	found_block_size
+
+	/* Advance to the next power of two boundary. */
+	mov	r1, r1, lsl #1
+
+	/* Loop back if the size has not reached 256MB. */
+	cmp	r1, #0x10000000
+	bne	check_block_size
+
+	/* A full 256MB of memory was found, so return it now. */
+	ldr	r0, =0x10000000
+	ldr	r1, =0x00000000
+	ldr	r2, =0x00000001
+	mov	pc, lr
+
+	/* An alias was found. See if the first block is 128MB in size. */
+found_block_size:
+	cmp	r1, #0x08000000
+
+	/* The first block is 128MB, so there is no further memory. Return it
+	 * now.
+	 */
+	ldreq	r0, =0x08000000
+	ldreq	r1, =0x00000000
+	ldreq	r2, =0x00000001
+	moveq	pc, lr
+
+	/* Save the block size, set the block address bits to zero, and
+	 * initialize the block count to one.
+	 */
+	mov	r3, r1
+	ldr	r4, =0x00000000
+	ldr	r5, =0x00000001
+
+	/* Look for additional blocks of memory by searching for non-aliases. */
+find_blocks:
+	/* Store zero back to address zero. It may be overwritten. */
+	str	r0, [r0]
+
+	/* Advance to the next power of two boundary. */
+	mov	r1, r1, lsl #1
+
+	/* Store the offset at the current offset. */
+	str	r1, [r0, r1]
+
+	/* Read back from zero. */
+	ldr	r2, [r0]
+
+	/* See if a non-alias was found. */
+	cmp	r1, r2
+
+	/* If a non-alias was found, then or in the block address bit and
+	 * multiply the block count by two (since there are two unique
+	 * blocks, one with this bit zero and one with it one).
+	 */
+	orrne	r4, r4, r1
+	movne	r5, r5, lsl #1
+
+	/* Continue searching if there are more address bits to check. */
+	cmp	r1, #0x08000000
+	bne	find_blocks
+
+	/* Return the block size, address mask, and count. */
+	mov	r0, r3
+	mov	r1, r4
+	mov	r2, r5
+
+	/* Return to the caller. */
+	mov	pc, lr
+
+
+.globl lowlevel_init
+lowlevel_init:
+
+	mov	r6, lr
+
+	/* Make sure caches are off and invalidated. */
+	ldr	r0, =0x00000000
+	mcr	p15, 0, r0, c1, c0, 0
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* Turn off the green LED and turn on the red LED. If the red LED
+	 * is left on for too long, the external reset circuit described
+	 * by application note AN258 will cause the system to reset.
+	 */
+	ldr	r1, =EP93XX_LED_DATA
+	ldr	r0, [r1]
+	bic	r0, r0, #EP93XX_LED_GREEN_ON
+	orr	r0, r0, #EP93XX_LED_RED_ON
+	str	r0, [r1]
+
+	/* Undo the silly static memory controller programming performed
+	 * by the boot rom.
+	 */
+	ldr	r0, =SMC_BASE
+
+	/* Set WST1 and WST2 to 31 HCLK cycles (slowest access) */
+	ldr	r1, =0x0000fbe0
+
+	/* Reset EP93XX_OFF_SMCBCR0 */
+	ldr	r2, [r0]
+	orr	r2, r2, r1
+	str	r2, [r0]
+
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR1]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR1]
+
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR2]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR2]
+
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR3]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR3]
+
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR6]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR6]
+
+	ldr	r2, [r0, #EP93XX_OFF_SMCBCR7]
+	orr	r2, r2, r1
+	str	r2, [r0, #EP93XX_OFF_SMCBCR7]
+
+	/* Set the PLL1 and processor clock. */
+	ldr	r0, =SYSCON_BASE
+#ifdef CONFIG_EDB9301
+	/* 332MHz, giving a 166MHz processor clock. */
+	ldr	r1, = 0x02b49907
+#else
+
+#ifdef CONFIG_EDB93XX_INDUSTRIAL
+	/* 384MHz, giving a 196MHz processor clock. */
+	ldr	r1, =0x02a4bb38
+#else
+	/* 400MHz, giving a 200MHz processor clock. */
+	ldr	r1, =0x02a4e39e
+#endif
+#endif
+	str	r1, [r0, #SYSCON_OFF_CLKSET1]
+
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* Need to make sure that SDRAM is configured correctly before
+	 * coping the code into it.
+	 */
+
+#ifdef CONFIG_EDB93XX_SDCS0
+	mov	r11, #SDRAM_DEVCFG0_BASE
+#endif
+#ifdef CONFIG_EDB93XX_SDCS1
+	mov	r11, #SDRAM_DEVCFG1_BASE
+#endif
+#ifdef CONFIG_EDB93XX_SDCS2
+	mov	r11, #SDRAM_DEVCFG2_BASE
+#endif
+#ifdef CONFIG_EDB93XX_SDCS3
+	ldr	r0, =SYSCON_BASE
+	ldr	r0, [r0, #SYSCON_OFF_SYSCFG]
+	ands	r0, r0, #SYSCON_SYSCFG_LASDO
+	moveq	r11, #SDRAM_DEVCFG3_ASD0_BASE
+	movne	r11, #SDRAM_DEVCFG3_ASD1_BASE
+#endif
+	/* See Table 13-5 in EP93xx datasheet for more info about DRAM
+	 * register mapping */
+
+	/* Try a 32-bit wide configuration of SDRAM. */
+	ldr	r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \
+			EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \
+			EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \
+			EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2)
+
+	/* Set burst count: 4 and CAS: 2
+	 * Burst mode [A11:A10]; CAS [A16:A14]
+	 */
+	orr	r2, r11, #0x00008800
+	bl	ep93xx_sdram_config
+
+	/* Test the SDRAM. */
+	mov	r0, r11
+	bl	ep93xx_sdram_test
+	cmp	r0, #0x00000000
+	beq	ep93xx_sdram_done
+
+	/* Try a 16-bit wide configuration of SDRAM. */
+	ldr	r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \
+			EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \
+			EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \
+			EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2 | \
+			EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH)
+
+	/* Set burst count: 8, CAS: 2, sequential burst
+	 * Accoring to Table 13-3 for 16bit operations mapping must be shifted.
+	 * Burst mode [A10:A9]; CAS [A15:A13]
+	 */
+	orr	r2, r11, #0x00004600
+	bl	ep93xx_sdram_config
+
+	/* Test the SDRAM. */
+	mov	r0, r11
+	bl	ep93xx_sdram_test
+	cmp	r0, #0x00000000
+	beq	ep93xx_sdram_done
+
+	/* Turn off the red LED. */
+	ldr	r0, =EP93XX_LED_DATA
+	ldr	r1, [r0]
+	bic	r1, r1, #EP93XX_LED_RED_ON
+	str	r1, [r0]
+
+	/* There is no SDRAM so flash the green LED. */
+flash_green:
+	orr	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00010000
+flash_green_delay_1:
+	subs	r2, r2, #1
+	bne	flash_green_delay_1
+	bic	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00010000
+flash_green_delay_2:
+	subs	r2, r2, #1
+	bne	flash_green_delay_2
+	orr	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00010000
+flash_green_delay_3:
+	subs	r2, r2, #1
+	bne	flash_green_delay_3
+	bic	r1, r1, #EP93XX_LED_GREEN_ON
+	str	r1, [r0]
+	ldr	r2, =0x00050000
+flash_green_delay_4:
+	subs	r2, r2, #1
+	bne	flash_green_delay_4
+	b	flash_green
+
+
+ep93xx_sdram_done:
+	ldr	r1, =EP93XX_LED_DATA
+	ldr	r0, [r1]
+	bic	r0, r0, #EP93XX_LED_RED_ON
+	str	r0, [r1]
+
+	/* Determine the size of the SDRAM. */
+	mov	r0, r11
+	bl	ep93xx_sdram_size
+
+	/* Save the SDRAM characteristics. */
+	mov	r8, r0
+	mov	r9, r1
+	mov	r10, r2
+
+	/* Compute total memory size into r1 */
+	mul	r1, r8, r10
+#ifdef CONFIG_EDB93XX_SDCS0
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG0]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS1
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG1]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS2
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG2]
+#endif
+#ifdef CONFIG_EDB93XX_SDCS3
+	ldr	r2, [r0, #SDRAM_OFF_DEVCFG3]
+#endif
+
+	/* Consider small DRAM size as:
+	 * < 32Mb for 32bit bus
+	 * < 64Mb for 16bit bus
+	 */
+	tst	r2, #EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH
+	moveq	r1, r1, lsr #1
+	cmp	r1, #0x02000000
+
+#if defined(CONFIG_EDB9301)
+	/* Set refresh counter to 20ms for small DRAM size, otherwise 9.6ms */
+	movlt	r1, #0x03f0
+	movge	r1, #0x01e0
+#else
+	/* Set refresh counter to 30.7ms for small DRAM size, otherwise 15ms */
+	movlt	r1, #0x0600
+	movge	r1, #0x2f0
+#endif
+	str	r1, [r0, #SDRAM_OFF_REFRSHTIMR]
+
+	/* Save the memory configuration information. */
+	orr	r0, r11, #UBOOT_MEMORYCNF_BANK_SIZE
+	stmia	r0, {r8-r11}
+
+	mov	lr, r6
+	mov	pc, lr
diff --git a/arch/arm/cpu/arm920t/ep93xx/speed.c b/arch/arm/cpu/arm920t/ep93xx/speed.c
new file mode 100644
index 0000000..51e9dda
--- /dev/null
+++ b/arch/arm/cpu/arm920t/ep93xx/speed.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cirrus Logic EP93xx PLL support.
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ */
+
+#include <common.h>
+#include <asm/arch/ep93xx.h>
+#include <asm/io.h>
+#include <div64.h>
+
+/*
+ * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL.
+ *
+ * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of
+ * the specified bus in HZ.
+ */
+
+/*
+ * return the PLL output frequency
+ *
+ * PLL rate = CONFIG_SYS_CLK_FREQ * (X1FBD + 1) * (X2FBD + 1)
+ * / (X2IPD + 1) / 2^PS
+ */
+static ulong get_PLLCLK(uint32_t *pllreg)
+{
+	uint8_t i;
+	const uint32_t clkset = readl(pllreg);
+	uint64_t rate = CONFIG_SYS_CLK_FREQ;
+	rate *= ((clkset >> SYSCON_CLKSET_PLL_X1FBD1_SHIFT) & 0x1f) + 1;
+	rate *= ((clkset >> SYSCON_CLKSET_PLL_X2FBD2_SHIFT) & 0x3f) + 1;
+	do_div(rate, (clkset  & 0x1f) + 1);			/* X2IPD */
+	for (i = 0; i < ((clkset >> SYSCON_CLKSET_PLL_PS_SHIFT) & 3); i++)
+		rate >>= 1;
+
+	return (ulong)rate;
+}
+
+/* return FCLK frequency */
+ulong get_FCLK(void)
+{
+	const uint8_t fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
+	struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+
+	const uint32_t clkset1 = readl(&syscon->clkset1);
+	const uint8_t fclk_div =
+		fclk_divisors[(clkset1 >> SYSCON_CLKSET1_FCLK_DIV_SHIFT) & 7];
+	const ulong fclk_rate = get_PLLCLK(&syscon->clkset1) / fclk_div;
+
+	return fclk_rate;
+}
+
+/* return HCLK frequency */
+ulong get_HCLK(void)
+{
+	const uint8_t hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
+	struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+
+	const uint32_t clkset1 = readl(&syscon->clkset1);
+	const uint8_t hclk_div =
+		hclk_divisors[(clkset1 >> SYSCON_CLKSET1_HCLK_DIV_SHIFT) & 7];
+	const ulong hclk_rate = get_PLLCLK(&syscon->clkset1) / hclk_div;
+
+	return hclk_rate;
+}
+
+/* return PCLK frequency */
+ulong get_PCLK(void)
+{
+	const uint8_t pclk_divisors[] = { 1, 2, 4, 8 };
+	struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+
+	const uint32_t clkset1 = readl(&syscon->clkset1);
+	const uint8_t pclk_div =
+		pclk_divisors[(clkset1 >> SYSCON_CLKSET1_PCLK_DIV_SHIFT) & 3];
+	const ulong pclk_rate = get_HCLK() / pclk_div;
+
+	return pclk_rate;
+}
+
+/* return UCLK frequency */
+ulong get_UCLK(void)
+{
+	struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+	ulong uclk_rate;
+
+	const uint32_t value = readl(&syscon->pwrcnt);
+	if (value & SYSCON_PWRCNT_UART_BAUD)
+		uclk_rate = CONFIG_SYS_CLK_FREQ;
+	else
+		uclk_rate = CONFIG_SYS_CLK_FREQ / 2;
+
+	return uclk_rate;
+}
diff --git a/arch/arm/cpu/arm920t/ep93xx/timer.c b/arch/arm/cpu/arm920t/ep93xx/timer.c
new file mode 100644
index 0000000..49bf49b
--- /dev/null
+++ b/arch/arm/cpu/arm920t/ep93xx/timer.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cirrus Logic EP93xx timer support.
+ *
+ * Copyright (C) 2009, 2010 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2004, 2005
+ * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
+ *
+ * Based on the original intr.c Cirrus Logic EP93xx Rev D. interrupt support,
+ * author unknown.
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <asm/arch/ep93xx.h>
+#include <asm/io.h>
+#include <div64.h>
+
+#define TIMER_CLKSEL	(1 << 3)
+#define TIMER_ENABLE	(1 << 7)
+
+#define TIMER_FREQ			508469		/* ticks / second */
+#define TIMER_MAX_VAL			0xFFFFFFFF
+
+static struct ep93xx_timer
+{
+	unsigned long long ticks;
+	unsigned long last_read;
+} timer;
+
+static inline unsigned long long usecs_to_ticks(unsigned long usecs)
+{
+	unsigned long long ticks = (unsigned long long)usecs * TIMER_FREQ;
+	do_div(ticks, 1000 * 1000);
+
+	return ticks;
+}
+
+static inline void read_timer(void)
+{
+	struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE;
+	const unsigned long now = TIMER_MAX_VAL - readl(&timer_regs->timer3.value);
+
+	if (now >= timer.last_read)
+		timer.ticks += now - timer.last_read;
+	else
+		/* an overflow occurred */
+		timer.ticks += TIMER_MAX_VAL - timer.last_read + now;
+
+	timer.last_read = now;
+}
+
+/*
+ * Get the number of ticks (in CONFIG_SYS_HZ resolution)
+ */
+unsigned long long get_ticks(void)
+{
+	unsigned long long sys_ticks;
+
+	read_timer();
+
+	sys_ticks = timer.ticks * CONFIG_SYS_HZ;
+	do_div(sys_ticks, TIMER_FREQ);
+
+	return sys_ticks;
+}
+
+unsigned long get_timer(unsigned long base)
+{
+	return get_ticks() - base;
+}
+
+void __udelay(unsigned long usec)
+{
+	unsigned long long target;
+
+	read_timer();
+
+	target = timer.ticks + usecs_to_ticks(usec);
+
+	while (timer.ticks < target)
+		read_timer();
+}
+
+int timer_init(void)
+{
+	struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE;
+
+	/* use timer 3 with 508KHz and free running, not enabled now */
+	writel(TIMER_CLKSEL, &timer_regs->timer3.control);
+
+	/* set initial timer value */
+	writel(TIMER_MAX_VAL, &timer_regs->timer3.load);
+
+	/* Enable the timer */
+	writel(TIMER_ENABLE | TIMER_CLKSEL,
+		&timer_regs->timer3.control);
+
+	/* Reset the timer */
+	read_timer();
+	timer.ticks = 0;
+
+	return 0;
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+unsigned long get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/cpu/arm920t/imx/Makefile b/arch/arm/cpu/arm920t/imx/Makefile
new file mode 100644
index 0000000..04bc129
--- /dev/null
+++ b/arch/arm/cpu/arm920t/imx/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y	+= generic.o
+obj-y	+= speed.o
+obj-y	+= timer.o
diff --git a/arch/arm/cpu/arm920t/imx/generic.c b/arch/arm/cpu/arm920t/imx/generic.c
new file mode 100644
index 0000000..dbb908e
--- /dev/null
+++ b/arch/arm/cpu/arm920t/imx/generic.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  arch/arm/mach-imx/generic.c
+ *
+ *  author: Sascha Hauer
+ *  Created: april 20th, 2004
+ *  Copyright: Synertronixx GmbH
+ *
+ *  Common code for i.MX machines
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_IMX
+
+#include <asm/arch/imx-regs.h>
+
+void imx_gpio_mode(int gpio_mode)
+{
+	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5;
+	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10;
+	unsigned int tmp;
+
+	/* Pullup enable */
+	if(gpio_mode & GPIO_PUEN)
+		PUEN(port) |= (1<<pin);
+	else
+		PUEN(port) &= ~(1<<pin);
+
+	/* Data direction */
+	if(gpio_mode & GPIO_OUT)
+		DDIR(port) |= 1<<pin;
+	else
+		DDIR(port) &= ~(1<<pin);
+
+	/* Primary / alternate function */
+	if(gpio_mode & GPIO_AF)
+		GPR(port) |= (1<<pin);
+	else
+		GPR(port) &= ~(1<<pin);
+
+	/* use as gpio? */
+	if( ocr == 3 )
+		GIUS(port) |= (1<<pin);
+	else
+		GIUS(port) &= ~(1<<pin);
+
+	/* Output / input configuration */
+	/* FIXME: I'm not very sure about OCR and ICONF, someone
+	 * should have a look over it
+	 */
+	if(pin<16) {
+		tmp = OCR1(port);
+		tmp &= ~( 3<<(pin*2));
+		tmp |= (ocr << (pin*2));
+		OCR1(port) = tmp;
+
+		if( gpio_mode &	GPIO_AOUT )
+			ICONFA1(port) &= ~( 3<<(pin*2));
+		if( gpio_mode &	GPIO_BOUT )
+			ICONFB1(port) &= ~( 3<<(pin*2));
+	} else {
+		tmp = OCR2(port);
+		tmp &= ~( 3<<((pin-16)*2));
+		tmp |= (ocr << ((pin-16)*2));
+		OCR2(port) = tmp;
+
+		if( gpio_mode &	GPIO_AOUT )
+			ICONFA2(port) &= ~( 3<<((pin-16)*2));
+		if( gpio_mode &	GPIO_BOUT )
+			ICONFB2(port) &= ~( 3<<((pin-16)*2));
+	}
+}
+
+#endif /* CONFIG_IMX */
diff --git a/arch/arm/cpu/arm920t/imx/speed.c b/arch/arm/cpu/arm920t/imx/speed.c
new file mode 100644
index 0000000..eff6113
--- /dev/null
+++ b/arch/arm/cpu/arm920t/imx/speed.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *
+ * (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ */
+
+
+#include <common.h>
+#if defined (CONFIG_IMX)
+
+#include <asm/arch/imx-regs.h>
+
+/* ------------------------------------------------------------------------- */
+/* NOTE: This describes the proper use of this file.
+ *
+ * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL.
+ * SH FIXME: 16780000 in our case
+ * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of
+ * the specified bus in HZ.
+ */
+/* ------------------------------------------------------------------------- */
+
+ulong get_systemPLLCLK(void)
+{
+	/* FIXME: We assume System_SEL = 0 here */
+	u32 spctl0 = SPCTL0;
+	u32 mfi = (spctl0 >> 10) & 0xf;
+	u32 mfn = spctl0 & 0x3f;
+	u32 mfd = (spctl0 >> 16) & 0x3f;
+	u32 pd =  (spctl0 >> 26) & 0xf;
+
+	mfi = mfi<=5 ? 5 : mfi;
+
+	return (2*(CONFIG_SYSPLL_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1);
+}
+
+ulong get_mcuPLLCLK(void)
+{
+	/* FIXME: We assume System_SEL = 0 here */
+	u32 mpctl0 = MPCTL0;
+	u32 mfi = (mpctl0 >> 10) & 0xf;
+	u32 mfn = mpctl0 & 0x3f;
+	u32 mfd = (mpctl0 >> 16) & 0x3f;
+	u32 pd =  (mpctl0 >> 26) & 0xf;
+
+	mfi = mfi<=5 ? 5 : mfi;
+
+	return (2*(CONFIG_SYS_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1);
+}
+
+ulong get_FCLK(void)
+{
+	return (( CSCR>>15)&1) ? get_mcuPLLCLK()>>1 : get_mcuPLLCLK();
+}
+
+/* return HCLK frequency */
+ulong get_HCLK(void)
+{
+	u32 bclkdiv = (( CSCR >> 10 ) & 0xf) + 1;
+	printf("bclkdiv: %d\n", bclkdiv);
+	return get_systemPLLCLK() / bclkdiv;
+}
+
+/* return BCLK frequency */
+ulong get_BCLK(void)
+{
+	return get_HCLK();
+}
+
+ulong get_PERCLK1(void)
+{
+	return get_systemPLLCLK() / (((PCDR) & 0xf)+1);
+}
+
+ulong get_PERCLK2(void)
+{
+	return get_systemPLLCLK() / (((PCDR>>4) & 0xf)+1);
+}
+
+ulong get_PERCLK3(void)
+{
+	return get_systemPLLCLK() / (((PCDR>>16) & 0x7f)+1);
+}
+
+#endif /* defined (CONFIG_IMX) */
diff --git a/arch/arm/cpu/arm920t/imx/timer.c b/arch/arm/cpu/arm920t/imx/timer.c
new file mode 100644
index 0000000..96fff3f
--- /dev/null
+++ b/arch/arm/cpu/arm920t/imx/timer.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+#include <common.h>
+#if defined (CONFIG_IMX)
+
+#include <asm/arch/imx-regs.h>
+
+int timer_init (void)
+{
+	int i;
+	/* setup GP Timer 1 */
+	TCTL1 = TCTL_SWR;
+	for ( i=0; i<100; i++) TCTL1 = 0; /* We have no udelay by now */
+	TPRER1 = get_PERCLK1() / 1000000; /* 1 MHz */
+	TCTL1 |= TCTL_FRR | (1<<1); /* Freerun Mode, PERCLK1 input */
+
+	/* Reset the timer */
+	TCTL1 &= ~TCTL_TEN;
+	TCTL1 |= TCTL_TEN; /* Enable timer */
+
+	return (0);
+}
+
+/*
+ * timer without interrupts
+ */
+static ulong get_timer_masked (void)
+{
+	return TCN1;
+}
+
+ulong get_timer (ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+void __udelay (unsigned long usec)
+{
+	ulong endtime = get_timer_masked() + usec;
+	signed long diff;
+
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk (void)
+{
+	return CONFIG_SYS_HZ;
+}
+
+/*
+ * Reset the cpu by setting up the watchdog timer and let him time out
+ */
+void reset_cpu (ulong ignored)
+{
+	/* Disable watchdog and set Time-Out field to 0 */
+	WCR = 0x00000000;
+
+	/* Write Service Sequence */
+	WSR = 0x00005555;
+	WSR = 0x0000AAAA;
+
+	/* Enable watchdog */
+	WCR = 0x00000001;
+
+	while (1);
+	/*NOTREACHED*/
+}
+
+#endif /* defined (CONFIG_IMX) */
diff --git a/arch/arm/cpu/arm920t/start.S b/arch/arm/cpu/arm920t/start.S
new file mode 100644
index 0000000..e9326f4
--- /dev/null
+++ b/arch/arm/cpu/arm920t/start.S
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for ARM920 CPU-core
+ *
+ *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ */
+
+#include <asm-offsets.h>
+#include <common.h>
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (called from the ARM reset exception vector)
+ *
+ * do important init only if we don't start from memory!
+ * relocate armboot to ram
+ * setup stack
+ * jump to second stage
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0, cpsr
+	bic	r0, r0, #0x1f
+	orr	r0, r0, #0xd3
+	msr	cpsr, r0
+
+#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
+	/*
+	 * relocate exception table
+	 */
+	ldr	r0, =_start
+	ldr	r1, =0x0
+	mov	r2, #16
+copyex:
+	subs	r2, r2, #1
+	ldr	r3, [r0], #4
+	str	r3, [r1], #4
+	bne	copyex
+#endif
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+	mov	pc, lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
+	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
+	orr	r0, r0, #0x00000002	@ set bit 1 (A) Align
+	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache
+	mcr	p15, 0, r0, c1, c0, 0
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+	/*
+	 * before relocating, we have to setup RAM timing
+	 * because memory timing is board-dependend, you will
+	 * find a lowlevel_init.S in your board directory.
+	 */
+	mov	ip, lr
+
+	bl	lowlevel_init
+	mov	lr, ip
+#endif
+	mov	pc, lr
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile
new file mode 100644
index 0000000..fdb0c92
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/Makefile
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	= start.o
+obj-y	= cpu.o cache.o
+
+ifdef	CONFIG_SPL_BUILD
+ifdef	CONFIG_SPL_NO_CPU_SUPPORT_CODE
+extra-y	:=
+endif
+endif
+
+obj-$(CONFIG_ARMADA100) += armada100/
+obj-$(if $(filter lpc32xx,$(SOC)),y) += lpc32xx/
+obj-$(CONFIG_MX25) += mx25/
+obj-$(CONFIG_MX27) += mx27/
+obj-$(if $(filter mxs,$(SOC)),y) += mxs/
+obj-$(if $(filter spear,$(SOC)),y) += spear/
+
+# some files can only build in ARM or THUMB2, not THUMB1
+
+ifdef CONFIG_$(SPL_)SYS_THUMB_BUILD
+ifndef CONFIG_HAS_THUMB2
+
+CFLAGS_cpu.o := -marm
+CFLAGS_cache.o := -marm
+
+endif
+endif
diff --git a/arch/arm/cpu/arm926ejs/armada100/Makefile b/arch/arm/cpu/arm926ejs/armada100/Makefile
new file mode 100644
index 0000000..77ac0e2
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/armada100/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2010
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+
+obj-y	= cpu.o timer.o dram.o
diff --git a/arch/arm/cpu/arm926ejs/armada100/cpu.c b/arch/arm/cpu/arm926ejs/armada100/cpu.c
new file mode 100644
index 0000000..4cd8511
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/armada100/cpu.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ * Contributor: Mahavir Jain <mjain@marvell.com>
+ */
+
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/armada100.h>
+
+#define UARTCLK14745KHZ	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1))
+#define SET_MRVL_ID	(1<<8)
+#define L2C_RAM_SEL	(1<<4)
+
+int arch_cpu_init(void)
+{
+	u32 val;
+	struct armd1cpu_registers *cpuregs =
+		(struct armd1cpu_registers *) ARMD1_CPU_BASE;
+
+	struct armd1apb1_registers *apb1clkres =
+		(struct armd1apb1_registers *) ARMD1_APBC1_BASE;
+
+	struct armd1mpmu_registers *mpmu =
+		(struct armd1mpmu_registers *) ARMD1_MPMU_BASE;
+
+	/* set SEL_MRVL_ID bit in ARMADA100_CPU_CONF register */
+	val = readl(&cpuregs->cpu_conf);
+	val = val | SET_MRVL_ID;
+	writel(val, &cpuregs->cpu_conf);
+
+	/* Enable Clocks for all hardware units */
+	writel(0xFFFFFFFF, &mpmu->acgr);
+
+	/* Turn on AIB and AIB-APB Functional clock */
+	writel(APBC_APBCLK | APBC_FNCLK, &apb1clkres->aib);
+
+	/* ensure L2 cache is not mapped as SRAM */
+	val = readl(&cpuregs->cpu_conf);
+	val = val & ~(L2C_RAM_SEL);
+	writel(val, &cpuregs->cpu_conf);
+
+	/* Enable GPIO clock */
+	writel(APBC_APBCLK, &apb1clkres->gpio);
+
+#ifdef CONFIG_I2C_MV
+	/* Enable general I2C clock */
+	writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0);
+	writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0);
+
+	/* Enable power I2C clock */
+	writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1);
+	writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1);
+#endif
+
+	/*
+	 * Enable Functional and APB clock at 14.7456MHz
+	 * for configured UART console
+	 */
+#if (CONFIG_SYS_NS16550_COM1 == ARMD1_UART3_BASE)
+	writel(UARTCLK14745KHZ, &apb1clkres->uart3);
+#elif (CONFIG_SYS_NS16550_COM1 == ARMD1_UART2_BASE)
+	writel(UARTCLK14745KHZ, &apb1clkres->uart2);
+#else
+	writel(UARTCLK14745KHZ, &apb1clkres->uart1);
+#endif
+	icache_enable();
+
+	return 0;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	u32 id;
+	struct armd1cpu_registers *cpuregs =
+		(struct armd1cpu_registers *) ARMD1_CPU_BASE;
+
+	id = readl(&cpuregs->chip_id);
+	printf("SoC:   Armada 88AP%X-%X\n", (id & 0xFFF), (id >> 0x10));
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_I2C_MV
+void i2c_clk_enable(void)
+{
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/armada100/dram.c b/arch/arm/cpu/arm926ejs/armada100/dram.c
new file mode 100644
index 0000000..f4e1f0d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/armada100/dram.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>,
+ * Contributor: Mahavir Jain <mjain@marvell.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/armada100.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * ARMADA100 DRAM controller supports upto 8 banks
+ * for chip select 0 and 1
+ */
+
+/*
+ * DDR Memory Control Registers
+ * Refer Datasheet Appendix A.17
+ */
+struct armd1ddr_map_registers {
+	u32	cs;	/* Memory Address Map Register -CS */
+	u32	pad[3];
+};
+
+struct armd1ddr_registers {
+	u8	pad[0x100 - 0x000];
+	struct armd1ddr_map_registers mmap[2];
+};
+
+/*
+ * armd1_sdram_base - reads SDRAM Base Address Register
+ */
+u32 armd1_sdram_base(int chip_sel)
+{
+	struct armd1ddr_registers *ddr_regs =
+		(struct armd1ddr_registers *)ARMD1_DRAM_BASE;
+	u32 result = 0;
+	u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs);
+
+	if (!CS_valid)
+		return 0;
+
+	result = readl(&ddr_regs->mmap[chip_sel].cs) & 0xFF800000;
+	return result;
+}
+
+/*
+ * armd1_sdram_size - reads SDRAM size
+ */
+u32 armd1_sdram_size(int chip_sel)
+{
+	struct armd1ddr_registers *ddr_regs =
+		(struct armd1ddr_registers *)ARMD1_DRAM_BASE;
+	u32 result = 0;
+	u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs);
+
+	if (!CS_valid)
+		return 0;
+
+	result = readl(&ddr_regs->mmap[chip_sel].cs);
+	result = (result >> 16) & 0xF;
+	if (result < 0x7) {
+		printf("Unknown DRAM Size\n");
+		return -1;
+	} else {
+		return ((0x8 << (result - 0x7)) * 1024 * 1024);
+	}
+}
+
+int dram_init(void)
+{
+	int i;
+
+	gd->ram_size = 0;
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		gd->bd->bi_dram[i].start = armd1_sdram_base(i);
+		gd->bd->bi_dram[i].size = armd1_sdram_size(i);
+		/*
+		 * It is assumed that all memory banks are consecutive
+		 * and without gaps.
+		 * If the gap is found, ram_size will be reported for
+		 * consecutive memory only
+		 */
+		if (gd->bd->bi_dram[i].start != gd->ram_size)
+			break;
+
+		gd->ram_size += gd->bd->bi_dram[i].size;
+
+	}
+
+	for (; i < CONFIG_NR_DRAM_BANKS; i++) {
+		/* If above loop terminated prematurely, we need to set
+		 * remaining banks' start address & size as 0. Otherwise other
+		 * u-boot functions and Linux kernel gets wrong values which
+		 * could result in crash */
+		gd->bd->bi_dram[i].start = 0;
+		gd->bd->bi_dram[i].size = 0;
+	}
+	return 0;
+}
+
+/*
+ * If this function is not defined here,
+ * board.c alters dram bank zero configuration defined above.
+ */
+int dram_init_banksize(void)
+{
+	dram_init();
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/armada100/timer.c b/arch/arm/cpu/arm926ejs/armada100/timer.c
new file mode 100644
index 0000000..d2ecbd0
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/armada100/timer.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ * Contributor: Mahavir Jain <mjain@marvell.com>
+ */
+
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/armada100.h>
+
+/*
+ * Timer registers
+ * Refer Section A.6 in Datasheet
+ */
+struct armd1tmr_registers {
+	u32 clk_ctrl;	/* Timer clk control reg */
+	u32 match[9];	/* Timer match registers */
+	u32 count[3];	/* Timer count registers */
+	u32 status[3];
+	u32 ie[3];
+	u32 preload[3];	/* Timer preload value */
+	u32 preload_ctrl[3];
+	u32 wdt_match_en;
+	u32 wdt_match_r;
+	u32 wdt_val;
+	u32 wdt_sts;
+	u32 icr[3];
+	u32 wdt_icr;
+	u32 cer;	/* Timer count enable reg */
+	u32 cmr;
+	u32 ilr[3];
+	u32 wcr;
+	u32 wfar;
+	u32 wsar;
+	u32 cvwr;
+};
+
+#define TIMER			0	/* Use TIMER 0 */
+/* Each timer has 3 match registers */
+#define MATCH_CMP(x)		((3 * TIMER) + x)
+#define TIMER_LOAD_VAL 		0xffffffff
+#define	COUNT_RD_REQ		0x1
+
+DECLARE_GLOBAL_DATA_PTR;
+/* Using gd->arch.tbu from timestamp and gd->arch.tbl for lastdec */
+
+/* For preventing risk of instability in reading counter value,
+ * first set read request to register cvwr and then read same
+ * register after it captures counter value.
+ */
+ulong read_timer(void)
+{
+	struct armd1tmr_registers *armd1timers =
+		(struct armd1tmr_registers *) ARMD1_TIMER_BASE;
+	volatile int loop=100;
+
+	writel(COUNT_RD_REQ, &armd1timers->cvwr);
+	while (loop--);
+	return(readl(&armd1timers->cvwr));
+}
+
+static ulong get_timer_masked(void)
+{
+	ulong now = read_timer();
+
+	if (now >= gd->arch.tbl) {
+		/* normal mode */
+		gd->arch.tbu += now - gd->arch.tbl;
+	} else {
+		/* we have an overflow ... */
+		gd->arch.tbu += now + TIMER_LOAD_VAL - gd->arch.tbl;
+	}
+	gd->arch.tbl = now;
+
+	return gd->arch.tbu;
+}
+
+ulong get_timer(ulong base)
+{
+	return ((get_timer_masked() / (CONFIG_SYS_HZ_CLOCK / 1000)) -
+		base);
+}
+
+void __udelay(unsigned long usec)
+{
+	ulong delayticks;
+	ulong endtime;
+
+	delayticks = (usec * (CONFIG_SYS_HZ_CLOCK / 1000000));
+	endtime = get_timer_masked() + delayticks;
+
+	while (get_timer_masked() < endtime);
+}
+
+/*
+ * init the Timer
+ */
+int timer_init(void)
+{
+	struct armd1apb1_registers *apb1clkres =
+		(struct armd1apb1_registers *) ARMD1_APBC1_BASE;
+	struct armd1tmr_registers *armd1timers =
+		(struct armd1tmr_registers *) ARMD1_TIMER_BASE;
+
+	/* Enable Timer clock at 3.25 MHZ */
+	writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), &apb1clkres->timers);
+
+	/* load value into timer */
+	writel(0x0, &armd1timers->clk_ctrl);
+	/* Use Timer 0 Match Resiger 0 */
+	writel(TIMER_LOAD_VAL, &armd1timers->match[MATCH_CMP(0)]);
+	/* Preload value is 0 */
+	writel(0x0, &armd1timers->preload[TIMER]);
+	/* Enable match comparator 0 for Timer 0 */
+	writel(0x1, &armd1timers->preload_ctrl[TIMER]);
+
+	/* Enable timer 0 */
+	writel(0x1, &armd1timers->cer);
+	/* init the gd->arch.tbu and gd->arch.tbl value */
+	gd->arch.tbl = read_timer();
+	gd->arch.tbu = 0;
+
+	return 0;
+}
+
+#define MPMU_APRR_WDTR	(1<<4)
+#define TMR_WFAR	0xbaba	/* WDT Register First key */
+#define TMP_WSAR	0xeb10	/* WDT Register Second key */
+
+/*
+ * This function uses internal Watchdog Timer
+ * based reset mechanism.
+ * Steps to write watchdog registers (protected access)
+ * 1. Write key value to TMR_WFAR reg.
+ * 2. Write key value to TMP_WSAR reg.
+ * 3. Perform write operation.
+ */
+void reset_cpu (unsigned long ignored)
+{
+	struct armd1mpmu_registers *mpmu =
+		(struct armd1mpmu_registers *) ARMD1_MPMU_BASE;
+	struct armd1tmr_registers *armd1timers =
+		(struct armd1tmr_registers *) ARMD1_TIMER_BASE;
+	u32 val;
+
+	/* negate hardware reset to the WDT after system reset */
+	val = readl(&mpmu->aprr);
+	val = val | MPMU_APRR_WDTR;
+	writel(val, &mpmu->aprr);
+
+	/* reset/enable WDT clock */
+	writel(APBC_APBCLK | APBC_FNCLK | APBC_RST, &mpmu->wdtpcr);
+	readl(&mpmu->wdtpcr);
+	writel(APBC_APBCLK | APBC_FNCLK, &mpmu->wdtpcr);
+	readl(&mpmu->wdtpcr);
+
+	/* clear previous WDT status */
+	writel(TMR_WFAR, &armd1timers->wfar);
+	writel(TMP_WSAR, &armd1timers->wsar);
+	writel(0, &armd1timers->wdt_sts);
+
+	/* set match counter */
+	writel(TMR_WFAR, &armd1timers->wfar);
+	writel(TMP_WSAR, &armd1timers->wsar);
+	writel(0xf, &armd1timers->wdt_match_r);
+
+	/* enable WDT reset */
+	writel(TMR_WFAR, &armd1timers->wfar);
+	writel(TMP_WSAR, &armd1timers->wsar);
+	writel(0x3, &armd1timers->wdt_match_en);
+
+	while(1);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk (void)
+{
+	return (ulong)CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c
new file mode 100644
index 0000000..22a55f5
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/cache.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011
+ * Ilya Yanok, EmCraft Systems
+ */
+#include <linux/types.h>
+#include <common.h>
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void invalidate_dcache_all(void)
+{
+	asm volatile("mcr p15, 0, %0, c7, c6, 0\n" : : "r"(0));
+}
+
+void flush_dcache_all(void)
+{
+	asm volatile(
+		"0:"
+		"mrc p15, 0, r15, c7, c14, 3\n"
+		"bne 0b\n"
+		"mcr p15, 0, %0, c7, c10, 4\n"
+		 : : "r"(0) : "memory"
+	);
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+	if (!check_cache_range(start, stop))
+		return;
+
+	while (start < stop) {
+		asm volatile("mcr p15, 0, %0, c7, c6, 1\n" : : "r"(start));
+		start += CONFIG_SYS_CACHELINE_SIZE;
+	}
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+	if (!check_cache_range(start, stop))
+		return;
+
+	while (start < stop) {
+		asm volatile("mcr p15, 0, %0, c7, c14, 1\n" : : "r"(start));
+		start += CONFIG_SYS_CACHELINE_SIZE;
+	}
+
+	asm volatile("mcr p15, 0, %0, c7, c10, 4\n" : : "r"(0));
+}
+#else /* #ifndef CONFIG_SYS_DCACHE_OFF */
+void invalidate_dcache_all(void)
+{
+}
+
+void flush_dcache_all(void)
+{
+}
+#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
+
+/*
+ * Stub implementations for l2 cache operations
+ */
+
+__weak void l2_cache_disable(void) {}
+
+#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
+__weak void invalidate_l2_cache(void) {}
+#endif
+
+#ifndef CONFIG_SYS_ICACHE_OFF
+/* Invalidate entire I-cache and branch predictor array */
+void invalidate_icache_all(void)
+{
+	unsigned long i = 0;
+
+	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i));
+}
+#else
+void invalidate_icache_all(void) {}
+#endif
+
+void enable_caches(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+	icache_enable();
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+	dcache_enable();
+#endif
+}
+
diff --git a/arch/arm/cpu/arm926ejs/cpu.c b/arch/arm/cpu/arm926ejs/cpu.c
new file mode 100644
index 0000000..c3f1ee1
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/cpu.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+
+static void cache_flush(void);
+
+int cleanup_before_linux (void)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * we turn off caches etc ...
+	 */
+
+	disable_interrupts ();
+
+
+	/* turn off I/D-cache */
+	icache_disable();
+	dcache_disable();
+	l2_cache_disable();
+
+	/* flush I/D-cache */
+	cache_flush();
+
+	return 0;
+}
+
+/* flush I/D-cache */
+static void cache_flush (void)
+{
+#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
+	unsigned long i = 0;
+
+	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
+#endif
+}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig b/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig
new file mode 100644
index 0000000..1db1262
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig
@@ -0,0 +1,21 @@
+if ARCH_LPC32XX
+
+config SYS_SOC
+	default "lpc32xx"
+
+choice
+	prompt "NXP LPC32xx board select"
+
+config TARGET_DEVKIT3250
+	bool "Timll DevKit3250"
+
+config TARGET_WORK_92105
+	bool "Work Microwave Work_92105"
+
+endchoice
+
+source "board/timll/devkit3250/Kconfig"
+source "board/work-microwave/work_92105/Kconfig"
+
+endif
+
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
new file mode 100644
index 0000000..6303570
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y   = cpu.o clk.o devices.o timer.o
+
+obj-$(CONFIG_SPL_BUILD) += dram.o lowlevel_init.o
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
new file mode 100644
index 0000000..5eb630d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com>
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clk.h>
+#include <asm/io.h>
+
+static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
+
+unsigned int get_sys_clk_rate(void)
+{
+	if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397)
+		return RTC_CLK_FREQUENCY * 397;
+	else
+		return OSC_CLK_FREQUENCY;
+}
+
+unsigned int get_hclk_pll_rate(void)
+{
+	unsigned long long fin, fref, fcco, fout;
+	u32 val, m_div, n_div, p_div;
+
+	/*
+	 * Valid frequency ranges:
+	 *     1 * 10^6 <=  Fin <=  20 * 10^6
+	 *     1 * 10^6 <= Fref <=  27 * 10^6
+	 *   156 * 10^6 <= Fcco <= 320 * 10^6
+	 */
+
+	fref = fin = get_sys_clk_rate();
+	if (fin > 20000000ULL || fin < 1000000ULL)
+		return 0;
+
+	val = readl(&clk->hclkpll_ctrl);
+	m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1;
+	n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1;
+	if (val & CLK_HCLK_PLL_DIRECT)
+		p_div = 0;
+	else
+		p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1;
+	p_div = 1 << p_div;
+
+	if (val & CLK_HCLK_PLL_BYPASS) {
+		do_div(fin, p_div);
+		return fin;
+	}
+
+	do_div(fref, n_div);
+	if (fref > 27000000ULL || fref < 1000000ULL)
+		return 0;
+
+	fcco = fref * m_div;
+	fout = fcco;
+	if (val & CLK_HCLK_PLL_FEEDBACK)
+		fcco *= p_div;
+	else
+		do_div(fout, p_div);
+
+	if (fcco > 320000000ULL || fcco < 156000000ULL)
+		return 0;
+
+	return fout;
+}
+
+unsigned int get_hclk_clk_div(void)
+{
+	u32 val;
+
+	val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK;
+
+	return 1 << val;
+}
+
+unsigned int get_hclk_clk_rate(void)
+{
+	return get_hclk_pll_rate() / get_hclk_clk_div();
+}
+
+unsigned int get_periph_clk_div(void)
+{
+	u32 val;
+
+	val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK;
+
+	return (val >> 2) + 1;
+}
+
+unsigned int get_periph_clk_rate(void)
+{
+	if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN))
+		return get_sys_clk_rate();
+
+	return get_hclk_pll_rate() / get_periph_clk_div();
+}
+
+unsigned int get_sdram_clk_rate(void)
+{
+	unsigned int src_clk;
+
+	if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN))
+		return get_sys_clk_rate();
+
+	src_clk = get_hclk_pll_rate();
+
+	if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) {
+		/* using DDR */
+		switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) {
+		case CLK_HCLK_DDRAM_HALF:
+			return src_clk/2;
+		case CLK_HCLK_DDRAM_NOMINAL:
+			return src_clk;
+		default:
+			return 0;
+		}
+	} else {
+		/* using SDR */
+		switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) {
+		case CLK_HCLK_ARM_PLL_DIV_4:
+			return src_clk/4;
+		case CLK_HCLK_ARM_PLL_DIV_2:
+			return src_clk/2;
+		case CLK_HCLK_ARM_PLL_DIV_1:
+			return src_clk;
+		default:
+			return 0;
+		}
+	}
+}
+
+int get_serial_clock(void)
+{
+	return get_periph_clk_rate();
+}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
new file mode 100644
index 0000000..5117177
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011-2015 by Vladimir Zapolskiy <vz@mleia.com>
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/wdt.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+
+static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
+static struct wdt_regs  *wdt = (struct wdt_regs *)WDT_BASE;
+
+void reset_cpu(ulong addr)
+{
+	/* Enable watchdog clock */
+	setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG);
+
+	/* To be compatible with the original U-Boot code:
+	 * addr: - 0: perform hard reset.
+	 *       - !=0: perform a soft reset; i.e. "RESOUT_N" not asserted). */
+	if (addr == 0) {
+		/* Reset pulse length is 13005 peripheral clock frames */
+		writel(13000, &wdt->pulse);
+
+		/* Force WDOG_RESET2 and RESOUT_N signal active */
+		writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1
+		       | WDTIM_MCTRL_M_RES2, &wdt->mctrl);
+	} else {
+		/* Force match output active */
+		writel(0x01, &wdt->emr);
+
+		/* Internal reset on match output (no pulse on "RESOUT_N") */
+		writel(WDTIM_MCTRL_M_RES1, &wdt->mctrl);
+	}
+
+	while (1)
+		/* NOP */;
+}
+
+#if defined(CONFIG_ARCH_CPU_INIT)
+int arch_cpu_init(void)
+{
+	/*
+	 * It might be necessary to flush data cache, if U-Boot is loaded
+	 * from kickstart bootloader, e.g. from S1L loader
+	 */
+	flush_dcache_all();
+
+	return 0;
+}
+#else
+#error "You have to select CONFIG_ARCH_CPU_INIT"
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("CPU:   NXP LPC32XX\n");
+	printf("CPU clock:        %uMHz\n", get_hclk_pll_rate() / 1000000);
+	printf("AHB bus clock:    %uMHz\n", get_hclk_clk_rate() / 1000000);
+	printf("Peripheral clock: %uMHz\n", get_periph_clk_rate() / 1000000);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_LPC32XX_ETH
+int cpu_eth_init(bd_t *bis)
+{
+	lpc32xx_eth_initialize(bis);
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c
new file mode 100644
index 0000000..7e7646a
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <dm/platform_data/lpc32xx_hsuart.h>
+
+#include <asm/arch/clk.h>
+#include <asm/arch/uart.h>
+#include <asm/arch/mux.h>
+#include <asm/io.h>
+
+static struct clk_pm_regs    *clk  = (struct clk_pm_regs *)CLK_PM_BASE;
+static struct uart_ctrl_regs *ctrl = (struct uart_ctrl_regs *)UART_CTRL_BASE;
+static struct mux_regs *mux = (struct mux_regs *)MUX_BASE;
+
+void lpc32xx_uart_init(unsigned int uart_id)
+{
+	if (uart_id < 1 || uart_id > 7)
+		return;
+
+	/* Disable loopback mode, if it is set by S1L bootloader */
+	clrbits_le32(&ctrl->loop,
+		     UART_LOOPBACK(CONFIG_SYS_LPC32XX_UART));
+
+	if (uart_id < 3 || uart_id > 6)
+		return;
+
+	/* Enable UART system clock */
+	setbits_le32(&clk->uartclk_ctrl, CLK_UART(uart_id));
+
+	/* Set UART into autoclock mode */
+	clrsetbits_le32(&ctrl->clkmode,
+			UART_CLKMODE_MASK(uart_id),
+			UART_CLKMODE_AUTO(uart_id));
+
+	/* Bypass pre-divider of UART clock */
+	writel(CLK_UART_X_DIV(1) | CLK_UART_Y_DIV(1),
+	       &clk->u3clk + (uart_id - 3));
+}
+
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct ns16550_platdata lpc32xx_uart[] = {
+	{ .base = UART3_BASE, .reg_shift = 2,
+	  .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
+	{ .base = UART4_BASE, .reg_shift = 2,
+	  .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
+	{ .base = UART5_BASE, .reg_shift = 2,
+	  .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
+	{ .base = UART6_BASE, .reg_shift = 2,
+	  .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
+};
+
+#if defined(CONFIG_LPC32XX_HSUART)
+static const struct lpc32xx_hsuart_platdata lpc32xx_hsuart[] = {
+	{ HS_UART1_BASE, },
+	{ HS_UART2_BASE, },
+	{ HS_UART7_BASE, },
+};
+#endif
+
+U_BOOT_DEVICES(lpc32xx_uarts) = {
+#if defined(CONFIG_LPC32XX_HSUART)
+	{ "lpc32xx_hsuart", &lpc32xx_hsuart[0], },
+	{ "lpc32xx_hsuart", &lpc32xx_hsuart[1], },
+#endif
+	{ "ns16550_serial", &lpc32xx_uart[0], },
+	{ "ns16550_serial", &lpc32xx_uart[1], },
+	{ "ns16550_serial", &lpc32xx_uart[2], },
+	{ "ns16550_serial", &lpc32xx_uart[3], },
+#if defined(CONFIG_LPC32XX_HSUART)
+	{ "lpc32xx_hsuart", &lpc32xx_hsuart[2], },
+#endif
+};
+#endif
+
+void lpc32xx_dma_init(void)
+{
+	/* Enable DMA interface */
+	writel(CLK_DMA_ENABLE, &clk->dmaclk_ctrl);
+}
+
+void lpc32xx_mac_init(void)
+{
+	/* Enable MAC interface */
+	writel(CLK_MAC_REG | CLK_MAC_SLAVE | CLK_MAC_MASTER
+#if defined(CONFIG_RMII)
+		| CLK_MAC_RMII,
+#else
+		| CLK_MAC_MII,
+#endif
+		&clk->macclk_ctrl);
+}
+
+void lpc32xx_mlc_nand_init(void)
+{
+	/* Enable NAND interface */
+	writel(CLK_NAND_MLC | CLK_NAND_MLC_INT, &clk->flashclk_ctrl);
+}
+
+void lpc32xx_slc_nand_init(void)
+{
+	/* Enable SLC NAND interface */
+	writel(CLK_NAND_SLC | CLK_NAND_SLC_SELECT, &clk->flashclk_ctrl);
+}
+
+void lpc32xx_usb_init(void)
+{
+	/* Do not route the UART 5 Tx/Rx pins to the USB D+ and USB D- pins. */
+	clrbits_le32(&ctrl->ctrl, UART_CTRL_UART5_USB_MODE);
+}
+
+void lpc32xx_i2c_init(unsigned int devnum)
+{
+	/* Enable I2C interface */
+	uint32_t ctrl = readl(&clk->i2cclk_ctrl);
+	if (devnum == 1)
+		ctrl |= CLK_I2C1_ENABLE;
+	if (devnum == 2)
+		ctrl |= CLK_I2C2_ENABLE;
+	writel(ctrl, &clk->i2cclk_ctrl);
+}
+
+U_BOOT_DEVICE(lpc32xx_gpios) = {
+	.name = "gpio_lpc32xx"
+};
+
+/* Mux for SCK0, MISO0, MOSI0. We do not use SSEL0. */
+
+#define P_MUX_SET_SSP0 0x1600
+
+void lpc32xx_ssp_init(void)
+{
+	/* Enable SSP0 interface */
+	writel(CLK_SSP0_ENABLE_CLOCK, &clk->ssp_ctrl);
+	/* Mux SSP0 pins */
+	writel(P_MUX_SET_SSP0, &mux->p_mux_set);
+}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/dram.c b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c
new file mode 100644
index 0000000..4f97569
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * LPC32xx dram init
+ *
+ * (C) Copyright 2014  DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
+ *
+ * This is called by SPL to gain access to the SDR DRAM.
+ *
+ * This code runs from SRAM.
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/wdt.h>
+#include <asm/arch/emc.h>
+#include <asm/io.h>
+
+static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
+static struct emc_regs *emc = (struct emc_regs *)EMC_BASE;
+
+void ddr_init(struct emc_dram_settings *dram)
+{
+	uint32_t ck;
+
+	/* Enable EMC interface and choose little endian mode */
+	writel(1, &emc->ctrl);
+	writel(0, &emc->config);
+	/* Select maximum EMC Dynamic Memory Refresh Time */
+	writel(0x7FF, &emc->refresh);
+	/* Determine CLK */
+	ck = get_sdram_clk_rate();
+	/* Configure SDRAM */
+	writel(dram->cmddelay, &clk->sdramclk_ctrl);
+	writel(dram->config0, &emc->config0);
+	writel(dram->rascas0, &emc->rascas0);
+	writel(dram->rdconfig, &emc->read_config);
+	/* Set timings */
+	writel((ck / dram->trp) & 0x0000000F, &emc->t_rp);
+	writel((ck / dram->tras) & 0x0000000F, &emc->t_ras);
+	writel((ck / dram->tsrex) & 0x0000007F, &emc->t_srex);
+	writel((ck / dram->twr) & 0x0000000F, &emc->t_wr);
+	writel((ck / dram->trc) & 0x0000001F, &emc->t_rc);
+	writel((ck / dram->trfc) & 0x0000001F, &emc->t_rfc);
+	writel((ck / dram->txsr) & 0x000000FF, &emc->t_xsr);
+	writel(dram->trrd, &emc->t_rrd);
+	writel(dram->tmrd, &emc->t_mrd);
+	writel(dram->tcdlr, &emc->t_cdlr);
+	/* Dynamic refresh */
+	writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh);
+	udelay(10);
+	/* Force all clocks, enable inverted ck, issue NOP command */
+	writel(0x00000193, &emc->control);
+	udelay(100);
+	/* Keep all clocks enabled, issue a PRECHARGE ALL command */
+	writel(0x00000113, &emc->control);
+	/* Fast dynamic refresh for at least a few SDRAM ck cycles */
+	writel((((128) >> 4) & 0x7FF), &emc->refresh);
+	udelay(10);
+	/* set correct dynamic refresh timing */
+	writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh);
+	udelay(10);
+	/* set normal mode to CAS=3 */
+	writel(0x00000093, &emc->control);
+	readl(EMC_DYCS0_BASE | dram->mode);
+	/* set extended mode to all zeroes */
+	writel(0x00000093, &emc->control);
+	readl(EMC_DYCS0_BASE | dram->emode);
+	/* stop forcing clocks, keep inverted clock, issue normal mode */
+	writel(0x00000010, &emc->control);
+}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
new file mode 100644
index 0000000..d42da2b
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * WORK Microwave work_92105 board low level init
+ *
+ * (C) Copyright 2014  DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
+ *
+ * Low level init is called from SPL to set up the clocks.
+ * On entry, the LPC3250 is in Direct Run mode with all clocks
+ * running at 13 MHz; on exit, ARM clock is 208 MHz, HCLK is
+ * 104 MHz and PCLK is 13 MHz.
+ *
+ * This code must run from SRAM so that the clock changes do
+ * not prevent it from executing.
+ */
+
+.globl lowlevel_init
+
+lowlevel_init:
+
+	/* Set ARM, HCLK, PCLK dividers for normal mode */
+	ldr	r0, =0x0000003D
+	ldr	r1, =0x40004040
+	str	r0, [r1]
+
+	/* Start HCLK PLL for 208 MHz */
+	ldr	r0, =0x0001401E
+	ldr	r1, =0x40004058
+	str	r0, [r1]
+
+	/* wait for HCLK PLL to lock */
+1:
+	ldr	r0, [r1]
+	ands	r0, r0, #1
+	beq	1b
+
+	/* switch to normal mode */
+	ldr	r1, =0x40004044
+	ldr	r0, [r1]
+	orr	r0, #0x00000004
+	str	r0, [r1]
+
+	/* Return to U-Boot via saved link register */
+	mov	pc, lr
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/timer.c b/arch/arm/cpu/arm926ejs/lpc32xx/timer.c
new file mode 100644
index 0000000..404ccbb
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/timer.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com>
+ */
+
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/timer.h>
+#include <asm/io.h>
+
+static struct timer_regs  *timer0 = (struct timer_regs *)TIMER0_BASE;
+static struct timer_regs  *timer1 = (struct timer_regs *)TIMER1_BASE;
+static struct clk_pm_regs *clk    = (struct clk_pm_regs *)CLK_PM_BASE;
+
+static void lpc32xx_timer_clock(u32 bit, int enable)
+{
+	if (enable)
+		setbits_le32(&clk->timclk_ctrl1, bit);
+	else
+		clrbits_le32(&clk->timclk_ctrl1, bit);
+}
+
+static void lpc32xx_timer_reset(struct timer_regs *timer, u32 freq)
+{
+	writel(TIMER_TCR_COUNTER_RESET,   &timer->tcr);
+	writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr);
+	writel(0, &timer->tc);
+	writel(0, &timer->pr);
+
+	/* Count mode is every rising PCLK edge */
+	writel(TIMER_CTCR_MODE_TIMER, &timer->ctcr);
+
+	/* Set prescale counter value */
+	writel((get_periph_clk_rate() / freq) - 1, &timer->pr);
+}
+
+static void lpc32xx_timer_count(struct timer_regs *timer, int enable)
+{
+	if (enable)
+		writel(TIMER_TCR_COUNTER_ENABLE,  &timer->tcr);
+	else
+		writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr);
+}
+
+int timer_init(void)
+{
+	lpc32xx_timer_clock(CLK_TIMCLK_TIMER0, 1);
+	lpc32xx_timer_reset(timer0, CONFIG_SYS_HZ);
+	lpc32xx_timer_count(timer0, 1);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	return readl(&timer0->tc) - base;
+}
+
+void __udelay(unsigned long usec)
+{
+	lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 1);
+	lpc32xx_timer_reset(timer1, CONFIG_SYS_HZ * 1000);
+	lpc32xx_timer_count(timer1, 1);
+
+	while (readl(&timer1->tc) < usec)
+		/* NOP */;
+
+	lpc32xx_timer_count(timer1, 0);
+	lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 0);
+}
+
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+ulong get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx25/Makefile b/arch/arm/cpu/arm926ejs/mx25/Makefile
new file mode 100644
index 0000000..ac5ebaf
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx25/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+
+obj-y	+= generic.o timer.o reset.o relocate.o
diff --git a/arch/arm/cpu/arm926ejs/mx25/generic.c b/arch/arm/cpu/arm926ejs/mx25/generic.c
new file mode 100644
index 0000000..2795a5f
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx25/generic.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009 DENX Software Engineering
+ * Author: John Rigby <jrigby@gmail.com>
+ *
+ * Based on mx27/generic.c:
+ *  Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ *  Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/arch-imx/cpu.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+/*
+ *  get the system pll clock in Hz
+ *
+ *                  mfi + mfn / (mfd +1)
+ *  f = 2 * f_ref * --------------------
+ *                        pd + 1
+ */
+static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref)
+{
+	unsigned int mfi = (pll >> CCM_PLL_MFI_SHIFT)
+	    & CCM_PLL_MFI_MASK;
+	int mfn = (pll >> CCM_PLL_MFN_SHIFT)
+	    & CCM_PLL_MFN_MASK;
+	unsigned int mfd = (pll >> CCM_PLL_MFD_SHIFT)
+	    & CCM_PLL_MFD_MASK;
+	unsigned int pd = (pll >> CCM_PLL_PD_SHIFT)
+	    & CCM_PLL_PD_MASK;
+
+	mfi = mfi <= 5 ? 5 : mfi;
+	mfn = mfn >= 512 ? mfn - 1024 : mfn;
+	mfd += 1;
+	pd += 1;
+
+	return lldiv(2 * (u64) f_ref * (mfi * mfd + mfn),
+		     mfd * pd);
+}
+
+static ulong imx_get_mpllclk(void)
+{
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+	ulong fref = MXC_HCLK;
+
+	return imx_decode_pll(readl(&ccm->mpctl), fref);
+}
+
+static ulong imx_get_upllclk(void)
+{
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+	ulong fref = MXC_HCLK;
+
+	return imx_decode_pll(readl(&ccm->upctl), fref);
+}
+
+static ulong imx_get_armclk(void)
+{
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+	ulong cctl = readl(&ccm->cctl);
+	ulong fref = imx_get_mpllclk();
+	ulong div;
+
+	if (cctl & CCM_CCTL_ARM_SRC)
+		fref = lldiv((u64) fref * 3, 4);
+
+	div = ((cctl >> CCM_CCTL_ARM_DIV_SHIFT)
+	       & CCM_CCTL_ARM_DIV_MASK) + 1;
+
+	return fref / div;
+}
+
+static ulong imx_get_ahbclk(void)
+{
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+	ulong cctl = readl(&ccm->cctl);
+	ulong fref = imx_get_armclk();
+	ulong div;
+
+	div = ((cctl >> CCM_CCTL_AHB_DIV_SHIFT)
+	       & CCM_CCTL_AHB_DIV_MASK) + 1;
+
+	return fref / div;
+}
+
+static ulong imx_get_ipgclk(void)
+{
+	return imx_get_ahbclk() / 2;
+}
+
+static ulong imx_get_perclk(int clk)
+{
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+	ulong fref = readl(&ccm->mcr) & (1 << clk) ? imx_get_upllclk() :
+						     imx_get_ahbclk();
+	ulong div;
+
+	div = readl(&ccm->pcdr[CCM_PERCLK_REG(clk)]);
+	div = ((div >> CCM_PERCLK_SHIFT(clk)) & CCM_PERCLK_MASK) + 1;
+
+	return fref / div;
+}
+
+int imx_set_perclk(enum mxc_clock clk, bool from_upll, unsigned int freq)
+{
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+	ulong fref = from_upll ? imx_get_upllclk() : imx_get_ahbclk();
+	ulong div = (fref + freq - 1) / freq;
+
+	if (clk > MXC_UART_CLK || !div || --div > CCM_PERCLK_MASK)
+		return -EINVAL;
+
+	clrsetbits_le32(&ccm->pcdr[CCM_PERCLK_REG(clk)],
+			CCM_PERCLK_MASK << CCM_PERCLK_SHIFT(clk),
+			div << CCM_PERCLK_SHIFT(clk));
+	if (from_upll)
+		setbits_le32(&ccm->mcr, 1 << clk);
+	else
+		clrbits_le32(&ccm->mcr, 1 << clk);
+	return 0;
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	if (clk >= MXC_CLK_NUM)
+		return -1;
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return imx_get_armclk();
+	case MXC_AHB_CLK:
+		return imx_get_ahbclk();
+	case MXC_IPG_CLK:
+	case MXC_CSPI_CLK:
+	case MXC_FEC_CLK:
+		return imx_get_ipgclk();
+	default:
+		return imx_get_perclk(clk);
+	}
+}
+
+u32 get_cpu_rev(void)
+{
+	u32 srev;
+	u32 system_rev = 0x25000;
+
+	/* read SREV register from IIM module */
+	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+	srev = readl(&iim->iim_srev);
+
+	switch (srev) {
+	case 0x00:
+		system_rev |= CHIP_REV_1_0;
+		break;
+	case 0x01:
+		system_rev |= CHIP_REV_1_1;
+		break;
+	case 0x02:
+		system_rev |= CHIP_REV_1_2;
+		break;
+	default:
+		system_rev |= 0x8000;
+		break;
+	}
+
+	return system_rev;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+static char *get_reset_cause(void)
+{
+	/* read RCSR register from CCM module */
+	struct ccm_regs *ccm =
+		(struct ccm_regs *)IMX_CCM_BASE;
+
+	u32 cause = readl(&ccm->rcsr) & 0x0f;
+
+	if (cause == 0)
+		return "POR";
+	else if (cause == 1)
+		return "RST";
+	else if ((cause & 2) == 2)
+		return "WDOG";
+	else if ((cause & 4) == 4)
+		return "SW RESET";
+	else if ((cause & 8) == 8)
+		return "JTAG";
+	else
+		return "unknown reset";
+
+}
+
+int print_cpuinfo(void)
+{
+	char buf[32];
+	u32 cpurev = get_cpu_rev();
+
+	printf("CPU:   Freescale i.MX25 rev%d.%d%s at %s MHz\n",
+		(cpurev & 0xF0) >> 4, (cpurev & 0x0F),
+		((cpurev & 0x8000) ? " unknown" : ""),
+		strmhz(buf, imx_get_armclk()));
+	printf("Reset cause: %s\n", get_reset_cause());
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_FEC_MXC)
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+	ulong val;
+
+	val = readl(&ccm->cgr0);
+	val |= (1 << 23);
+	writel(val, &ccm->cgr0);
+	return fecmxc_initialize(bis);
+}
+#endif
+
+int get_clocks(void)
+{
+#ifdef CONFIG_FSL_ESDHC
+#if CONFIG_SYS_FSL_ESDHC_ADDR == IMX_MMC_SDHC2_BASE
+	gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+#else
+	gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK);
+#endif
+#endif
+	return 0;
+}
+
+#ifdef CONFIG_FSL_ESDHC
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+	return fsl_esdhc_mmc_init(bis);
+}
+#endif
+
+#ifdef CONFIG_FEC_MXC
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+	int i;
+	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+	struct fuse_bank *bank = &iim->bank[0];
+	struct fuse_bank0_regs *fuse =
+			(struct fuse_bank0_regs *)bank->fuse_regs;
+
+	for (i = 0; i < 6; i++)
+		mac[i] = readl(&fuse->mac_addr[i]) & 0xff;
+}
+#endif /* CONFIG_FEC_MXC */
diff --git a/arch/arm/cpu/arm926ejs/mx25/relocate.S b/arch/arm/cpu/arm926ejs/mx25/relocate.S
new file mode 100644
index 0000000..709e35c
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx25/relocate.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  relocate - i.MX25-specific vector relocation
+ *
+ *  Copyright (c) 2013  Albert ARIBAUD <albert.u.boot@aribaud.net>
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * The i.MX25 SoC is very specific with respect to exceptions: it
+ * does not provide RAM at the high vectors address (0xFFFF0000),
+ * thus only the low address (0x00000000) is useable; but that is
+ * in ROM, so let's avoid relocating the vectors.
+ */
+	.section	.text.relocate_vectors,"ax",%progbits
+
+ENTRY(relocate_vectors)
+
+	bx	lr
+
+ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm926ejs/mx25/reset.c b/arch/arm/cpu/arm926ejs/mx25/reset.c
new file mode 100644
index 0000000..576f7fa
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx25/reset.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/*
+ * Reset the cpu by setting up the watchdog timer and let it time out
+ */
+void reset_cpu(ulong ignored)
+{
+	struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
+	/* Disable watchdog and set Time-Out field to 0 */
+	writew(0, &regs->wcr);
+
+	/* Write Service Sequence */
+	writew(WSR_UNLOCK1, &regs->wsr);
+	writew(WSR_UNLOCK2, &regs->wsr);
+
+	/* Enable watchdog */
+	writew(WCR_WDE, &regs->wcr);
+
+	while (1) ;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx25/timer.c b/arch/arm/cpu/arm926ejs/mx25/timer.c
new file mode 100644
index 0000000..04698fe
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx25/timer.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ *
+ * (C) Copyright 2009 DENX Software Engineering
+ * Author: John Rigby <jrigby@gmail.com>
+ *	Add support for MX25
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/* nothing really to do with interrupts, just starts up a counter. */
+/* The 32KHz 32-bit timer overruns in 134217 seconds */
+int timer_init(void)
+{
+	int i;
+	struct gpt_regs *gpt = (struct gpt_regs *)IMX_GPT1_BASE;
+	struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
+
+	/* setup GP Timer 1 */
+	writel(GPT_CTRL_SWR, &gpt->ctrl);
+
+	writel(readl(&ccm->cgr1) | CCM_CGR1_GPT1, &ccm->cgr1);
+
+	for (i = 0; i < 100; i++)
+		writel(0, &gpt->ctrl); /* We have no udelay by now */
+	writel(0, &gpt->pre); /* prescaler = 1 */
+	/* Freerun Mode, 32KHz input */
+	writel(readl(&gpt->ctrl) | GPT_CTRL_CLKSOURCE_32 | GPT_CTRL_FRR,
+			&gpt->ctrl);
+	writel(readl(&gpt->ctrl) | GPT_CTRL_TEN, &gpt->ctrl);
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx27/Makefile b/arch/arm/cpu/arm926ejs/mx27/Makefile
new file mode 100644
index 0000000..ac5ebaf
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx27/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+
+obj-y	+= generic.o timer.o reset.o relocate.o
diff --git a/arch/arm/cpu/arm926ejs/mx27/generic.c b/arch/arm/cpu/arm926ejs/mx27/generic.c
new file mode 100644
index 0000000..08b1b4d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx27/generic.c
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ *  Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-imx/sys_proto.h>
+#ifdef CONFIG_MMC_MXC
+#include <asm/arch/mxcmmc.h>
+#endif
+
+/*
+ *  get the system pll clock in Hz
+ *
+ *                  mfi + mfn / (mfd +1)
+ *  f = 2 * f_ref * --------------------
+ *                        pd + 1
+ */
+static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref)
+{
+	unsigned int mfi = (pll >> 10) & 0xf;
+	unsigned int mfn = pll & 0x3ff;
+	unsigned int mfd = (pll >> 16) & 0x3ff;
+	unsigned int pd =  (pll >> 26) & 0xf;
+
+	mfi = mfi <= 5 ? 5 : mfi;
+
+	return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn),
+			(mfd + 1) * (pd + 1));
+}
+
+static ulong clk_in_32k(void)
+{
+	return 1024 * CONFIG_MX27_CLK32;
+}
+
+static ulong clk_in_26m(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) {
+		/* divide by 1.5 */
+		return 26000000 * 2 / 3;
+	} else {
+		return 26000000;
+	}
+}
+
+static ulong imx_get_mpllclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref;
+
+	if (cscr & CSCR_MCU_SEL)
+		fref = clk_in_26m();
+	else
+		fref = clk_in_32k();
+
+	return imx_decode_pll(readl(&pll->mpctl0), fref);
+}
+
+static ulong imx_get_armclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref = imx_get_mpllclk();
+	ulong div;
+
+	if (!(cscr & CSCR_ARM_SRC_MPLL))
+		fref = lldiv((fref * 2), 3);
+
+	div = ((cscr >> 12) & 0x3) + 1;
+
+	return lldiv(fref, div);
+}
+
+static ulong imx_get_ahbclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref = imx_get_mpllclk();
+	ulong div;
+
+	div = ((cscr >> 8) & 0x3) + 1;
+
+	return lldiv(fref * 2, 3 * div);
+}
+
+static __attribute__((unused)) ulong imx_get_spllclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref;
+
+	if (cscr & CSCR_SP_SEL)
+		fref = clk_in_26m();
+	else
+		fref = clk_in_32k();
+
+	return imx_decode_pll(readl(&pll->spctl0), fref);
+}
+
+static ulong imx_decode_perclk(ulong div)
+{
+	return lldiv((imx_get_mpllclk() * 2), (div * 3));
+}
+
+static ulong imx_get_perclk1(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1);
+}
+
+static ulong imx_get_perclk2(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1);
+}
+
+static __attribute__((unused)) ulong imx_get_perclk3(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1);
+}
+
+static __attribute__((unused)) ulong imx_get_perclk4(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1);
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return imx_get_armclk();
+	case MXC_I2C_CLK:
+		return imx_get_ahbclk()/2;
+	case MXC_UART_CLK:
+		return imx_get_perclk1();
+	case MXC_FEC_CLK:
+		return imx_get_ahbclk();
+	case MXC_ESDHC_CLK:
+		return imx_get_perclk2();
+	}
+	return -1;
+}
+
+
+u32 get_cpu_rev(void)
+{
+	return MXC_CPU_MX27 << 12;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo (void)
+{
+	char buf[32];
+
+	printf("CPU:   Freescale i.MX27 at %s MHz\n\n",
+			strmhz(buf, imx_get_mpllclk()));
+	return 0;
+}
+#endif
+
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_FEC_MXC)
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	/* enable FEC clock */
+	writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
+	writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+	return fecmxc_initialize(bis);
+#else
+	return 0;
+#endif
+}
+
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_MMC_MXC
+	return mxc_mmc_init(bis);
+#else
+	return 0;
+#endif
+}
+
+void imx_gpio_mode(int gpio_mode)
+{
+	struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE;
+	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
+	unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT;
+	unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT;
+	unsigned int tmp;
+
+	/* Pullup enable */
+	if (gpio_mode & GPIO_PUEN) {
+		writel(readl(&regs->port[port].puen) | (1 << pin),
+				&regs->port[port].puen);
+	} else {
+		writel(readl(&regs->port[port].puen) & ~(1 << pin),
+				&regs->port[port].puen);
+	}
+
+	/* Data direction */
+	if (gpio_mode & GPIO_OUT) {
+		writel(readl(&regs->port[port].gpio_dir) | 1 << pin,
+				&regs->port[port].gpio_dir);
+	} else {
+		writel(readl(&regs->port[port].gpio_dir) & ~(1 << pin),
+				&regs->port[port].gpio_dir);
+	}
+
+	/* Primary / alternate function */
+	if (gpio_mode & GPIO_AF) {
+		writel(readl(&regs->port[port].gpr) | (1 << pin),
+				&regs->port[port].gpr);
+	} else {
+		writel(readl(&regs->port[port].gpr) & ~(1 << pin),
+				&regs->port[port].gpr);
+	}
+
+	/* use as gpio? */
+	if (!(gpio_mode & (GPIO_PF | GPIO_AF))) {
+		writel(readl(&regs->port[port].gius) | (1 << pin),
+				&regs->port[port].gius);
+	} else {
+		writel(readl(&regs->port[port].gius) & ~(1 << pin),
+				&regs->port[port].gius);
+	}
+
+	/* Output / input configuration */
+	if (pin < 16) {
+		tmp = readl(&regs->port[port].ocr1);
+		tmp &= ~(3 << (pin * 2));
+		tmp |= (ocr << (pin * 2));
+		writel(tmp, &regs->port[port].ocr1);
+
+		writel(readl(&regs->port[port].iconfa1) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfa1);
+		writel(readl(&regs->port[port].iconfa1) | aout << (pin * 2),
+				&regs->port[port].iconfa1);
+		writel(readl(&regs->port[port].iconfb1) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfb1);
+		writel(readl(&regs->port[port].iconfb1) | bout << (pin * 2),
+				&regs->port[port].iconfb1);
+	} else {
+		pin -= 16;
+
+		tmp = readl(&regs->port[port].ocr2);
+		tmp &= ~(3 << (pin * 2));
+		tmp |= (ocr << (pin * 2));
+		writel(tmp, &regs->port[port].ocr2);
+
+		writel(readl(&regs->port[port].iconfa2) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfa2);
+		writel(readl(&regs->port[port].iconfa2) | aout << (pin * 2),
+				&regs->port[port].iconfa2);
+		writel(readl(&regs->port[port].iconfb2) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfb2);
+		writel(readl(&regs->port[port].iconfb2) | bout << (pin * 2),
+				&regs->port[port].iconfb2);
+	}
+}
+
+#ifdef CONFIG_MXC_UART
+void mx27_uart1_init_pins(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PE12_PF_UART1_TXD,
+		PE13_PF_UART1_RXD,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIG_MXC_UART */
+
+#ifdef CONFIG_FEC_MXC
+void mx27_fec_init_pins(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PD0_AIN_FEC_TXD0,
+		PD1_AIN_FEC_TXD1,
+		PD2_AIN_FEC_TXD2,
+		PD3_AIN_FEC_TXD3,
+		PD4_AOUT_FEC_RX_ER,
+		PD5_AOUT_FEC_RXD1,
+		PD6_AOUT_FEC_RXD2,
+		PD7_AOUT_FEC_RXD3,
+		PD8_AF_FEC_MDIO,
+		PD9_AIN_FEC_MDC | GPIO_PUEN,
+		PD10_AOUT_FEC_CRS,
+		PD11_AOUT_FEC_TX_CLK,
+		PD12_AOUT_FEC_RXD0,
+		PD13_AOUT_FEC_RX_DV,
+		PD14_AOUT_FEC_CLR,
+		PD15_AOUT_FEC_COL,
+		PD16_AIN_FEC_TX_ER,
+		PF23_AIN_FEC_TX_EN,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+}
+
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+	int i;
+	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+	struct fuse_bank *bank = &iim->bank[0];
+	struct fuse_bank0_regs *fuse =
+			(struct fuse_bank0_regs *)bank->fuse_regs;
+
+	for (i = 0; i < 6; i++)
+		mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff;
+}
+#endif /* CONFIG_FEC_MXC */
+
+#ifdef CONFIG_MMC_MXC
+void mx27_sd1_init_pins(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PE18_PF_SD1_D0,
+		PE19_PF_SD1_D1,
+		PE20_PF_SD1_D2,
+		PE21_PF_SD1_D3,
+		PE22_PF_SD1_CMD,
+		PE23_PF_SD1_CLK,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+}
+
+void mx27_sd2_init_pins(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PB4_PF_SD2_D0,
+		PB5_PF_SD2_D1,
+		PB6_PF_SD2_D2,
+		PB7_PF_SD2_D3,
+		PB8_PF_SD2_CMD,
+		PB9_PF_SD2_CLK,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIG_MMC_MXC */
diff --git a/arch/arm/cpu/arm926ejs/mx27/relocate.S b/arch/arm/cpu/arm926ejs/mx27/relocate.S
new file mode 100644
index 0000000..5dfa272
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx27/relocate.S
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  relocate - i.MX27-specific vector relocation
+ *
+ *  Copyright (c) 2013  Albert ARIBAUD <albert.u.boot@aribaud.net>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+/*
+ * The i.MX27 SoC is very specific with respect to exceptions: it
+ * does not provide RAM at the high vectors address (0xFFFF0000),
+ * thus only the low address (0x00000000) is useable; but that is
+ * in ROM. Therefore, vectors cannot be changed at all.
+ *
+ * However, these ROM-based vectors actually just perform indirect
+ * calls through pointers located in RAM at SoC-specific addresses,
+ * as follows:
+ *
+ * Offset      Exception              Use by ROM code
+ * 0x00000000  reset                  indirect branch to [0x00000014]
+ * 0x00000004  undefined instruction  indirect branch to [0xfffffef0]
+ * 0x00000008  software interrupt     indirect branch to [0xfffffef4]
+ * 0x0000000c  prefetch abort         indirect branch to [0xfffffef8]
+ * 0x00000010  data abort             indirect branch to [0xfffffefc]
+ * 0x00000014  (reserved in ARMv5)    vector to ROM reset: 0xc0000000
+ * 0x00000018  IRQ                    indirect branch to [0xffffff00]
+ * 0x0000001c  FIQ                    indirect branch to [0xffffff04]
+ *
+ * In order to initialize exceptions on i.MX27, we must copy U-Boot's
+ * indirect (not exception!) vector table into 0xfffffef0..0xffffff04
+ * taking care not to copy vectors number 5 (reserved exception).
+ */
+
+	.section	.text.relocate_vectors,"ax",%progbits
+
+ENTRY(relocate_vectors)
+
+	ldr	r0, [r9, #GD_RELOCADDR]	/* r0 = gd->relocaddr */
+	ldr	r1, =32			/* size of vector table */
+	add	r0, r0, r1		/* skip to indirect table */
+	ldr	r1, =0xFFFFFEF0		/* i.MX27 indirect table */
+	ldmia	r0!, {r2-r8}		/* load indirect vectors 1..7 */
+	stmia	r1!, {r2-r5, r7,r8}	/* write all but vector 5 */
+
+	bx	lr
+
+ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm926ejs/mx27/reset.c b/arch/arm/cpu/arm926ejs/mx27/reset.c
new file mode 100644
index 0000000..e2437d1
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx27/reset.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/*
+ * Reset the cpu by setting up the watchdog timer and let it time out
+ */
+void reset_cpu(ulong ignored)
+{
+	struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
+	/* Disable watchdog and set Time-Out field to 0 */
+	writew(0x0000, &regs->wcr);
+
+	/* Write Service Sequence */
+	writew(0x5555, &regs->wsr);
+	writew(0xAAAA, &regs->wsr);
+
+	/* Enable watchdog */
+	writew(WCR_WDE, &regs->wcr);
+
+	while (1);
+	/*NOTREACHED*/
+}
diff --git a/arch/arm/cpu/arm926ejs/mx27/timer.c b/arch/arm/cpu/arm926ejs/mx27/timer.c
new file mode 100644
index 0000000..94b5d45
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx27/timer.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/* General purpose timers bitfields */
+#define GPTCR_SWR		(1 << 15)	/* Software reset	*/
+#define GPTCR_FRR		(1 << 8)	/* Freerun / restart	*/
+#define GPTCR_CLKSOURCE_32	(4 << 1)	/* Clock source		*/
+#define GPTCR_TEN		1		/* Timer enable		*/
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp	(gd->arch.tbl)
+#define lastinc		(gd->arch.lastinc)
+
+/*
+ * "time" is measured in 1 / CONFIG_SYS_HZ seconds,
+ * "tick" is internal timer period
+ */
+#ifdef CONFIG_MX27_TIMER_HIGH_PRECISION
+/* ~0.4% error - measured with stop-watch on 100s boot-delay */
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, CONFIG_MX27_CLK32);
+	return tick;
+}
+
+static inline unsigned long long time_to_tick(unsigned long long time)
+{
+	time *= CONFIG_MX27_CLK32;
+	do_div(time, CONFIG_SYS_HZ);
+	return time;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+	us = us * CONFIG_MX27_CLK32 + 999999;
+	do_div(us, 1000000);
+	return us;
+}
+#else
+/* ~2% error */
+#define TICK_PER_TIME	((CONFIG_MX27_CLK32 + CONFIG_SYS_HZ / 2) / \
+		CONFIG_SYS_HZ)
+#define US_PER_TICK	(1000000 / CONFIG_MX27_CLK32)
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	do_div(tick, TICK_PER_TIME);
+	return tick;
+}
+
+static inline unsigned long long time_to_tick(unsigned long long time)
+{
+	return time * TICK_PER_TIME;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+	us += US_PER_TICK - 1;
+	do_div(us, US_PER_TICK);
+	return us;
+}
+#endif
+
+/* nothing really to do with interrupts, just starts up a counter. */
+/* The 32768Hz 32-bit timer overruns in 131072 seconds */
+int timer_init(void)
+{
+	int i;
+	struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	/* setup GP Timer 1 */
+	writel(GPTCR_SWR, &regs->gpt_tctl);
+
+	writel(readl(&pll->pccr0) | PCCR0_GPT1_EN, &pll->pccr0);
+	writel(readl(&pll->pccr1) | PCCR1_PERCLK1_EN, &pll->pccr1);
+
+	for (i = 0; i < 100; i++)
+		writel(0, &regs->gpt_tctl); /* We have no udelay by now */
+	writel(0, &regs->gpt_tprer); /* 32Khz */
+	/* Freerun Mode, PERCLK1 input */
+	writel(readl(&regs->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
+			&regs->gpt_tctl);
+	writel(readl(&regs->gpt_tctl) | GPTCR_TEN, &regs->gpt_tctl);
+
+	return 0;
+}
+
+unsigned long long get_ticks(void)
+{
+	struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
+	ulong now = readl(&regs->gpt_tcn); /* current tick value */
+
+	if (now >= lastinc) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (now - lastinc);
+	} else {
+		/* we have rollover of incrementer */
+		timestamp += (0xFFFFFFFF - lastinc) + now;
+	}
+	lastinc = now;
+	return timestamp;
+}
+
+static ulong get_timer_masked(void)
+{
+	/*
+	 * get_ticks() returns a long long (64 bit), it wraps in
+	 * 2^64 / CONFIG_MX27_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
+	 * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
+	 * 5 * 10^6 days - long enough.
+	 */
+	return tick_to_time(get_ticks());
+}
+
+ulong get_timer(ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+/* delay x useconds AND preserve advance timstamp value */
+void __udelay(unsigned long usec)
+{
+	unsigned long long tmp;
+	ulong tmo;
+
+	tmo = us_to_tick(usec);
+	tmp = get_ticks() + tmo;	/* get current timestamp */
+
+	while (get_ticks() < tmp)	/* loop till event */
+		 /*NOP*/;
+}
+
+ulong get_tbclk(void)
+{
+	return CONFIG_MX27_CLK32;
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/Makefile b/arch/arm/cpu/arm926ejs/mxs/Makefile
new file mode 100644
index 0000000..f60e61e
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/Makefile
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-$(CONFIG_SPL_BUILD) := start.o
+
+obj-y	= clock.o mxs.o iomux.o timer.o
+
+ifdef	CONFIG_SPL_BUILD
+obj-y	+= spl_boot.o spl_lradc_init.o spl_mem_init.o spl_power_init.o
+endif
+
+# Specify the target for use in elftosb call
+MKIMAGE_TARGET-$(CONFIG_MX23) = mxsimage$(CONFIG_SPL_FRAMEWORK:%=-spl).mx23.cfg
+MKIMAGE_TARGET-$(CONFIG_MX28) = mxsimage$(CONFIG_SPL_FRAMEWORK:%=-spl).mx28.cfg
+
+# Generate HAB-capable IVT
+#
+# Note on computing the post-IVT size field value for the U-Boot binary.
+# The value is the result of adding the following:
+#  -> The size of U-Boot binary aligned to 64B (u-boot.bin)
+#  -> The size of IVT block aligned to 64B (u-boot.ivt)
+#  -> The size of U-Boot signature (u-boot.sig), 3904 B
+#  -> The 64B hole in front of U-Boot binary for 'struct mxs_spl_data' passing
+#
+quiet_cmd_mkivt_mxs = MXSIVT  $@
+cmd_mkivt_mxs =								\
+	sz=`expr \`stat -c "%s" $^\` + 64 + 3904 + 128` ;		\
+	echo -n "0x402000d1 $2 0 0 0 $3 $4 0 $$sz 0 0 0 0 0 0 0" |	\
+	tr -s " " | xargs -d " " -i printf "%08x\n" "{}" | rev |	\
+	sed "s/\(.\)\(.\)/\\\\\\\\x\2\1\n/g" | xargs -i printf "{}" >$@
+
+# Align binary to 64B
+quiet_cmd_mkalign_mxs = MXSALGN $@
+cmd_mkalign_mxs =							\
+	dd if=$^ of=$@ ibs=64 conv=sync 2>/dev/null &&			\
+	mv $@ $^
+
+# Assemble the CSF file
+quiet_cmd_mkcsfreq_mxs = MXSCSFR $@
+cmd_mkcsfreq_mxs =							\
+	ivt=$(word 1,$^) ;						\
+	bin=$(word 2,$^) ;						\
+	csf=$(word 3,$^) ;						\
+	sed "s@VENDOR@$(VENDOR)@g;s@BOARD@$(BOARD)@g" "$$csf" |		\
+		sed '/^\#\#Blocks/ d' > $@ ;				\
+	echo "  Blocks = $2 0x0 `stat -c '%s' $$bin` \"$$bin\" , \\" >> $@ ; \
+	echo "           $3 0x0 0x40 \"$$ivt\"" >> $@
+
+# Sign files
+quiet_cmd_mkcst_mxs = MXSCST  $@
+cmd_mkcst_mxs = cst -o $@ < $^						\
+	$(if $(KBUILD_VERBOSE:1=), >/dev/null)
+
+spl/u-boot-spl.ivt: spl/u-boot-spl.bin
+	$(call if_changed,mkalign_mxs)
+	$(call if_changed,mkivt_mxs,$(CONFIG_SPL_TEXT_BASE),\
+		0x00008000,0x00008040)
+
+u-boot.ivt: u-boot.bin
+	$(call if_changed,mkalign_mxs)
+	$(call if_changed,mkivt_mxs,$(CONFIG_SYS_TEXT_BASE),\
+		0x40001000,0x40001040)
+
+spl/u-boot-spl.csf: spl/u-boot-spl.ivt spl/u-boot-spl.bin board/$(VENDOR)/$(BOARD)/sign/u-boot-spl.csf
+	$(call if_changed,mkcsfreq_mxs,$(CONFIG_SPL_TEXT_BASE),0x8000)
+
+u-boot.csf: u-boot.ivt u-boot.bin board/$(VENDOR)/$(BOARD)/sign/u-boot.csf
+	$(call if_changed,mkcsfreq_mxs,$(CONFIG_SYS_TEXT_BASE),0x40001000)
+
+%.sig: %.csf
+	$(call if_changed,mkcst_mxs)
+
+MKIMAGEFLAGS_u-boot.sb = -n $< -T mxsimage
+u-boot.sb: $(src)/$(MKIMAGE_TARGET-y) u-boot.bin spl/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
+MKIMAGEFLAGS_u-boot-signed.sb = -n $< -T mxsimage
+u-boot-signed.sb: $(src)/mxsimage-signed.cfg u-boot.ivt u-boot.sig spl/u-boot-spl.ivt spl/u-boot-spl.sig FORCE
+	$(call if_changed,mkimage)
diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c
new file mode 100644
index 0000000..43d044d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/clock.c
@@ -0,0 +1,435 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX23/i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+
+/*
+ * The PLL frequency is 480MHz and XTAL frequency is 24MHz
+ *   iMX23: datasheet section 4.2
+ *   iMX28: datasheet section 10.2
+ */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+#if defined(CONFIG_MX23)
+#define MXC_SSPCLK_MAX MXC_SSPCLK0
+#elif defined(CONFIG_MX28)
+#define MXC_SSPCLK_MAX MXC_SSPCLK3
+#endif
+
+static uint32_t mxs_get_pclk(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, div;
+	uint8_t clkfrac, frac;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
+	frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mxs_get_hclk(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mxs_get_pclk() / div;
+}
+
+static uint32_t mxs_get_emiclk(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, div;
+	uint8_t clkfrac, frac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
+	frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mxs_get_gpmiclk(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+#if defined(CONFIG_MX23)
+	uint8_t *reg =
+		&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU];
+#elif defined(CONFIG_MX28)
+	uint8_t *reg =
+		&clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI];
+#endif
+	uint32_t clkctrl, clkseq, div;
+	uint8_t clkfrac, frac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readb(reg);
+	frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+	int io_reg;
+
+	if (freq == 0)
+		return;
+
+	if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1))
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	io_reg = CLKCTRL_FRAC0_IO0 - io;	/* Register order is reversed */
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_set[io_reg]);
+	writeb(CLKCTRL_FRAC_CLKGATE | (div & CLKCTRL_FRAC_FRAC_MASK),
+		&clkctrl_regs->hw_clkctrl_frac0[io_reg]);
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_clr[io_reg]);
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+static uint32_t mxs_get_ioclk(enum mxs_ioclock io)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint8_t ret;
+	int io_reg;
+
+	if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1))
+		return 0;
+
+	io_reg = CLKCTRL_FRAC0_IO0 - io;	/* Register order is reversed */
+
+	ret = readb(&clkctrl_regs->hw_clkctrl_frac0[io_reg]) &
+		CLKCTRL_FRAC_FRAC_MASK;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > MXC_SSPCLK_MAX)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mxs_register_32));
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mxs_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+static uint32_t mxs_get_sspclk(enum mxs_sspclock ssp)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > MXC_SSPCLK_MAX)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mxs_register_32));
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mxs_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mxs_ssp_regs *ssp_regs;
+	const enum mxs_sspclock clk = mxs_ssp_clock_by_bus(bus);
+	const uint32_t sspclk = mxs_get_sspclk(clk);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = mxs_ssp_regs_by_bus(bus);
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+void mxs_set_lcdclk(uint32_t __maybe_unused lcd_base, uint32_t freq)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t fp, x, k_rest, k_best, x_best, tk;
+	int32_t k_best_l = 999, k_best_t = 0, x_best_l = 0xff, x_best_t = 0xff;
+
+	if (freq == 0)
+		return;
+
+#if defined(CONFIG_MX23)
+	writel(CLKCTRL_CLKSEQ_BYPASS_PIX, &clkctrl_regs->hw_clkctrl_clkseq_clr);
+#elif defined(CONFIG_MX28)
+	writel(CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF, &clkctrl_regs->hw_clkctrl_clkseq_clr);
+#endif
+
+	/*
+	 *             /               18 \     1       1
+	 * freq kHz = | 480000000 Hz * --  | * --- * ------
+	 *             \                x /     k     1000
+	 *
+	 *      480000000 Hz   18
+	 *      ------------ * --
+	 *        freq kHz      x
+	 * k = -------------------
+	 *             1000
+	 */
+
+	fp = ((PLL_FREQ_KHZ * 1000) / freq) * 18;
+
+	for (x = 18; x <= 35; x++) {
+		tk = fp / x;
+		if ((tk / 1000 == 0) || (tk / 1000 > 255))
+			continue;
+
+		k_rest = tk % 1000;
+
+		if (k_rest < (k_best_l % 1000)) {
+			k_best_l = tk;
+			x_best_l = x;
+		}
+
+		if (k_rest > (k_best_t % 1000)) {
+			k_best_t = tk;
+			x_best_t = x;
+		}
+	}
+
+	if (1000 - (k_best_t % 1000) > (k_best_l % 1000)) {
+		k_best = k_best_l;
+		x_best = x_best_l;
+	} else {
+		k_best = k_best_t;
+		x_best = x_best_t;
+	}
+
+	k_best /= 1000;
+
+#if defined(CONFIG_MX23)
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_PIX]);
+	writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK),
+		&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_PIX]);
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_PIX]);
+
+	writel(CLKCTRL_PIX_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pix_set);
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_pix,
+			CLKCTRL_PIX_DIV_MASK | CLKCTRL_PIX_CLKGATE,
+			k_best << CLKCTRL_PIX_DIV_OFFSET);
+
+	while (readl(&clkctrl_regs->hw_clkctrl_pix) & CLKCTRL_PIX_BUSY)
+		;
+#elif defined(CONFIG_MX28)
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac1_set[CLKCTRL_FRAC1_PIX]);
+	writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK),
+		&clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_PIX]);
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac1_clr[CLKCTRL_FRAC1_PIX]);
+
+	writel(CLKCTRL_DIS_LCDIF_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_lcdif_set);
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_lcdif,
+			CLKCTRL_DIS_LCDIF_DIV_MASK | CLKCTRL_DIS_LCDIF_CLKGATE,
+			k_best << CLKCTRL_DIS_LCDIF_DIV_OFFSET);
+
+	while (readl(&clkctrl_regs->hw_clkctrl_lcdif) & CLKCTRL_DIS_LCDIF_BUSY)
+		;
+#endif
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mxs_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mxs_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mxs_get_hclk() * 1000000;
+	case MXC_EMI_CLK:
+		return mxs_get_emiclk();
+	case MXC_IO0_CLK:
+		return mxs_get_ioclk(MXC_IOCLK0);
+	case MXC_IO1_CLK:
+		return mxs_get_ioclk(MXC_IOCLK1);
+	case MXC_XTAL_CLK:
+		return XTAL_FREQ_KHZ * 1000;
+	case MXC_SSP0_CLK:
+		return mxs_get_sspclk(MXC_SSPCLK0);
+#ifdef CONFIG_MX28
+	case MXC_SSP1_CLK:
+		return mxs_get_sspclk(MXC_SSPCLK1);
+	case MXC_SSP2_CLK:
+		return mxs_get_sspclk(MXC_SSPCLK2);
+	case MXC_SSP3_CLK:
+		return mxs_get_sspclk(MXC_SSPCLK3);
+#endif
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/iomux.c b/arch/arm/cpu/arm926ejs/mxs/iomux.c
new file mode 100644
index 0000000..381264b
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/iomux.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *                       <armlinux@phytec.de>
+ */
+
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+
+#if	defined(CONFIG_MX23)
+#define	DRIVE_OFFSET	0x200
+#define	PULL_OFFSET	0x400
+#elif	defined(CONFIG_MX28)
+#define	DRIVE_OFFSET	0x300
+#define	PULL_OFFSET	0x600
+#else
+#error "Please select CONFIG_MX23 or CONFIG_MX28"
+#endif
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxs_iomux_setup_pad(iomux_cfg_t pad)
+{
+	u32 reg, ofs, bp, bm;
+	void *iomux_base = (void *)MXS_PINCTRL_BASE;
+	struct mxs_register_32 *mxs_reg;
+
+	/* muxsel */
+	ofs = 0x100;
+	ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10;
+	bp = PAD_PIN(pad) % 16 * 2;
+	bm = 0x3 << bp;
+	reg = readl(iomux_base + ofs);
+	reg &= ~bm;
+	reg |= PAD_MUXSEL(pad) << bp;
+	writel(reg, iomux_base + ofs);
+
+	/* drive */
+	ofs = DRIVE_OFFSET;
+	ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10;
+	/* mA */
+	if (PAD_MA_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4;
+		bm = 0x3 << bp;
+		reg = readl(iomux_base + ofs);
+		reg &= ~bm;
+		reg |= PAD_MA(pad) << bp;
+		writel(reg, iomux_base + ofs);
+	}
+	/* vol */
+	if (PAD_VOL_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4 + 2;
+		mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs);
+		if (PAD_VOL(pad))
+			writel(1 << bp, &mxs_reg->reg_set);
+		else
+			writel(1 << bp, &mxs_reg->reg_clr);
+	}
+
+	/* pull */
+	if (PAD_PULL_VALID(pad)) {
+		ofs = PULL_OFFSET;
+		ofs += PAD_BANK(pad) * 0x10;
+		bp = PAD_PIN(pad);
+		mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs);
+		if (PAD_PULL(pad))
+			writel(1 << bp, &mxs_reg->reg_set);
+		else
+			writel(1 << bp, &mxs_reg->reg_clr);
+	}
+
+	return 0;
+}
+
+int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count)
+{
+	const iomux_cfg_t *p = pad_list;
+	int i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		ret = mxs_iomux_setup_pad(*p);
+		if (ret)
+			return ret;
+		p++;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs.c b/arch/arm/cpu/arm926ejs/mxs/mxs.c
new file mode 100644
index 0000000..85c65dc
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/mxs.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX23/i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/mach-imx/dma.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+__weak void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+	struct mxs_rtc_regs *rtc_regs =
+		(struct mxs_rtc_regs *)MXS_RTC_BASE;
+	struct mxs_lcdif_regs *lcdif_regs =
+		(struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+
+	/*
+	 * Shut down the LCD controller as it interferes with BootROM boot mode
+	 * pads sampling.
+	 */
+	writel(LCDIF_CTRL_RUN, &lcdif_regs->hw_lcdif_ctrl_clr);
+
+	/* Wait 1 uS before doing the actual watchdog reset */
+	writel(1, &rtc_regs->hw_rtc_watchdog);
+	writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+/*
+ * This function will craft a jumptable at 0x0 which will redirect interrupt
+ * vectoring to proper location of U-Boot in RAM.
+ *
+ * The structure of the jumptable will be as follows:
+ *  ldr pc, [pc, #0x18] ..... for each vector, thus repeated 8 times
+ *  <destination address> ... for each previous ldr, thus also repeated 8 times
+ *
+ * The "ldr pc, [pc, #0x18]" instruction above loads address from memory at
+ * offset 0x18 from current value of PC register. Note that PC is already
+ * incremented by 4 when computing the offset, so the effective offset is
+ * actually 0x20, this the associated <destination address>. Loading the PC
+ * register with an address performs a jump to that address.
+ */
+void mx28_fixup_vt(uint32_t start_addr)
+{
+	/* ldr pc, [pc, #0x18] */
+	const uint32_t ldr_pc = 0xe59ff018;
+	/* Jumptable location is 0x0 */
+	uint32_t *vt = (uint32_t *)0x0;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		/* cppcheck-suppress nullPointer */
+		vt[i] = ldr_pc;
+		/* cppcheck-suppress nullPointer */
+		vt[i + 8] = start_addr + (4 * i);
+	}
+}
+
+#ifdef	CONFIG_ARCH_MISC_INIT
+int arch_misc_init(void)
+{
+	mx28_fixup_vt(gd->relocaddr);
+	return 0;
+}
+#endif
+
+int arch_cpu_init(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	extern uint32_t _start;
+
+	mx28_fixup_vt((uint32_t)&_start);
+
+	/*
+	 * Enable NAND clock
+	 */
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+	udelay(1000);
+
+	/*
+	 * Configure GPIO unit
+	 */
+	mxs_gpio_init();
+
+#ifdef	CONFIG_APBH_DMA
+	/* Start APBH DMA */
+	mxs_dma_init();
+#endif
+
+	return 0;
+}
+
+u32 get_cpu_rev(void)
+{
+	struct mxs_digctl_regs *digctl_regs =
+		(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
+	uint8_t rev = readl(&digctl_regs->hw_digctl_chipid) & 0x000000FF;
+
+	switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
+	case HW_DIGCTL_CHIPID_MX23:
+		switch (rev) {
+		case 0x0:
+		case 0x1:
+		case 0x2:
+		case 0x3:
+		case 0x4:
+			return (MXC_CPU_MX23 << 12) | (rev + 0x10);
+		default:
+			return 0;
+		}
+	case HW_DIGCTL_CHIPID_MX28:
+		switch (rev) {
+		case 0x1:
+			return (MXC_CPU_MX28 << 12) | 0x12;
+		default:
+			return 0;
+		}
+	default:
+		return 0;
+	}
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+const char *get_imx_type(u32 imxtype)
+{
+	switch (imxtype) {
+	case MXC_CPU_MX23:
+		return "23";
+	case MXC_CPU_MX28:
+		return "28";
+	default:
+		return "??";
+	}
+}
+
+int print_cpuinfo(void)
+{
+	u32 cpurev;
+	struct mxs_spl_data *data = MXS_SPL_DATA;
+
+	cpurev = get_cpu_rev();
+	printf("CPU:   Freescale i.MX%s rev%d.%d at %d MHz\n",
+		get_imx_type((cpurev & 0xFF000) >> 12),
+		(cpurev & 0x000F0) >> 4,
+		(cpurev & 0x0000F) >> 0,
+		mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BOOT:  %s\n", mxs_boot_modes[data->boot_mode_idx].mode);
+	return 0;
+}
+#endif
+
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ */
+#if defined(CONFIG_MX28) && defined(CONFIG_CMD_NET)
+int cpu_eth_init(bd_t *bis)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Turn on ENET clocks */
+	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+	/* Set up ENET PLL for 50 MHz */
+	/* Power on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+	udelay(10);
+
+	/* Gate on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+	/* Enable pad output */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
+	return 0;
+}
+#endif
+
+__weak void mx28_adjust_mac(int dev_id, unsigned char *mac)
+{
+	mac[0] = 0x00;
+	mac[1] = 0x04; /* Use FSL vendor MAC address by default */
+
+	if (dev_id == 1) /* Let MAC1 be MAC0 + 1 by default */
+		mac[5] += 1;
+}
+
+#ifdef	CONFIG_MX28_FEC_MAC_IN_OCOTP
+
+#define	MXS_OCOTP_MAX_TIMEOUT	1000000
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+	struct mxs_ocotp_regs *ocotp_regs =
+		(struct mxs_ocotp_regs *)MXS_OCOTP_BASE;
+	uint32_t data;
+
+	memset(mac, 0, 6);
+
+	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+	if (mxs_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+				MXS_OCOTP_MAX_TIMEOUT)) {
+		printf("MXS FEC: Can't get MAC from OCOTP\n");
+		return;
+	}
+
+	data = readl(&ocotp_regs->hw_ocotp_cust0);
+
+	mac[2] = (data >> 24) & 0xff;
+	mac[3] = (data >> 16) & 0xff;
+	mac[4] = (data >> 8) & 0xff;
+	mac[5] = data & 0xff;
+	mx28_adjust_mac(dev_id, mac);
+}
+#else
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+	memset(mac, 0, 6);
+}
+#endif
+
+int mxs_dram_init(void)
+{
+	struct mxs_spl_data *data = MXS_SPL_DATA;
+
+	if (data->mem_dram_size == 0) {
+		printf("MXS:\n"
+			"Error, the RAM size passed up from SPL is 0!\n");
+		hang();
+	}
+
+	gd->ram_size = data->mem_dram_size;
+	return 0;
+}
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+	"display clocks",
+	""
+);
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs_init.h b/arch/arm/cpu/arm926ejs/mxs/mxs_init.h
new file mode 100644
index 0000000..062deb7
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/mxs_init.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Freescale i.MX28 SPL functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ */
+
+#ifndef	__M28_INIT_H__
+#define	__M28_INIT_H__
+
+void early_delay(int delay);
+
+void mxs_power_init(void);
+
+#ifdef	CONFIG_SPL_MXS_PSWITCH_WAIT
+void mxs_power_wait_pswitch(void);
+#else
+static inline void mxs_power_wait_pswitch(void) { }
+#endif
+
+void mxs_mem_init(void);
+uint32_t mxs_mem_get_size(void);
+
+void mxs_lradc_init(void);
+void mxs_lradc_enable_batt_measurement(void);
+
+#endif	/* __M28_INIT_H__ */
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg
new file mode 100644
index 0000000..83953da
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg
@@ -0,0 +1,11 @@
+DISPLAYPROGRESS
+SECTION 0x0 BOOTABLE
+ TAG LAST
+ LOAD     0x1000     spl/u-boot-spl.bin
+ LOAD     0x8000     spl/u-boot-spl.ivt
+ LOAD     0x8040     spl/u-boot-spl.sig
+ CALL HAB 0x8000     0x0
+ LOAD     0x40002000 u-boot.bin
+ LOAD     0x40001000 u-boot.ivt
+ LOAD     0x40001040 u-boot.sig
+ CALL HAB 0x40001000 0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx23.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx23.cfg
new file mode 100644
index 0000000..ab2183e
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx23.cfg
@@ -0,0 +1,5 @@
+DISPLAYPROGRESS
+SECTION 0x0 BOOTABLE
+ TAG LAST
+ LOAD     0x1000     spl/u-boot-spl.bin
+ CALL     0x1000     0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx28.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx28.cfg
new file mode 100644
index 0000000..0d95064
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx28.cfg
@@ -0,0 +1,6 @@
+DISPLAYPROGRESS
+SECTION 0x0 BOOTABLE
+ TAG LAST
+ LOAD     0x1000     spl/u-boot-spl.bin
+ LOAD IVT 0x8000     0x1000
+ CALL HAB 0x8000     0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg
new file mode 100644
index 0000000..e702809
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg
@@ -0,0 +1,7 @@
+DISPLAYPROGRESS
+SECTION 0x0 BOOTABLE
+ TAG LAST
+ LOAD     0x1000     spl/u-boot-spl.bin
+ CALL     0x1000     0x0
+ LOAD     0x40002000 u-boot.bin
+ CALL     0x40002000 0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg
new file mode 100644
index 0000000..3f7bf59
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg
@@ -0,0 +1,9 @@
+DISPLAYPROGRESS
+SECTION 0x0 BOOTABLE
+ TAG LAST
+ LOAD     0x1000     spl/u-boot-spl.bin
+ LOAD IVT 0x8000     0x1000
+ CALL HAB 0x8000     0x0
+ LOAD     0x40002000 u-boot.bin
+ LOAD IVT 0x8000     0x40002000
+ CALL HAB 0x8000     0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
new file mode 100644
index 0000000..cb361ac
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX28 Boot setup
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <linux/compiler.h>
+
+#include "mxs_init.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+static gd_t gdata __section(".data");
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
+static bd_t bdata __section(".data");
+#endif
+
+/*
+ * This delay function is intended to be used only in early stage of boot, where
+ * clock are not set up yet. The timer used here is reset on every boot and
+ * takes a few seconds to roll. The boot doesn't take that long, so to keep the
+ * code simple, it doesn't take rolling into consideration.
+ */
+void early_delay(int delay)
+{
+	struct mxs_digctl_regs *digctl_regs =
+		(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
+
+	uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
+	st += delay;
+	while (st > readl(&digctl_regs->hw_digctl_microseconds))
+		;
+}
+
+#if defined(CONFIG_MX23)
+#define	MUX_CONFIG_BOOTMODE_PAD	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+static const iomux_cfg_t iomux_boot[] = {
+	MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
+	MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
+	MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
+	MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
+	MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
+	MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
+};
+#endif
+
+static uint8_t mxs_get_bootmode_index(void)
+{
+	uint8_t bootmode = 0;
+	int i;
+	uint8_t masked;
+
+#if defined(CONFIG_MX23)
+	/* Setup IOMUX of bootmode pads to GPIO */
+	mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
+
+	/* Setup bootmode pins as GPIO input */
+	gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0);
+	gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1);
+	gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2);
+	gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3);
+	gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5);
+
+	/* Read bootmode pads */
+	bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
+	bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
+	bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
+	bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
+	bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
+#elif defined(CONFIG_MX28)
+	/* The global boot mode will be detected by ROM code and its value
+	 * is stored at the fixed address 0x00019BF0 in OCRAM.
+	 */
+#define GLOBAL_BOOT_MODE_ADDR 0x00019BF0
+	bootmode = __raw_readl(GLOBAL_BOOT_MODE_ADDR);
+#endif
+
+	for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) {
+		masked = bootmode & mxs_boot_modes[i].boot_mask;
+		if (masked == mxs_boot_modes[i].boot_pads)
+			break;
+	}
+
+	return i;
+}
+
+static void mxs_spl_fixup_vectors(void)
+{
+	/*
+	 * Copy our vector table to 0x0, since due to HAB, we cannot
+	 * be loaded to 0x0. We want to have working vectoring though,
+	 * thus this fixup. Our vectoring table is PIC, so copying is
+	 * fine.
+	 */
+	extern uint32_t _start;
+
+	/* cppcheck-suppress nullPointer */
+	memcpy(0x0, &_start, 0x60);
+}
+
+static void mxs_spl_console_init(void)
+{
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
+	gd->bd = &bdata;
+	gd->baudrate = CONFIG_BAUDRATE;
+	serial_init();
+	gd->have_console = 1;
+#endif
+}
+
+void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
+			 const iomux_cfg_t *iomux_setup,
+			 const unsigned int iomux_size)
+{
+	struct mxs_spl_data *data = MXS_SPL_DATA;
+	uint8_t bootmode = mxs_get_bootmode_index();
+	gd = &gdata;
+
+	mxs_spl_fixup_vectors();
+
+	mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
+
+	mxs_spl_console_init();
+	debug("SPL: Serial Console Initialised\n");
+
+	mxs_power_init();
+
+	mxs_mem_init();
+	data->mem_dram_size = mxs_mem_get_size();
+
+	data->boot_mode_idx = bootmode;
+
+	mxs_power_wait_pswitch();
+
+	if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) {
+		debug("SPL: Waiting for JTAG user\n");
+		asm volatile ("x: b x");
+	}
+}
+
+#ifndef CONFIG_SPL_FRAMEWORK
+/* Support aparatus */
+inline void board_init_f(unsigned long bootflag)
+{
+	for (;;)
+		;
+}
+
+inline void board_init_r(gd_t *id, ulong dest_addr)
+{
+	for (;;)
+		;
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
new file mode 100644
index 0000000..cfd6c4a
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX28 Battery measurement init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+#include "mxs_init.h"
+
+void mxs_lradc_init(void)
+{
+	struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE;
+
+	debug("SPL: Initialisating LRADC\n");
+
+	writel(LRADC_CTRL0_SFTRST, &regs->hw_lradc_ctrl0_clr);
+	writel(LRADC_CTRL0_CLKGATE, &regs->hw_lradc_ctrl0_clr);
+	writel(LRADC_CTRL0_ONCHIP_GROUNDREF, &regs->hw_lradc_ctrl0_clr);
+
+	clrsetbits_le32(&regs->hw_lradc_ctrl3,
+			LRADC_CTRL3_CYCLE_TIME_MASK,
+			LRADC_CTRL3_CYCLE_TIME_6MHZ);
+
+	clrsetbits_le32(&regs->hw_lradc_ctrl4,
+			LRADC_CTRL4_LRADC7SELECT_MASK |
+			LRADC_CTRL4_LRADC6SELECT_MASK,
+			LRADC_CTRL4_LRADC7SELECT_CHANNEL7 |
+			LRADC_CTRL4_LRADC6SELECT_CHANNEL10);
+}
+
+void mxs_lradc_enable_batt_measurement(void)
+{
+	struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE;
+
+	debug("SPL: Enabling LRADC battery measurement\n");
+
+	/* Check if the channel is present at all. */
+	if (!(readl(&regs->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) {
+		debug("SPL: LRADC channel 7 is not present - aborting\n");
+		return;
+	}
+
+	debug("SPL: LRADC channel 7 is present - configuring\n");
+
+	writel(LRADC_CTRL1_LRADC7_IRQ_EN, &regs->hw_lradc_ctrl1_clr);
+	writel(LRADC_CTRL1_LRADC7_IRQ, &regs->hw_lradc_ctrl1_clr);
+
+	clrsetbits_le32(&regs->hw_lradc_conversion,
+			LRADC_CONVERSION_SCALE_FACTOR_MASK,
+			LRADC_CONVERSION_SCALE_FACTOR_LI_ION);
+	writel(LRADC_CONVERSION_AUTOMATIC, &regs->hw_lradc_conversion_set);
+
+	/* Configure the channel. */
+	writel((1 << 7) << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET,
+		&regs->hw_lradc_ctrl2_clr);
+	writel(0xffffffff, &regs->hw_lradc_ch7_clr);
+	clrbits_le32(&regs->hw_lradc_ch7, LRADC_CH_NUM_SAMPLES_MASK);
+	writel(LRADC_CH_ACCUMULATE, &regs->hw_lradc_ch7_clr);
+
+	/* Schedule the channel. */
+	writel(1 << 7, &regs->hw_lradc_ctrl0_set);
+
+	/* Start the channel sampling. */
+	writel(((1 << 7) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) |
+		((1 << 3) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) |
+		100, &regs->hw_lradc_delay3);
+
+	writel(0xffffffff, &regs->hw_lradc_ch7_clr);
+	writel(LRADC_DELAY_KICK, &regs->hw_lradc_delay3_set);
+
+	debug("SPL: LRADC channel 7 configuration complete\n");
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
new file mode 100644
index 0000000..7818d72
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX28 RAM init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/compiler.h>
+
+#include "mxs_init.h"
+
+__weak uint32_t mxs_dram_vals[] = {
+/*
+ * i.MX28 DDR2 at 200MHz
+ */
+#if defined(CONFIG_MX28)
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00010101, 0x01010101,
+	0x000f0f01, 0x0f02020a, 0x00000000, 0x00010101,
+	0x00000100, 0x00000100, 0x00000000, 0x00000002,
+	0x01010000, 0x07080403, 0x06005003, 0x0a0000c8,
+	0x02009c40, 0x0002030c, 0x0036a609, 0x031a0612,
+	0x02030202, 0x00c8001c, 0x00000000, 0x00000000,
+	0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
+	0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
+	0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000612, 0x01000F02,
+	0x06120612, 0x00000200, 0x00020007, 0xf4004a27,
+	0xf4004a27, 0xf4004a27, 0xf4004a27, 0x07000300,
+	0x07000300, 0x07400300, 0x07400300, 0x00000005,
+	0x00000000, 0x00000000, 0x01000000, 0x01020408,
+	0x08040201, 0x000f1133, 0x00000000, 0x00001f04,
+	0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00001f04, 0x00001f04, 0x00001f04, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00010000, 0x00030404,
+	0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x01010000,
+	0x01000000, 0x03030000, 0x00010303, 0x01020202,
+	0x00000000, 0x02040303, 0x21002103, 0x00061200,
+	0x06120612, 0x04420442, 0x04420442, 0x00040004,
+	0x00040004, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0xffffffff
+
+/*
+ * i.MX23 DDR at 133MHz
+ */
+#elif defined(CONFIG_MX23)
+	0x01010001, 0x00010100, 0x01000101, 0x00000001,
+	0x00000101, 0x00000000, 0x00010000, 0x01000001,
+	0x00000000, 0x00000001, 0x07000200, 0x00070202,
+	0x02020000, 0x04040a01, 0x00000201, 0x02040000,
+	0x02000000, 0x19000f08, 0x0d0d0000, 0x02021313,
+	0x02061521, 0x0000000a, 0x00080008, 0x00200020,
+	0x00200020, 0x00200020, 0x000003f7, 0x00000000,
+	0x00000000, 0x00000020, 0x00000020, 0x00c80000,
+	0x000a23cd, 0x000000c8, 0x00006665, 0x00000000,
+	0x00000101, 0x00040001, 0x00000000, 0x00000000,
+	0x00010000
+#else
+#error Unsupported memory initialization
+#endif
+};
+
+__weak void mxs_adjust_memory_params(uint32_t *dram_vals)
+{
+	debug("SPL: Using default SDRAM parameters\n");
+}
+
+#ifdef CONFIG_MX28
+static void initialize_dram_values(void)
+{
+	int i;
+
+	debug("SPL: Setting mx28 board specific SDRAM parameters\n");
+	mxs_adjust_memory_params(mxs_dram_vals);
+
+	debug("SPL: Applying SDRAM parameters\n");
+	for (i = 0; i < ARRAY_SIZE(mxs_dram_vals); i++)
+		writel(mxs_dram_vals[i], MXS_DRAM_BASE + (4 * i));
+}
+#else
+static void initialize_dram_values(void)
+{
+	int i;
+
+	debug("SPL: Setting mx23 board specific SDRAM parameters\n");
+	mxs_adjust_memory_params(mxs_dram_vals);
+
+	/*
+	 * HW_DRAM_CTL27, HW_DRAM_CTL28 and HW_DRAM_CTL35 are not initialized as
+	 * per FSL bootlets code.
+	 *
+	 * mx23 Reference Manual marks HW_DRAM_CTL27 and HW_DRAM_CTL28 as
+	 * "reserved".
+	 * HW_DRAM_CTL8 is setup as the last element.
+	 * So skip the initialization of these HW_DRAM_CTL registers.
+	 */
+	debug("SPL: Applying SDRAM parameters\n");
+	for (i = 0; i < ARRAY_SIZE(mxs_dram_vals); i++) {
+		if (i == 8 || i == 27 || i == 28 || i == 35)
+			continue;
+		writel(mxs_dram_vals[i], MXS_DRAM_BASE + (4 * i));
+	}
+
+	/*
+	 * Enable tRAS lockout in HW_DRAM_CTL08 ; it must be the last
+	 * element to be set
+	 */
+	writel((1 << 24), MXS_DRAM_BASE + (4 * 8));
+}
+#endif
+
+static void mxs_mem_init_clock(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+#if defined(CONFIG_MX23)
+	/* Fractional divider for ref_emi is 33 ; 480 * 18 / 33 = 266MHz */
+	const unsigned char divider = 33;
+#elif defined(CONFIG_MX28)
+	/* Fractional divider for ref_emi is 21 ; 480 * 18 / 21 = 411MHz */
+	const unsigned char divider = 21;
+#endif
+
+	debug("SPL: Initialising FRAC0\n");
+
+	/* Gate EMI clock */
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
+
+	/* Set fractional divider for ref_emi */
+	writeb(CLKCTRL_FRAC_CLKGATE | (divider & CLKCTRL_FRAC_FRAC_MASK),
+		&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
+
+	/* Ungate EMI clock */
+	writeb(CLKCTRL_FRAC_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]);
+
+	early_delay(11000);
+
+	/* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */
+	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
+		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
+		&clkctrl_regs->hw_clkctrl_emi);
+
+	/* Unbypass EMI */
+	writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+
+	early_delay(10000);
+	debug("SPL: FRAC0 Initialised\n");
+}
+
+static void mxs_mem_setup_cpu_and_hbus(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	debug("SPL: Setting CPU and HBUS clock frequencies\n");
+
+	/* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz
+	 * and ungate CPU clock */
+	writeb(19 & CLKCTRL_FRAC_FRAC_MASK,
+		(uint8_t *)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
+
+	/* Set CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* HBUS = 151MHz */
+	writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
+	writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
+		&clkctrl_regs->hw_clkctrl_hbus_clr);
+
+	early_delay(10000);
+
+	/* CPU clock divider = 1 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
+			CLKCTRL_CPU_DIV_CPU_MASK, 1);
+
+	/* Disable CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+
+	early_delay(15000);
+}
+
+static void mxs_mem_setup_vdda(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Configuring VDDA\n");
+
+	writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vddactrl);
+}
+
+uint32_t mxs_mem_get_size(void)
+{
+	uint32_t sz, da;
+	uint32_t *vt = (uint32_t *)0x20;
+	/* The following is "subs pc, r14, #4", used as return from DABT. */
+	const uint32_t data_abort_memdetect_handler = 0xe25ef004;
+
+	/* Replace the DABT handler. */
+	da = vt[4];
+	vt[4] = data_abort_memdetect_handler;
+
+	sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+
+	/* Restore the old DABT handler. */
+	vt[4] = da;
+
+	return sz;
+}
+
+#ifdef CONFIG_MX23
+static void mx23_mem_setup_vddmem(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Setting mx23 VDDMEM\n");
+
+	/* We must wait before and after disabling the current limiter! */
+	early_delay(10000);
+
+	clrbits_le32(&power_regs->hw_power_vddmemctrl,
+		POWER_VDDMEMCTRL_ENABLE_ILIMIT);
+
+	early_delay(10000);
+
+}
+
+static void mx23_mem_init(void)
+{
+	debug("SPL: Initialising mx23 SDRAM Controller\n");
+
+	/*
+	 * Reset/ungate the EMI block. This is essential, otherwise the system
+	 * suffers from memory instability. This thing is mx23 specific and is
+	 * no longer present on mx28.
+	 */
+	mxs_reset_block((struct mxs_register_32 *)MXS_EMI_BASE);
+
+	mx23_mem_setup_vddmem();
+
+	/*
+	 * Configure the DRAM registers
+	 */
+
+	/* Clear START and SREFRESH bit from DRAM_CTL8 */
+	clrbits_le32(MXS_DRAM_BASE + 0x20, (1 << 16) | (1 << 8));
+
+	initialize_dram_values();
+
+	/* Set START bit in DRAM_CTL8 */
+	setbits_le32(MXS_DRAM_BASE + 0x20, 1 << 16);
+
+	clrbits_le32(MXS_DRAM_BASE + 0x40, 1 << 17);
+
+	/* Wait for EMI_STAT bit DRAM_HALTED */
+	for (;;) {
+		if (!(readl(MXS_EMI_BASE + 0x10) & (1 << 1)))
+			break;
+		early_delay(1000);
+	}
+
+	/* Adjust EMI port priority. */
+	clrsetbits_le32(0x80020000, 0x1f << 16, 0x2);
+	early_delay(20000);
+
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 19);
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 11);
+}
+#endif
+
+#ifdef CONFIG_MX28
+static void mx28_mem_init(void)
+{
+	struct mxs_pinctrl_regs *pinctrl_regs =
+		(struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE;
+
+	debug("SPL: Initialising mx28 SDRAM Controller\n");
+
+	/* Set DDR2 mode */
+	writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
+		&pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
+
+	/*
+	 * Configure the DRAM registers
+	 */
+
+	/* Clear START bit from DRAM_CTL16 */
+	clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	initialize_dram_values();
+
+	/* Clear SREFRESH bit from DRAM_CTL17 */
+	clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
+
+	/* Set START bit in DRAM_CTL16 */
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	/* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
+	while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
+		;
+}
+#endif
+
+void mxs_mem_init(void)
+{
+	early_delay(11000);
+
+	mxs_mem_init_clock();
+
+	mxs_mem_setup_vdda();
+
+#if defined(CONFIG_MX23)
+	mx23_mem_init();
+#elif defined(CONFIG_MX28)
+	mx28_mem_init();
+#endif
+
+	early_delay(10000);
+
+	mxs_mem_setup_cpu_and_hbus();
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
new file mode 100644
index 0000000..a5c528a
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
@@ -0,0 +1,1289 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX28 Boot PMIC init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+#include "mxs_init.h"
+
+#ifdef CONFIG_SYS_MXS_VDD5V_ONLY
+#define DCDC4P2_DROPOUT_CONFIG	POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
+				POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2
+#else
+#define DCDC4P2_DROPOUT_CONFIG	POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
+				POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL
+#endif
+/**
+ * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL
+ *
+ * This function switches the CPU core clock from PLL to 24MHz XTAL
+ * oscilator. This is necessary if the PLL is being reconfigured to
+ * prevent crash of the CPU core.
+ */
+static void mxs_power_clock2xtal(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	debug("SPL: Switching CPU clock to 24MHz XTAL\n");
+
+	/* Set XTAL as CPU reference clock */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+}
+
+/**
+ * mxs_power_clock2pll() - Switch CPU core clock source to PLL
+ *
+ * This function switches the CPU core clock from 24MHz XTAL oscilator
+ * to PLL. This can only be called once the PLL has re-locked and once
+ * the PLL is stable after reconfiguration.
+ */
+static void mxs_power_clock2pll(void)
+{
+	struct mxs_clkctrl_regs *clkctrl_regs =
+		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	debug("SPL: Switching CPU core clock source to PLL\n");
+
+	/*
+	 * TODO: Are we really? It looks like we turn on PLL0, but we then
+	 * set the CLKCTRL_CLKSEQ_BYPASS_CPU bit of the (which was already
+	 * set by mxs_power_clock2xtal()). Clearing this bit here seems to
+	 * introduce some instability (causing the CPU core to hang). Maybe
+	 * we aren't giving PLL0 enough time to stabilise?
+	 */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
+			CLKCTRL_PLL0CTRL0_POWER);
+	early_delay(100);
+
+	/*
+	 * TODO: Should the PLL0 FORCE_LOCK bit be set here followed be a
+	 * wait on the PLL0 LOCK bit?
+	 */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
+			CLKCTRL_CLKSEQ_BYPASS_CPU);
+}
+
+/**
+ * mxs_power_set_auto_restart() - Set the auto-restart bit
+ *
+ * This function ungates the RTC block and sets the AUTO_RESTART
+ * bit to work around a design bug on MX28EVK Rev. A .
+ */
+
+static void mxs_power_set_auto_restart(void)
+{
+	struct mxs_rtc_regs *rtc_regs =
+		(struct mxs_rtc_regs *)MXS_RTC_BASE;
+
+	debug("SPL: Setting auto-restart bit\n");
+
+	writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
+		;
+
+	writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
+		;
+
+	/* Do nothing if flag already set */
+	if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
+		return;
+
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+
+	setbits_le32(&rtc_regs->hw_rtc_persistent0,
+			RTC_PERSISTENT0_AUTO_RESTART);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
+		;
+}
+
+/**
+ * mxs_power_set_linreg() - Set linear regulators 25mV below DC-DC converter
+ *
+ * This function configures the VDDIO, VDDA and VDDD linear regulators output
+ * to be 25mV below the VDDIO, VDDA and VDDD output from the DC-DC switching
+ * converter. This is the recommended setting for the case where we use both
+ * linear regulators and DC-DC converter to power the VDDIO rail.
+ */
+static void mxs_power_set_linreg(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	/* Set linear regulator 25mV below switching converter */
+	debug("SPL: Setting VDDD 25mV below DC-DC converters\n");
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	debug("SPL: Setting VDDA 25mV below DC-DC converters\n");
+	clrsetbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_LINREG_OFFSET_MASK,
+			POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	debug("SPL: Setting VDDIO 25mV below DC-DC converters\n");
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
+}
+
+/**
+ * mxs_get_batt_volt() - Measure battery input voltage
+ *
+ * This function retrieves the battery input voltage and returns it.
+ */
+static int mxs_get_batt_volt(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	debug("SPL: Battery Voltage = %dmV\n", volt);
+	return volt;
+}
+
+/**
+ * mxs_is_batt_ready() - Test if the battery provides enough voltage to boot
+ *
+ * This function checks if the battery input voltage is higher than 3.6V and
+ * therefore allows the system to successfully boot using this power source.
+ */
+static int mxs_is_batt_ready(void)
+{
+	return (mxs_get_batt_volt() >= 3600);
+}
+
+/**
+ * mxs_is_batt_good() - Test if battery is operational at all
+ *
+ * This function starts recharging the battery and tests if the input current
+ * provided by the 5V input recharging the battery is also sufficient to power
+ * the DC-DC converter.
+ */
+static int mxs_is_batt_good(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t volt = mxs_get_batt_volt();
+
+	if ((volt >= 2400) && (volt <= 4300)) {
+		debug("SPL: Battery is good\n");
+		return 1;
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	clrsetbits_le32(&power_regs->hw_power_charge,
+		POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	early_delay(500000);
+
+	volt = mxs_get_batt_volt();
+
+	if (volt >= 3500) {
+		debug("SPL: Battery Voltage too high\n");
+		return 0;
+	}
+
+	if (volt >= 2400) {
+		debug("SPL: Battery is good\n");
+		return 1;
+	}
+
+	writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		&power_regs->hw_power_charge_clr);
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+	debug("SPL: Battery Voltage too low\n");
+	return 0;
+}
+
+/**
+ * mxs_power_setup_5v_detect() - Start the 5V input detection comparator
+ *
+ * This function enables the 5V detection comparator and sets the 5V valid
+ * threshold to 4.4V . We use 4.4V threshold here to make sure that even
+ * under high load, the voltage drop on the 5V input won't be so critical
+ * to cause undervolt on the 4P2 linear regulator supplying the DC-DC
+ * converter and thus making the system crash.
+ */
+static void mxs_power_setup_5v_detect(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	/* Start 5V detection */
+	debug("SPL: Starting 5V input detection comparator\n");
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK,
+			POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
+			POWER_5VCTRL_PWRUP_VBUS_CMPS);
+}
+
+/**
+ * mxs_power_switch_dcdc_clocksource() - Switch PLL clock for DC-DC converters
+ * @freqsel:	One of the POWER_MISC_FREQSEL_xxx defines to select the clock
+ *
+ * This function configures and then enables an alternative PLL clock source
+ * for the DC-DC converters.
+ */
+void mxs_power_switch_dcdc_clocksource(uint32_t freqsel)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	/* Select clocksource for DC-DC converters */
+	clrsetbits_le32(&power_regs->hw_power_misc,
+			POWER_MISC_FREQSEL_MASK,
+			freqsel);
+	setbits_le32(&power_regs->hw_power_misc,
+			POWER_MISC_SEL_PLLCLK);
+}
+
+/**
+ * mxs_power_setup_dcdc_clocksource() - Setup PLL clock source for DC-DC converters
+ *
+ * Normally, there is no need to switch DC-DC clocksource. This is the reason,
+ * why this function is a stub and does nothing. However, boards can implement
+ * this function when required and call mxs_power_switch_dcdc_clocksource() to
+ * switch to an alternative clock source.
+ */
+__weak void mxs_power_setup_dcdc_clocksource(void)
+{
+	debug("SPL: Using default DC-DC clocksource\n");
+}
+
+/**
+ * mxs_src_power_init() - Preconfigure the power block
+ *
+ * This function configures reasonable values for the DC-DC control loop
+ * and battery monitor.
+ */
+static void mxs_src_power_init(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Pre-Configuring power block\n");
+
+	/* Improve efficieny and reduce transient ripple */
+	writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
+		POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
+
+	clrsetbits_le32(&power_regs->hw_power_dclimits,
+			POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
+			0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
+
+	setbits_le32(&power_regs->hw_power_battmonitor,
+			POWER_BATTMONITOR_EN_BATADJ);
+
+	/* Increase the RCSCALE level for quick DCDC response to dynamic load */
+	clrsetbits_le32(&power_regs->hw_power_loopctrl,
+			POWER_LOOPCTRL_EN_RCSCALE_MASK,
+			POWER_LOOPCTRL_RCSCALE_THRESH |
+			POWER_LOOPCTRL_EN_RCSCALE_8X);
+
+	clrsetbits_le32(&power_regs->hw_power_minpwr,
+			POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+	/* 5V to battery handoff ... FIXME */
+	setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+	early_delay(30);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+}
+
+/**
+ * mxs_power_init_4p2_params() - Configure the parameters of the 4P2 regulator
+ *
+ * This function configures the necessary parameters for the 4P2 linear
+ * regulator to supply the DC-DC converter from 5V input.
+ */
+static void mxs_power_init_4p2_params(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Configuring common 4P2 regulator params\n");
+
+	/* Setup 4P2 parameters */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
+		POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_HEADROOM_ADJ_MASK,
+		0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
+
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_DROPOUT_CTRL_MASK,
+		DCDC4P2_DROPOUT_CONFIG);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+}
+
+/**
+ * mxs_enable_4p2_dcdc_input() - Enable or disable the DCDC input from 4P2
+ * @xfer:	Select if the input shall be enabled or disabled
+ *
+ * This function enables or disables the 4P2 input into the DC-DC converter.
+ */
+static void mxs_enable_4p2_dcdc_input(int xfer)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
+	uint32_t prev_5v_brnout, prev_5v_droop;
+
+	debug("SPL: %s 4P2 DC-DC Input\n", xfer ? "Enabling" : "Disabling");
+
+	if (xfer && (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+		return;
+	}
+
+	prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
+				POWER_5VCTRL_PWDN_5VBRNOUT;
+	prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
+				POWER_CTRL_ENIRQ_VDD5V_DROOP;
+
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+
+	clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
+
+	/*
+	 * Recording orignal values that will be modified temporarlily
+	 * to handle a chip bug. See chip errata for CQ ENGR00115837
+	 */
+	tmp = readl(&power_regs->hw_power_5vctrl);
+	vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
+	vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
+
+	pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
+
+	/*
+	 * Disable mechanisms that get erroneously tripped by when setting
+	 * the DCDC4P2 EN_DCDC
+	 */
+	clrbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_VBUSVALID_5VDETECT |
+		POWER_5VCTRL_VBUSVALID_TRSH_MASK);
+
+	writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
+
+	if (xfer) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+		early_delay(20);
+		clrbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_ENABLE_DCDC);
+	} else {
+		setbits_le32(&power_regs->hw_power_dcdc4p2,
+				POWER_DCDC4P2_ENABLE_DCDC);
+	}
+
+	early_delay(25);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
+
+	if (vbus_5vdetect)
+		writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
+
+	if (!pwd_bo)
+		clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
+		writel(POWER_CTRL_VBUS_VALID_IRQ,
+			&power_regs->hw_power_ctrl_clr);
+
+	if (prev_5v_brnout) {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_set);
+		writel(POWER_RESET_UNLOCK_KEY,
+			&power_regs->hw_power_reset);
+	} else {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+			&power_regs->hw_power_reset);
+	}
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
+		writel(POWER_CTRL_VDD5V_DROOP_IRQ,
+			&power_regs->hw_power_ctrl_clr);
+
+	if (prev_5v_droop)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+	else
+		setbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+}
+
+/**
+ * mxs_power_init_4p2_regulator() - Start the 4P2 regulator
+ *
+ * This function enables the 4P2 regulator and switches the DC-DC converter
+ * to use the 4P2 input.
+ */
+static void mxs_power_init_4p2_regulator(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, tmp2;
+
+	debug("SPL: Enabling 4P2 regulator\n");
+
+	setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
+
+	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
+
+	writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
+
+	/* Power up the 4p2 rail and logic/control */
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	/*
+	 * Start charging up the 4p2 capacitor. We ramp of this charge
+	 * gradually to avoid large inrush current from the 5V cable which can
+	 * cause transients/problems
+	 */
+	debug("SPL: Charging 4P2 capacitor\n");
+	mxs_enable_4p2_dcdc_input(0);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		/*
+		 * If we arrived here, we were unable to recover from mx23 chip
+		 * errata 5837. 4P2 is disabled and sufficient battery power is
+		 * not present. Exiting to not enable DCDC power during 5V
+		 * connected state.
+		 */
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+
+		debug("SPL: Unable to recover from mx23 errata 5837\n");
+		hang();
+	}
+
+	/*
+	 * Here we set the 4p2 brownout level to something very close to 4.2V.
+	 * We then check the brownout status. If the brownout status is false,
+	 * the voltage is already close to the target voltage of 4.2V so we
+	 * can go ahead and set the 4P2 current limit to our max target limit.
+	 * If the brownout status is true, we need to ramp us the current limit
+	 * so that we don't cause large inrush current issues. We step up the
+	 * current limit until the brownout status is false or until we've
+	 * reached our maximum defined 4p2 current limit.
+	 */
+	debug("SPL: Setting 4P2 brownout level\n");
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_BO_MASK,
+			22 << POWER_DCDC4P2_BO_OFFSET);	/* 4.15V */
+
+	if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+			0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	} else {
+		tmp = (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+		while (tmp < 0x3f) {
+			if (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DCDC_4P2_BO)) {
+				tmp = readl(&power_regs->hw_power_5vctrl);
+				tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				early_delay(100);
+				writel(tmp, &power_regs->hw_power_5vctrl);
+				break;
+			} else {
+				tmp++;
+				tmp2 = readl(&power_regs->hw_power_5vctrl);
+				tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				tmp2 |= tmp <<
+					POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+				writel(tmp2, &power_regs->hw_power_5vctrl);
+				early_delay(100);
+			}
+		}
+	}
+
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+}
+
+/**
+ * mxs_power_init_dcdc_4p2_source() - Switch DC-DC converter to 4P2 source
+ *
+ * This function configures the DC-DC converter to be supplied from the 4P2
+ * linear regulator.
+ */
+static void mxs_power_init_dcdc_4p2_source(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Switching DC-DC converters to 4P2\n");
+
+	if (!(readl(&power_regs->hw_power_dcdc4p2) &
+		POWER_DCDC4P2_ENABLE_DCDC)) {
+		debug("SPL: Already switched - aborting\n");
+		hang();
+	}
+
+	mxs_enable_4p2_dcdc_input(1);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_ENABLE_DCDC,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+	}
+}
+
+/**
+ * mxs_power_enable_4p2() - Power up the 4P2 regulator
+ *
+ * This function drives the process of powering up the 4P2 linear regulator
+ * and switching the DC-DC converter input over to the 4P2 linear regulator.
+ */
+static void mxs_power_enable_4p2(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t vdddctrl, vddactrl, vddioctrl;
+	uint32_t tmp;
+
+	debug("SPL: Powering up 4P2 regulator\n");
+
+	vdddctrl = readl(&power_regs->hw_power_vdddctrl);
+	vddactrl = readl(&power_regs->hw_power_vddactrl);
+	vddioctrl = readl(&power_regs->hw_power_vddioctrl);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+		POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+		POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+		POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
+
+	mxs_power_init_4p2_params();
+	mxs_power_init_4p2_regulator();
+
+	/* Shutdown battery (none present) */
+	if (!mxs_is_batt_ready()) {
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+				POWER_DCDC4P2_BO_MASK);
+		writel(POWER_CTRL_DCDC4P2_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+		writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
+				&power_regs->hw_power_ctrl_clr);
+	}
+
+	mxs_power_init_dcdc_4p2_source();
+
+	writel(vdddctrl, &power_regs->hw_power_vdddctrl);
+	early_delay(20);
+	writel(vddactrl, &power_regs->hw_power_vddactrl);
+	early_delay(20);
+	writel(vddioctrl, &power_regs->hw_power_vddioctrl);
+
+	/*
+	 * Check if FET is enabled on either powerout and if so,
+	 * disable load.
+	 */
+	tmp = 0;
+	tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
+			POWER_VDDDCTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddactrl) &
+			POWER_VDDACTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
+			POWER_VDDIOCTRL_DISABLE_FET);
+	if (tmp)
+		writel(POWER_CHARGE_ENABLE_LOAD,
+			&power_regs->hw_power_charge_clr);
+
+	debug("SPL: 4P2 regulator powered-up\n");
+}
+
+/**
+ * mxs_boot_valid_5v() - Boot from 5V supply
+ *
+ * This function configures the power block to boot from valid 5V input.
+ * This is called only if the 5V is reliable and can properly supply the
+ * CPU. This function proceeds to configure the 4P2 converter to be supplied
+ * from the 5V input.
+ */
+static void mxs_boot_valid_5v(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Booting from 5V supply\n");
+
+	/*
+	 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
+	 * disconnect event. FIXME
+	 */
+	writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
+		&power_regs->hw_power_5vctrl_set);
+
+	/* Configure polarity to check for 5V disconnection. */
+	writel(POWER_CTRL_POLARITY_VBUSVALID |
+		POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
+		&power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
+		&power_regs->hw_power_ctrl_clr);
+
+	mxs_power_enable_4p2();
+}
+
+/**
+ * mxs_powerdown() - Shut down the system
+ *
+ * This function powers down the CPU completely.
+ */
+static void mxs_powerdown(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("Powering Down\n");
+
+	writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+}
+
+/**
+ * mxs_batt_boot() - Configure the power block to boot from battery input
+ *
+ * This function configures the power block to boot from the battery voltage
+ * supply.
+ */
+static void mxs_batt_boot(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Configuring power block to boot from battery\n");
+
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
+
+	clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
+	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
+
+	/* 5V to battery handoff. */
+	setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+	early_delay(30);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+
+	writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+	clrsetbits_le32(&power_regs->hw_power_minpwr,
+			POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+	mxs_power_set_linreg();
+
+	clrbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
+
+	clrbits_le32(&power_regs->hw_power_vddactrl,
+		POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
+
+	clrbits_le32(&power_regs->hw_power_vddioctrl,
+		POWER_VDDIOCTRL_DISABLE_FET);
+
+	setbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
+
+	setbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_ENABLE_DCDC);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+
+	mxs_power_enable_4p2();
+}
+
+/**
+ * mxs_handle_5v_conflict() - Test if the 5V input is reliable
+ *
+ * This function tests if the 5V input can reliably supply the system. If it
+ * can, then proceed to configuring the system to boot from 5V source, otherwise
+ * try booting from battery supply. If we can not boot from battery supply
+ * either, shut down the system.
+ */
+static void mxs_handle_5v_conflict(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	debug("SPL: Resolving 5V conflict\n");
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_BO_OFFSET_MASK);
+
+	for (;;) {
+		tmp = readl(&power_regs->hw_power_sts);
+
+		if (tmp & POWER_STS_VDDIO_BO) {
+			/*
+			 * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
+			 * unreliable
+			 */
+			debug("SPL: VDDIO has a brownout\n");
+			mxs_powerdown();
+			break;
+		}
+
+		if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+			debug("SPL: POWER_STS_VDD5V_GT_VDDIO is set\n");
+			mxs_boot_valid_5v();
+			break;
+		} else {
+			debug("SPL: POWER_STS_VDD5V_GT_VDDIO is not set\n");
+			mxs_powerdown();
+			break;
+		}
+
+		/*
+		 * TODO: I can't see this being reached. We'll either
+		 * powerdown or boot from a stable 5V supply.
+		 */
+		if (tmp & POWER_STS_PSWITCH_MASK) {
+			debug("SPL: POWER_STS_PSWITCH_MASK is set\n");
+			mxs_batt_boot();
+			break;
+		}
+	}
+}
+
+/**
+ * mxs_5v_boot() - Configure the power block to boot from 5V input
+ *
+ * This function handles configuration of the power block when supplied by
+ * a 5V input.
+ */
+static void mxs_5v_boot(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Configuring power block to boot from 5V input\n");
+
+	/*
+	 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
+	 * but their implementation always returns 1 so we omit it here.
+	 */
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		debug("SPL: 5V VDD good\n");
+		mxs_boot_valid_5v();
+		return;
+	}
+
+	early_delay(1000);
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		debug("SPL: 5V VDD good (after delay)\n");
+		mxs_boot_valid_5v();
+		return;
+	}
+
+	debug("SPL: 5V VDD not good\n");
+	mxs_handle_5v_conflict();
+}
+
+/**
+ * mxs_init_batt_bo() - Configure battery brownout threshold
+ *
+ * This function configures the battery input brownout threshold. The value
+ * at which the battery brownout happens is configured to 3.0V in the code.
+ */
+static void mxs_init_batt_bo(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Initialising battery brown-out level to 3.0V\n");
+
+	/* Brownout at 3V */
+	clrsetbits_le32(&power_regs->hw_power_battmonitor,
+		POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
+		15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+
+	writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+}
+
+/**
+ * mxs_switch_vddd_to_dcdc_source() - Switch VDDD rail to DC-DC converter
+ *
+ * This function turns off the VDDD linear regulator and therefore makes
+ * the VDDD rail be supplied only by the DC-DC converter.
+ */
+static void mxs_switch_vddd_to_dcdc_source(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Switching VDDD to DC-DC converters\n");
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_DISABLE_STEPPING);
+}
+
+/**
+ * mxs_power_configure_power_source() - Configure power block source
+ *
+ * This function is the core of the power configuration logic. The function
+ * selects the power block input source and configures the whole power block
+ * accordingly. After the configuration is complete and the system is stable
+ * again, the function switches the CPU clock source back to PLL. Finally,
+ * the function switches the voltage rails to DC-DC converter.
+ */
+static void mxs_power_configure_power_source(void)
+{
+	int batt_ready, batt_good;
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	struct mxs_lradc_regs *lradc_regs =
+		(struct mxs_lradc_regs *)MXS_LRADC_BASE;
+
+	debug("SPL: Configuring power source\n");
+
+	mxs_power_setup_dcdc_clocksource();
+	mxs_src_power_init();
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		batt_ready = mxs_is_batt_ready();
+		if (batt_ready) {
+			/* 5V source detected, good battery detected. */
+			mxs_batt_boot();
+		} else {
+			batt_good = mxs_is_batt_good();
+			if (!batt_good) {
+				/* 5V source detected, bad battery detected. */
+				writel(LRADC_CONVERSION_AUTOMATIC,
+					&lradc_regs->hw_lradc_conversion_clr);
+				clrbits_le32(&power_regs->hw_power_battmonitor,
+					POWER_BATTMONITOR_BATT_VAL_MASK);
+			}
+			mxs_5v_boot();
+		}
+	} else {
+		/* 5V not detected, booting from battery. */
+		mxs_batt_boot();
+	}
+
+	/*
+	 * TODO: Do not switch CPU clock to PLL if we are VDD5V is sourced
+	 * from USB VBUS
+	 */
+	mxs_power_clock2pll();
+
+	mxs_init_batt_bo();
+
+	mxs_switch_vddd_to_dcdc_source();
+
+#ifdef CONFIG_MX23
+	/* Fire up the VDDMEM LinReg now that we're all set. */
+	debug("SPL: Enabling mx23 VDDMEM linear regulator\n");
+	writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT,
+		&power_regs->hw_power_vddmemctrl);
+#endif
+}
+
+/**
+ * mxs_enable_output_rail_protection() - Enable power rail protection
+ *
+ * This function enables overload protection on the power rails. This is
+ * triggered if the power rails' voltage drops rapidly due to overload and
+ * in such case, the supply to the powerrail is cut-off, protecting the
+ * CPU from damage. Note that under such condition, the system will likely
+ * crash or misbehave.
+ */
+static void mxs_enable_output_rail_protection(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Enabling output rail protection\n");
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_PWDN_BRNOUT);
+}
+
+/**
+ * mxs_get_vddio_power_source_off() - Get VDDIO rail power source
+ *
+ * This function tests if the VDDIO rail is supplied by linear regulator
+ * or by the DC-DC converter. Returns 1 if powered by linear regulator,
+ * returns 0 if powered by the DC-DC converter.
+ */
+static int mxs_get_vddio_power_source_off(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		tmp = readl(&power_regs->hw_power_vddioctrl);
+		if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+
+}
+
+/**
+ * mxs_get_vddd_power_source_off() - Get VDDD rail power source
+ *
+ * This function tests if the VDDD rail is supplied by linear regulator
+ * or by the DC-DC converter. Returns 1 if powered by linear regulator,
+ * returns 0 if powered by the DC-DC converter.
+ */
+static int mxs_get_vddd_power_source_off(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&power_regs->hw_power_vdddctrl);
+	if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+			return 1;
+		}
+	}
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			return 1;
+		}
+	}
+
+	if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+struct mxs_vddx_cfg {
+	uint32_t		*reg;
+	uint8_t			step_mV;
+	uint16_t		lowest_mV;
+	int			(*powered_by_linreg)(void);
+	uint32_t		trg_mask;
+	uint32_t		bo_irq;
+	uint32_t		bo_enirq;
+	uint32_t		bo_offset_mask;
+	uint32_t		bo_offset_offset;
+};
+
+static const struct mxs_vddx_cfg mxs_vddio_cfg = {
+	.reg			= &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+					hw_power_vddioctrl),
+#if defined(CONFIG_MX23)
+	.step_mV		= 25,
+#else
+	.step_mV		= 50,
+#endif
+	.lowest_mV		= 2800,
+	.powered_by_linreg	= mxs_get_vddio_power_source_off,
+	.trg_mask		= POWER_VDDIOCTRL_TRG_MASK,
+	.bo_irq			= POWER_CTRL_VDDIO_BO_IRQ,
+	.bo_enirq		= POWER_CTRL_ENIRQ_VDDIO_BO,
+	.bo_offset_mask		= POWER_VDDIOCTRL_BO_OFFSET_MASK,
+	.bo_offset_offset	= POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
+};
+
+static const struct mxs_vddx_cfg mxs_vddd_cfg = {
+	.reg			= &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+					hw_power_vdddctrl),
+	.step_mV		= 25,
+	.lowest_mV		= 800,
+	.powered_by_linreg	= mxs_get_vddd_power_source_off,
+	.trg_mask		= POWER_VDDDCTRL_TRG_MASK,
+	.bo_irq			= POWER_CTRL_VDDD_BO_IRQ,
+	.bo_enirq		= POWER_CTRL_ENIRQ_VDDD_BO,
+	.bo_offset_mask		= POWER_VDDDCTRL_BO_OFFSET_MASK,
+	.bo_offset_offset	= POWER_VDDDCTRL_BO_OFFSET_OFFSET,
+};
+
+#ifdef CONFIG_MX23
+static const struct mxs_vddx_cfg mxs_vddmem_cfg = {
+	.reg			= &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+					hw_power_vddmemctrl),
+	.step_mV		= 50,
+	.lowest_mV		= 1700,
+	.powered_by_linreg	= NULL,
+	.trg_mask		= POWER_VDDMEMCTRL_TRG_MASK,
+	.bo_irq			= 0,
+	.bo_enirq		= 0,
+	.bo_offset_mask		= 0,
+	.bo_offset_offset	= 0,
+};
+#endif
+
+/**
+ * mxs_power_set_vddx() - Configure voltage on DC-DC converter rail
+ * @cfg:		Configuration data of the DC-DC converter rail
+ * @new_target:		New target voltage of the DC-DC converter rail
+ * @new_brownout:	New brownout trigger voltage
+ *
+ * This function configures the output voltage on the DC-DC converter rail.
+ * The rail is selected by the @cfg argument. The new voltage target is
+ * selected by the @new_target and the voltage is specified in mV. The
+ * new brownout value is selected by the @new_brownout argument and the
+ * value is also in mV.
+ */
+static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
+				uint32_t new_target, uint32_t new_brownout)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+	int adjust_up, tmp;
+
+	new_brownout = DIV_ROUND_CLOSEST(new_target - new_brownout,
+					 cfg->step_mV);
+
+	cur_target = readl(cfg->reg);
+	cur_target &= cfg->trg_mask;
+	cur_target *= cfg->step_mV;
+	cur_target += cfg->lowest_mV;
+
+	adjust_up = new_target > cur_target;
+	if (cfg->powered_by_linreg)
+		powered_by_linreg = cfg->powered_by_linreg();
+
+	if (adjust_up && cfg->bo_irq) {
+		if (powered_by_linreg) {
+			bo_int = readl(cfg->reg);
+			clrbits_le32(cfg->reg, cfg->bo_enirq);
+		}
+		setbits_le32(cfg->reg, cfg->bo_offset_mask);
+	}
+
+	do {
+		if (abs(new_target - cur_target) > 100) {
+			if (adjust_up)
+				diff = cur_target + 100;
+			else
+				diff = cur_target - 100;
+		} else {
+			diff = new_target;
+		}
+
+		diff -= cfg->lowest_mV;
+		diff /= cfg->step_mV;
+
+		clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
+
+		if (powered_by_linreg ||
+			(readl(&power_regs->hw_power_sts) &
+				POWER_STS_VDD5V_GT_VDDIO))
+			early_delay(500);
+		else {
+			for (;;) {
+				tmp = readl(&power_regs->hw_power_sts);
+				if (tmp & POWER_STS_DC_OK)
+					break;
+			}
+		}
+
+		cur_target = readl(cfg->reg);
+		cur_target &= cfg->trg_mask;
+		cur_target *= cfg->step_mV;
+		cur_target += cfg->lowest_mV;
+	} while (new_target > cur_target);
+
+	if (cfg->bo_irq) {
+		if (adjust_up && powered_by_linreg) {
+			writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
+			if (bo_int & cfg->bo_enirq)
+				setbits_le32(cfg->reg, cfg->bo_enirq);
+		}
+
+		clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
+				new_brownout << cfg->bo_offset_offset);
+	}
+}
+
+/**
+ * mxs_setup_batt_detect() - Start the battery voltage measurement logic
+ *
+ * This function starts and configures the LRADC block. This allows the
+ * power initialization code to measure battery voltage and based on this
+ * knowledge, decide whether to boot at all, boot from battery or boot
+ * from 5V input.
+ */
+static void mxs_setup_batt_detect(void)
+{
+	debug("SPL: Starting battery voltage measurement logic\n");
+
+	mxs_lradc_init();
+	mxs_lradc_enable_batt_measurement();
+	early_delay(10);
+}
+
+/**
+ * mxs_ungate_power() - Ungate the POWER block
+ *
+ * This function ungates clock to the power block. In case the power block
+ * was still gated at this point, it will not be possible to configure the
+ * block and therefore the power initialization would fail. This function
+ * is only needed on i.MX233, on i.MX28 the power block is always ungated.
+ */
+static void mxs_ungate_power(void)
+{
+#ifdef CONFIG_MX23
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr);
+#endif
+}
+
+/**
+ * mxs_power_init() - The power block init main function
+ *
+ * This function calls all the power block initialization functions in
+ * proper sequence to start the power block.
+ */
+void mxs_power_init(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Initialising Power Block\n");
+
+	mxs_ungate_power();
+
+	mxs_power_clock2xtal();
+	mxs_power_set_auto_restart();
+	mxs_power_set_linreg();
+	mxs_power_setup_5v_detect();
+
+	mxs_setup_batt_detect();
+
+	mxs_power_configure_power_source();
+	mxs_enable_output_rail_protection();
+
+	debug("SPL: Setting VDDIO to 3V3 (brownout @ 3v15)\n");
+	mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
+
+	debug("SPL: Setting VDDD to 1V5 (brownout @ 1v315)\n");
+	mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1315);
+#ifdef CONFIG_MX23
+	debug("SPL: Setting mx23 VDDMEM to 2V5 (brownout @ 1v7)\n");
+	mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700);
+#endif
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
+		POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
+		POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
+
+	early_delay(1000);
+}
+
+#ifdef	CONFIG_SPL_MXS_PSWITCH_WAIT
+/**
+ * mxs_power_wait_pswitch() - Wait for power switch to be pressed
+ *
+ * This function waits until the power-switch was pressed to start booting
+ * the board.
+ */
+void mxs_power_wait_pswitch(void)
+{
+	struct mxs_power_regs *power_regs =
+		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("SPL: Waiting for power switch input\n");
+	while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
+		;
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/mxs/start.S b/arch/arm/cpu/arm926ejs/mxs/start.S
new file mode 100644
index 0000000..adec2c8
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/start.S
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Groger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Zupke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ *
+ * Change to support call back into iMX28 bootrom
+ * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <common.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+reset:
+	/*
+	 * If the CPU is configured in "Wait JTAG connection mode", the stack
+	 * pointer is not configured and is zero. This will cause crash when
+	 * trying to push data onto stack right below here. Load the SP and make
+	 * it point to the end of OCRAM if the SP is zero.
+	 */
+	cmp	sp, #0x00000000
+	ldreq	sp, =CONFIG_SYS_INIT_SP_ADDR
+
+	/*
+	 * Store all registers on old stack pointer, this will allow us later to
+	 * return to the BootROM and let the BootROM load U-Boot into RAM.
+	 *
+	 * WARNING: Register r0 and r1 are used by the BootROM to pass data
+	 *          to the called code. Register r0 will contain arbitrary
+	 *          data that are set in the BootStream. In case this code
+	 *          was started with CALL instruction, register r1 will contain
+	 *          pointer to the return value this function can then set.
+	 *          The code below MUST NOT CHANGE register r0 and r1 !
+	 */
+	push	{r0-r12,r14}
+
+	/* Save control register c1 */
+	mrc	p15, 0, r2, c1, c0, 0
+	push	{r2}
+
+	/* Set the cpu to SVC32 mode and store old CPSR register content. */
+	mrs	r2, cpsr
+	push	{r2}
+	bic	r2, r2, #0x1f
+	orr	r2, r2, #0xd3
+	msr	cpsr, r2
+
+	bl	board_init_ll
+
+	/* Restore BootROM's CPU mode (especially FIQ). */
+	pop	{r2}
+	msr	cpsr,r2
+
+	/*
+	 * Restore c1 register. Especially set exception vector location
+	 * back to BootROM space which is required by bootrom for USB boot.
+	 */
+	pop	{r2}
+	mcr	p15, 0, r2, c1, c0, 0
+
+	pop	{r0-r12,r14}
+
+	/*
+	 * In case this code was started by the CALL instruction, the register
+	 * r0 is examined by the BootROM after this code returns. The value in
+	 * r0 must be set to 0 to indicate successful return.
+	 */
+	mov r0, #0
+
+	bx	lr
diff --git a/arch/arm/cpu/arm926ejs/mxs/timer.c b/arch/arm/cpu/arm926ejs/mxs/timer.c
new file mode 100644
index 0000000..7492ba4
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/timer.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* Maximum fixed count */
+#if defined(CONFIG_MX23)
+#define TIMER_LOAD_VAL 0xffff
+#elif defined(CONFIG_MX28)
+#define TIMER_LOAD_VAL 0xffffffff
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->arch.tbl)
+#define lastdec (gd->arch.lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MXS_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MXS_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mxs_timrot_regs *timrot_regs =
+		(struct mxs_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mxs_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+#if defined(CONFIG_MX23)
+	writel(0, &timrot_regs->hw_timrot_timcount0);
+#elif defined(CONFIG_MX28)
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+#endif
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+#if defined(CONFIG_MX23)
+	writel(TIMER_LOAD_VAL - 1, &timrot_regs->hw_timrot_timcount0);
+#elif defined(CONFIG_MX28)
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+#endif
+
+	return 0;
+}
+
+unsigned long long get_ticks(void)
+{
+	struct mxs_timrot_regs *timrot_regs =
+		(struct mxs_timrot_regs *)MXS_TIMROT_BASE;
+	uint32_t now;
+
+	/* Current tick value */
+#if defined(CONFIG_MX23)
+	/* Upper bits are the valid ones. */
+	now = readl(&timrot_regs->hw_timrot_timcount0) >>
+		TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET;
+#elif defined(CONFIG_MX28)
+	now = readl(&timrot_regs->hw_timrot_running_count0);
+#else
+#error "Don't know how to read timrot_regs"
+#endif
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return timestamp;
+}
+
+ulong get_timer(ulong base)
+{
+	return tick_to_time(get_ticks()) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MXS_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MXS_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MXS_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
+
+ulong get_tbclk(void)
+{
+	return MXS_INCREMENTER_HZ;
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd
new file mode 100644
index 0000000..3a51879
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd
@@ -0,0 +1,18 @@
+options {
+	driveTag = 0x00;
+	flags = 0x01;
+}
+
+sources {
+	u_boot_spl="spl/u-boot-spl.bin";
+	u_boot="u-boot.bin";
+}
+
+section (0) {
+	load u_boot_spl > 0x0000;
+	load ivt (entry = 0x0014) > 0x8000;
+	call 0x8000;
+
+	load u_boot > 0x40000100;
+	call 0x40000100;
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd
new file mode 100644
index 0000000..c60615a
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd
@@ -0,0 +1,14 @@
+sources {
+	u_boot_spl="spl/u-boot-spl.bin";
+	u_boot="u-boot.bin";
+}
+
+section (0) {
+	load u_boot_spl > 0x0000;
+	load ivt (entry = 0x0014) > 0x8000;
+	hab call 0x8000;
+
+	load u_boot > 0x40000100;
+	load ivt (entry = 0x40000100) > 0x8000;
+	hab call 0x8000;
+}
diff --git a/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds
new file mode 100644
index 0000000..ffc70ce
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = CONFIG_SPL_TEXT_BASE;
+
+	. = ALIGN(4);
+	.text	:
+	{
+		*(.vectors)
+		arch/arm/cpu/arm926ejs/mxs/start.o	(.text*)
+		*(.text*)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data*)
+	}
+
+	. = ALIGN(4);
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.bss : {
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	}
+
+	.end :
+	{
+		*(.__end)
+	}
+
+	_image_binary_end = .;
+
+	.dynsym _image_binary_end : { *(.dynsym) }
+	.dynbss : { *(.dynbss) }
+	.dynstr : { *(.dynstr*) }
+	.dynamic : { *(.dynamic*) }
+	.hash : { *(.hash*) }
+	.plt : { *(.plt*) }
+	.interp : { *(.interp*) }
+	.gnu : { *(.gnu*) }
+	.ARM.exidx : { *(.ARM.exidx*) }
+}
diff --git a/arch/arm/cpu/arm926ejs/orion5x/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/orion5x/u-boot-spl.lds
new file mode 100644
index 0000000..fbdb1d7
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/orion5x/u-boot-spl.lds
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014 Albert ARIBAUD <albert.u.boot@aribaud.net>
+ *
+ * Based on:
+ *
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Based on omap-common/u-boot-spl.lds:
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *	Aneesh V <aneesh@ti.com>
+ */
+MEMORY { .nor : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+		LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .bss : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	.text      :
+	{
+		__start = .;
+		*(.vectors)
+		CPUDIR/start.o	(.text)
+		*(.text*)
+	} > .nor
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.nor
+
+	. = ALIGN(4);
+	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.nor
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	} > .nor
+
+	. = ALIGN(4);
+	__image_copy_end = .;
+	_end = .;
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} > .bss
+}
diff --git a/arch/arm/cpu/arm926ejs/spear/Makefile b/arch/arm/cpu/arm926ejs/spear/Makefile
new file mode 100644
index 0000000..b1b6b40
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/Makefile
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y	:= cpu.o \
+	   reset.o \
+	   timer.o
+
+ifdef CONFIG_SPL_BUILD
+obj-y	+= spl.o
+obj-$(CONFIG_SPEAR600) += spear600.o
+obj-$(CONFIG_DDR_MT47H64M16) += spr600_mt47h64m16_3_333_cl5_psync.o
+obj-$(CONFIG_DDR_MT47H32M16) += spr600_mt47h32m16_333_cl5_psync.o
+obj-$(CONFIG_DDR_MT47H32M16) += spr600_mt47h32m16_37e_166_cl4_sync.o
+obj-$(CONFIG_DDR_MT47H128M8) += spr600_mt47h128m8_3_266_cl5_async.o
+else
+obj-y += spr_misc.o spr_lowlevel_init.o
+endif
+
+extra-$(CONFIG_SPL_BUILD) := start.o
diff --git a/arch/arm/cpu/arm926ejs/spear/cpu.c b/arch/arm/cpu/arm926ejs/spear/cpu.c
new file mode 100644
index 0000000..51c4a73
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/cpu.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spr_misc.h>
+
+int arch_cpu_init(void)
+{
+	struct misc_regs *const misc_p =
+	    (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+	u32 periph1_clken, periph_clk_cfg;
+
+	periph1_clken = readl(&misc_p->periph1_clken);
+
+#if defined(CONFIG_SPEAR3XX)
+	periph1_clken |= MISC_GPT2ENB;
+#elif defined(CONFIG_SPEAR600)
+	periph1_clken |= MISC_GPT3ENB;
+#endif
+
+#if defined(CONFIG_PL011_SERIAL)
+	periph1_clken |= MISC_UART0ENB;
+
+	periph_clk_cfg = readl(&misc_p->periph_clk_cfg);
+	periph_clk_cfg &= ~CONFIG_SPEAR_UARTCLKMSK;
+	periph_clk_cfg |= CONFIG_SPEAR_UART48M;
+	writel(periph_clk_cfg, &misc_p->periph_clk_cfg);
+#endif
+#if defined(CONFIG_ETH_DESIGNWARE)
+	periph1_clken |= MISC_ETHENB;
+#endif
+#if defined(CONFIG_DW_UDC)
+	periph1_clken |= MISC_USBDENB;
+#endif
+#if defined(CONFIG_SYS_I2C_DW)
+	periph1_clken |= MISC_I2CENB;
+#endif
+#if defined(CONFIG_ST_SMI)
+	periph1_clken |= MISC_SMIENB;
+#endif
+#if defined(CONFIG_NAND_FSMC)
+	periph1_clken |= MISC_FSMCENB;
+#endif
+#if defined(CONFIG_USB_EHCI_SPEAR)
+	periph1_clken |= PERIPH_USBH1 | PERIPH_USBH2;
+#endif
+#if defined(CONFIG_SPEAR_GPIO)
+	periph1_clken |= MISC_GPIO3ENB | MISC_GPIO4ENB;
+#endif
+#if defined(CONFIG_PL022_SPI)
+	periph1_clken |= MISC_SSP1ENB | MISC_SSP2ENB | MISC_SSP3ENB;
+#endif
+
+	writel(periph1_clken, &misc_p->periph1_clken);
+
+	return 0;
+}
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+int print_cpuinfo(void)
+{
+#ifdef CONFIG_SPEAR300
+	printf("CPU:   SPEAr300\n");
+#elif defined(CONFIG_SPEAR310)
+	printf("CPU:   SPEAr310\n");
+#elif defined(CONFIG_SPEAR320)
+	printf("CPU:   SPEAr320\n");
+#elif defined(CONFIG_SPEAR600)
+	printf("CPU:   SPEAr600\n");
+#else
+#error CPU not supported in spear platform
+#endif
+	return 0;
+}
+#endif
+
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_NAND_ECC_BCH) && defined(CONFIG_NAND_FSMC)
+static int do_switch_ecc(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char *const argv[])
+{
+	if (argc != 2)
+		goto usage;
+
+	if (strncmp(argv[1], "hw", 2) == 0) {
+		/* 1-bit HW ECC */
+		printf("Switching to 1-bit HW ECC\n");
+		fsmc_nand_switch_ecc(1);
+	} else if (strncmp(argv[1], "bch4", 2) == 0) {
+		/* 4-bit SW ECC BCH4 */
+		printf("Switching to 4-bit SW ECC (BCH4)\n");
+		fsmc_nand_switch_ecc(4);
+	} else {
+		goto usage;
+	}
+
+	return 0;
+
+usage:
+	printf("Usage: nandecc %s\n", cmdtp->usage);
+	return 1;
+}
+
+U_BOOT_CMD(
+	nandecc, 2, 0,	do_switch_ecc,
+	"switch NAND ECC calculation algorithm",
+	"hw|bch4 - Switch between NAND hardware 1-bit HW and"
+	" 4-bit SW BCH\n"
+);
+#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/reset.c b/arch/arm/cpu/arm926ejs/spear/reset.c
new file mode 100644
index 0000000..05c7ecd
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/reset.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spr_syscntl.h>
+
+void reset_cpu(ulong ignored)
+{
+	struct syscntl_regs *syscntl_regs_p =
+	    (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE;
+
+	printf("System is going to reboot ...\n");
+
+	/*
+	 * This 1 second delay will allow the above message
+	 * to be printed before reset
+	 */
+	udelay((1000 * 1000));
+
+	/* Going into slow mode before resetting SOC */
+	writel(0x02, &syscntl_regs_p->scctrl);
+
+	/*
+	 * Writing any value to the system status register will
+	 * reset the SoC
+	 */
+	writel(0x00, &syscntl_regs_p->scsysstat);
+
+	/* system will restart */
+	while (1)
+		;
+}
diff --git a/arch/arm/cpu/arm926ejs/spear/spear600.c b/arch/arm/cpu/arm926ejs/spear/spear600.c
new file mode 100644
index 0000000..b31ede5
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spear600.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Viresh Kumar, ST Microelectronics, viresh.kumar@st.com
+ * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com
+ */
+
+#include <common.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/spr_misc.h>
+#include <asm/arch/spr_defs.h>
+
+void spear_late_init(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+
+	writel(0x80000007, &misc_p->arb_icm_ml1);
+	writel(0x80000007, &misc_p->arb_icm_ml2);
+	writel(0x80000007, &misc_p->arb_icm_ml3);
+	writel(0x80000007, &misc_p->arb_icm_ml4);
+	writel(0x80000007, &misc_p->arb_icm_ml5);
+	writel(0x80000007, &misc_p->arb_icm_ml6);
+	writel(0x80000007, &misc_p->arb_icm_ml7);
+	writel(0x80000007, &misc_p->arb_icm_ml8);
+	writel(0x80000007, &misc_p->arb_icm_ml9);
+}
+
+static void sel_1v8(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+	u32 ddr1v8, ddr2v5;
+
+	ddr2v5 = readl(&misc_p->ddr_2v5_compensation);
+	ddr2v5 &= 0x8080ffc0;
+	ddr2v5 |= 0x78000003;
+	writel(ddr2v5, &misc_p->ddr_2v5_compensation);
+
+	ddr1v8 = readl(&misc_p->ddr_1v8_compensation);
+	ddr1v8 &= 0x8080ffc0;
+	ddr1v8 |= 0x78000010;
+	writel(ddr1v8, &misc_p->ddr_1v8_compensation);
+
+	while (!(readl(&misc_p->ddr_1v8_compensation) & DDR_COMP_ACCURATE))
+		;
+}
+
+static void sel_2v5(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+	u32 ddr1v8, ddr2v5;
+
+	ddr1v8 = readl(&misc_p->ddr_1v8_compensation);
+	ddr1v8 &= 0x8080ffc0;
+	ddr1v8 |= 0x78000003;
+	writel(ddr1v8, &misc_p->ddr_1v8_compensation);
+
+	ddr2v5 = readl(&misc_p->ddr_2v5_compensation);
+	ddr2v5 &= 0x8080ffc0;
+	ddr2v5 |= 0x78000010;
+	writel(ddr2v5, &misc_p->ddr_2v5_compensation);
+
+	while (!(readl(&misc_p->ddr_2v5_compensation) & DDR_COMP_ACCURATE))
+		;
+}
+
+/*
+ * plat_ddr_init:
+ */
+void plat_ddr_init(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+	u32 ddrpad;
+	u32 core3v3, ddr1v8, ddr2v5;
+
+	/* DDR pad register configurations */
+	ddrpad = readl(&misc_p->ddr_pad);
+	ddrpad &= ~DDR_PAD_CNF_MSK;
+
+#if (CONFIG_DDR_HCLK)
+	ddrpad |= 0xEAAB;
+#elif (CONFIG_DDR_2HCLK)
+	ddrpad |= 0xEAAD;
+#elif (CONFIG_DDR_PLL2)
+	ddrpad |= 0xEAAD;
+#endif
+	writel(ddrpad, &misc_p->ddr_pad);
+
+	/* Compensation register configurations */
+	core3v3 = readl(&misc_p->core_3v3_compensation);
+	core3v3 &= 0x8080ffe0;
+	core3v3 |= 0x78000002;
+	writel(core3v3, &misc_p->core_3v3_compensation);
+
+	ddr1v8 = readl(&misc_p->ddr_1v8_compensation);
+	ddr1v8 &= 0x8080ffc0;
+	ddr1v8 |= 0x78000004;
+	writel(ddr1v8, &misc_p->ddr_1v8_compensation);
+
+	ddr2v5 = readl(&misc_p->ddr_2v5_compensation);
+	ddr2v5 &= 0x8080ffc0;
+	ddr2v5 |= 0x78000004;
+	writel(ddr2v5, &misc_p->ddr_2v5_compensation);
+
+	if ((readl(&misc_p->ddr_pad) & DDR_PAD_SW_CONF) == DDR_PAD_SW_CONF) {
+		/* Software memory configuration */
+		if (readl(&misc_p->ddr_pad) & DDR_PAD_SSTL_SEL)
+			sel_1v8();
+		else
+			sel_2v5();
+	} else {
+		/* Hardware memory configuration */
+		if (readl(&misc_p->ddr_pad) & DDR_PAD_DRAM_TYPE)
+			sel_1v8();
+		else
+			sel_2v5();
+	}
+}
+
+/*
+ * xxx_boot_selected:
+ *
+ * return true if the particular booting option is selected
+ * return false otherwise
+ */
+static u32 read_bootstrap(void)
+{
+	return (readl(CONFIG_SPEAR_BOOTSTRAPCFG) >> CONFIG_SPEAR_BOOTSTRAPSHFT)
+		& CONFIG_SPEAR_BOOTSTRAPMASK;
+}
+
+int snor_boot_selected(void)
+{
+	u32 bootstrap = read_bootstrap();
+
+	if (SNOR_BOOT_SUPPORTED) {
+		/* Check whether SNOR boot is selected */
+		if ((bootstrap & CONFIG_SPEAR_ONLYSNORBOOT) ==
+			CONFIG_SPEAR_ONLYSNORBOOT)
+			return true;
+
+		if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) ==
+			CONFIG_SPEAR_NORNAND8BOOT)
+			return true;
+
+		if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) ==
+			CONFIG_SPEAR_NORNAND16BOOT)
+			return true;
+	}
+
+	return false;
+}
+
+int nand_boot_selected(void)
+{
+	u32 bootstrap = read_bootstrap();
+
+	if (NAND_BOOT_SUPPORTED) {
+		/* Check whether NAND boot is selected */
+		if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) ==
+			CONFIG_SPEAR_NORNAND8BOOT)
+			return true;
+
+		if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) ==
+			CONFIG_SPEAR_NORNAND16BOOT)
+			return true;
+	}
+
+	return false;
+}
+
+int pnor_boot_selected(void)
+{
+	/* Parallel NOR boot is not selected in any SPEAr600 revision */
+	return false;
+}
+
+int usb_boot_selected(void)
+{
+	u32 bootstrap = read_bootstrap();
+
+	if (USB_BOOT_SUPPORTED) {
+		/* Check whether USB boot is selected */
+		if (!(bootstrap & CONFIG_SPEAR_USBBOOT))
+			return true;
+	}
+
+	return false;
+}
+
+int tftp_boot_selected(void)
+{
+	/* TFTP boot is not selected in any SPEAr600 revision */
+	return false;
+}
+
+int uart_boot_selected(void)
+{
+	/* UART boot is not selected in any SPEAr600 revision */
+	return false;
+}
+
+int spi_boot_selected(void)
+{
+	/* SPI boot is not selected in any SPEAr600 revision */
+	return false;
+}
+
+int i2c_boot_selected(void)
+{
+	/* I2C boot is not selected in any SPEAr600 revision */
+	return false;
+}
+
+int mmc_boot_selected(void)
+{
+	return false;
+}
+
+void plat_late_init(void)
+{
+	spear_late_init();
+}
diff --git a/arch/arm/cpu/arm926ejs/spear/spl.c b/arch/arm/cpu/arm926ejs/spear/spl.c
new file mode 100644
index 0000000..d2bddb5
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spl.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ *
+ * Copyright (C) 2012 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <version.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spr_defs.h>
+#include <asm/arch/spr_misc.h>
+#include <asm/arch/spr_syscntl.h>
+#include <linux/mtd/st_smi.h>
+
+static void ddr_clock_init(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+	u32 clkenb, ddrpll;
+
+	clkenb = readl(&misc_p->periph1_clken);
+	clkenb &= ~PERIPH_MPMCMSK;
+	clkenb |= PERIPH_MPMC_WE;
+
+	/* Intentionally done twice */
+	writel(clkenb, &misc_p->periph1_clken);
+	writel(clkenb, &misc_p->periph1_clken);
+
+	ddrpll = readl(&misc_p->pll_ctr_reg);
+	ddrpll &= ~MEM_CLK_SEL_MSK;
+#if (CONFIG_DDR_HCLK)
+	ddrpll |= MEM_CLK_HCLK;
+#elif (CONFIG_DDR_2HCLK)
+	ddrpll |= MEM_CLK_2HCLK;
+#elif (CONFIG_DDR_PLL2)
+	ddrpll |= MEM_CLK_PLL2;
+#else
+#error "please define one of CONFIG_DDR_(HCLK|2HCLK|PLL2)"
+#endif
+	writel(ddrpll, &misc_p->pll_ctr_reg);
+
+	writel(readl(&misc_p->periph1_clken) | PERIPH_MPMC_EN,
+			&misc_p->periph1_clken);
+}
+
+static void mpmc_init_values(void)
+{
+	u32 i;
+	u32 *mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE;
+	u32 *mpmc_val_p = &mpmc_conf_vals[0];
+
+	for (i = 0; i < CONFIG_SPEAR_MPMCREGS; i++, mpmc_reg_p++, mpmc_val_p++)
+		writel(*mpmc_val_p, mpmc_reg_p);
+
+	mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE;
+
+	/*
+	 * MPMC controller start
+	 * MPMC waiting for DLLLOCKREG high
+	 */
+	writel(0x01000100, &mpmc_reg_p[7]);
+
+	while (!(readl(&mpmc_reg_p[3]) & 0x10000))
+		;
+}
+
+static void mpmc_init(void)
+{
+	/* Clock related settings for DDR */
+	ddr_clock_init();
+
+	/*
+	 * DDR pad register bits are different for different SoCs
+	 * Compensation values are also handled separately
+	 */
+	plat_ddr_init();
+
+	/* Initialize mpmc register values */
+	mpmc_init_values();
+}
+
+static void pll_init(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+
+	/* Initialize PLLs */
+	writel(FREQ_332, &misc_p->pll1_frq);
+	writel(0x1C0A, &misc_p->pll1_cntl);
+	writel(0x1C0E, &misc_p->pll1_cntl);
+	writel(0x1C06, &misc_p->pll1_cntl);
+	writel(0x1C0E, &misc_p->pll1_cntl);
+
+	writel(FREQ_332, &misc_p->pll2_frq);
+	writel(0x1C0A, &misc_p->pll2_cntl);
+	writel(0x1C0E, &misc_p->pll2_cntl);
+	writel(0x1C06, &misc_p->pll2_cntl);
+	writel(0x1C0E, &misc_p->pll2_cntl);
+
+	/* wait for pll locks */
+	while (!(readl(&misc_p->pll1_cntl) & 0x1))
+		;
+	while (!(readl(&misc_p->pll2_cntl) & 0x1))
+		;
+}
+
+static void mac_init(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+
+	writel(readl(&misc_p->periph1_clken) & (~PERIPH_GMAC),
+			&misc_p->periph1_clken);
+
+	writel(SYNTH23, &misc_p->gmac_synth_clk);
+
+	switch (get_socrev()) {
+	case SOC_SPEAR600_AA:
+	case SOC_SPEAR600_AB:
+	case SOC_SPEAR600_BA:
+	case SOC_SPEAR600_BB:
+	case SOC_SPEAR600_BC:
+	case SOC_SPEAR600_BD:
+		writel(0x0, &misc_p->gmac_ctr_reg);
+		break;
+
+	case SOC_SPEAR300:
+	case SOC_SPEAR310:
+	case SOC_SPEAR320:
+		writel(0x4, &misc_p->gmac_ctr_reg);
+		break;
+	}
+
+	writel(readl(&misc_p->periph1_clken) | PERIPH_GMAC,
+			&misc_p->periph1_clken);
+
+	writel(readl(&misc_p->periph1_rst) | PERIPH_GMAC,
+			&misc_p->periph1_rst);
+	writel(readl(&misc_p->periph1_rst) & (~PERIPH_GMAC),
+			&misc_p->periph1_rst);
+}
+
+static void sys_init(void)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+	struct syscntl_regs *syscntl_p =
+		(struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE;
+
+	/* Set system state to SLOW */
+	writel(SLOW, &syscntl_p->scctrl);
+	writel(PLL_TIM << 3, &syscntl_p->scpllctrl);
+
+	/* Initialize PLLs */
+	pll_init();
+
+	/*
+	 * Ethernet configuration
+	 * To be done only if the tftp boot is not selected already
+	 * Boot code ensures the correct configuration in tftp booting
+	 */
+	if (!tftp_boot_selected())
+		mac_init();
+
+	writel(RTC_DISABLE | PLLTIMEEN, &misc_p->periph_clk_cfg);
+	writel(0x555, &misc_p->amba_clk_cfg);
+
+	writel(NORMAL, &syscntl_p->scctrl);
+
+	/* Wait for system to switch to normal mode */
+	while (((readl(&syscntl_p->scctrl) >> MODE_SHIFT) & MODE_MASK)
+		!= NORMAL)
+		;
+}
+
+/*
+ * get_socrev
+ *
+ * Get SoC Revision.
+ * @return SOC_SPEARXXX
+ */
+int get_socrev(void)
+{
+#if defined(CONFIG_SPEAR600)
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+	u32 soc_id = readl(&misc_p->soc_core_id);
+	u32 pri_socid = (soc_id >> SOC_PRI_SHFT) & 0xFF;
+	u32 sec_socid = (soc_id >> SOC_SEC_SHFT) & 0xFF;
+
+	if ((pri_socid == 'B') && (sec_socid == 'B'))
+		return SOC_SPEAR600_BB;
+	else if ((pri_socid == 'B') && (sec_socid == 'C'))
+		return SOC_SPEAR600_BC;
+	else if ((pri_socid == 'B') && (sec_socid == 'D'))
+		return SOC_SPEAR600_BD;
+	else if (soc_id == 0)
+		return SOC_SPEAR600_BA;
+	else
+		return SOC_SPEAR_NA;
+#elif defined(CONFIG_SPEAR300)
+	return SOC_SPEAR300;
+#elif defined(CONFIG_SPEAR310)
+	return SOC_SPEAR310;
+#elif defined(CONFIG_SPEAR320)
+	return SOC_SPEAR320;
+#endif
+}
+
+/*
+ * SNOR (Serial NOR flash) related functions
+ */
+static void snor_init(void)
+{
+	struct smi_regs *const smicntl =
+		(struct smi_regs * const)CONFIG_SYS_SMI_BASE;
+
+	/* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */
+	writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4,
+	       &smicntl->smi_cr1);
+}
+
+u32 spl_boot_device(void)
+{
+	u32 mode = 0;
+
+	/* Currently only SNOR is supported as the only */
+	if (snor_boot_selected()) {
+		/* SNOR-SMI initialization */
+		snor_init();
+
+		mode = BOOT_DEVICE_NOR;
+	}
+
+	return mode;
+}
+
+void board_init_f(ulong dummy)
+{
+	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+
+	/* Initialize PLLs */
+	sys_init();
+
+	preloader_console_init();
+	arch_cpu_init();
+
+	/* Enable IPs (release reset) */
+	writel(PERIPH_RST_ALL, &misc_p->periph1_rst);
+
+	/* Initialize MPMC */
+	puts("Configure DDR\n");
+	mpmc_init();
+	spear_late_init();
+
+	board_init_r(NULL, 0);
+}
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c
new file mode 100644
index 0000000..79ab2a7
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com
+ */
+
+#include <common.h>
+
+#if (CONFIG_DDR_PLL2)
+
+const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = {
+	0x00000001,
+	0x00000000,
+	0x01000000,
+	0x00000101,
+	0x00000001,
+	0x01000000,
+	0x00010001,
+	0x00000100,
+	0x00010001,
+	0x00000003,
+	0x01000201,
+	0x06000202,
+	0x06060106,
+	0x03050502,
+	0x03040404,
+	0x02020503,
+	0x02010106,
+	0x03000404,
+	0x02030202,
+	0x03000204,
+	0x0707073f,
+	0x07070707,
+	0x06060607,
+	0x06060606,
+	0x05050506,
+	0x05050505,
+	0x04040405,
+	0x04040404,
+	0x03030304,
+	0x03030303,
+	0x02020203,
+	0x02020202,
+	0x01010102,
+	0x01010101,
+	0x08080a01,
+	0x0000023f,
+	0x00040800,
+	0x00000000,
+	0x00000f02,
+	0x00001b1b,
+	0x7f000000,
+	0x005f0000,
+	0x1c040b6a,
+	0x00640064,
+	0x00640064,
+	0x00640064,
+	0x00000064,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x000007ff,
+	0x00000000,
+	0x47ec00c8,
+	0x00c8001f,
+	0x00000000,
+	0x0000cd98,
+	0x00000000,
+	0x03030100,
+	0x03030303,
+	0x03030303,
+	0x03030303,
+	0x00270000,
+	0x00250027,
+	0x00300000,
+	0x008900b7,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c
new file mode 100644
index 0000000..121b636
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com
+ */
+
+#include <common.h>
+
+#if (CONFIG_DDR_PLL2 || CONFIG_DDR_2HCLK)
+
+const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = {
+#if (CONFIG_DDR_PLL2)
+	0x00000001,
+	0x00000000,
+#elif (CONFIG_DDR_2HCLK)
+	0x02020201,
+	0x02020202,
+#endif
+	0x01000000,
+	0x00000101,
+	0x00000101,
+	0x01000000,
+	0x00010001,
+	0x00000100,
+	0x01010001,
+	0x00000201,
+	0x01000101,
+	0x06000002,
+	0x06060106,
+	0x03050502,
+	0x03040404,
+	0x02020503,
+	0x02010106,
+	0x03000405,
+	0x03040202,
+	0x04000305,
+	0x0707073f,
+	0x07070707,
+	0x06060607,
+	0x06060606,
+	0x05050506,
+	0x05050505,
+	0x04040405,
+	0x04040404,
+	0x03030304,
+	0x03030303,
+	0x02020203,
+	0x02020202,
+	0x01010102,
+	0x01010101,
+	0x0a0a0a01,
+	0x0000023f,
+	0x00050a00,
+	0x11000000,
+	0x00001302,
+	0x00000A0A,
+	0x72000000,
+	0x00550000,
+	0x2b050e86,
+	0x00640064,
+	0x00640064,
+	0x00640064,
+	0x00000064,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00000a24,
+	0x43C20000,
+	0x5b1c00c8,
+	0x00c8002e,
+	0x00000000,
+	0x0001046b,
+	0x00000000,
+	0x03030100,
+	0x03030303,
+	0x03030303,
+	0x03030303,
+	0x00210000,
+	0x00010021,
+	0x00200000,
+	0x006c0090,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c
new file mode 100644
index 0000000..64c8bab
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com
+ */
+
+#include <common.h>
+
+#if (CONFIG_DDR_HCLK)
+
+const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = {
+	0x03030301,
+	0x03030303,
+	0x01000000,
+	0x00000101,
+	0x00000001,
+	0x01000000,
+	0x00010001,
+	0x00000100,
+	0x00010001,
+	0x00000003,
+	0x01000201,
+	0x06000202,
+	0x06060106,
+	0x03050502,
+	0x03040404,
+	0x02020503,
+	0x02010106,
+	0x03000404,
+	0x02020202,
+	0x03000203,
+	0x0707073f,
+	0x07070707,
+	0x06060607,
+	0x06060606,
+	0x05050506,
+	0x05050505,
+	0x04040405,
+	0x04040404,
+	0x03030304,
+	0x03030303,
+	0x02020203,
+	0x02020202,
+	0x01010102,
+	0x01010101,
+	0x08080a01,
+	0x0000023f,
+	0x00030600,
+	0x00000000,
+	0x00000a02,
+	0x00001c1c,
+	0x7f000000,
+	0x005f0000,
+	0x12030743,
+	0x00640064,
+	0x00640064,
+	0x00640064,
+	0x00000064,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x0000050e,
+	0x00000000,
+	0x2d8900c8,
+	0x00c80014,
+	0x00000000,
+	0x00008236,
+	0x00000000,
+	0x03030100,
+	0x03030303,
+	0x03030303,
+	0x03030303,
+	0x00400000,
+	0x003a0040,
+	0x00680000,
+	0x00d80120,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c
new file mode 100644
index 0000000..8765466
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com
+ */
+
+#include <common.h>
+
+#if (CONFIG_DDR_PLL2 || CONFIG_DDR_2HCLK)
+
+const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = {
+#if (CONFIG_DDR_PLL2)
+	0x00000001,
+	0x00000000,
+#elif (CONFIG_DDR_2HCLK)
+	0x02020201,
+	0x02020202,
+#endif
+	0x01000000,
+	0x00000101,
+	0x00000101,
+	0x01000000,
+	0x00010001,
+	0x00000100,
+	0x01010001,
+	0x00000201,
+	0x01000101,
+	0x06000002,
+	0x06060106,
+	0x03050502,
+	0x03040404,
+	0x02020503,
+#ifdef CONFIG_X600
+	0x02030206,
+#else
+	0x02010106,
+#endif
+	0x03000405,
+	0x03040202,
+	0x04000305,
+	0x0707073f,
+	0x07070707,
+	0x06060607,
+	0x06060606,
+	0x05050506,
+	0x05050505,
+	0x04040405,
+	0x04040404,
+	0x03030304,
+	0x03030303,
+	0x02020203,
+	0x02020202,
+	0x01010102,
+	0x01010101,
+	0x0a0a0a01,
+	0x0000023f,
+	0x00050a00,
+	0x11000000,
+	0x00001302,
+	0x00000A0A,
+#ifdef CONFIG_X600
+	0x7f000000,
+	0x005c0000,
+#else
+	0x72000000,
+	0x00550000,
+#endif
+	0x2b050e86,
+	0x00640064,
+	0x00640064,
+	0x00640064,
+	0x00000064,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00200020,
+	0x00000a24,
+	0x43C20000,
+	0x5b1c00c8,
+	0x00c8002e,
+	0x00000000,
+	0x0001046b,
+	0x00000000,
+	0x03030100,
+	0x03030303,
+	0x03030303,
+	0x03030303,
+	0x00210000,
+	0x00010021,
+	0x00200000,
+	0x006c0090,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x003fffff,
+	0x003fffff,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr_lowlevel_init.S b/arch/arm/cpu/arm926ejs/spear/spr_lowlevel_init.S
new file mode 100644
index 0000000..417e87a
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spr_lowlevel_init.S
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2006
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ */
+
+#include <config.h>
+
+/*
+ * platform specific initializations are already done in Xloader
+ * Initializations already done include
+ * DDR, PLLs, IP's clock enable and reset release etc
+ */
+.globl lowlevel_init
+lowlevel_init:
+	mov	pc, lr
+
+/* void setfreq(unsigned int device, unsigned int frequency) */
+.global setfreq
+setfreq:
+	stmfd 	sp!,{r14}
+	stmfd 	sp!,{r0-r12}
+
+	mov  	r8,sp
+	ldr 	sp,SRAM_STACK_V
+
+	/* Saving the function arguements for later use */
+	mov  	r4,r0
+	mov  	r5,r1
+
+	/* Putting DDR into self refresh */
+	ldr 	r0,DDR_07_V
+	ldr	r1,[r0]
+	ldr	r2,DDR_ACTIVE_V
+	bic	r1, r1, r2
+	str	r1,[r0]
+	ldr 	r0,DDR_57_V
+	ldr	r1,[r0]
+	ldr	r2,CYCLES_MASK_V
+	bic	r1, r1, r2
+	ldr	r2,REFRESH_CYCLES_V
+	orr	r1, r1, r2, lsl #16
+	str	r1,[r0]
+	ldr 	r0,DDR_07_V
+	ldr	r1,[r0]
+	ldr	r2,SREFRESH_MASK_V
+	orr	r1, r1, r2
+	str	r1,[r0]
+
+	/* flush pipeline */
+	b	flush
+	.align 5
+flush:
+	/* Delay to ensure self refresh mode */
+	ldr	r0,SREFRESH_DELAY_V
+delay:
+	sub	r0,r0,#1
+	cmp	r0,#0
+	bne	delay
+
+	/* Putting system in slow mode */
+	ldr	r0,SCCTRL_V
+	mov	r1,#2
+	str	r1,[r0]
+
+	/* Changing PLL(1/2) frequency */
+	mov	r0,r4
+	mov	r1,r5
+
+	cmp	r4,#0
+	beq	pll1_freq
+
+	/* Change PLL2 (DDR frequency) */
+	ldr	r6,PLL2_FREQ_V
+	ldr	r7,PLL2_CNTL_V
+	b	pll2_freq
+
+pll1_freq:
+	/* Change PLL1 (CPU frequency) */
+	ldr	r6,PLL1_FREQ_V
+	ldr	r7,PLL1_CNTL_V
+
+pll2_freq:
+	mov	r0,r6
+	ldr	r1,[r0]
+	ldr	r2,PLLFREQ_MASK_V
+	bic	r1,r1,r2
+	mov	r2,r5,lsr#1
+	orr	r1,r1,r2,lsl#24
+	str	r1,[r0]
+
+	mov	r0,r7
+	ldr	r1,P1C0A_V
+	str	r1,[r0]
+	ldr	r1,P1C0E_V
+	str	r1,[r0]
+	ldr	r1,P1C06_V
+	str	r1,[r0]
+	ldr	r1,P1C0E_V
+	str	r1,[r0]
+
+lock:
+	ldr	r1,[r0]
+	and	r1,r1,#1
+	cmp	r1,#0
+	beq	lock
+
+	/* Putting system back to normal mode */
+	ldr	r0,SCCTRL_V
+	mov	r1,#4
+	str	r1,[r0]
+
+	/* Putting DDR back to normal */
+	ldr	r0,DDR_07_V
+	ldr	r1,[R0]
+	ldr	r2,SREFRESH_MASK_V
+	bic	r1, r1, r2
+	str	r1,[r0]
+	ldr	r2,DDR_ACTIVE_V
+	orr	r1, r1, r2
+	str	r1,[r0]
+
+	/* Delay to ensure self refresh mode */
+	ldr	r0,SREFRESH_DELAY_V
+1:
+	sub	r0,r0,#1
+	cmp	r0,#0
+	bne	1b
+
+	mov	sp,r8
+	/* Resuming back to code */
+	ldmia	sp!,{r0-r12}
+	ldmia	sp!,{pc}
+
+SCCTRL_V:
+	.word 0xfca00000
+PLL1_FREQ_V:
+	.word 0xfca8000C
+PLL1_CNTL_V:
+	.word 0xfca80008
+PLL2_FREQ_V:
+	.word 0xfca80018
+PLL2_CNTL_V:
+	.word 0xfca80014
+PLLFREQ_MASK_V:
+	.word 0xff000000
+P1C0A_V:
+	.word 0x1C0A
+P1C0E_V:
+	.word 0x1C0E
+P1C06_V:
+	.word 0x1C06
+
+SREFRESH_DELAY_V:
+	.word 0x9999
+SRAM_STACK_V:
+	.word 0xD2800600
+DDR_07_V:
+	.word 0xfc60001c
+DDR_ACTIVE_V:
+	.word 0x01000000
+DDR_57_V:
+	.word 0xfc6000e4
+CYCLES_MASK_V:
+	.word 0xffff0000
+REFRESH_CYCLES_V:
+	.word 0xf0f0
+SREFRESH_MASK_V:
+	.word 0x00010000
+
+.global setfreq_sz
+setfreq_sz:
+	.word setfreq_sz - setfreq
diff --git a/arch/arm/cpu/arm926ejs/spear/spr_misc.c b/arch/arm/cpu/arm926ejs/spear/spr_misc.c
new file mode 100644
index 0000000..371dea5
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spr_misc.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <i2c.h>
+#include <net.h>
+#include <linux/mtd/st_smi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spr_emi.h>
+#include <asm/arch/spr_defs.h>
+
+#define CPU		0
+#define DDR		1
+#define SRAM_REL	0xD2801000
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CMD_NET)
+static int i2c_read_mac(uchar *buffer);
+#endif
+
+int dram_init(void)
+{
+	/* Store complete RAM size and return */
+	gd->ram_size = get_ram_size(PHYS_SDRAM_1, PHYS_SDRAM_1_MAXSIZE);
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = gd->ram_size;
+
+	return 0;
+}
+
+int board_early_init_f()
+{
+#if defined(CONFIG_ST_SMI)
+	smi_init();
+#endif
+	return 0;
+}
+int misc_init_r(void)
+{
+#if defined(CONFIG_CMD_NET)
+	uchar mac_id[6];
+
+	if (!eth_env_get_enetaddr("ethaddr", mac_id) && !i2c_read_mac(mac_id))
+		eth_env_set_enetaddr("ethaddr", mac_id);
+#endif
+	env_set("verify", "n");
+
+#if defined(CONFIG_SPEAR_USBTTY)
+	env_set("stdin", "usbtty");
+	env_set("stdout", "usbtty");
+	env_set("stderr", "usbtty");
+
+#ifndef CONFIG_SYS_NO_DCACHE
+	dcache_enable();
+#endif
+#endif
+	return 0;
+}
+
+#ifdef CONFIG_SPEAR_EMI
+struct cust_emi_para {
+	unsigned int tap;
+	unsigned int tsdp;
+	unsigned int tdpw;
+	unsigned int tdpr;
+	unsigned int tdcs;
+};
+
+/* EMI timing setting of m28w640hc of linux kernel */
+const struct cust_emi_para emi_timing_m28w640hc = {
+	.tap = 0x10,
+	.tsdp = 0x05,
+	.tdpw = 0x0a,
+	.tdpr = 0x0a,
+	.tdcs = 0x05,
+};
+
+/* EMI timing setting of bootrom */
+const struct cust_emi_para emi_timing_bootrom = {
+	.tap = 0xf,
+	.tsdp = 0x0,
+	.tdpw = 0xff,
+	.tdpr = 0x111,
+	.tdcs = 0x02,
+};
+
+void spear_emi_init(void)
+{
+	const struct cust_emi_para *p = &emi_timing_m28w640hc;
+	struct emi_regs *emi_regs_p = (struct emi_regs *)CONFIG_SPEAR_EMIBASE;
+	unsigned int cs;
+	unsigned int val, tmp;
+
+	val = readl(CONFIG_SPEAR_RASBASE);
+
+	if (val & EMI_ACKMSK)
+		tmp = 0x3f;
+	else
+		tmp = 0x0;
+
+	writel(tmp, &emi_regs_p->ack);
+
+	for (cs = 0; cs < CONFIG_SYS_MAX_FLASH_BANKS; cs++) {
+		writel(p->tap, &emi_regs_p->bank_regs[cs].tap);
+		writel(p->tsdp, &emi_regs_p->bank_regs[cs].tsdp);
+		writel(p->tdpw, &emi_regs_p->bank_regs[cs].tdpw);
+		writel(p->tdpr, &emi_regs_p->bank_regs[cs].tdpr);
+		writel(p->tdcs, &emi_regs_p->bank_regs[cs].tdcs);
+		writel(EMI_CNTL_ENBBYTERW | ((val & 0x18) >> 3),
+		       &emi_regs_p->bank_regs[cs].control);
+	}
+}
+#endif
+
+int spear_board_init(ulong mach_type)
+{
+	gd->bd->bi_arch_number = mach_type;
+
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_BOOT_PARAMS_ADDR;
+
+#ifdef CONFIG_SPEAR_EMI
+	spear_emi_init();
+#endif
+	return 0;
+}
+
+#if defined(CONFIG_CMD_NET)
+static int i2c_read_mac(uchar *buffer)
+{
+	u8 buf[2];
+
+	i2c_read(CONFIG_I2C_CHIPADDRESS, MAGIC_OFF, 1, buf, MAGIC_LEN);
+
+	/* Check if mac in i2c memory is valid */
+	if ((buf[0] == MAGIC_BYTE0) && (buf[1] == MAGIC_BYTE1)) {
+		/* Valid mac address is saved in i2c eeprom */
+		i2c_read(CONFIG_I2C_CHIPADDRESS, MAC_OFF, 1, buffer, MAC_LEN);
+		return 0;
+	}
+
+	return -1;
+}
+
+static int write_mac(uchar *mac)
+{
+	u8 buf[2];
+
+	buf[0] = (u8)MAGIC_BYTE0;
+	buf[1] = (u8)MAGIC_BYTE1;
+	i2c_write(CONFIG_I2C_CHIPADDRESS, MAGIC_OFF, 1, buf, MAGIC_LEN);
+
+	buf[0] = (u8)~MAGIC_BYTE0;
+	buf[1] = (u8)~MAGIC_BYTE1;
+
+	i2c_read(CONFIG_I2C_CHIPADDRESS, MAGIC_OFF, 1, buf, MAGIC_LEN);
+
+	/* check if valid MAC address is saved in I2C EEPROM or not? */
+	if ((buf[0] == MAGIC_BYTE0) && (buf[1] == MAGIC_BYTE1)) {
+		i2c_write(CONFIG_I2C_CHIPADDRESS, MAC_OFF, 1, mac, MAC_LEN);
+		puts("I2C EEPROM written with mac address \n");
+		return 0;
+	}
+
+	puts("I2C EEPROM writing failed\n");
+	return -1;
+}
+#endif
+
+int do_chip_config(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	void (*sram_setfreq) (unsigned int, unsigned int);
+	unsigned int frequency;
+#if defined(CONFIG_CMD_NET)
+	unsigned char mac[6];
+#endif
+
+	if ((argc > 3) || (argc < 2))
+		return cmd_usage(cmdtp);
+
+	if ((!strcmp(argv[1], "cpufreq")) || (!strcmp(argv[1], "ddrfreq"))) {
+
+		frequency = simple_strtoul(argv[2], NULL, 0);
+
+		if (frequency > 333) {
+			printf("Frequency is limited to 333MHz\n");
+			return 1;
+		}
+
+		sram_setfreq = memcpy((void *)SRAM_REL, setfreq, setfreq_sz);
+
+		if (!strcmp(argv[1], "cpufreq")) {
+			sram_setfreq(CPU, frequency);
+			printf("CPU frequency changed to %u\n", frequency);
+		} else {
+			sram_setfreq(DDR, frequency);
+			printf("DDR frequency changed to %u\n", frequency);
+		}
+
+		return 0;
+
+#if defined(CONFIG_CMD_NET)
+	} else if (!strcmp(argv[1], "ethaddr")) {
+
+		u32 reg;
+		char *e, *s = argv[2];
+		for (reg = 0; reg < 6; ++reg) {
+			mac[reg] = s ? simple_strtoul(s, &e, 16) : 0;
+			if (s)
+				s = (*e) ? e + 1 : e;
+		}
+		write_mac(mac);
+
+		return 0;
+#endif
+	} else if (!strcmp(argv[1], "print")) {
+#if defined(CONFIG_CMD_NET)
+		if (!i2c_read_mac(mac)) {
+			printf("Ethaddr (from i2c mem) = %pM\n", mac);
+		} else {
+			printf("Ethaddr (from i2c mem) = Not set\n");
+		}
+#endif
+		return 0;
+	}
+
+	return cmd_usage(cmdtp);
+}
+
+U_BOOT_CMD(chip_config, 3, 1, do_chip_config,
+	   "configure chip",
+	   "chip_config cpufreq/ddrfreq frequency\n"
+#if defined(CONFIG_CMD_NET)
+	   "chip_config ethaddr XX:XX:XX:XX:XX:XX\n"
+#endif
+	   "chip_config print");
diff --git a/arch/arm/cpu/arm926ejs/spear/start.S b/arch/arm/cpu/arm926ejs/spear/start.S
new file mode 100644
index 0000000..1cab4ca
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/start.S
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ */
+
+
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * Below are the critical initializations already taken place in BootROM.
+ * So, these are not taken care in Xloader
+ * 1. Relocation to RAM
+ * 2. Initializing stacks
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+/*
+ * Xloader has to return back to BootROM in a few cases.
+ * eg. Ethernet boot, UART boot, USB boot
+ * Saving registers for returning back
+ */
+	stmdb	sp!, {r0-r12,r14}
+	bl	cpu_init_crit
+/*
+ * Clearing bss area is not done in Xloader.
+ * BSS area lies in the DDR location which is not yet initialized
+ * bss is assumed to be uninitialized.
+ */
+	ldmia	sp!, {r0-r12,pc}
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * enable instruction cache
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+	mcr	p15, 0, r0, c1, c0, 0
+
+	/*
+	 * Go setup Memory and board specific bits prior to relocation.
+	 */
+	stmdb	sp!, {lr}
+	bl	_main	/* _main will call board_init_f */
+	ldmia	sp!, {pc}
diff --git a/arch/arm/cpu/arm926ejs/spear/timer.c b/arch/arm/cpu/arm926ejs/spear/timer.c
new file mode 100644
index 0000000..e7b5bda
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/timer.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spr_gpt.h>
+#include <asm/arch/spr_misc.h>
+
+#define GPT_RESOLUTION	(CONFIG_SPEAR_HZ_CLOCK / CONFIG_SPEAR_HZ)
+#define READ_TIMER()	(readl(&gpt_regs_p->count) & GPT_FREE_RUNNING)
+
+static struct gpt_regs *const gpt_regs_p =
+    (struct gpt_regs *)CONFIG_SPEAR_TIMERBASE;
+
+static struct misc_regs *const misc_regs_p =
+    (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong get_timer_masked(void);
+
+#define timestamp gd->arch.tbl
+#define lastdec gd->arch.lastinc
+
+int timer_init(void)
+{
+	u32 synth;
+
+	/* Prescaler setting */
+#if defined(CONFIG_SPEAR3XX)
+	writel(MISC_PRSC_CFG, &misc_regs_p->prsc2_clk_cfg);
+	synth = MISC_GPT4SYNTH;
+#elif defined(CONFIG_SPEAR600)
+	writel(MISC_PRSC_CFG, &misc_regs_p->prsc1_clk_cfg);
+	synth = MISC_GPT3SYNTH;
+#else
+# error Incorrect config. Can only be SPEAR{600|300|310|320}
+#endif
+
+	writel(readl(&misc_regs_p->periph_clk_cfg) | synth,
+	       &misc_regs_p->periph_clk_cfg);
+
+	/* disable timers */
+	writel(GPT_PRESCALER_1 | GPT_MODE_AUTO_RELOAD, &gpt_regs_p->control);
+
+	/* load value for free running */
+	writel(GPT_FREE_RUNNING, &gpt_regs_p->compare);
+
+	/* auto reload, start timer */
+	writel(readl(&gpt_regs_p->control) | GPT_ENABLE, &gpt_regs_p->control);
+
+	/* Reset the timer */
+	lastdec = READ_TIMER();
+	timestamp = 0;
+
+	return 0;
+}
+
+/*
+ * timer without interrupts
+ */
+ulong get_timer(ulong base)
+{
+	return (get_timer_masked() / GPT_RESOLUTION) - base;
+}
+
+void __udelay(unsigned long usec)
+{
+	ulong tmo;
+	ulong start = get_timer_masked();
+	ulong tenudelcnt = CONFIG_SPEAR_HZ_CLOCK / (1000 * 100);
+	ulong rndoff;
+
+	rndoff = (usec % 10) ? 1 : 0;
+
+	/* tenudelcnt timer tick gives 10 microsecconds delay */
+	tmo = ((usec / 10) + rndoff) * tenudelcnt;
+
+	while ((ulong) (get_timer_masked() - start) < tmo)
+		;
+}
+
+static ulong get_timer_masked(void)
+{
+	ulong now = READ_TIMER();
+
+	if (now >= lastdec) {
+		/* normal mode */
+		timestamp += now - lastdec;
+	} else {
+		/* we have an overflow ... */
+		timestamp += now + GPT_FREE_RUNNING - lastdec;
+	}
+	lastdec = now;
+
+	return timestamp;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_SPEAR_HZ;
+}
diff --git a/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds
new file mode 100644
index 0000000..569704c
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+		LENGTH = CONFIG_SPL_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	.text      :
+	{
+		__start = .;
+		*(.vectors)
+		CPUDIR/spear/start.o	(.text*)
+		*(.text*)
+	} > .sram
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+	. = ALIGN(4);
+	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	} > .sram
+
+	. = ALIGN(4);
+	__image_copy_end = .;
+	_end = .;
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} > .sram
+}
diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S
new file mode 100644
index 0000000..1045673
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/start.S
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <common.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+	bx	lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush D cache before disabling it
+	 */
+	mov	r0, #0
+flush_dcache:
+	mrc	p15, 0, r15, c7, c10, 3
+	bne	flush_dcache
+
+	mcr	p15, 0, r0, c8, c7, 0	/* invalidate TLB */
+	mcr	p15, 0, r0, c7, c5, 0	/* invalidate I Cache */
+
+	/*
+	 * disable MMU and D cache
+	 * enable I cache if CONFIG_SYS_ICACHE_OFF is not defined
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00000300	/* clear bits 9:8 (---- --RS) */
+	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
+#ifdef CONFIG_SYS_EXCEPTION_VECTORS_HIGH
+	orr	r0, r0, #0x00002000	/* set bit 13 (--V- ----) */
+#else
+	bic	r0, r0, #0x00002000	/* clear bit 13 (--V- ----) */
+#endif
+	orr	r0, r0, #0x00000002	/* set bit 1 (A) Align */
+#ifndef CONFIG_SYS_ICACHE_OFF
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+#endif
+	mcr	p15, 0, r0, c1, c0, 0
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+	/*
+	 * Go setup Memory and board specific bits prior to relocation.
+	 */
+	mov	r4, lr		/* perserve link reg across call */
+	bl	lowlevel_init	/* go setup pll,mux,memory */
+	mov	lr, r4		/* restore link */
+#endif
+	mov	pc, lr		/* back to my caller */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm946es/Makefile b/arch/arm/cpu/arm946es/Makefile
new file mode 100644
index 0000000..24cebe3
--- /dev/null
+++ b/arch/arm/cpu/arm946es/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	= start.o
+
+obj-y	= cpu.o
diff --git a/arch/arm/cpu/arm946es/cpu.c b/arch/arm/cpu/arm946es/cpu.c
new file mode 100644
index 0000000..3b4f5de
--- /dev/null
+++ b/arch/arm/cpu/arm946es/cpu.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+static void cache_flush(void);
+
+int cleanup_before_linux (void)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * we turn off caches etc ...
+	 */
+
+	disable_interrupts ();
+
+	/* ARM926E-S needs the protection unit enabled for the icache to have
+	 * been enabled	 - left for possible later use
+	 * should turn off the protection unit as well....
+	 */
+	/* turn off I/D-cache */
+	icache_disable();
+	dcache_disable();
+	/* flush I/D-cache */
+	cache_flush();
+
+	return 0;
+}
+
+/* flush I/D-cache */
+static void cache_flush (void)
+{
+	unsigned long i = 0;
+
+	asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i));
+	asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (i));
+}
+
+#ifndef CONFIG_ARCH_INTEGRATOR
+
+__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused)))
+{
+	writew(0x0, 0xfffece10);
+	writew(0x8, 0xfffece10);
+	for (;;)
+		;
+}
+
+#endif	/* #ifdef CONFIG_ARCH_INTEGRATOR */
diff --git a/arch/arm/cpu/arm946es/start.S b/arch/arm/cpu/arm946es/start.S
new file mode 100644
index 0000000..0ec340b
--- /dev/null
+++ b/arch/arm/cpu/arm946es/start.S
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+	mov	pc, lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0	/* flush v4 I-cache */
+	mcr	p15, 0, r0, c7, c6, 0	/* flush v4 D-cache */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
+	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
+	orr	r0, r0, #0x00000002	/* set bit 1 (A) Align */
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+	mcr	p15, 0, r0, c1, c0, 0
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+	/*
+	 * Go setup Memory and board specific bits prior to relocation.
+	 */
+	mov	ip, lr		/* perserve link reg across call */
+	bl	lowlevel_init	/* go setup memory */
+	mov	lr, ip		/* restore link */
+#endif
+	mov	pc, lr		/* back to my caller */
+#endif
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
new file mode 100644
index 0000000..4d0dcee
--- /dev/null
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -0,0 +1,62 @@
+if CPU_V7A
+
+config CPU_V7_HAS_NONSEC
+        bool
+
+config CPU_V7_HAS_VIRT
+        bool
+
+config ARCH_SUPPORT_PSCI
+        bool
+
+config ARMV7_NONSEC
+	bool "Enable support for booting in non-secure mode" if EXPERT
+	depends on CPU_V7_HAS_NONSEC
+	default y
+	---help---
+	Say Y here to enable support for booting in non-secure / SVC mode.
+
+config ARMV7_BOOT_SEC_DEFAULT
+	bool "Boot in secure mode by default" if EXPERT
+	depends on ARMV7_NONSEC
+	default y if TEGRA
+	---help---
+	Say Y here to boot in secure mode by default even if non-secure mode
+	is supported. This option is useful to boot kernels which do not
+	suppport booting in non-secure mode. Only set this if you need it.
+	This can be overridden at run-time by setting the bootm_boot_mode env.
+	variable to "sec" or "nonsec".
+
+config ARMV7_VIRT
+	bool "Enable support for hardware virtualization" if EXPERT
+	depends on CPU_V7_HAS_VIRT && ARMV7_NONSEC
+	default y
+	---help---
+	Say Y here to boot in hypervisor (HYP) mode when booting non-secure.
+
+config ARMV7_PSCI
+	bool "Enable PSCI support" if EXPERT
+	depends on ARMV7_NONSEC && ARCH_SUPPORT_PSCI
+	default y
+	help
+	  Say Y here to enable PSCI support.
+
+config ARMV7_PSCI_NR_CPUS
+	int "Maximum supported CPUs for PSCI"
+	depends on ARMV7_NONSEC
+	default 4
+	help
+	  The maximum number of CPUs supported in the PSCI firmware.
+	  It is no problem to set a larger value than the number of
+	  CPUs in the actual hardware implementation.
+
+config ARMV7_LPAE
+	bool "Use LPAE page table format" if EXPERT
+	depends on CPU_V7A
+	default y if ARMV7_VIRT
+	---help---
+	Say Y here to use the long descriptor page table format. This is
+	required if U-Boot runs in HYP mode.
+
+endif
+
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
new file mode 100644
index 0000000..4f4647c
--- /dev/null
+++ b/arch/arm/cpu/armv7/Makefile
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	:= start.o
+
+obj-y	+= cache_v7.o cache_v7_asm.o
+
+obj-y	+= cpu.o cp15.o
+obj-y	+= syslib.o
+
+obj-$(CONFIG_SYS_ARM_MPU) += mpu_v7r.o
+
+ifneq ($(CONFIG_SPL_BUILD),y)
+obj-$(CONFIG_EFI_LOADER) += sctlr.o
+endif
+
+ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y)
+obj-y	+= lowlevel_init.o
+endif
+
+obj-$(CONFIG_ARM_SMCCC)		+= smccc-call.o
+obj-$(CONFIG_ARMV7_NONSEC)	+= nonsec_virt.o virt-v7.o virt-dt.o
+obj-$(CONFIG_ARMV7_PSCI)	+= psci.o psci-common.o
+
+obj-$(CONFIG_IPROC) += iproc-common/
+obj-$(CONFIG_KONA) += kona-common/
+obj-$(CONFIG_SYS_ARCH_TIMER) += arch_timer.o
+
+ifneq (,$(filter s5pc1xx exynos,$(SOC)))
+obj-y += s5p-common/
+endif
+
+obj-$(if $(filter bcm235xx,$(SOC)),y) += bcm235xx/
+obj-$(if $(filter bcm281xx,$(SOC)),y) += bcm281xx/
+obj-$(if $(filter bcmcygnus,$(SOC)),y) += bcmcygnus/
+obj-$(if $(filter bcmnsp,$(SOC)),y) += bcmnsp/
+obj-$(if $(filter ls102xa,$(SOC)),y) += ls102xa/
+obj-$(CONFIG_RMOBILE) += rmobile/
+obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/
+obj-$(CONFIG_ARCH_SUNXI) += sunxi/
+obj-$(CONFIG_VF610) += vf610/
diff --git a/arch/arm/cpu/armv7/arch_timer.c b/arch/arm/cpu/armv7/arch_timer.c
new file mode 100644
index 0000000..3db31c0
--- /dev/null
+++ b/arch/arm/cpu/armv7/arch_timer.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012-2014
+ *     Texas Instruments Incorporated, <www.ti.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <div64.h>
+#include <bootstage.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SYS_HZ_CLOCK
+static inline u32 read_cntfrq(void)
+{
+	u32 frq;
+
+	asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq));
+	return frq;
+}
+#endif
+
+int timer_init(void)
+{
+	gd->arch.tbl = 0;
+	gd->arch.tbu = 0;
+
+#ifdef CONFIG_SYS_HZ_CLOCK
+	gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK;
+#else
+	gd->arch.timer_rate_hz = read_cntfrq();
+#endif
+	return 0;
+}
+
+unsigned long long get_ticks(void)
+{
+	ulong nowl, nowu;
+
+	asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (nowl), "=r" (nowu));
+
+	gd->arch.tbl = nowl;
+	gd->arch.tbu = nowu;
+
+	return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
+}
+
+
+ulong timer_get_boot_us(void)
+{
+	return lldiv(get_ticks(), gd->arch.timer_rate_hz / 1000000);
+}
+
+ulong get_tbclk(void)
+{
+	return gd->arch.timer_rate_hz;
+}
diff --git a/arch/arm/cpu/armv7/bcm235xx/Makefile b/arch/arm/cpu/armv7/bcm235xx/Makefile
new file mode 100644
index 0000000..3d09126
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2013 Broadcom Corporation.
+
+obj-y	+= clk-core.o
+obj-y	+= clk-bcm235xx.o
+obj-y	+= clk-sdio.o
+obj-y	+= clk-bsc.o
+obj-$(CONFIG_BCM_SF2_ETH) += clk-eth.o
+obj-y	+= clk-usb-otg.o
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-bcm235xx.c b/arch/arm/cpu/armv7/bcm235xx/clk-bcm235xx.c
new file mode 100644
index 0000000..39217c5
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/clk-bcm235xx.c
@@ -0,0 +1,568 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+/*
+ *
+ * bcm235xx-specific clock tables
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define CLOCK_1K		1000
+#define CLOCK_1M		(CLOCK_1K * 1000)
+
+/* declare a reference clock */
+#define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \
+static struct refclk clk_name = { \
+	.clk	=	{ \
+		.name	=	#clk_name, \
+		.parent =	clk_parent, \
+		.rate	=	clk_rate, \
+		.div	=	clk_div, \
+		.ops	=	&ref_clk_ops, \
+	}, \
+}
+
+/*
+ * Reference clocks
+ */
+
+/* Declare a list of reference clocks */
+DECLARE_REF_CLK(ref_crystal,	0,		26  * CLOCK_1M,	1);
+DECLARE_REF_CLK(var_96m,	0,		96  * CLOCK_1M,	1);
+DECLARE_REF_CLK(ref_96m,	0,		96  * CLOCK_1M,	1);
+DECLARE_REF_CLK(ref_312m,	0,		312 * CLOCK_1M,	0);
+DECLARE_REF_CLK(ref_104m,	&ref_312m.clk,	104 * CLOCK_1M,	3);
+DECLARE_REF_CLK(ref_52m,	&ref_104m.clk,	52  * CLOCK_1M,	2);
+DECLARE_REF_CLK(ref_13m,	&ref_52m.clk,	13  * CLOCK_1M,	4);
+DECLARE_REF_CLK(var_312m,	0,		312 * CLOCK_1M,	0);
+DECLARE_REF_CLK(var_104m,	&var_312m.clk,	104 * CLOCK_1M,	3);
+DECLARE_REF_CLK(var_52m,	&var_104m.clk,	52  * CLOCK_1M,	2);
+DECLARE_REF_CLK(var_13m,	&var_52m.clk,	13  * CLOCK_1M,	4);
+
+struct refclk_lkup {
+	struct refclk *procclk;
+	const char *name;
+};
+
+/* Lookup table for string to clk tranlation */
+#define MKSTR(x) {&x, #x}
+static struct refclk_lkup refclk_str_tbl[] = {
+	MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m),
+	MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m),
+	MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m),
+	MKSTR(var_52m), MKSTR(var_13m),
+};
+
+int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
+
+/* convert ref clock string to clock structure pointer */
+struct refclk *refclk_str_to_clk(const char *name)
+{
+	int i;
+	struct refclk_lkup *tblp = refclk_str_tbl;
+	for (i = 0; i < refclk_entries; i++, tblp++) {
+		if (!(strcmp(name, tblp->name)))
+			return tblp->procclk;
+	}
+	return NULL;
+}
+
+/* frequency tables indexed by freq_id */
+unsigned long master_axi_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	52 * CLOCK_1M,
+	104 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M,
+	208 * CLOCK_1M,
+	312 * CLOCK_1M,
+	312 * CLOCK_1M
+};
+
+unsigned long master_ahb_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	52 * CLOCK_1M,
+	52 * CLOCK_1M,
+	52 * CLOCK_1M,
+	78 * CLOCK_1M,
+	104 * CLOCK_1M,
+	104 * CLOCK_1M,
+	156 * CLOCK_1M
+};
+
+unsigned long slave_axi_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	52 * CLOCK_1M,
+	78 * CLOCK_1M,
+	104 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M
+};
+
+unsigned long slave_apb_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	26 * CLOCK_1M,
+	39 * CLOCK_1M,
+	52 * CLOCK_1M,
+	52 * CLOCK_1M,
+	78 * CLOCK_1M
+};
+
+unsigned long esub_freq_tbl[8] = {
+	78 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M,
+	208 * CLOCK_1M,
+	208 * CLOCK_1M,
+	208 * CLOCK_1M
+};
+
+static struct bus_clk_data bsc1_apb_data = {
+	.gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
+};
+
+static struct bus_clk_data bsc2_apb_data = {
+	.gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
+};
+
+static struct bus_clk_data bsc3_apb_data = {
+	.gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
+};
+
+/* * Master CCU clocks */
+static struct peri_clk_data sdio1_data = {
+	.gate		= HW_SW_GATE(0x0358, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a28, 0, 3),
+	.div		= DIVIDER(0x0a28, 4, 14),
+	.trig		= TRIGGER(0x0afc, 9),
+};
+
+static struct peri_clk_data sdio2_data = {
+	.gate		= HW_SW_GATE(0x035c, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a2c, 0, 3),
+	.div		= DIVIDER(0x0a2c, 4, 14),
+	.trig		= TRIGGER(0x0afc, 10),
+};
+
+static struct peri_clk_data sdio3_data = {
+	.gate		= HW_SW_GATE(0x0364, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a34, 0, 3),
+	.div		= DIVIDER(0x0a34, 4, 14),
+	.trig		= TRIGGER(0x0afc, 12),
+};
+
+static struct peri_clk_data sdio4_data = {
+	.gate		= HW_SW_GATE(0x0360, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a30, 0, 3),
+	.div		= DIVIDER(0x0a30, 4, 14),
+	.trig		= TRIGGER(0x0afc, 11),
+};
+
+static struct peri_clk_data sdio1_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x0358, 20, 4),
+};
+
+static struct peri_clk_data sdio2_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x035c, 20, 4),
+};
+
+static struct peri_clk_data sdio3_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x0364, 20, 4),
+};
+
+static struct peri_clk_data sdio4_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x0360, 20, 4),
+};
+
+static struct bus_clk_data usb_otg_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0348, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio1_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio2_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio3_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio4_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
+};
+
+/* * Slave CCU clocks */
+static struct peri_clk_data bsc1_data = {
+	.gate		= HW_SW_GATE(0x0458, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_104m",
+				 "ref_104m",
+				 "var_13m",
+				 "ref_13m"),
+	.sel		= SELECTOR(0x0a64, 0, 3),
+	.trig		= TRIGGER(0x0afc, 23),
+};
+
+static struct peri_clk_data bsc2_data = {
+	.gate		= HW_SW_GATE(0x045c, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_104m",
+				 "ref_104m",
+				 "var_13m",
+				 "ref_13m"),
+	.sel		= SELECTOR(0x0a68, 0, 3),
+	.trig		= TRIGGER(0x0afc, 24),
+};
+
+static struct peri_clk_data bsc3_data = {
+	.gate		= HW_SW_GATE(0x0484, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_104m",
+				 "ref_104m",
+				 "var_13m",
+				 "ref_13m"),
+	.sel		= SELECTOR(0x0a84, 0, 3),
+	.trig		= TRIGGER(0x0b00, 2),
+};
+
+/*
+ * CCU clocks
+ */
+
+static struct ccu_clock kpm_ccu_clk = {
+	.clk = {
+		.name = "kpm_ccu_clk",
+		.ops = &ccu_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.num_policy_masks = 1,
+	.policy_freq_offset = 0x00000008,
+	.freq_bit_shift = 8,
+	.policy_ctl_offset = 0x0000000c,
+	.policy0_mask_offset = 0x00000010,
+	.policy1_mask_offset = 0x00000014,
+	.policy2_mask_offset = 0x00000018,
+	.policy3_mask_offset = 0x0000001c,
+	.lvm_en_offset = 0x00000034,
+	.freq_id = 2,
+	.freq_tbl = master_axi_freq_tbl,
+};
+
+static struct ccu_clock kps_ccu_clk = {
+	.clk = {
+		.name = "kps_ccu_clk",
+		.ops = &ccu_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.num_policy_masks = 1,
+	.policy_freq_offset = 0x00000008,
+	.freq_bit_shift = 8,
+	.policy_ctl_offset = 0x0000000c,
+	.policy0_mask_offset = 0x00000010,
+	.policy1_mask_offset = 0x00000014,
+	.policy2_mask_offset = 0x00000018,
+	.policy3_mask_offset = 0x0000001c,
+	.lvm_en_offset = 0x00000034,
+	.freq_id = 2,
+	.freq_tbl = slave_axi_freq_tbl,
+};
+
+#ifdef CONFIG_BCM_SF2_ETH
+static struct ccu_clock esub_ccu_clk = {
+	.clk = {
+		.name = "esub_ccu_clk",
+		.ops = &ccu_clk_ops,
+		.ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR,
+	},
+	.num_policy_masks = 1,
+	.policy_freq_offset = 0x00000008,
+	.freq_bit_shift = 8,
+	.policy_ctl_offset = 0x0000000c,
+	.policy0_mask_offset = 0x00000010,
+	.policy1_mask_offset = 0x00000014,
+	.policy2_mask_offset = 0x00000018,
+	.policy3_mask_offset = 0x0000001c,
+	.lvm_en_offset = 0x00000034,
+	.freq_id = 2,
+	.freq_tbl = esub_freq_tbl,
+};
+#endif
+
+/*
+ * Bus clocks
+ */
+
+/* KPM bus clocks */
+static struct bus_clock usb_otg_ahb_clk = {
+	.clk = {
+		.name = "usb_otg_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &usb_otg_ahb_data,
+};
+
+static struct bus_clock sdio1_ahb_clk = {
+	.clk = {
+		.name = "sdio1_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio1_ahb_data,
+};
+
+static struct bus_clock sdio2_ahb_clk = {
+	.clk = {
+		.name = "sdio2_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio2_ahb_data,
+};
+
+static struct bus_clock sdio3_ahb_clk = {
+	.clk = {
+		.name = "sdio3_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio3_ahb_data,
+};
+
+static struct bus_clock sdio4_ahb_clk = {
+	.clk = {
+		.name = "sdio4_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio4_ahb_data,
+};
+
+static struct bus_clock bsc1_apb_clk = {
+	.clk = {
+		.name = "bsc1_apb_clk",
+		.parent = &kps_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.freq_tbl = slave_apb_freq_tbl,
+	.data = &bsc1_apb_data,
+};
+
+static struct bus_clock bsc2_apb_clk = {
+	.clk = {
+		.name = "bsc2_apb_clk",
+		.parent = &kps_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+		},
+	.freq_tbl = slave_apb_freq_tbl,
+	.data = &bsc2_apb_data,
+};
+
+static struct bus_clock bsc3_apb_clk = {
+	.clk = {
+		.name = "bsc3_apb_clk",
+		.parent = &kps_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+		},
+	.freq_tbl = slave_apb_freq_tbl,
+	.data = &bsc3_apb_data,
+};
+
+/* KPM peripheral */
+static struct peri_clock sdio1_clk = {
+	.clk = {
+		.name = "sdio1_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio1_data,
+};
+
+static struct peri_clock sdio2_clk = {
+	.clk = {
+		.name = "sdio2_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio2_data,
+};
+
+static struct peri_clock sdio3_clk = {
+	.clk = {
+		.name = "sdio3_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio3_data,
+};
+
+static struct peri_clock sdio4_clk = {
+	.clk = {
+		.name = "sdio4_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio4_data,
+};
+
+static struct peri_clock sdio1_sleep_clk = {
+	.clk = {
+		.name = "sdio1_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio1_sleep_data,
+};
+
+static struct peri_clock sdio2_sleep_clk = {
+	.clk = {
+		.name = "sdio2_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio2_sleep_data,
+};
+
+static struct peri_clock sdio3_sleep_clk = {
+	.clk = {
+		.name = "sdio3_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio3_sleep_data,
+};
+
+static struct peri_clock sdio4_sleep_clk = {
+	.clk = {
+		.name = "sdio4_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio4_sleep_data,
+};
+
+/* KPS peripheral clock */
+static struct peri_clock bsc1_clk = {
+	.clk = {
+		.name = "bsc1_clk",
+		.parent = &ref_13m.clk,
+		.rate = 13 * CLOCK_1M,
+		.div = 1,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.data = &bsc1_data,
+};
+
+static struct peri_clock bsc2_clk = {
+	.clk = {
+		.name = "bsc2_clk",
+		.parent = &ref_13m.clk,
+		.rate = 13 * CLOCK_1M,
+		.div = 1,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.data = &bsc2_data,
+};
+
+static struct peri_clock bsc3_clk = {
+	.clk = {
+		.name = "bsc3_clk",
+		.parent = &ref_13m.clk,
+		.rate = 13 * CLOCK_1M,
+		.div = 1,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.data = &bsc3_data,
+};
+
+/* public table for registering clocks */
+struct clk_lookup arch_clk_tbl[] = {
+	/* Peripheral clocks */
+	CLK_LK(sdio1),
+	CLK_LK(sdio2),
+	CLK_LK(sdio3),
+	CLK_LK(sdio4),
+	CLK_LK(sdio1_sleep),
+	CLK_LK(sdio2_sleep),
+	CLK_LK(sdio3_sleep),
+	CLK_LK(sdio4_sleep),
+	CLK_LK(bsc1),
+	CLK_LK(bsc2),
+	CLK_LK(bsc3),
+	/* Bus clocks */
+	CLK_LK(usb_otg_ahb),
+	CLK_LK(sdio1_ahb),
+	CLK_LK(sdio2_ahb),
+	CLK_LK(sdio3_ahb),
+	CLK_LK(sdio4_ahb),
+	CLK_LK(bsc1_apb),
+	CLK_LK(bsc2_apb),
+	CLK_LK(bsc3_apb),
+#ifdef CONFIG_BCM_SF2_ETH
+	CLK_LK(esub_ccu),
+#endif
+};
+
+/* public array size */
+unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-bsc.c b/arch/arm/cpu/armv7/bcm235xx/clk-bsc.c
new file mode 100644
index 0000000..1b3f36a
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/clk-bsc.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for a BSC/I2C port */
+int clk_bsc_enable(void *base)
+{
+	int ret;
+	char *bscstr, *apbstr;
+
+	switch ((u32) base) {
+	case PMU_BSC_BASE_ADDR:
+		/* PMU clock is always enabled */
+		return 0;
+	case BSC1_BASE_ADDR:
+		bscstr = "bsc1_clk";
+		apbstr = "bsc1_apb_clk";
+		break;
+	case BSC2_BASE_ADDR:
+		bscstr = "bsc2_clk";
+		apbstr = "bsc2_apb_clk";
+		break;
+	case BSC3_BASE_ADDR:
+		bscstr = "bsc3_clk";
+		apbstr = "bsc3_apb_clk";
+		break;
+	default:
+		printf("%s: base 0x%p not found\n", __func__, base);
+		return -EINVAL;
+	}
+
+	/* Note that the bus clock must be enabled first */
+
+	ret = clk_get_and_enable(apbstr);
+	if (ret)
+		return ret;
+
+	ret = clk_get_and_enable(bscstr);
+	if (ret)
+		return ret;
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-core.c b/arch/arm/cpu/armv7/bcm235xx/clk-core.c
new file mode 100644
index 0000000..72f8eb7
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/clk-core.c
@@ -0,0 +1,512 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+/*
+ *
+ * bcm235xx architecture clock framework
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <bitfield.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define CLK_WR_ACCESS_PASSWORD	0x00a5a501
+#define WR_ACCESS_OFFSET	0	/* common to all clock blocks */
+#define POLICY_CTL_GO		1	/* Load and refresh policy masks */
+#define POLICY_CTL_GO_ATL	4	/* Active Load */
+
+/* Helper function */
+int clk_get_and_enable(char *clkstr)
+{
+	int ret = 0;
+	struct clk *c;
+
+	debug("%s: %s\n", __func__, clkstr);
+
+	c = clk_get(clkstr);
+	if (c) {
+		ret = clk_enable(c);
+		if (ret)
+			return ret;
+	} else {
+		printf("%s: Couldn't find %s\n", __func__, clkstr);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Poll a register in a CCU's address space, returning when the
+ * specified bit in that register's value is set (or clear). Delay
+ * a microsecond after each read of the register. Returns true if
+ * successful, or false if we gave up trying.
+ *
+ * Caller must ensure the CCU lock is held.
+ */
+#define CLK_GATE_DELAY_USEC 2000
+static inline int wait_bit(void *base, u32 offset, u32 bit, bool want)
+{
+	unsigned int tries;
+	u32 bit_mask = 1 << bit;
+
+	for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) {
+		u32 val;
+		bool bit_val;
+
+		val = readl(base + offset);
+		bit_val = (val & bit_mask) ? 1 : 0;
+		if (bit_val == want)
+			return 0;	/* success */
+		udelay(1);
+	}
+
+	debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n",
+	      __func__, base + offset, bit, want);
+
+	return -ETIMEDOUT;
+}
+
+/* Enable a peripheral clock */
+static int peri_clk_enable(struct clk *c, int enable)
+{
+	int ret = 0;
+	u32 reg;
+	struct peri_clock *peri_clk = to_peri_clk(c);
+	struct peri_clk_data *cd = peri_clk->data;
+	struct bcm_clk_gate *gate = &cd->gate;
+	void *base = (void *)c->ccu_clk_mgr_base;
+
+
+	debug("%s: %s\n", __func__, c->name);
+
+	clk_get_rate(c);	/* Make sure rate and sel are filled in */
+
+	/* enable access */
+	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+	if (enable) {
+		debug("%s %s set rate %lu div %lu sel %d parent %lu\n",
+		      __func__, c->name, c->rate, c->div, c->sel,
+		      c->parent->rate);
+
+		/*
+		 * clkgate - only software controllable gates are
+		 * supported by u-boot which includes all clocks
+		 * that matter. This avoids bringing in a lot of extra
+		 * complexity as done in the kernel framework.
+		 */
+		if (gate_exists(gate)) {
+			reg = readl(base + cd->gate.offset);
+			reg |= (1 << cd->gate.en_bit);
+			writel(reg, base + cd->gate.offset);
+		}
+
+		/* div and pll select */
+		if (divider_exists(&cd->div)) {
+			reg = readl(base + cd->div.offset);
+			bitfield_replace(reg, cd->div.shift, cd->div.width,
+					 c->div - 1);
+			writel(reg, base + cd->div.offset);
+		}
+
+		/* frequency selector */
+		if (selector_exists(&cd->sel)) {
+			reg = readl(base + cd->sel.offset);
+			bitfield_replace(reg, cd->sel.shift, cd->sel.width,
+					 c->sel);
+			writel(reg, base + cd->sel.offset);
+		}
+
+		/* trigger */
+		if (trigger_exists(&cd->trig)) {
+			writel((1 << cd->trig.bit), base + cd->trig.offset);
+
+			/* wait for trigger status bit to go to 0 */
+			ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0);
+			if (ret)
+				return ret;
+		}
+
+		/* wait for running (status_bit = 1) */
+		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1);
+		if (ret)
+			return ret;
+	} else {
+		debug("%s disable clock %s\n", __func__, c->name);
+
+		/* clkgate */
+		reg = readl(base + cd->gate.offset);
+		reg &= ~(1 << cd->gate.en_bit);
+		writel(reg, base + cd->gate.offset);
+
+		/* wait for stop (status_bit = 0) */
+		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0);
+	}
+
+	/* disable access */
+	writel(0, base + WR_ACCESS_OFFSET);
+
+	return ret;
+}
+
+/* Set the rate of a peripheral clock */
+static int peri_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret = 0;
+	int i;
+	unsigned long diff;
+	unsigned long new_rate = 0, div = 1;
+	struct peri_clock *peri_clk = to_peri_clk(c);
+	struct peri_clk_data *cd = peri_clk->data;
+	const char **clock;
+
+	debug("%s: %s\n", __func__, c->name);
+	diff = rate;
+
+	i = 0;
+	for (clock = cd->clocks; *clock; clock++, i++) {
+		struct refclk *ref = refclk_str_to_clk(*clock);
+		if (!ref) {
+			printf("%s: Lookup of %s failed\n", __func__, *clock);
+			return -EINVAL;
+		}
+
+		/* round to the new rate */
+		div = ref->clk.rate / rate;
+		if (div == 0)
+			div = 1;
+
+		new_rate = ref->clk.rate / div;
+
+		/* get the min diff */
+		if (abs(new_rate - rate) < diff) {
+			diff = abs(new_rate - rate);
+			c->sel = i;
+			c->parent = &ref->clk;
+			c->rate = new_rate;
+			c->div = div;
+		}
+	}
+
+	debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__,
+	      c->name, c->rate, c->div, c->sel, c->parent->rate);
+	return ret;
+}
+
+/* Get the rate of a peripheral clock */
+static unsigned long peri_clk_get_rate(struct clk *c)
+{
+	struct peri_clock *peri_clk = to_peri_clk(c);
+	struct peri_clk_data *cd = peri_clk->data;
+	void *base = (void *)c->ccu_clk_mgr_base;
+	int div = 1;
+	const char **clock;
+	struct refclk *ref;
+	u32 reg;
+
+	debug("%s: %s\n", __func__, c->name);
+	if (selector_exists(&cd->sel)) {
+		reg = readl(base + cd->sel.offset);
+		c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width);
+	} else {
+		/*
+		 * For peri clocks that don't have a selector, the single
+		 * reference clock will always exist at index 0.
+		 */
+		c->sel = 0;
+	}
+
+	if (divider_exists(&cd->div)) {
+		reg = readl(base + cd->div.offset);
+		div = bitfield_extract(reg, cd->div.shift, cd->div.width);
+		div += 1;
+	}
+
+	clock = cd->clocks;
+	ref = refclk_str_to_clk(clock[c->sel]);
+	if (!ref) {
+		printf("%s: Can't lookup %s\n", __func__, clock[c->sel]);
+		return 0;
+	}
+
+	c->parent = &ref->clk;
+	c->div = div;
+	c->rate = c->parent->rate / c->div;
+	debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__,
+	      c->parent->rate, div, c->sel, c->rate);
+
+	return c->rate;
+}
+
+/* Peripheral clock operations */
+struct clk_ops peri_clk_ops = {
+	.enable = peri_clk_enable,
+	.set_rate = peri_clk_set_rate,
+	.get_rate = peri_clk_get_rate,
+};
+
+/* Enable a CCU clock */
+static int ccu_clk_enable(struct clk *c, int enable)
+{
+	struct ccu_clock *ccu_clk = to_ccu_clk(c);
+	void *base = (void *)c->ccu_clk_mgr_base;
+	int ret = 0;
+	u32 reg;
+
+	debug("%s: %s\n", __func__, c->name);
+	if (!enable)
+		return -EINVAL;	/* CCU clock cannot shutdown */
+
+	/* enable access */
+	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+	/* config enable for policy engine */
+	writel(1, base + ccu_clk->lvm_en_offset);
+
+	/* wait for bit to go to 0 */
+	ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0);
+	if (ret)
+		return ret;
+
+	/* freq ID */
+	if (!ccu_clk->freq_bit_shift)
+		ccu_clk->freq_bit_shift = 8;
+
+	/* Set frequency id for each of the 4 policies */
+	reg = ccu_clk->freq_id |
+	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) |
+	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) |
+	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3));
+	writel(reg, base + ccu_clk->policy_freq_offset);
+
+	/* enable all clock mask */
+	writel(0x7fffffff, base + ccu_clk->policy0_mask_offset);
+	writel(0x7fffffff, base + ccu_clk->policy1_mask_offset);
+	writel(0x7fffffff, base + ccu_clk->policy2_mask_offset);
+	writel(0x7fffffff, base + ccu_clk->policy3_mask_offset);
+
+	if (ccu_clk->num_policy_masks == 2) {
+		writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset);
+		writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset);
+		writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset);
+		writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset);
+	}
+
+	/* start policy engine */
+	reg = readl(base + ccu_clk->policy_ctl_offset);
+	reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL);
+	writel(reg, base + ccu_clk->policy_ctl_offset);
+
+	/* wait till started */
+	ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0);
+	if (ret)
+		return ret;
+
+	/* disable access */
+	writel(0, base + WR_ACCESS_OFFSET);
+
+	return ret;
+}
+
+/* Get the CCU clock rate */
+static unsigned long ccu_clk_get_rate(struct clk *c)
+{
+	struct ccu_clock *ccu_clk = to_ccu_clk(c);
+	debug("%s: %s\n", __func__, c->name);
+	c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id];
+	return c->rate;
+}
+
+/* CCU clock operations */
+struct clk_ops ccu_clk_ops = {
+	.enable = ccu_clk_enable,
+	.get_rate = ccu_clk_get_rate,
+};
+
+/* Enable a bus clock */
+static int bus_clk_enable(struct clk *c, int enable)
+{
+	struct bus_clock *bus_clk = to_bus_clk(c);
+	struct bus_clk_data *cd = bus_clk->data;
+	void *base = (void *)c->ccu_clk_mgr_base;
+	int ret = 0;
+	u32 reg;
+
+	debug("%s: %s\n", __func__, c->name);
+	/* enable access */
+	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+	/* enable gating */
+	reg = readl(base + cd->gate.offset);
+	if (!!(reg & (1 << cd->gate.status_bit)) == !!enable)
+		debug("%s already %s\n", c->name,
+		      enable ? "enabled" : "disabled");
+	else {
+		int want = (enable) ? 1 : 0;
+		reg |= (1 << cd->gate.hw_sw_sel_bit);
+
+		if (enable)
+			reg |= (1 << cd->gate.en_bit);
+		else
+			reg &= ~(1 << cd->gate.en_bit);
+
+		writel(reg, base + cd->gate.offset);
+		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit,
+			       want);
+		if (ret)
+			return ret;
+	}
+
+	/* disable access */
+	writel(0, base + WR_ACCESS_OFFSET);
+
+	return ret;
+}
+
+/* Get the rate of a bus clock */
+static unsigned long bus_clk_get_rate(struct clk *c)
+{
+	struct bus_clock *bus_clk = to_bus_clk(c);
+	struct ccu_clock *ccu_clk;
+
+	debug("%s: %s\n", __func__, c->name);
+	ccu_clk = to_ccu_clk(c->parent);
+
+	c->rate = bus_clk->freq_tbl[ccu_clk->freq_id];
+	c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate;
+	return c->rate;
+}
+
+/* Bus clock operations */
+struct clk_ops bus_clk_ops = {
+	.enable = bus_clk_enable,
+	.get_rate = bus_clk_get_rate,
+};
+
+/* Enable a reference clock */
+static int ref_clk_enable(struct clk *c, int enable)
+{
+	debug("%s: %s\n", __func__, c->name);
+	return 0;
+}
+
+/* Reference clock operations */
+struct clk_ops ref_clk_ops = {
+	.enable = ref_clk_enable,
+};
+
+/*
+ * clk.h implementation follows
+ */
+
+/* Initialize the clock framework */
+int clk_init(void)
+{
+	debug("%s:\n", __func__);
+	return 0;
+}
+
+/* Get a clock handle, give a name string */
+struct clk *clk_get(const char *con_id)
+{
+	int i;
+	struct clk_lookup *clk_tblp;
+
+	debug("%s: %s\n", __func__, con_id);
+
+	clk_tblp = arch_clk_tbl;
+	for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) {
+		if (clk_tblp->con_id) {
+			if (!con_id || strcmp(clk_tblp->con_id, con_id))
+				continue;
+			return clk_tblp->clk;
+		}
+	}
+	return NULL;
+}
+
+/* Enable a clock */
+int clk_enable(struct clk *c)
+{
+	int ret = 0;
+
+	debug("%s: %s\n", __func__, c->name);
+	if (!c->ops || !c->ops->enable)
+		return -1;
+
+	/* enable parent clock first */
+	if (c->parent)
+		ret = clk_enable(c->parent);
+
+	if (ret)
+		return ret;
+
+	if (!c->use_cnt)
+		ret = c->ops->enable(c, 1);
+	c->use_cnt++;
+
+	return ret;
+}
+
+/* Disable a clock */
+void clk_disable(struct clk *c)
+{
+	debug("%s: %s\n", __func__, c->name);
+	if (!c->ops || !c->ops->enable)
+		return;
+
+	if (c->use_cnt > 0) {
+		c->use_cnt--;
+		if (c->use_cnt == 0)
+			c->ops->enable(c, 0);
+	}
+
+	/* disable parent */
+	if (c->parent)
+		clk_disable(c->parent);
+}
+
+/* Get the clock rate */
+unsigned long clk_get_rate(struct clk *c)
+{
+	unsigned long rate;
+
+	if (!c || !c->ops || !c->ops->get_rate)
+		return 0;
+	debug("%s: %s\n", __func__, c->name);
+
+	rate = c->ops->get_rate(c);
+	debug("%s: rate = %ld\n", __func__, rate);
+	return rate;
+}
+
+/* Set the clock rate */
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+
+	if (!c || !c->ops || !c->ops->set_rate)
+		return -EINVAL;
+	debug("%s: %s rate=%ld\n", __func__, c->name, rate);
+
+	if (c->use_cnt)
+		return -EINVAL;
+
+	ret = c->ops->set_rate(c, rate);
+
+	return ret;
+}
+
+/* Not required for this arch */
+/*
+long clk_round_rate(struct clk *clk, unsigned long rate);
+int clk_set_parent(struct clk *clk, struct clk *parent);
+struct clk *clk_get_parent(struct clk *clk);
+*/
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-core.h b/arch/arm/cpu/armv7/bcm235xx/clk-core.h
new file mode 100644
index 0000000..ac475b6
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/clk-core.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <linux/stddef.h>
+
+#ifdef CONFIG_CLK_DEBUG
+#undef writel
+#undef readl
+static inline void writel(u32 val, void *addr)
+{
+	printf("Write [0x%p] = 0x%08x\n", addr, val);
+	*(u32 *)addr = val;
+}
+
+static inline u32 readl(void *addr)
+{
+	u32 val = *(u32 *)addr;
+	printf("Read  [0x%p] = 0x%08x\n", addr, val);
+	return val;
+}
+#endif
+
+struct clk;
+
+struct clk_lookup {
+	const char *dev_id;
+	const char *con_id;
+	struct clk *clk;
+};
+
+extern struct clk_lookup arch_clk_tbl[];
+extern unsigned int arch_clk_tbl_array_size;
+
+/**
+ * struct clk_ops - standard clock operations
+ * @enable: enable/disable clock, see clk_enable() and clk_disable()
+ * @set_rate: set the clock rate, see clk_set_rate().
+ * @get_rate: get the clock rate, see clk_get_rate().
+ * @round_rate: round a given clock rate, see clk_round_rate().
+ * @set_parent: set the clock's parent, see clk_set_parent().
+ *
+ * Group the common clock implementations together so that we
+ * don't have to keep setting the same fiels again. We leave
+ * enable in struct clk.
+ *
+ */
+struct clk_ops {
+	int (*enable)(struct clk *c, int enable);
+	int (*set_rate)(struct clk *c, unsigned long rate);
+	unsigned long (*get_rate)(struct clk *c);
+	unsigned long (*round_rate)(struct clk *c, unsigned long rate);
+	int (*set_parent)(struct clk *c, struct clk *parent);
+};
+
+struct clk {
+	struct clk *parent;
+	const char *name;
+	int use_cnt;
+	unsigned long rate;	/* in HZ */
+
+	/* programmable divider. 0 means fixed ratio to parent clock */
+	unsigned long div;
+
+	struct clk_src *src;
+	struct clk_ops *ops;
+
+	unsigned long ccu_clk_mgr_base;
+	int sel;
+};
+
+struct refclk *refclk_str_to_clk(const char *name);
+
+/* The common clock framework uses u8 to represent a parent index */
+#define PARENT_COUNT_MAX	((u32)U8_MAX)
+
+#define BAD_CLK_INDEX		U8_MAX	/* Can't ever be valid */
+#define BAD_CLK_NAME		((const char *)-1)
+
+#define BAD_SCALED_DIV_VALUE	U64_MAX
+
+/*
+ * Utility macros for object flag management. If possible, flags
+ * should be defined such that 0 is the desired default value.
+ */
+#define FLAG(type, flag)		BCM_CLK_ ## type ## _FLAGS_ ## flag
+#define FLAG_SET(obj, type, flag)	((obj)->flags |= FLAG(type, flag))
+#define FLAG_CLEAR(obj, type, flag)	((obj)->flags &= ~(FLAG(type, flag)))
+#define FLAG_FLIP(obj, type, flag)	((obj)->flags ^= FLAG(type, flag))
+#define FLAG_TEST(obj, type, flag)	(!!((obj)->flags & FLAG(type, flag)))
+
+/* Clock field state tests */
+
+#define gate_exists(gate)		FLAG_TEST(gate, GATE, EXISTS)
+#define gate_is_enabled(gate)		FLAG_TEST(gate, GATE, ENABLED)
+#define gate_is_hw_controllable(gate)	FLAG_TEST(gate, GATE, HW)
+#define gate_is_sw_controllable(gate)	FLAG_TEST(gate, GATE, SW)
+#define gate_is_sw_managed(gate)	FLAG_TEST(gate, GATE, SW_MANAGED)
+#define gate_is_no_disable(gate)	FLAG_TEST(gate, GATE, NO_DISABLE)
+
+#define gate_flip_enabled(gate)		FLAG_FLIP(gate, GATE, ENABLED)
+
+#define divider_exists(div)		FLAG_TEST(div, DIV, EXISTS)
+#define divider_is_fixed(div)		FLAG_TEST(div, DIV, FIXED)
+#define divider_has_fraction(div)	(!divider_is_fixed(div) && \
+						(div)->frac_width > 0)
+
+#define selector_exists(sel)		((sel)->width != 0)
+#define trigger_exists(trig)		FLAG_TEST(trig, TRIG, EXISTS)
+
+/* Clock type, used to tell common block what it's part of */
+enum bcm_clk_type {
+	bcm_clk_none,		/* undefined clock type */
+	bcm_clk_bus,
+	bcm_clk_core,
+	bcm_clk_peri
+};
+
+/*
+ * Gating control and status is managed by a 32-bit gate register.
+ *
+ * There are several types of gating available:
+ * - (no gate)
+ *     A clock with no gate is assumed to be always enabled.
+ * - hardware-only gating (auto-gating)
+ *     Enabling or disabling clocks with this type of gate is
+ *     managed automatically by the hardware. Such clocks can be
+ *     considered by the software to be enabled. The current status
+ *     of auto-gated clocks can be read from the gate status bit.
+ * - software-only gating
+ *     Auto-gating is not available for this type of clock.
+ *     Instead, software manages whether it's enabled by setting or
+ *     clearing the enable bit. The current gate status of a gate
+ *     under software control can be read from the gate status bit.
+ *     To ensure a change to the gating status is complete, the
+ *     status bit can be polled to verify that the gate has entered
+ *     the desired state.
+ * - selectable hardware or software gating
+ *     Gating for this type of clock can be configured to be either
+ *     under software or hardware control. Which type is in use is
+ *     determined by the hw_sw_sel bit of the gate register.
+ */
+struct bcm_clk_gate {
+	u32 offset;		/* gate register offset */
+	u32 status_bit;		/* 0: gate is disabled; 0: gatge is enabled */
+	u32 en_bit;		/* 0: disable; 1: enable */
+	u32 hw_sw_sel_bit;	/* 0: hardware gating; 1: software gating */
+	u32 flags;		/* BCM_CLK_GATE_FLAGS_* below */
+};
+
+/*
+ * Gate flags:
+ *   HW         means this gate can be auto-gated
+ *   SW         means the state of this gate can be software controlled
+ *   NO_DISABLE means this gate is (only) enabled if under software control
+ *   SW_MANAGED means the status of this gate is under software control
+ *   ENABLED    means this software-managed gate is *supposed* to be enabled
+ */
+#define BCM_CLK_GATE_FLAGS_EXISTS	((u32)1 << 0)	/* Gate is valid */
+#define BCM_CLK_GATE_FLAGS_HW		((u32)1 << 1)	/* Can auto-gate */
+#define BCM_CLK_GATE_FLAGS_SW		((u32)1 << 2)	/* Software control */
+#define BCM_CLK_GATE_FLAGS_NO_DISABLE	((u32)1 << 3)	/* HW or enabled */
+#define BCM_CLK_GATE_FLAGS_SW_MANAGED	((u32)1 << 4)	/* SW now in control */
+#define BCM_CLK_GATE_FLAGS_ENABLED	((u32)1 << 5)	/* If SW_MANAGED */
+
+/*
+ * Gate initialization macros.
+ *
+ * Any gate initially under software control will be enabled.
+ */
+
+/* A hardware/software gate initially under software control */
+#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)	\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.hw_sw_sel_bit = (_hw_sw_sel_bit),			\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, SW)|			\
+			FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)|	\
+			FLAG(GATE, EXISTS),				\
+	}
+
+/* A hardware/software gate initially under hardware control */
+#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)	\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.hw_sw_sel_bit = (_hw_sw_sel_bit),			\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, SW)|			\
+			FLAG(GATE, EXISTS),				\
+	}
+
+/* A hardware-or-enabled gate (enabled if not under hardware control) */
+#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)	\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.hw_sw_sel_bit = (_hw_sw_sel_bit),			\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, SW)|			\
+			FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS),	\
+	}
+
+/* A software-only gate */
+#define SW_ONLY_GATE(_offset, _status_bit, _en_bit)			\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)|		\
+			FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS),		\
+	}
+
+/* A hardware-only gate */
+#define HW_ONLY_GATE(_offset, _status_bit)				\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS),		\
+	}
+
+/*
+ * Each clock can have zero, one, or two dividers which change the
+ * output rate of the clock. Each divider can be either fixed or
+ * variable. If there are two dividers, they are the "pre-divider"
+ * and the "regular" or "downstream" divider. If there is only one,
+ * there is no pre-divider.
+ *
+ * A fixed divider is any non-zero (positive) value, and it
+ * indicates how the input rate is affected by the divider.
+ *
+ * The value of a variable divider is maintained in a sub-field of a
+ * 32-bit divider register. The position of the field in the
+ * register is defined by its offset and width. The value recorded
+ * in this field is always 1 less than the value it represents.
+ *
+ * In addition, a variable divider can indicate that some subset
+ * of its bits represent a "fractional" part of the divider. Such
+ * bits comprise the low-order portion of the divider field, and can
+ * be viewed as representing the portion of the divider that lies to
+ * the right of the decimal point. Most variable dividers have zero
+ * fractional bits. Variable dividers with non-zero fraction width
+ * still record a value 1 less than the value they represent; the
+ * added 1 does *not* affect the low-order bit in this case, it
+ * affects the bits above the fractional part only. (Often in this
+ * code a divider field value is distinguished from the value it
+ * represents by referring to the latter as a "divisor".)
+ *
+ * In order to avoid dealing with fractions, divider arithmetic is
+ * performed using "scaled" values. A scaled value is one that's
+ * been left-shifted by the fractional width of a divider. Dividing
+ * a scaled value by a scaled divisor produces the desired quotient
+ * without loss of precision and without any other special handling
+ * for fractions.
+ *
+ * The recorded value of a variable divider can be modified. To
+ * modify either divider (or both), a clock must be enabled (i.e.,
+ * using its gate). In addition, a trigger register (described
+ * below) must be used to commit the change, and polled to verify
+ * the change is complete.
+ */
+struct bcm_clk_div {
+	union {
+		struct {	/* variable divider */
+			u32 offset;	/* divider register offset */
+			u32 shift;	/* field shift */
+			u32 width;	/* field width */
+			u32 frac_width;	/* field fraction width */
+
+			u64 scaled_div;	/* scaled divider value */
+		};
+		u32 fixed;	/* non-zero fixed divider value */
+	};
+	u32 flags;		/* BCM_CLK_DIV_FLAGS_* below */
+};
+
+/*
+ * Divider flags:
+ *   EXISTS means this divider exists
+ *   FIXED means it is a fixed-rate divider
+ */
+#define BCM_CLK_DIV_FLAGS_EXISTS	((u32)1 << 0)	/* Divider is valid */
+#define BCM_CLK_DIV_FLAGS_FIXED		((u32)1 << 1)	/* Fixed-value */
+
+/* Divider initialization macros */
+
+/* A fixed (non-zero) divider */
+#define FIXED_DIVIDER(_value)						\
+	{								\
+		.fixed = (_value),					\
+		.flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED),		\
+	}
+
+/* A divider with an integral divisor */
+#define DIVIDER(_offset, _shift, _width)				\
+	{								\
+		.offset = (_offset),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.scaled_div = BAD_SCALED_DIV_VALUE,			\
+		.flags = FLAG(DIV, EXISTS),				\
+	}
+
+/* A divider whose divisor has an integer and fractional part */
+#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width)		\
+	{								\
+		.offset = (_offset),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.frac_width = (_frac_width),				\
+		.scaled_div = BAD_SCALED_DIV_VALUE,			\
+		.flags = FLAG(DIV, EXISTS),				\
+	}
+
+/*
+ * Clocks may have multiple "parent" clocks. If there is more than
+ * one, a selector must be specified to define which of the parent
+ * clocks is currently in use. The selected clock is indicated in a
+ * sub-field of a 32-bit selector register. The range of
+ * representable selector values typically exceeds the number of
+ * available parent clocks. Occasionally the reset value of a
+ * selector field is explicitly set to a (specific) value that does
+ * not correspond to a defined input clock.
+ *
+ * We register all known parent clocks with the common clock code
+ * using a packed array (i.e., no empty slots) of (parent) clock
+ * names, and refer to them later using indexes into that array.
+ * We maintain an array of selector values indexed by common clock
+ * index values in order to map between these common clock indexes
+ * and the selector values used by the hardware.
+ *
+ * Like dividers, a selector can be modified, but to do so a clock
+ * must be enabled, and a trigger must be used to commit the change.
+ */
+struct bcm_clk_sel {
+	u32 offset;		/* selector register offset */
+	u32 shift;		/* field shift */
+	u32 width;		/* field width */
+
+	u32 parent_count;	/* number of entries in parent_sel[] */
+	u32 *parent_sel;	/* array of parent selector values */
+	u8 clk_index;		/* current selected index in parent_sel[] */
+};
+
+/* Selector initialization macro */
+#define SELECTOR(_offset, _shift, _width)				\
+	{								\
+		.offset = (_offset),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.clk_index = BAD_CLK_INDEX,				\
+	}
+
+/*
+ * Making changes to a variable divider or a selector for a clock
+ * requires the use of a trigger. A trigger is defined by a single
+ * bit within a register. To signal a change, a 1 is written into
+ * that bit. To determine when the change has been completed, that
+ * trigger bit is polled; the read value will be 1 while the change
+ * is in progress, and 0 when it is complete.
+ *
+ * Occasionally a clock will have more than one trigger. In this
+ * case, the "pre-trigger" will be used when changing a clock's
+ * selector and/or its pre-divider.
+ */
+struct bcm_clk_trig {
+	u32 offset;		/* trigger register offset */
+	u32 bit;		/* trigger bit */
+	u32 flags;		/* BCM_CLK_TRIG_FLAGS_* below */
+};
+
+/*
+ * Trigger flags:
+ *   EXISTS means this trigger exists
+ */
+#define BCM_CLK_TRIG_FLAGS_EXISTS	((u32)1 << 0)	/* Trigger is valid */
+
+/* Trigger initialization macro */
+#define TRIGGER(_offset, _bit)						\
+	{								\
+		.offset = (_offset),					\
+		.bit = (_bit),						\
+		.flags = FLAG(TRIG, EXISTS),				\
+	}
+
+struct bus_clk_data {
+	struct bcm_clk_gate gate;
+};
+
+struct core_clk_data {
+	struct bcm_clk_gate gate;
+};
+
+struct peri_clk_data {
+	struct bcm_clk_gate gate;
+	struct bcm_clk_trig pre_trig;
+	struct bcm_clk_div pre_div;
+	struct bcm_clk_trig trig;
+	struct bcm_clk_div div;
+	struct bcm_clk_sel sel;
+	const char *clocks[];	/* must be last; use CLOCKS() to declare */
+};
+#define CLOCKS(...)	{ __VA_ARGS__, NULL, }
+#define NO_CLOCKS	{ NULL, }	/* Must use of no parent clocks */
+
+struct refclk {
+	struct clk clk;
+};
+
+struct peri_clock {
+	struct clk clk;
+	struct peri_clk_data *data;
+};
+
+struct ccu_clock {
+	struct clk clk;
+
+	int num_policy_masks;
+	unsigned long policy_freq_offset;
+	int freq_bit_shift;	/* 8 for most CCUs */
+	unsigned long policy_ctl_offset;
+	unsigned long policy0_mask_offset;
+	unsigned long policy1_mask_offset;
+	unsigned long policy2_mask_offset;
+	unsigned long policy3_mask_offset;
+	unsigned long policy0_mask2_offset;
+	unsigned long policy1_mask2_offset;
+	unsigned long policy2_mask2_offset;
+	unsigned long policy3_mask2_offset;
+	unsigned long lvm_en_offset;
+
+	int freq_id;
+	unsigned long *freq_tbl;
+};
+
+struct bus_clock {
+	struct clk clk;
+	struct bus_clk_data *data;
+	unsigned long *freq_tbl;
+};
+
+struct ref_clock {
+	struct clk clk;
+};
+
+static inline int is_same_clock(struct clk *a, struct clk *b)
+{
+	return a == b;
+}
+
+#define to_clk(p) (&((p)->clk))
+#define name_to_clk(name) (&((name##_clk).clk))
+/* declare a struct clk_lookup */
+#define CLK_LK(name) \
+{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),}
+
+static inline struct refclk *to_refclk(struct clk *clock)
+{
+	return container_of(clock, struct refclk, clk);
+}
+
+static inline struct peri_clock *to_peri_clk(struct clk *clock)
+{
+	return container_of(clock, struct peri_clock, clk);
+}
+
+static inline struct ccu_clock *to_ccu_clk(struct clk *clock)
+{
+	return container_of(clock, struct ccu_clock, clk);
+}
+
+static inline struct bus_clock *to_bus_clk(struct clk *clock)
+{
+	return container_of(clock, struct bus_clock, clk);
+}
+
+static inline struct ref_clock *to_ref_clk(struct clk *clock)
+{
+	return container_of(clock, struct ref_clock, clk);
+}
+
+extern struct clk_ops peri_clk_ops;
+extern struct clk_ops ccu_clk_ops;
+extern struct clk_ops bus_clk_ops;
+extern struct clk_ops ref_clk_ops;
+
+int clk_get_and_enable(char *clkstr);
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-eth.c b/arch/arm/cpu/armv7/bcm235xx/clk-eth.c
new file mode 100644
index 0000000..618af70
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/clk-eth.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define WR_ACCESS_ADDR			ESUB_CLK_BASE_ADDR
+#define WR_ACCESS_PASSWORD				0xA5A500
+
+#define PLLE_POST_RESETB_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000C00)
+
+#define PLLE_RESETB_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000C58)
+#define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK		0x00010000
+#define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK	0x00000001
+
+#define PLL_LOCK_ADDR			(ESUB_CLK_BASE_ADDR + 0x00000C38)
+#define PLL_LOCK_PLL_LOCK_PLLE_MASK			0x00000001
+
+#define ESW_SYS_DIV_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000A04)
+#define ESW_SYS_DIV_PLL_SELECT_MASK			0x00000300
+#define ESW_SYS_DIV_DIV_MASK				0x0000001C
+#define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT		0x00000100
+#define ESW_SYS_DIV_DIV_SELECT				0x4
+#define ESW_SYS_DIV_TRIGGER_MASK			0x00000001
+
+#define ESUB_AXI_DIV_DEBUG_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000E04)
+#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK		0x0000001C
+#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK	0x00000040
+#define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT	0x0
+#define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK			0x00000001
+
+#define PLL_MAX_RETRY	100
+
+/* Enable appropriate clocks for Ethernet */
+int clk_eth_enable(void)
+{
+	int rc = -1;
+	int retry_count = 0;
+	rc = clk_get_and_enable("esub_ccu_clk");
+
+	/* Enable Access to CCU registers */
+	writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR);
+
+	writel(readl(PLLE_POST_RESETB_ADDR) &
+	       ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
+	       PLLE_POST_RESETB_ADDR);
+
+	/* Take PLL out of reset and put into normal mode */
+	writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK,
+	       PLLE_RESETB_ADDR);
+
+	/* Wait for PLL lock */
+	rc = -1;
+	while (retry_count < PLL_MAX_RETRY) {
+		udelay(100);
+		if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) {
+			rc = 0;
+			break;
+		}
+		retry_count++;
+	}
+
+	if (rc == -1) {
+		printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n",
+		       __func__);
+		return -1;
+	}
+
+	writel(readl(PLLE_POST_RESETB_ADDR) |
+	       PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
+	       PLLE_POST_RESETB_ADDR);
+
+	/* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */
+	writel((readl(ESW_SYS_DIV_ADDR) &
+		~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) |
+	       ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT,
+	       ESW_SYS_DIV_ADDR);
+
+	writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK,
+	       ESW_SYS_DIV_ADDR);
+
+	/* Wait for trigger complete */
+	rc = -1;
+	retry_count = 0;
+	while (retry_count < PLL_MAX_RETRY) {
+		udelay(100);
+		if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) {
+			rc = 0;
+			break;
+		}
+		retry_count++;
+	}
+
+	if (rc == -1) {
+		printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n",
+		       __func__);
+		return -1;
+	}
+
+	/* switch Esub AXI clock to 208MHz */
+	writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) &
+		~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK |
+		  ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK |
+		  ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) |
+	       ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT |
+	       ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK,
+	       ESUB_AXI_DIV_DEBUG_ADDR);
+
+	writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) |
+	       ESUB_AXI_DIV_DEBUG_TRIGGER_MASK,
+	       ESUB_AXI_DIV_DEBUG_ADDR);
+
+	/* Wait for trigger complete */
+	rc = -1;
+	retry_count = 0;
+	while (retry_count < PLL_MAX_RETRY) {
+		udelay(100);
+		if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) &
+		      ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) {
+			rc = 0;
+			break;
+		}
+		retry_count++;
+	}
+
+	if (rc == -1) {
+		printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n",
+		       __func__);
+		return -1;
+	}
+
+	/* Disable Access to CCU registers */
+	writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR);
+
+	return rc;
+}
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-sdio.c b/arch/arm/cpu/armv7/bcm235xx/clk-sdio.c
new file mode 100644
index 0000000..f2ba354
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/clk-sdio.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for an SDIO port */
+int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep)
+{
+	int ret;
+	struct clk *c;
+
+	char *clkstr;
+	char *slpstr;
+	char *ahbstr;
+
+	switch ((u32) base) {
+	case CONFIG_SYS_SDIO_BASE0:
+		clkstr = CONFIG_SYS_SDIO0 "_clk";
+		ahbstr = CONFIG_SYS_SDIO0 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO0 "_sleep_clk";
+		break;
+	case CONFIG_SYS_SDIO_BASE1:
+		clkstr = CONFIG_SYS_SDIO1 "_clk";
+		ahbstr = CONFIG_SYS_SDIO1 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO1 "_sleep_clk";
+		break;
+	case CONFIG_SYS_SDIO_BASE2:
+		clkstr = CONFIG_SYS_SDIO2 "_clk";
+		ahbstr = CONFIG_SYS_SDIO2 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO2 "_sleep_clk";
+		break;
+	case CONFIG_SYS_SDIO_BASE3:
+		clkstr = CONFIG_SYS_SDIO3 "_clk";
+		ahbstr = CONFIG_SYS_SDIO3 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO3 "_sleep_clk";
+		break;
+	default:
+		printf("%s: base 0x%p not found\n", __func__, base);
+		return -EINVAL;
+	}
+
+	ret = clk_get_and_enable(ahbstr);
+	if (ret)
+		return ret;
+
+	ret = clk_get_and_enable(slpstr);
+	if (ret)
+		return ret;
+
+	c = clk_get(clkstr);
+	if (c) {
+		ret = clk_set_rate(c, rate);
+		if (ret)
+			return ret;
+
+		ret = clk_enable(c);
+		if (ret)
+			return ret;
+	} else {
+		printf("%s: Couldn't find %s\n", __func__, clkstr);
+		return -EINVAL;
+	}
+	*actual_ratep = rate;
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-usb-otg.c b/arch/arm/cpu/armv7/bcm235xx/clk-usb-otg.c
new file mode 100644
index 0000000..f604aec
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm235xx/clk-usb-otg.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for the USB OTG port */
+int clk_usb_otg_enable(void *base)
+{
+	char *ahbstr;
+
+	switch ((u32) base) {
+	case HSOTG_BASE_ADDR:
+		ahbstr = "usb_otg_ahb_clk";
+		break;
+	default:
+		printf("%s: base 0x%p not found\n", __func__, base);
+		return -EINVAL;
+	}
+
+	return clk_get_and_enable(ahbstr);
+}
diff --git a/arch/arm/cpu/armv7/bcm281xx/Makefile b/arch/arm/cpu/armv7/bcm281xx/Makefile
new file mode 100644
index 0000000..e509997
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2013 Broadcom Corporation.
+
+obj-y	+= reset.o
+obj-y	+= clk-core.o
+obj-y	+= clk-bcm281xx.o
+obj-y	+= clk-sdio.o
+obj-y	+= clk-bsc.o
+obj-$(CONFIG_BCM_SF2_ETH) += clk-eth.o
+obj-y	+= clk-usb-otg.o
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c b/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
new file mode 100644
index 0000000..8f6260e
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
@@ -0,0 +1,572 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+/*
+ *
+ * bcm281xx-specific clock tables
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define CLOCK_1K		1000
+#define CLOCK_1M		(CLOCK_1K * 1000)
+
+/* declare a reference clock */
+#define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \
+static struct refclk clk_name = { \
+	.clk    =       { \
+		.name   =       #clk_name, \
+		.parent =       clk_parent, \
+		.rate   =       clk_rate, \
+		.div    =       clk_div, \
+		.ops    =       &ref_clk_ops, \
+	}, \
+}
+
+/*
+ * Reference clocks
+ */
+
+/* Declare a list of reference clocks */
+DECLARE_REF_CLK(ref_crystal,	0,		26  * CLOCK_1M,	1);
+DECLARE_REF_CLK(var_96m,	0,		96  * CLOCK_1M,	1);
+DECLARE_REF_CLK(ref_96m,	0,		96  * CLOCK_1M,	1);
+DECLARE_REF_CLK(ref_312m,	0,		312 * CLOCK_1M,	0);
+DECLARE_REF_CLK(ref_104m,	&ref_312m.clk,	104 * CLOCK_1M,	3);
+DECLARE_REF_CLK(ref_52m,	&ref_104m.clk,	52  * CLOCK_1M,	2);
+DECLARE_REF_CLK(ref_13m,	&ref_52m.clk,	13  * CLOCK_1M,	4);
+DECLARE_REF_CLK(var_312m,	0,		312 * CLOCK_1M,	0);
+DECLARE_REF_CLK(var_104m,	&var_312m.clk,	104 * CLOCK_1M,	3);
+DECLARE_REF_CLK(var_52m,	&var_104m.clk,	52  * CLOCK_1M,	2);
+DECLARE_REF_CLK(var_13m,	&var_52m.clk,	13  * CLOCK_1M,	4);
+
+struct refclk_lkup {
+	struct refclk *procclk;
+	const char *name;
+};
+
+/* Lookup table for string to clk tranlation */
+#define MKSTR(x) {&x, #x}
+static struct refclk_lkup refclk_str_tbl[] = {
+	MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m),
+	MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m),
+	MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m),
+	MKSTR(var_52m), MKSTR(var_13m),
+};
+
+int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
+
+/* convert ref clock string to clock structure pointer */
+struct refclk *refclk_str_to_clk(const char *name)
+{
+	int i;
+	struct refclk_lkup *tblp = refclk_str_tbl;
+	for (i = 0; i < refclk_entries; i++, tblp++) {
+		if (!(strcmp(name, tblp->name)))
+			return tblp->procclk;
+	}
+	return NULL;
+}
+
+/* frequency tables indexed by freq_id */
+unsigned long master_axi_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	52 * CLOCK_1M,
+	104 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M,
+	208 * CLOCK_1M,
+	312 * CLOCK_1M,
+	312 * CLOCK_1M
+};
+
+unsigned long master_ahb_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	52 * CLOCK_1M,
+	52 * CLOCK_1M,
+	52 * CLOCK_1M,
+	78 * CLOCK_1M,
+	104 * CLOCK_1M,
+	104 * CLOCK_1M,
+	156 * CLOCK_1M
+};
+
+unsigned long slave_axi_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	52 * CLOCK_1M,
+	78 * CLOCK_1M,
+	104 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M
+};
+
+unsigned long slave_apb_freq_tbl[8] = {
+	26 * CLOCK_1M,
+	26 * CLOCK_1M,
+	39 * CLOCK_1M,
+	52 * CLOCK_1M,
+	52 * CLOCK_1M,
+	78 * CLOCK_1M
+};
+
+unsigned long esub_freq_tbl[8] = {
+	78 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M,
+	156 * CLOCK_1M,
+	208 * CLOCK_1M,
+	208 * CLOCK_1M,
+	208 * CLOCK_1M
+};
+
+static struct bus_clk_data bsc1_apb_data = {
+	.gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
+};
+
+static struct bus_clk_data bsc2_apb_data = {
+	.gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
+};
+
+static struct bus_clk_data bsc3_apb_data = {
+	.gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
+};
+
+/* * Master CCU clocks */
+static struct peri_clk_data sdio1_data = {
+	.gate		= HW_SW_GATE(0x0358, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a28, 0, 3),
+	.div		= DIVIDER(0x0a28, 4, 14),
+	.trig		= TRIGGER(0x0afc, 9),
+};
+
+static struct peri_clk_data sdio2_data = {
+	.gate		= HW_SW_GATE(0x035c, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a2c, 0, 3),
+	.div		= DIVIDER(0x0a2c, 4, 14),
+	.trig		= TRIGGER(0x0afc, 10),
+};
+
+static struct peri_clk_data sdio3_data = {
+	.gate		= HW_SW_GATE(0x0364, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a34, 0, 3),
+	.div		= DIVIDER(0x0a34, 4, 14),
+	.trig		= TRIGGER(0x0afc, 12),
+};
+
+static struct peri_clk_data sdio4_data = {
+	.gate		= HW_SW_GATE(0x0360, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_52m",
+				 "ref_52m",
+				 "var_96m",
+				 "ref_96m"),
+	.sel		= SELECTOR(0x0a30, 0, 3),
+	.div		= DIVIDER(0x0a30, 4, 14),
+	.trig		= TRIGGER(0x0afc, 11),
+};
+
+static struct peri_clk_data sdio1_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x0358, 20, 4),
+};
+
+static struct peri_clk_data sdio2_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x035c, 20, 4),
+};
+
+static struct peri_clk_data sdio3_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x0364, 20, 4),
+};
+
+static struct peri_clk_data sdio4_sleep_data = {
+	.clocks		= CLOCKS("ref_32k"),
+	.gate		= SW_ONLY_GATE(0x0360, 20, 4),
+};
+
+static struct bus_clk_data usb_otg_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0348, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio1_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio2_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio3_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio4_ahb_data = {
+	.gate		= HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
+};
+
+/* * Slave CCU clocks */
+static struct peri_clk_data bsc1_data = {
+	.gate		= HW_SW_GATE(0x0458, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_104m",
+				 "ref_104m",
+				 "var_13m",
+				 "ref_13m"),
+	.sel		= SELECTOR(0x0a64, 0, 3),
+	.trig		= TRIGGER(0x0afc, 23),
+};
+
+static struct peri_clk_data bsc2_data = {
+	.gate		= HW_SW_GATE(0x045c, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_104m",
+				 "ref_104m",
+				 "var_13m",
+				 "ref_13m"),
+	.sel		= SELECTOR(0x0a68, 0, 3),
+	.trig		= TRIGGER(0x0afc, 24),
+};
+
+static struct peri_clk_data bsc3_data = {
+	.gate		= HW_SW_GATE(0x0484, 18, 2, 3),
+	.clocks		= CLOCKS("ref_crystal",
+				 "var_104m",
+				 "ref_104m",
+				 "var_13m",
+				 "ref_13m"),
+	.sel		= SELECTOR(0x0a84, 0, 3),
+	.trig		= TRIGGER(0x0b00, 2),
+};
+
+/*
+ * CCU clocks
+ */
+
+static struct ccu_clock kpm_ccu_clk = {
+	.clk = {
+		.name = "kpm_ccu_clk",
+		.ops = &ccu_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.num_policy_masks = 1,
+	.policy_freq_offset = 0x00000008,
+	.freq_bit_shift = 8,
+	.policy_ctl_offset = 0x0000000c,
+	.policy0_mask_offset = 0x00000010,
+	.policy1_mask_offset = 0x00000014,
+	.policy2_mask_offset = 0x00000018,
+	.policy3_mask_offset = 0x0000001c,
+	.lvm_en_offset = 0x00000034,
+	.freq_id = 2,
+	.freq_tbl = master_axi_freq_tbl,
+};
+
+static struct ccu_clock kps_ccu_clk = {
+	.clk = {
+		.name = "kps_ccu_clk",
+		.ops = &ccu_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.num_policy_masks = 2,
+	.policy_freq_offset = 0x00000008,
+	.freq_bit_shift = 8,
+	.policy_ctl_offset = 0x0000000c,
+	.policy0_mask_offset = 0x00000010,
+	.policy1_mask_offset = 0x00000014,
+	.policy2_mask_offset = 0x00000018,
+	.policy3_mask_offset = 0x0000001c,
+	.policy0_mask2_offset = 0x00000048,
+	.policy1_mask2_offset = 0x0000004c,
+	.policy2_mask2_offset = 0x00000050,
+	.policy3_mask2_offset = 0x00000054,
+	.lvm_en_offset = 0x00000034,
+	.freq_id = 2,
+	.freq_tbl = slave_axi_freq_tbl,
+};
+
+#ifdef CONFIG_BCM_SF2_ETH
+static struct ccu_clock esub_ccu_clk = {
+	.clk = {
+		.name = "esub_ccu_clk",
+		.ops = &ccu_clk_ops,
+		.ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR,
+	},
+	.num_policy_masks = 1,
+	.policy_freq_offset = 0x00000008,
+	.freq_bit_shift = 8,
+	.policy_ctl_offset = 0x0000000c,
+	.policy0_mask_offset = 0x00000010,
+	.policy1_mask_offset = 0x00000014,
+	.policy2_mask_offset = 0x00000018,
+	.policy3_mask_offset = 0x0000001c,
+	.lvm_en_offset = 0x00000034,
+	.freq_id = 2,
+	.freq_tbl = esub_freq_tbl,
+};
+#endif
+
+/*
+ * Bus clocks
+ */
+
+/* KPM bus clocks */
+static struct bus_clock usb_otg_ahb_clk = {
+	.clk = {
+		.name = "usb_otg_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &usb_otg_ahb_data,
+};
+
+static struct bus_clock sdio1_ahb_clk = {
+	.clk = {
+		.name = "sdio1_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio1_ahb_data,
+};
+
+static struct bus_clock sdio2_ahb_clk = {
+	.clk = {
+		.name = "sdio2_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio2_ahb_data,
+};
+
+static struct bus_clock sdio3_ahb_clk = {
+	.clk = {
+		.name = "sdio3_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio3_ahb_data,
+};
+
+static struct bus_clock sdio4_ahb_clk = {
+	.clk = {
+		.name = "sdio4_ahb_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.freq_tbl = master_ahb_freq_tbl,
+	.data = &sdio4_ahb_data,
+};
+
+static struct bus_clock bsc1_apb_clk = {
+	.clk = {
+		.name = "bsc1_apb_clk",
+		.parent = &kps_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.freq_tbl = slave_apb_freq_tbl,
+	.data = &bsc1_apb_data,
+};
+
+static struct bus_clock bsc2_apb_clk = {
+	.clk = {
+		.name = "bsc2_apb_clk",
+		.parent = &kps_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+		},
+	.freq_tbl = slave_apb_freq_tbl,
+	.data = &bsc2_apb_data,
+};
+
+static struct bus_clock bsc3_apb_clk = {
+	.clk = {
+		.name = "bsc3_apb_clk",
+		.parent = &kps_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+		},
+	.freq_tbl = slave_apb_freq_tbl,
+	.data = &bsc3_apb_data,
+};
+
+/* KPM peripheral */
+static struct peri_clock sdio1_clk = {
+	.clk = {
+		.name = "sdio1_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio1_data,
+};
+
+static struct peri_clock sdio2_clk = {
+	.clk = {
+		.name = "sdio2_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio2_data,
+};
+
+static struct peri_clock sdio3_clk = {
+	.clk = {
+		.name = "sdio3_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio3_data,
+};
+
+static struct peri_clock sdio4_clk = {
+	.clk = {
+		.name = "sdio4_clk",
+		.parent = &ref_52m.clk,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio4_data,
+};
+
+static struct peri_clock sdio1_sleep_clk = {
+	.clk = {
+		.name = "sdio1_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio1_sleep_data,
+};
+
+static struct peri_clock sdio2_sleep_clk = {
+	.clk = {
+		.name = "sdio2_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio2_sleep_data,
+};
+
+static struct peri_clock sdio3_sleep_clk = {
+	.clk = {
+		.name = "sdio3_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio3_sleep_data,
+};
+
+static struct peri_clock sdio4_sleep_clk = {
+	.clk = {
+		.name = "sdio4_sleep_clk",
+		.parent = &kpm_ccu_clk.clk,
+		.ops = &bus_clk_ops,
+		.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+	},
+	.data = &sdio4_sleep_data,
+};
+
+/* KPS peripheral clock */
+static struct peri_clock bsc1_clk = {
+	.clk = {
+		.name = "bsc1_clk",
+		.parent = &ref_13m.clk,
+		.rate = 13 * CLOCK_1M,
+		.div = 1,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.data = &bsc1_data,
+};
+
+static struct peri_clock bsc2_clk = {
+	.clk = {
+		.name = "bsc2_clk",
+		.parent = &ref_13m.clk,
+		.rate = 13 * CLOCK_1M,
+		.div = 1,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.data = &bsc2_data,
+};
+
+static struct peri_clock bsc3_clk = {
+	.clk = {
+		.name = "bsc3_clk",
+		.parent = &ref_13m.clk,
+		.rate = 13 * CLOCK_1M,
+		.div = 1,
+		.ops = &peri_clk_ops,
+		.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+	},
+	.data = &bsc3_data,
+};
+
+/* public table for registering clocks */
+struct clk_lookup arch_clk_tbl[] = {
+	/* Peripheral clocks */
+	CLK_LK(sdio1),
+	CLK_LK(sdio2),
+	CLK_LK(sdio3),
+	CLK_LK(sdio4),
+	CLK_LK(sdio1_sleep),
+	CLK_LK(sdio2_sleep),
+	CLK_LK(sdio3_sleep),
+	CLK_LK(sdio4_sleep),
+	CLK_LK(bsc1),
+	CLK_LK(bsc2),
+	CLK_LK(bsc3),
+	/* Bus clocks */
+	CLK_LK(usb_otg_ahb),
+	CLK_LK(sdio1_ahb),
+	CLK_LK(sdio2_ahb),
+	CLK_LK(sdio3_ahb),
+	CLK_LK(sdio4_ahb),
+	CLK_LK(bsc1_apb),
+	CLK_LK(bsc2_apb),
+	CLK_LK(bsc3_apb),
+#ifdef CONFIG_BCM_SF2_ETH
+	CLK_LK(esub_ccu),
+#endif
+};
+
+/* public array size */
+unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c b/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c
new file mode 100644
index 0000000..1b3f36a
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for a BSC/I2C port */
+int clk_bsc_enable(void *base)
+{
+	int ret;
+	char *bscstr, *apbstr;
+
+	switch ((u32) base) {
+	case PMU_BSC_BASE_ADDR:
+		/* PMU clock is always enabled */
+		return 0;
+	case BSC1_BASE_ADDR:
+		bscstr = "bsc1_clk";
+		apbstr = "bsc1_apb_clk";
+		break;
+	case BSC2_BASE_ADDR:
+		bscstr = "bsc2_clk";
+		apbstr = "bsc2_apb_clk";
+		break;
+	case BSC3_BASE_ADDR:
+		bscstr = "bsc3_clk";
+		apbstr = "bsc3_apb_clk";
+		break;
+	default:
+		printf("%s: base 0x%p not found\n", __func__, base);
+		return -EINVAL;
+	}
+
+	/* Note that the bus clock must be enabled first */
+
+	ret = clk_get_and_enable(apbstr);
+	if (ret)
+		return ret;
+
+	ret = clk_get_and_enable(bscstr);
+	if (ret)
+		return ret;
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-core.c b/arch/arm/cpu/armv7/bcm281xx/clk-core.c
new file mode 100644
index 0000000..6a36f94
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/clk-core.c
@@ -0,0 +1,512 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+/*
+ *
+ * bcm281xx architecture clock framework
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <bitfield.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define CLK_WR_ACCESS_PASSWORD	0x00a5a501
+#define WR_ACCESS_OFFSET	0	/* common to all clock blocks */
+#define POLICY_CTL_GO		1	/* Load and refresh policy masks */
+#define POLICY_CTL_GO_ATL	4	/* Active Load */
+
+/* Helper function */
+int clk_get_and_enable(char *clkstr)
+{
+	int ret = 0;
+	struct clk *c;
+
+	debug("%s: %s\n", __func__, clkstr);
+
+	c = clk_get(clkstr);
+	if (c) {
+		ret = clk_enable(c);
+		if (ret)
+			return ret;
+	} else {
+		printf("%s: Couldn't find %s\n", __func__, clkstr);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Poll a register in a CCU's address space, returning when the
+ * specified bit in that register's value is set (or clear).  Delay
+ * a microsecond after each read of the register.  Returns true if
+ * successful, or false if we gave up trying.
+ *
+ * Caller must ensure the CCU lock is held.
+ */
+#define CLK_GATE_DELAY_USEC 2000
+static inline int wait_bit(void *base, u32 offset, u32 bit, bool want)
+{
+	unsigned int tries;
+	u32 bit_mask = 1 << bit;
+
+	for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) {
+		u32 val;
+		bool bit_val;
+
+		val = readl(base + offset);
+		bit_val = (val & bit_mask) ? 1 : 0;
+		if (bit_val == want)
+			return 0;	/* success */
+		udelay(1);
+	}
+
+	debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n",
+	      __func__, base + offset, bit, want);
+
+	return -ETIMEDOUT;
+}
+
+/* Enable a peripheral clock */
+static int peri_clk_enable(struct clk *c, int enable)
+{
+	int ret = 0;
+	u32 reg;
+	struct peri_clock *peri_clk = to_peri_clk(c);
+	struct peri_clk_data *cd = peri_clk->data;
+	struct bcm_clk_gate *gate = &cd->gate;
+	void *base = (void *)c->ccu_clk_mgr_base;
+
+
+	debug("%s: %s\n", __func__, c->name);
+
+	clk_get_rate(c);	/* Make sure rate and sel are filled in */
+
+	/* enable access */
+	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+	if (enable) {
+		debug("%s %s set rate %lu div %lu sel %d parent %lu\n",
+		      __func__, c->name, c->rate, c->div, c->sel,
+		      c->parent->rate);
+
+		/*
+		 * clkgate - only software controllable gates are
+		 * supported by u-boot which includes all clocks
+		 * that matter. This avoids bringing in a lot of extra
+		 * complexity as done in the kernel framework.
+		 */
+		if (gate_exists(gate)) {
+			reg = readl(base + cd->gate.offset);
+			reg |= (1 << cd->gate.en_bit);
+			writel(reg, base + cd->gate.offset);
+		}
+
+		/* div and pll select */
+		if (divider_exists(&cd->div)) {
+			reg = readl(base + cd->div.offset);
+			bitfield_replace(reg, cd->div.shift, cd->div.width,
+					 c->div - 1);
+			writel(reg, base + cd->div.offset);
+		}
+
+		/* frequency selector */
+		if (selector_exists(&cd->sel)) {
+			reg = readl(base + cd->sel.offset);
+			bitfield_replace(reg, cd->sel.shift, cd->sel.width,
+					 c->sel);
+			writel(reg, base + cd->sel.offset);
+		}
+
+		/* trigger */
+		if (trigger_exists(&cd->trig)) {
+			writel((1 << cd->trig.bit), base + cd->trig.offset);
+
+			/* wait for trigger status bit to go to 0 */
+			ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0);
+			if (ret)
+				return ret;
+		}
+
+		/* wait for running (status_bit = 1) */
+		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1);
+		if (ret)
+			return ret;
+	} else {
+		debug("%s disable clock %s\n", __func__, c->name);
+
+		/* clkgate */
+		reg = readl(base + cd->gate.offset);
+		reg &= ~(1 << cd->gate.en_bit);
+		writel(reg, base + cd->gate.offset);
+
+		/* wait for stop (status_bit = 0) */
+		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0);
+	}
+
+	/* disable access */
+	writel(0, base + WR_ACCESS_OFFSET);
+
+	return ret;
+}
+
+/* Set the rate of a peripheral clock */
+static int peri_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret = 0;
+	int i;
+	unsigned long diff;
+	unsigned long new_rate = 0, div = 1;
+	struct peri_clock *peri_clk = to_peri_clk(c);
+	struct peri_clk_data *cd = peri_clk->data;
+	const char **clock;
+
+	debug("%s: %s\n", __func__, c->name);
+	diff = rate;
+
+	i = 0;
+	for (clock = cd->clocks; *clock; clock++, i++) {
+		struct refclk *ref = refclk_str_to_clk(*clock);
+		if (!ref) {
+			printf("%s: Lookup of %s failed\n", __func__, *clock);
+			return -EINVAL;
+		}
+
+		/* round to the new rate */
+		div = ref->clk.rate / rate;
+		if (div == 0)
+			div = 1;
+
+		new_rate = ref->clk.rate / div;
+
+		/* get the min diff */
+		if (abs(new_rate - rate) < diff) {
+			diff = abs(new_rate - rate);
+			c->sel = i;
+			c->parent = &ref->clk;
+			c->rate = new_rate;
+			c->div = div;
+		}
+	}
+
+	debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__,
+	      c->name, c->rate, c->div, c->sel, c->parent->rate);
+	return ret;
+}
+
+/* Get the rate of a peripheral clock */
+static unsigned long peri_clk_get_rate(struct clk *c)
+{
+	struct peri_clock *peri_clk = to_peri_clk(c);
+	struct peri_clk_data *cd = peri_clk->data;
+	void *base = (void *)c->ccu_clk_mgr_base;
+	int div = 1;
+	const char **clock;
+	struct refclk *ref;
+	u32 reg;
+
+	debug("%s: %s\n", __func__, c->name);
+	if (selector_exists(&cd->sel)) {
+		reg = readl(base + cd->sel.offset);
+		c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width);
+	} else {
+		/*
+		 * For peri clocks that don't have a selector, the single
+		 * reference clock will always exist at index 0.
+		 */
+		c->sel = 0;
+	}
+
+	if (divider_exists(&cd->div)) {
+		reg = readl(base + cd->div.offset);
+		div = bitfield_extract(reg, cd->div.shift, cd->div.width);
+		div += 1;
+	}
+
+	clock = cd->clocks;
+	ref = refclk_str_to_clk(clock[c->sel]);
+	if (!ref) {
+		printf("%s: Can't lookup %s\n", __func__, clock[c->sel]);
+		return 0;
+	}
+
+	c->parent = &ref->clk;
+	c->div = div;
+	c->rate = c->parent->rate / c->div;
+	debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__,
+	      c->parent->rate, div, c->sel, c->rate);
+
+	return c->rate;
+}
+
+/* Peripheral clock operations */
+struct clk_ops peri_clk_ops = {
+	.enable = peri_clk_enable,
+	.set_rate = peri_clk_set_rate,
+	.get_rate = peri_clk_get_rate,
+};
+
+/* Enable a CCU clock */
+static int ccu_clk_enable(struct clk *c, int enable)
+{
+	struct ccu_clock *ccu_clk = to_ccu_clk(c);
+	void *base = (void *)c->ccu_clk_mgr_base;
+	int ret = 0;
+	u32 reg;
+
+	debug("%s: %s\n", __func__, c->name);
+	if (!enable)
+		return -EINVAL;	/* CCU clock cannot shutdown */
+
+	/* enable access */
+	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+	/* config enable for policy engine */
+	writel(1, base + ccu_clk->lvm_en_offset);
+
+	/* wait for bit to go to 0 */
+	ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0);
+	if (ret)
+		return ret;
+
+	/* freq ID */
+	if (!ccu_clk->freq_bit_shift)
+		ccu_clk->freq_bit_shift = 8;
+
+	/* Set frequency id for each of the 4 policies */
+	reg = ccu_clk->freq_id |
+	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) |
+	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) |
+	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3));
+	writel(reg, base + ccu_clk->policy_freq_offset);
+
+	/* enable all clock mask */
+	writel(0x7fffffff, base + ccu_clk->policy0_mask_offset);
+	writel(0x7fffffff, base + ccu_clk->policy1_mask_offset);
+	writel(0x7fffffff, base + ccu_clk->policy2_mask_offset);
+	writel(0x7fffffff, base + ccu_clk->policy3_mask_offset);
+
+	if (ccu_clk->num_policy_masks == 2) {
+		writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset);
+		writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset);
+		writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset);
+		writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset);
+	}
+
+	/* start policy engine */
+	reg = readl(base + ccu_clk->policy_ctl_offset);
+	reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL);
+	writel(reg, base + ccu_clk->policy_ctl_offset);
+
+	/* wait till started */
+	ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0);
+	if (ret)
+		return ret;
+
+	/* disable access */
+	writel(0, base + WR_ACCESS_OFFSET);
+
+	return ret;
+}
+
+/* Get the CCU clock rate */
+static unsigned long ccu_clk_get_rate(struct clk *c)
+{
+	struct ccu_clock *ccu_clk = to_ccu_clk(c);
+	debug("%s: %s\n", __func__, c->name);
+	c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id];
+	return c->rate;
+}
+
+/* CCU clock operations */
+struct clk_ops ccu_clk_ops = {
+	.enable = ccu_clk_enable,
+	.get_rate = ccu_clk_get_rate,
+};
+
+/* Enable a bus clock */
+static int bus_clk_enable(struct clk *c, int enable)
+{
+	struct bus_clock *bus_clk = to_bus_clk(c);
+	struct bus_clk_data *cd = bus_clk->data;
+	void *base = (void *)c->ccu_clk_mgr_base;
+	int ret = 0;
+	u32 reg;
+
+	debug("%s: %s\n", __func__, c->name);
+	/* enable access */
+	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+	/* enable gating */
+	reg = readl(base + cd->gate.offset);
+	if (!!(reg & (1 << cd->gate.status_bit)) == !!enable)
+		debug("%s already %s\n", c->name,
+		      enable ? "enabled" : "disabled");
+	else {
+		int want = (enable) ? 1 : 0;
+		reg |= (1 << cd->gate.hw_sw_sel_bit);
+
+		if (enable)
+			reg |= (1 << cd->gate.en_bit);
+		else
+			reg &= ~(1 << cd->gate.en_bit);
+
+		writel(reg, base + cd->gate.offset);
+		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit,
+			       want);
+		if (ret)
+			return ret;
+	}
+
+	/* disable access */
+	writel(0, base + WR_ACCESS_OFFSET);
+
+	return ret;
+}
+
+/* Get the rate of a bus clock */
+static unsigned long bus_clk_get_rate(struct clk *c)
+{
+	struct bus_clock *bus_clk = to_bus_clk(c);
+	struct ccu_clock *ccu_clk;
+
+	debug("%s: %s\n", __func__, c->name);
+	ccu_clk = to_ccu_clk(c->parent);
+
+	c->rate = bus_clk->freq_tbl[ccu_clk->freq_id];
+	c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate;
+	return c->rate;
+}
+
+/* Bus clock operations */
+struct clk_ops bus_clk_ops = {
+	.enable = bus_clk_enable,
+	.get_rate = bus_clk_get_rate,
+};
+
+/* Enable a reference clock */
+static int ref_clk_enable(struct clk *c, int enable)
+{
+	debug("%s: %s\n", __func__, c->name);
+	return 0;
+}
+
+/* Reference clock operations */
+struct clk_ops ref_clk_ops = {
+	.enable = ref_clk_enable,
+};
+
+/*
+ * clk.h implementation follows
+ */
+
+/* Initialize the clock framework */
+int clk_init(void)
+{
+	debug("%s:\n", __func__);
+	return 0;
+}
+
+/* Get a clock handle, give a name string */
+struct clk *clk_get(const char *con_id)
+{
+	int i;
+	struct clk_lookup *clk_tblp;
+
+	debug("%s: %s\n", __func__, con_id);
+
+	clk_tblp = arch_clk_tbl;
+	for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) {
+		if (clk_tblp->con_id) {
+			if (!con_id || strcmp(clk_tblp->con_id, con_id))
+				continue;
+			return clk_tblp->clk;
+		}
+	}
+	return NULL;
+}
+
+/* Enable a clock */
+int clk_enable(struct clk *c)
+{
+	int ret = 0;
+
+	debug("%s: %s\n", __func__, c->name);
+	if (!c->ops || !c->ops->enable)
+		return -1;
+
+	/* enable parent clock first */
+	if (c->parent)
+		ret = clk_enable(c->parent);
+
+	if (ret)
+		return ret;
+
+	if (!c->use_cnt) {
+		c->use_cnt++;
+		ret = c->ops->enable(c, 1);
+	}
+
+	return ret;
+}
+
+/* Disable a clock */
+void clk_disable(struct clk *c)
+{
+	debug("%s: %s\n", __func__, c->name);
+	if (!c->ops || !c->ops->enable)
+		return;
+
+	if (c->use_cnt) {
+		c->use_cnt--;
+		c->ops->enable(c, 0);
+	}
+
+	/* disable parent */
+	if (c->parent)
+		clk_disable(c->parent);
+}
+
+/* Get the clock rate */
+unsigned long clk_get_rate(struct clk *c)
+{
+	unsigned long rate;
+
+	if (!c || !c->ops || !c->ops->get_rate)
+		return 0;
+	debug("%s: %s\n", __func__, c->name);
+
+	rate = c->ops->get_rate(c);
+	debug("%s: rate = %ld\n", __func__, rate);
+	return rate;
+}
+
+/* Set the clock rate */
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+
+	if (!c || !c->ops || !c->ops->set_rate)
+		return -EINVAL;
+	debug("%s: %s rate=%ld\n", __func__, c->name, rate);
+
+	if (c->use_cnt)
+		return -EINVAL;
+
+	ret = c->ops->set_rate(c, rate);
+
+	return ret;
+}
+
+/* Not required for this arch */
+/*
+long clk_round_rate(struct clk *clk, unsigned long rate);
+int clk_set_parent(struct clk *clk, struct clk *parent);
+struct clk *clk_get_parent(struct clk *clk);
+*/
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-core.h b/arch/arm/cpu/armv7/bcm281xx/clk-core.h
new file mode 100644
index 0000000..a736ae9
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/clk-core.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <linux/stddef.h>
+
+#ifdef CONFIG_CLK_DEBUG
+#undef writel
+#undef readl
+static inline void writel(u32 val, void *addr)
+{
+	printf("Write [0x%p] = 0x%08x\n", addr, val);
+	*(u32 *)addr = val;
+}
+
+static inline u32 readl(void *addr)
+{
+	u32 val = *(u32 *)addr;
+	printf("Read  [0x%p] = 0x%08x\n", addr, val);
+	return val;
+}
+#endif
+
+struct clk;
+
+struct clk_lookup {
+	const char *dev_id;
+	const char *con_id;
+	struct clk *clk;
+};
+
+extern struct clk_lookup arch_clk_tbl[];
+extern unsigned int arch_clk_tbl_array_size;
+
+/**
+ * struct clk_ops - standard clock operations
+ * @enable: enable/disable clock, see clk_enable() and clk_disable()
+ * @set_rate: set the clock rate, see clk_set_rate().
+ * @get_rate: get the clock rate, see clk_get_rate().
+ * @round_rate: round a given clock rate, see clk_round_rate().
+ * @set_parent: set the clock's parent, see clk_set_parent().
+ *
+ * Group the common clock implementations together so that we
+ * don't have to keep setting the same fiels again. We leave
+ * enable in struct clk.
+ *
+ */
+struct clk_ops {
+	int (*enable) (struct clk *c, int enable);
+	int (*set_rate) (struct clk *c, unsigned long rate);
+	unsigned long (*get_rate) (struct clk *c);
+	unsigned long (*round_rate) (struct clk *c, unsigned long rate);
+	int (*set_parent) (struct clk *c, struct clk *parent);
+};
+
+struct clk {
+	struct clk *parent;
+	const char *name;
+	int use_cnt;
+	unsigned long rate;	/* in HZ */
+
+	/* programmable divider. 0 means fixed ratio to parent clock */
+	unsigned long div;
+
+	struct clk_src *src;
+	struct clk_ops *ops;
+
+	unsigned long ccu_clk_mgr_base;
+	int sel;
+};
+
+struct refclk *refclk_str_to_clk(const char *name);
+
+/* The common clock framework uses u8 to represent a parent index */
+#define PARENT_COUNT_MAX	((u32)U8_MAX)
+
+#define BAD_CLK_INDEX		U8_MAX	/* Can't ever be valid */
+#define BAD_CLK_NAME		((const char *)-1)
+
+#define BAD_SCALED_DIV_VALUE	U64_MAX
+
+/*
+ * Utility macros for object flag management.  If possible, flags
+ * should be defined such that 0 is the desired default value.
+ */
+#define FLAG(type, flag)		BCM_CLK_ ## type ## _FLAGS_ ## flag
+#define FLAG_SET(obj, type, flag)	((obj)->flags |= FLAG(type, flag))
+#define FLAG_CLEAR(obj, type, flag)	((obj)->flags &= ~(FLAG(type, flag)))
+#define FLAG_FLIP(obj, type, flag)	((obj)->flags ^= FLAG(type, flag))
+#define FLAG_TEST(obj, type, flag)	(!!((obj)->flags & FLAG(type, flag)))
+
+/* Clock field state tests */
+
+#define gate_exists(gate)		FLAG_TEST(gate, GATE, EXISTS)
+#define gate_is_enabled(gate)		FLAG_TEST(gate, GATE, ENABLED)
+#define gate_is_hw_controllable(gate)	FLAG_TEST(gate, GATE, HW)
+#define gate_is_sw_controllable(gate)	FLAG_TEST(gate, GATE, SW)
+#define gate_is_sw_managed(gate)	FLAG_TEST(gate, GATE, SW_MANAGED)
+#define gate_is_no_disable(gate)	FLAG_TEST(gate, GATE, NO_DISABLE)
+
+#define gate_flip_enabled(gate)		FLAG_FLIP(gate, GATE, ENABLED)
+
+#define divider_exists(div)		FLAG_TEST(div, DIV, EXISTS)
+#define divider_is_fixed(div)		FLAG_TEST(div, DIV, FIXED)
+#define divider_has_fraction(div)	(!divider_is_fixed(div) && \
+						(div)->frac_width > 0)
+
+#define selector_exists(sel)		((sel)->width != 0)
+#define trigger_exists(trig)		FLAG_TEST(trig, TRIG, EXISTS)
+
+/* Clock type, used to tell common block what it's part of */
+enum bcm_clk_type {
+	bcm_clk_none,		/* undefined clock type */
+	bcm_clk_bus,
+	bcm_clk_core,
+	bcm_clk_peri
+};
+
+/*
+ * Gating control and status is managed by a 32-bit gate register.
+ *
+ * There are several types of gating available:
+ * - (no gate)
+ *     A clock with no gate is assumed to be always enabled.
+ * - hardware-only gating (auto-gating)
+ *     Enabling or disabling clocks with this type of gate is
+ *     managed automatically by the hardware.  Such clocks can be
+ *     considered by the software to be enabled.  The current status
+ *     of auto-gated clocks can be read from the gate status bit.
+ * - software-only gating
+ *     Auto-gating is not available for this type of clock.
+ *     Instead, software manages whether it's enabled by setting or
+ *     clearing the enable bit.  The current gate status of a gate
+ *     under software control can be read from the gate status bit.
+ *     To ensure a change to the gating status is complete, the
+ *     status bit can be polled to verify that the gate has entered
+ *     the desired state.
+ * - selectable hardware or software gating
+ *     Gating for this type of clock can be configured to be either
+ *     under software or hardware control.  Which type is in use is
+ *     determined by the hw_sw_sel bit of the gate register.
+ */
+struct bcm_clk_gate {
+	u32 offset;		/* gate register offset */
+	u32 status_bit;		/* 0: gate is disabled; 0: gatge is enabled */
+	u32 en_bit;		/* 0: disable; 1: enable */
+	u32 hw_sw_sel_bit;	/* 0: hardware gating; 1: software gating */
+	u32 flags;		/* BCM_CLK_GATE_FLAGS_* below */
+};
+
+/*
+ * Gate flags:
+ *   HW         means this gate can be auto-gated
+ *   SW         means the state of this gate can be software controlled
+ *   NO_DISABLE means this gate is (only) enabled if under software control
+ *   SW_MANAGED means the status of this gate is under software control
+ *   ENABLED    means this software-managed gate is *supposed* to be enabled
+ */
+#define BCM_CLK_GATE_FLAGS_EXISTS	((u32)1 << 0)	/* Gate is valid */
+#define BCM_CLK_GATE_FLAGS_HW		((u32)1 << 1)	/* Can auto-gate */
+#define BCM_CLK_GATE_FLAGS_SW		((u32)1 << 2)	/* Software control */
+#define BCM_CLK_GATE_FLAGS_NO_DISABLE	((u32)1 << 3)	/* HW or enabled */
+#define BCM_CLK_GATE_FLAGS_SW_MANAGED	((u32)1 << 4)	/* SW now in control */
+#define BCM_CLK_GATE_FLAGS_ENABLED	((u32)1 << 5)	/* If SW_MANAGED */
+
+/*
+ * Gate initialization macros.
+ *
+ * Any gate initially under software control will be enabled.
+ */
+
+/* A hardware/software gate initially under software control */
+#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)	\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.hw_sw_sel_bit = (_hw_sw_sel_bit),			\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, SW)|			\
+			FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)|	\
+			FLAG(GATE, EXISTS),				\
+	}
+
+/* A hardware/software gate initially under hardware control */
+#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)	\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.hw_sw_sel_bit = (_hw_sw_sel_bit),			\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, SW)|			\
+			FLAG(GATE, EXISTS),				\
+	}
+
+/* A hardware-or-enabled gate (enabled if not under hardware control) */
+#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)	\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.hw_sw_sel_bit = (_hw_sw_sel_bit),			\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, SW)|			\
+			FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS),	\
+	}
+
+/* A software-only gate */
+#define SW_ONLY_GATE(_offset, _status_bit, _en_bit)			\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.en_bit = (_en_bit),					\
+		.flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)|		\
+			FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS),		\
+	}
+
+/* A hardware-only gate */
+#define HW_ONLY_GATE(_offset, _status_bit)				\
+	{								\
+		.offset = (_offset),					\
+		.status_bit = (_status_bit),				\
+		.flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS),		\
+	}
+
+/*
+ * Each clock can have zero, one, or two dividers which change the
+ * output rate of the clock.  Each divider can be either fixed or
+ * variable.  If there are two dividers, they are the "pre-divider"
+ * and the "regular" or "downstream" divider.  If there is only one,
+ * there is no pre-divider.
+ *
+ * A fixed divider is any non-zero (positive) value, and it
+ * indicates how the input rate is affected by the divider.
+ *
+ * The value of a variable divider is maintained in a sub-field of a
+ * 32-bit divider register.  The position of the field in the
+ * register is defined by its offset and width.  The value recorded
+ * in this field is always 1 less than the value it represents.
+ *
+ * In addition, a variable divider can indicate that some subset
+ * of its bits represent a "fractional" part of the divider.  Such
+ * bits comprise the low-order portion of the divider field, and can
+ * be viewed as representing the portion of the divider that lies to
+ * the right of the decimal point.  Most variable dividers have zero
+ * fractional bits.  Variable dividers with non-zero fraction width
+ * still record a value 1 less than the value they represent; the
+ * added 1 does *not* affect the low-order bit in this case, it
+ * affects the bits above the fractional part only.  (Often in this
+ * code a divider field value is distinguished from the value it
+ * represents by referring to the latter as a "divisor".)
+ *
+ * In order to avoid dealing with fractions, divider arithmetic is
+ * performed using "scaled" values.  A scaled value is one that's
+ * been left-shifted by the fractional width of a divider.  Dividing
+ * a scaled value by a scaled divisor produces the desired quotient
+ * without loss of precision and without any other special handling
+ * for fractions.
+ *
+ * The recorded value of a variable divider can be modified.  To
+ * modify either divider (or both), a clock must be enabled (i.e.,
+ * using its gate).  In addition, a trigger register (described
+ * below) must be used to commit the change, and polled to verify
+ * the change is complete.
+ */
+struct bcm_clk_div {
+	union {
+		struct {	/* variable divider */
+			u32 offset;	/* divider register offset */
+			u32 shift;	/* field shift */
+			u32 width;	/* field width */
+			u32 frac_width;	/* field fraction width */
+
+			u64 scaled_div;	/* scaled divider value */
+		};
+		u32 fixed;	/* non-zero fixed divider value */
+	};
+	u32 flags;		/* BCM_CLK_DIV_FLAGS_* below */
+};
+
+/*
+ * Divider flags:
+ *   EXISTS means this divider exists
+ *   FIXED means it is a fixed-rate divider
+ */
+#define BCM_CLK_DIV_FLAGS_EXISTS	((u32)1 << 0)	/* Divider is valid */
+#define BCM_CLK_DIV_FLAGS_FIXED		((u32)1 << 1)	/* Fixed-value */
+
+/* Divider initialization macros */
+
+/* A fixed (non-zero) divider */
+#define FIXED_DIVIDER(_value)						\
+	{								\
+		.fixed = (_value),					\
+		.flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED),		\
+	}
+
+/* A divider with an integral divisor */
+#define DIVIDER(_offset, _shift, _width)				\
+	{								\
+		.offset = (_offset),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.scaled_div = BAD_SCALED_DIV_VALUE,			\
+		.flags = FLAG(DIV, EXISTS),				\
+	}
+
+/* A divider whose divisor has an integer and fractional part */
+#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width)		\
+	{								\
+		.offset = (_offset),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.frac_width = (_frac_width),				\
+		.scaled_div = BAD_SCALED_DIV_VALUE,			\
+		.flags = FLAG(DIV, EXISTS),				\
+	}
+
+/*
+ * Clocks may have multiple "parent" clocks.  If there is more than
+ * one, a selector must be specified to define which of the parent
+ * clocks is currently in use.  The selected clock is indicated in a
+ * sub-field of a 32-bit selector register.  The range of
+ * representable selector values typically exceeds the number of
+ * available parent clocks.  Occasionally the reset value of a
+ * selector field is explicitly set to a (specific) value that does
+ * not correspond to a defined input clock.
+ *
+ * We register all known parent clocks with the common clock code
+ * using a packed array (i.e., no empty slots) of (parent) clock
+ * names, and refer to them later using indexes into that array.
+ * We maintain an array of selector values indexed by common clock
+ * index values in order to map between these common clock indexes
+ * and the selector values used by the hardware.
+ *
+ * Like dividers, a selector can be modified, but to do so a clock
+ * must be enabled, and a trigger must be used to commit the change.
+ */
+struct bcm_clk_sel {
+	u32 offset;		/* selector register offset */
+	u32 shift;		/* field shift */
+	u32 width;		/* field width */
+
+	u32 parent_count;	/* number of entries in parent_sel[] */
+	u32 *parent_sel;	/* array of parent selector values */
+	u8 clk_index;		/* current selected index in parent_sel[] */
+};
+
+/* Selector initialization macro */
+#define SELECTOR(_offset, _shift, _width)				\
+	{								\
+		.offset = (_offset),					\
+		.shift = (_shift),					\
+		.width = (_width),					\
+		.clk_index = BAD_CLK_INDEX,				\
+	}
+
+/*
+ * Making changes to a variable divider or a selector for a clock
+ * requires the use of a trigger.  A trigger is defined by a single
+ * bit within a register.  To signal a change, a 1 is written into
+ * that bit.  To determine when the change has been completed, that
+ * trigger bit is polled; the read value will be 1 while the change
+ * is in progress, and 0 when it is complete.
+ *
+ * Occasionally a clock will have more than one trigger.  In this
+ * case, the "pre-trigger" will be used when changing a clock's
+ * selector and/or its pre-divider.
+ */
+struct bcm_clk_trig {
+	u32 offset;		/* trigger register offset */
+	u32 bit;		/* trigger bit */
+	u32 flags;		/* BCM_CLK_TRIG_FLAGS_* below */
+};
+
+/*
+ * Trigger flags:
+ *   EXISTS means this trigger exists
+ */
+#define BCM_CLK_TRIG_FLAGS_EXISTS	((u32)1 << 0)	/* Trigger is valid */
+
+/* Trigger initialization macro */
+#define TRIGGER(_offset, _bit)						\
+	{								\
+		.offset = (_offset),					\
+		.bit = (_bit),						\
+		.flags = FLAG(TRIG, EXISTS),				\
+	}
+
+struct bus_clk_data {
+	struct bcm_clk_gate gate;
+};
+
+struct core_clk_data {
+	struct bcm_clk_gate gate;
+};
+
+struct peri_clk_data {
+	struct bcm_clk_gate gate;
+	struct bcm_clk_trig pre_trig;
+	struct bcm_clk_div pre_div;
+	struct bcm_clk_trig trig;
+	struct bcm_clk_div div;
+	struct bcm_clk_sel sel;
+	const char *clocks[];	/* must be last; use CLOCKS() to declare */
+};
+#define CLOCKS(...)	{ __VA_ARGS__, NULL, }
+#define NO_CLOCKS	{ NULL, }	/* Must use of no parent clocks */
+
+struct refclk {
+	struct clk clk;
+};
+
+struct peri_clock {
+	struct clk clk;
+	struct peri_clk_data *data;
+};
+
+struct ccu_clock {
+	struct clk clk;
+
+	int num_policy_masks;
+	unsigned long policy_freq_offset;
+	int freq_bit_shift;	/* 8 for most CCUs */
+	unsigned long policy_ctl_offset;
+	unsigned long policy0_mask_offset;
+	unsigned long policy1_mask_offset;
+	unsigned long policy2_mask_offset;
+	unsigned long policy3_mask_offset;
+	unsigned long policy0_mask2_offset;
+	unsigned long policy1_mask2_offset;
+	unsigned long policy2_mask2_offset;
+	unsigned long policy3_mask2_offset;
+	unsigned long lvm_en_offset;
+
+	int freq_id;
+	unsigned long *freq_tbl;
+};
+
+struct bus_clock {
+	struct clk clk;
+	struct bus_clk_data *data;
+	unsigned long *freq_tbl;
+};
+
+struct ref_clock {
+	struct clk clk;
+};
+
+static inline int is_same_clock(struct clk *a, struct clk *b)
+{
+	return (a == b);
+}
+
+#define to_clk(p) (&((p)->clk))
+#define name_to_clk(name) (&((name##_clk).clk))
+/* declare a struct clk_lookup */
+#define CLK_LK(name) \
+{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),}
+
+static inline struct refclk *to_refclk(struct clk *clock)
+{
+	return container_of(clock, struct refclk, clk);
+}
+
+static inline struct peri_clock *to_peri_clk(struct clk *clock)
+{
+	return container_of(clock, struct peri_clock, clk);
+}
+
+static inline struct ccu_clock *to_ccu_clk(struct clk *clock)
+{
+	return container_of(clock, struct ccu_clock, clk);
+}
+
+static inline struct bus_clock *to_bus_clk(struct clk *clock)
+{
+	return container_of(clock, struct bus_clock, clk);
+}
+
+static inline struct ref_clock *to_ref_clk(struct clk *clock)
+{
+	return container_of(clock, struct ref_clock, clk);
+}
+
+extern struct clk_ops peri_clk_ops;
+extern struct clk_ops ccu_clk_ops;
+extern struct clk_ops bus_clk_ops;
+extern struct clk_ops ref_clk_ops;
+
+extern int clk_get_and_enable(char *clkstr);
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-eth.c b/arch/arm/cpu/armv7/bcm281xx/clk-eth.c
new file mode 100644
index 0000000..618af70
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/clk-eth.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define WR_ACCESS_ADDR			ESUB_CLK_BASE_ADDR
+#define WR_ACCESS_PASSWORD				0xA5A500
+
+#define PLLE_POST_RESETB_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000C00)
+
+#define PLLE_RESETB_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000C58)
+#define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK		0x00010000
+#define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK	0x00000001
+
+#define PLL_LOCK_ADDR			(ESUB_CLK_BASE_ADDR + 0x00000C38)
+#define PLL_LOCK_PLL_LOCK_PLLE_MASK			0x00000001
+
+#define ESW_SYS_DIV_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000A04)
+#define ESW_SYS_DIV_PLL_SELECT_MASK			0x00000300
+#define ESW_SYS_DIV_DIV_MASK				0x0000001C
+#define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT		0x00000100
+#define ESW_SYS_DIV_DIV_SELECT				0x4
+#define ESW_SYS_DIV_TRIGGER_MASK			0x00000001
+
+#define ESUB_AXI_DIV_DEBUG_ADDR		(ESUB_CLK_BASE_ADDR + 0x00000E04)
+#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK		0x0000001C
+#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK	0x00000040
+#define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT	0x0
+#define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK			0x00000001
+
+#define PLL_MAX_RETRY	100
+
+/* Enable appropriate clocks for Ethernet */
+int clk_eth_enable(void)
+{
+	int rc = -1;
+	int retry_count = 0;
+	rc = clk_get_and_enable("esub_ccu_clk");
+
+	/* Enable Access to CCU registers */
+	writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR);
+
+	writel(readl(PLLE_POST_RESETB_ADDR) &
+	       ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
+	       PLLE_POST_RESETB_ADDR);
+
+	/* Take PLL out of reset and put into normal mode */
+	writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK,
+	       PLLE_RESETB_ADDR);
+
+	/* Wait for PLL lock */
+	rc = -1;
+	while (retry_count < PLL_MAX_RETRY) {
+		udelay(100);
+		if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) {
+			rc = 0;
+			break;
+		}
+		retry_count++;
+	}
+
+	if (rc == -1) {
+		printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n",
+		       __func__);
+		return -1;
+	}
+
+	writel(readl(PLLE_POST_RESETB_ADDR) |
+	       PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
+	       PLLE_POST_RESETB_ADDR);
+
+	/* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */
+	writel((readl(ESW_SYS_DIV_ADDR) &
+		~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) |
+	       ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT,
+	       ESW_SYS_DIV_ADDR);
+
+	writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK,
+	       ESW_SYS_DIV_ADDR);
+
+	/* Wait for trigger complete */
+	rc = -1;
+	retry_count = 0;
+	while (retry_count < PLL_MAX_RETRY) {
+		udelay(100);
+		if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) {
+			rc = 0;
+			break;
+		}
+		retry_count++;
+	}
+
+	if (rc == -1) {
+		printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n",
+		       __func__);
+		return -1;
+	}
+
+	/* switch Esub AXI clock to 208MHz */
+	writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) &
+		~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK |
+		  ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK |
+		  ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) |
+	       ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT |
+	       ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK,
+	       ESUB_AXI_DIV_DEBUG_ADDR);
+
+	writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) |
+	       ESUB_AXI_DIV_DEBUG_TRIGGER_MASK,
+	       ESUB_AXI_DIV_DEBUG_ADDR);
+
+	/* Wait for trigger complete */
+	rc = -1;
+	retry_count = 0;
+	while (retry_count < PLL_MAX_RETRY) {
+		udelay(100);
+		if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) &
+		      ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) {
+			rc = 0;
+			break;
+		}
+		retry_count++;
+	}
+
+	if (rc == -1) {
+		printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n",
+		       __func__);
+		return -1;
+	}
+
+	/* Disable Access to CCU registers */
+	writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR);
+
+	return rc;
+}
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c b/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c
new file mode 100644
index 0000000..f2ba354
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for an SDIO port */
+int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep)
+{
+	int ret;
+	struct clk *c;
+
+	char *clkstr;
+	char *slpstr;
+	char *ahbstr;
+
+	switch ((u32) base) {
+	case CONFIG_SYS_SDIO_BASE0:
+		clkstr = CONFIG_SYS_SDIO0 "_clk";
+		ahbstr = CONFIG_SYS_SDIO0 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO0 "_sleep_clk";
+		break;
+	case CONFIG_SYS_SDIO_BASE1:
+		clkstr = CONFIG_SYS_SDIO1 "_clk";
+		ahbstr = CONFIG_SYS_SDIO1 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO1 "_sleep_clk";
+		break;
+	case CONFIG_SYS_SDIO_BASE2:
+		clkstr = CONFIG_SYS_SDIO2 "_clk";
+		ahbstr = CONFIG_SYS_SDIO2 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO2 "_sleep_clk";
+		break;
+	case CONFIG_SYS_SDIO_BASE3:
+		clkstr = CONFIG_SYS_SDIO3 "_clk";
+		ahbstr = CONFIG_SYS_SDIO3 "_ahb_clk";
+		slpstr = CONFIG_SYS_SDIO3 "_sleep_clk";
+		break;
+	default:
+		printf("%s: base 0x%p not found\n", __func__, base);
+		return -EINVAL;
+	}
+
+	ret = clk_get_and_enable(ahbstr);
+	if (ret)
+		return ret;
+
+	ret = clk_get_and_enable(slpstr);
+	if (ret)
+		return ret;
+
+	c = clk_get(clkstr);
+	if (c) {
+		ret = clk_set_rate(c, rate);
+		if (ret)
+			return ret;
+
+		ret = clk_enable(c);
+		if (ret)
+			return ret;
+	} else {
+		printf("%s: Couldn't find %s\n", __func__, clkstr);
+		return -EINVAL;
+	}
+	*actual_ratep = rate;
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c b/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c
new file mode 100644
index 0000000..f604aec
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/arch/sysmap.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for the USB OTG port */
+int clk_usb_otg_enable(void *base)
+{
+	char *ahbstr;
+
+	switch ((u32) base) {
+	case HSOTG_BASE_ADDR:
+		ahbstr = "usb_otg_ahb_clk";
+		break;
+	default:
+		printf("%s: base 0x%p not found\n", __func__, base);
+		return -EINVAL;
+	}
+
+	return clk_get_and_enable(ahbstr);
+}
diff --git a/arch/arm/cpu/armv7/bcm281xx/reset.c b/arch/arm/cpu/armv7/bcm281xx/reset.c
new file mode 100644
index 0000000..fbdeea4
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm281xx/reset.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sysmap.h>
+
+#define EN_MASK		0x08000000	/* Enable timer */
+#define SRSTEN_MASK	0x04000000	/* Enable soft reset */
+#define CLKS_SHIFT	20		/* Clock period shift */
+#define LD_SHIFT	0		/* Reload value shift */
+
+void reset_cpu(ulong ignored)
+{
+	/*
+	 * Set WD enable, RST enable,
+	 * 3.9 msec clock period (8), reload value (8*3.9ms)
+	 */
+	u32 reg = EN_MASK + SRSTEN_MASK + (8 << CLKS_SHIFT) + (8 << LD_SHIFT);
+	writel(reg, SECWD2_BASE_ADDR);
+
+	while (1)
+		;	/* loop forever till reset */
+}
diff --git a/arch/arm/cpu/armv7/bcmcygnus/Makefile b/arch/arm/cpu/armv7/bcmcygnus/Makefile
new file mode 100644
index 0000000..3496bcd
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcmcygnus/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2014 Broadcom Corporation.
+
+obj-y	+= reset.o
diff --git a/arch/arm/cpu/armv7/bcmcygnus/reset.c b/arch/arm/cpu/armv7/bcmcygnus/reset.c
new file mode 100644
index 0000000..7f3f405
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcmcygnus/reset.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#define CRMU_MAIL_BOX1		0x03024028
+#define CRMU_SOFT_RESET_CMD	0xFFFFFFFF
+
+void reset_cpu(ulong ignored)
+{
+	/* Send soft reset command via Mailbox. */
+	writel(CRMU_SOFT_RESET_CMD, CRMU_MAIL_BOX1);
+
+	while (1)
+		;	/* loop forever till reset */
+}
diff --git a/arch/arm/cpu/armv7/bcmnsp/Makefile b/arch/arm/cpu/armv7/bcmnsp/Makefile
new file mode 100644
index 0000000..3496bcd
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcmnsp/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2014 Broadcom Corporation.
+
+obj-y	+= reset.o
diff --git a/arch/arm/cpu/armv7/bcmnsp/reset.c b/arch/arm/cpu/armv7/bcmnsp/reset.c
new file mode 100644
index 0000000..674166d
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcmnsp/reset.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#define CRU_RESET_OFFSET	0x1803F184
+
+void reset_cpu(ulong ignored)
+{
+	/* Reset the cpu by setting software reset request bit */
+	writel(0x1, CRU_RESET_OFFSET);
+
+	while (1)
+		;	/* loop forever till reset */
+}
diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
new file mode 100644
index 0000000..99484c2
--- /dev/null
+++ b/arch/arm/cpu/armv7/cache_v7.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ * Aneesh V <aneesh@ti.com>
+ */
+#include <linux/types.h>
+#include <common.h>
+#include <asm/armv7.h>
+#include <asm/utils.h>
+
+#define ARMV7_DCACHE_INVAL_RANGE	1
+#define ARMV7_DCACHE_CLEAN_INVAL_RANGE	2
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+
+/* Asm functions from cache_v7_asm.S */
+void v7_flush_dcache_all(void);
+void v7_invalidate_dcache_all(void);
+
+static u32 get_ccsidr(void)
+{
+	u32 ccsidr;
+
+	/* Read current CP15 Cache Size ID Register */
+	asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
+	return ccsidr;
+}
+
+static void v7_dcache_clean_inval_range(u32 start, u32 stop, u32 line_len)
+{
+	u32 mva;
+
+	/* Align start to cache line boundary */
+	start &= ~(line_len - 1);
+	for (mva = start; mva < stop; mva = mva + line_len) {
+		/* DCCIMVAC - Clean & Invalidate data cache by MVA to PoC */
+		asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (mva));
+	}
+}
+
+static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len)
+{
+	u32 mva;
+
+	if (!check_cache_range(start, stop))
+		return;
+
+	for (mva = start; mva < stop; mva = mva + line_len) {
+		/* DCIMVAC - Invalidate data cache by MVA to PoC */
+		asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (mva));
+	}
+}
+
+static void v7_dcache_maint_range(u32 start, u32 stop, u32 range_op)
+{
+	u32 line_len, ccsidr;
+
+	ccsidr = get_ccsidr();
+	line_len = ((ccsidr & CCSIDR_LINE_SIZE_MASK) >>
+			CCSIDR_LINE_SIZE_OFFSET) + 2;
+	/* Converting from words to bytes */
+	line_len += 2;
+	/* converting from log2(linelen) to linelen */
+	line_len = 1 << line_len;
+
+	switch (range_op) {
+	case ARMV7_DCACHE_CLEAN_INVAL_RANGE:
+		v7_dcache_clean_inval_range(start, stop, line_len);
+		break;
+	case ARMV7_DCACHE_INVAL_RANGE:
+		v7_dcache_inval_range(start, stop, line_len);
+		break;
+	}
+
+	/* DSB to make sure the operation is complete */
+	dsb();
+}
+
+/* Invalidate TLB */
+static void v7_inval_tlb(void)
+{
+	/* Invalidate entire unified TLB */
+	asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0));
+	/* Invalidate entire data TLB */
+	asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0));
+	/* Invalidate entire instruction TLB */
+	asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0));
+	/* Full system DSB - make sure that the invalidation is complete */
+	dsb();
+	/* Full system ISB - make sure the instruction stream sees it */
+	isb();
+}
+
+void invalidate_dcache_all(void)
+{
+	v7_invalidate_dcache_all();
+
+	v7_outer_cache_inval_all();
+}
+
+/*
+ * Performs a clean & invalidation of the entire data cache
+ * at all levels
+ */
+void flush_dcache_all(void)
+{
+	v7_flush_dcache_all();
+
+	v7_outer_cache_flush_all();
+}
+
+/*
+ * Invalidates range in all levels of D-cache/unified cache used:
+ * Affects the range [start, stop - 1]
+ */
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+	check_cache_range(start, stop);
+
+	v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE);
+
+	v7_outer_cache_inval_range(start, stop);
+}
+
+/*
+ * Flush range(clean & invalidate) from all levels of D-cache/unified
+ * cache used:
+ * Affects the range [start, stop - 1]
+ */
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+	check_cache_range(start, stop);
+
+	v7_dcache_maint_range(start, stop, ARMV7_DCACHE_CLEAN_INVAL_RANGE);
+
+	v7_outer_cache_flush_range(start, stop);
+}
+
+void arm_init_before_mmu(void)
+{
+	v7_outer_cache_enable();
+	invalidate_dcache_all();
+	v7_inval_tlb();
+}
+
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+	flush_dcache_range(start, stop);
+	v7_inval_tlb();
+}
+#else /* #ifndef CONFIG_SYS_DCACHE_OFF */
+void invalidate_dcache_all(void)
+{
+}
+
+void flush_dcache_all(void)
+{
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void arm_init_before_mmu(void)
+{
+}
+
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+}
+
+void arm_init_domains(void)
+{
+}
+#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
+
+#ifndef CONFIG_SYS_ICACHE_OFF
+/* Invalidate entire I-cache and branch predictor array */
+void invalidate_icache_all(void)
+{
+	/*
+	 * Invalidate all instruction caches to PoU.
+	 * Also flushes branch target cache.
+	 */
+	asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+	/* Invalidate entire branch predictor array */
+	asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0));
+
+	/* Full system DSB - make sure that the invalidation is complete */
+	dsb();
+
+	/* ISB - make sure the instruction stream sees it */
+	isb();
+}
+#else
+void invalidate_icache_all(void)
+{
+}
+#endif
+
+/*  Stub implementations for outer cache operations */
+__weak void v7_outer_cache_enable(void) {}
+__weak void v7_outer_cache_disable(void) {}
+__weak void v7_outer_cache_flush_all(void) {}
+__weak void v7_outer_cache_inval_all(void) {}
+__weak void v7_outer_cache_flush_range(u32 start, u32 end) {}
+__weak void v7_outer_cache_inval_range(u32 start, u32 end) {}
diff --git a/arch/arm/cpu/armv7/cache_v7_asm.S b/arch/arm/cpu/armv7/cache_v7_asm.S
new file mode 100644
index 0000000..e38d72f
--- /dev/null
+++ b/arch/arm/cpu/armv7/cache_v7_asm.S
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <linux/sizes.h>
+#include <asm/system.h>
+
+#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
+#define ARM(x...)
+#define THUMB(x...)	x
+#else
+#define ARM(x...)	x
+#define THUMB(x...)
+#endif
+
+/*
+ *	v7_flush_dcache_all()
+ *
+ *	Flush the whole D-cache.
+ *
+ *	Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
+ *
+ *	Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4
+ */
+ENTRY(__v7_flush_dcache_all)
+	dmb					@ ensure ordering with previous memory accesses
+	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
+	mov	r3, r0, lsr #23			@ move LoC into position
+	ands	r3, r3, #7 << 1			@ extract LoC*2 from clidr
+	beq	finished			@ if loc is 0, then no need to clean
+start_flush_levels:
+	mov	r10, #0				@ start clean at cache level 0
+flush_levels:
+	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
+	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
+	and	r1, r1, #7			@ mask of the bits for current cache only
+	cmp	r1, #2				@ see what cache we have at this level
+	blt	skip				@ skip if no cache, or just i-cache
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	isb					@ isb to sych the new cssr&csidr
+	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
+	and	r2, r1, #7			@ extract the length of the cache lines
+	add	r2, r2, #4			@ add 4 (line length offset)
+	movw	r4, #0x3ff
+	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
+	clz	r5, r4				@ find bit position of way size increment
+	movw	r7, #0x7fff
+	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
+loop1:
+	mov	r9, r7				@ create working copy of max index
+loop2:
+ ARM(	orr	r11, r10, r4, lsl r5	)	@ factor way and cache number into r11
+ THUMB(	lsl	r6, r4, r5		)
+ THUMB(	orr	r11, r10, r6		)	@ factor way and cache number into r11
+ ARM(	orr	r11, r11, r9, lsl r2	)	@ factor index number into r11
+ THUMB(	lsl	r6, r9, r2		)
+ THUMB(	orr	r11, r11, r6		)	@ factor index number into r11
+	mcr	p15, 0, r11, c7, c14, 2		@ clean & invalidate by set/way
+	subs	r9, r9, #1			@ decrement the index
+	bge	loop2
+	subs	r4, r4, #1			@ decrement the way
+	bge	loop1
+skip:
+	add	r10, r10, #2			@ increment cache number
+	cmp	r3, r10
+	bgt	flush_levels
+finished:
+	mov	r10, #0				@ swith back to cache level 0
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	dsb	st
+	isb
+	bx	lr
+ENDPROC(__v7_flush_dcache_all)
+
+ENTRY(v7_flush_dcache_all)
+ ARM(	stmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
+ THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
+	bl	__v7_flush_dcache_all
+ ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
+ THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
+	bx	lr
+ENDPROC(v7_flush_dcache_all)
+
+/*
+ *	v7_invalidate_dcache_all()
+ *
+ *	Invalidate the whole D-cache.
+ *
+ *	Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
+ *
+ *	Note: copied from __v7_flush_dcache_all above with
+ *	mcr     p15, 0, r11, c7, c14, 2
+ *	Replaced with:
+ *	mcr     p15, 0, r11, c7, c6, 2
+ */
+ENTRY(__v7_invalidate_dcache_all)
+	dmb					@ ensure ordering with previous memory accesses
+	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
+	mov	r3, r0, lsr #23			@ move LoC into position
+	ands	r3, r3, #7 << 1			@ extract LoC*2 from clidr
+	beq	inval_finished			@ if loc is 0, then no need to clean
+	mov	r10, #0				@ start clean at cache level 0
+inval_levels:
+	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
+	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
+	and	r1, r1, #7			@ mask of the bits for current cache only
+	cmp	r1, #2				@ see what cache we have at this level
+	blt	inval_skip			@ skip if no cache, or just i-cache
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	isb					@ isb to sych the new cssr&csidr
+	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
+	and	r2, r1, #7			@ extract the length of the cache lines
+	add	r2, r2, #4			@ add 4 (line length offset)
+	movw	r4, #0x3ff
+	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
+	clz	r5, r4				@ find bit position of way size increment
+	movw	r7, #0x7fff
+	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
+inval_loop1:
+	mov	r9, r7				@ create working copy of max index
+inval_loop2:
+ ARM(	orr	r11, r10, r4, lsl r5	)	@ factor way and cache number into r11
+ THUMB(	lsl	r6, r4, r5		)
+ THUMB(	orr	r11, r10, r6		)	@ factor way and cache number into r11
+ ARM(	orr	r11, r11, r9, lsl r2	)	@ factor index number into r11
+ THUMB(	lsl	r6, r9, r2		)
+ THUMB(	orr	r11, r11, r6		)	@ factor index number into r11
+	mcr	p15, 0, r11, c7, c6, 2		@ invalidate by set/way
+	subs	r9, r9, #1			@ decrement the index
+	bge	inval_loop2
+	subs	r4, r4, #1			@ decrement the way
+	bge	inval_loop1
+inval_skip:
+	add	r10, r10, #2			@ increment cache number
+	cmp	r3, r10
+	bgt	inval_levels
+inval_finished:
+	mov	r10, #0				@ swith back to cache level 0
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	dsb	st
+	isb
+	bx	lr
+ENDPROC(__v7_invalidate_dcache_all)
+
+ENTRY(v7_invalidate_dcache_all)
+ ARM(	stmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
+ THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
+	bl	__v7_invalidate_dcache_all
+ ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
+ THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
+	bx	lr
+ENDPROC(v7_invalidate_dcache_all)
diff --git a/arch/arm/cpu/armv7/config.mk b/arch/arm/cpu/armv7/config.mk
new file mode 100644
index 0000000..68036d6
--- /dev/null
+++ b/arch/arm/cpu/armv7/config.mk
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+
+# On supported platforms we set the bit which causes us to trap on unaligned
+# memory access.  This is the opposite of what the compiler expects to be
+# the default so we must pass in -mno-unaligned-access so that it is aware
+# of our decision.
+PF_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,)
+PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED)
diff --git a/arch/arm/cpu/armv7/cp15.c b/arch/arm/cpu/armv7/cp15.c
new file mode 100644
index 0000000..0ac4e7b
--- /dev/null
+++ b/arch/arm/cpu/armv7/cp15.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Texas Insturments
+ */
+
+/*
+ * CP15 specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+#include <asm/cache.h>
+#include <asm/armv7.h>
+#include <linux/compiler.h>
+
+void __weak v7_arch_cp15_set_l2aux_ctrl(u32 l2actlr, u32 cpu_midr,
+				     u32 cpu_rev_comb, u32 cpu_variant,
+				     u32 cpu_rev)
+{
+	asm volatile ("mcr p15, 1, %0, c15, c0, 0\n\t" : : "r"(l2actlr));
+}
+
+void __weak v7_arch_cp15_set_acr(u32 acr, u32 cpu_midr, u32 cpu_rev_comb,
+				 u32 cpu_variant, u32 cpu_rev)
+{
+	asm volatile ("mcr p15, 0, %0, c1, c0, 1\n\t" : : "r"(acr));
+}
diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c
new file mode 100644
index 0000000..44f2757
--- /dev/null
+++ b/arch/arm/cpu/armv7/cpu.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008 Texas Insturments
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+#include <asm/cache.h>
+#include <asm/armv7.h>
+#include <linux/compiler.h>
+
+void __weak cpu_cache_initialization(void){}
+
+int cleanup_before_linux_select(int flags)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * we turn off caches etc ...
+	 */
+#ifndef CONFIG_SPL_BUILD
+	disable_interrupts();
+#endif
+
+	if (flags & CBL_DISABLE_CACHES) {
+		/*
+		* turn off D-cache
+		* dcache_disable() in turn flushes the d-cache and disables MMU
+		*/
+		dcache_disable();
+		v7_outer_cache_disable();
+
+		/*
+		* After D-cache is flushed and before it is disabled there may
+		* be some new valid entries brought into the cache. We are
+		* sure that these lines are not dirty and will not affect our
+		* execution. (because unwinding the call-stack and setting a
+		* bit in CP15 SCTRL is all we did during this. We have not
+		* pushed anything on to the stack. Neither have we affected
+		* any static data) So just invalidate the entire d-cache again
+		* to avoid coherency problems for kernel
+		*/
+		invalidate_dcache_all();
+
+		icache_disable();
+		invalidate_icache_all();
+	} else {
+		/*
+		 * Turn off I-cache and invalidate it
+		 */
+		icache_disable();
+		invalidate_icache_all();
+
+		flush_dcache_all();
+		invalidate_icache_all();
+		icache_enable();
+	}
+
+	/*
+	 * Some CPU need more cache attention before starting the kernel.
+	 */
+	cpu_cache_initialization();
+
+	return 0;
+}
+
+int cleanup_before_linux(void)
+{
+	return cleanup_before_linux_select(CBL_ALL);
+}
diff --git a/arch/arm/cpu/armv7/iproc-common/Makefile b/arch/arm/cpu/armv7/iproc-common/Makefile
new file mode 100644
index 0000000..6f5c837
--- /dev/null
+++ b/arch/arm/cpu/armv7/iproc-common/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2014 Broadcom Corporation.
+
+obj-y	+= armpll.o
+obj-y	+= hwinit-common.o
+obj-y	+= timer.o
diff --git a/arch/arm/cpu/armv7/iproc-common/armpll.c b/arch/arm/cpu/armv7/iproc-common/armpll.c
new file mode 100644
index 0000000..efa3d9e
--- /dev/null
+++ b/arch/arm/cpu/armv7/iproc-common/armpll.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/iproc-common/armpll.h>
+#include <asm/iproc-common/sysmap.h>
+
+#define NELEMS(x)	(sizeof(x) / sizeof(x[0]))
+
+struct armpll_parameters {
+	unsigned int mode;
+	unsigned int ndiv_int;
+	unsigned int ndiv_frac;
+	unsigned int pdiv;
+	unsigned int freqid;
+};
+
+struct armpll_parameters armpll_clk_tab[] = {
+	{   25, 64,      1, 1, 0},
+	{  100, 64,      1, 1, 2},
+	{  400, 64,      1, 1, 6},
+	{  448, 71, 713050, 1, 6},
+	{  500, 80,      1, 1, 6},
+	{  560, 89, 629145, 1, 6},
+	{  600, 96,      1, 1, 6},
+	{  800, 64,      1, 1, 7},
+	{  896, 71, 713050, 1, 7},
+	{ 1000, 80,      1, 1, 7},
+	{ 1100, 88,      1, 1, 7},
+	{ 1120, 89, 629145, 1, 7},
+	{ 1200, 96,      1, 1, 7},
+};
+
+uint32_t armpll_config(uint32_t clkmhz)
+{
+	uint32_t freqid;
+	uint32_t ndiv_frac;
+	uint32_t pll;
+	uint32_t status = 1;
+	uint32_t timeout_countdown;
+	int i;
+
+	for (i = 0; i < NELEMS(armpll_clk_tab); i++) {
+		if (armpll_clk_tab[i].mode == clkmhz) {
+			status = 0;
+			break;
+		}
+	}
+
+	if (status) {
+		printf("Error: Clock configuration not supported\n");
+		goto armpll_config_done;
+	}
+
+	/* Enable write access */
+	writel(IPROC_REG_WRITE_ACCESS, IHOST_PROC_CLK_WR_ACCESS);
+
+	if (clkmhz == 25)
+		freqid = 0;
+	else
+		freqid = 2;
+
+	/* Bypass ARM clock and run on sysclk */
+	writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE |
+	       freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R |
+	       freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R |
+	       freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R |
+	       freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R,
+	       IHOST_PROC_CLK_POLICY_FREQ);
+
+	writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO |
+	       1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC,
+	       IHOST_PROC_CLK_POLICY_CTL);
+
+	/* Poll CCU until operation complete */
+	timeout_countdown = 0x100000;
+	while (readl(IHOST_PROC_CLK_POLICY_CTL) &
+	       (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) {
+		timeout_countdown--;
+		if (timeout_countdown == 0) {
+			printf("CCU polling timedout\n");
+			status = 1;
+			goto armpll_config_done;
+		}
+	}
+
+	if (clkmhz == 25 || clkmhz == 100) {
+		status = 0;
+		goto armpll_config_done;
+	}
+
+	/* Now it is safe to program the PLL */
+	pll = readl(IHOST_PROC_CLK_PLLARMB);
+	pll &= ~((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1);
+	ndiv_frac =
+		((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1) &
+		 (armpll_clk_tab[i].ndiv_frac <<
+		 IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_R);
+	pll |= ndiv_frac;
+	writel(pll, IHOST_PROC_CLK_PLLARMB);
+
+	writel(1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK |
+	       armpll_clk_tab[i].ndiv_int <<
+			IHOST_PROC_CLK_PLLARMA__PLLARM_NDIV_INT_R |
+	       armpll_clk_tab[i].pdiv <<
+			IHOST_PROC_CLK_PLLARMA__PLLARM_PDIV_R |
+	       1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_RESETB,
+	       IHOST_PROC_CLK_PLLARMA);
+
+	/* Poll ARM PLL Lock until operation complete */
+	timeout_countdown = 0x100000;
+	while (readl(IHOST_PROC_CLK_PLLARMA) &
+	       (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK)) {
+		timeout_countdown--;
+		if (timeout_countdown == 0) {
+			printf("ARM PLL lock failed\n");
+			status = 1;
+			goto armpll_config_done;
+		}
+	}
+
+	pll = readl(IHOST_PROC_CLK_PLLARMA);
+	pll |= (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB);
+	writel(pll, IHOST_PROC_CLK_PLLARMA);
+
+	/* Set the policy */
+	writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE |
+	       armpll_clk_tab[i].freqid <<
+			IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R |
+	       armpll_clk_tab[i].freqid <<
+			IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R |
+	       armpll_clk_tab[i].freqid <<
+			IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R |
+	       armpll_clk_tab[i+4].freqid <<
+			IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R,
+	       IHOST_PROC_CLK_POLICY_FREQ);
+
+	writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE0_CLKGATE);
+	writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE1_CLKGATE);
+	writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_SWITCH_CLKGATE);
+	writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_PERIPH_CLKGATE);
+	writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_APB0_CLKGATE);
+
+	writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO |
+	       1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC,
+	       IHOST_PROC_CLK_POLICY_CTL);
+
+	/* Poll CCU until operation complete */
+	timeout_countdown = 0x100000;
+	while (readl(IHOST_PROC_CLK_POLICY_CTL) &
+	       (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) {
+		timeout_countdown--;
+		if (timeout_countdown == 0) {
+			printf("CCU polling failed\n");
+			status = 1;
+			goto armpll_config_done;
+		}
+	}
+
+	status = 0;
+armpll_config_done:
+	/* Disable access to PLL registers */
+	writel(0, IHOST_PROC_CLK_WR_ACCESS);
+
+	return status;
+}
diff --git a/arch/arm/cpu/armv7/iproc-common/hwinit-common.c b/arch/arm/cpu/armv7/iproc-common/hwinit-common.c
new file mode 100644
index 0000000..8bf06a3
--- /dev/null
+++ b/arch/arm/cpu/armv7/iproc-common/hwinit-common.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
diff --git a/arch/arm/cpu/armv7/iproc-common/timer.c b/arch/arm/cpu/armv7/iproc-common/timer.c
new file mode 100644
index 0000000..aaa767d
--- /dev/null
+++ b/arch/arm/cpu/armv7/iproc-common/timer.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <asm/iproc-common/timer.h>
+#include <asm/iproc-common/sysmap.h>
+
+static inline uint64_t timer_global_read(void)
+{
+	uint64_t cur_tick;
+	uint32_t count_h;
+	uint32_t count_l;
+
+	do {
+		count_h = readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+				TIMER_GLB_HI_OFFSET);
+		count_l = readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+				TIMER_GLB_LOW_OFFSET);
+		cur_tick = readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+				 TIMER_GLB_HI_OFFSET);
+	} while (cur_tick != count_h);
+
+	return (cur_tick << 32) + count_l;
+}
+
+void timer_global_init(void)
+{
+	writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_CTRL_OFFSET);
+	writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_LOW_OFFSET);
+	writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_HI_OFFSET);
+	writel(TIMER_GLB_TIM_CTRL_TIM_EN,
+	       IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_CTRL_OFFSET);
+}
+
+int timer_init(void)
+{
+	timer_global_init();
+	return 0;
+}
+
+unsigned long get_timer(unsigned long base)
+{
+	uint64_t count;
+	uint64_t ret;
+	uint64_t tim_clk;
+	uint64_t periph_clk;
+
+	count = timer_global_read();
+
+	/* default arm clk is 1GHz, periph_clk=arm_clk/2, tick per msec */
+	periph_clk = 500000;
+	tim_clk = lldiv(periph_clk,
+			(((readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+				 TIMER_GLB_CTRL_OFFSET) &
+			TIMER_GLB_TIM_CTRL_PRESC_MASK) >> 8) + 1));
+
+	ret = lldiv(count, (uint32_t)tim_clk);
+
+	/* returns msec */
+	return ret - base;
+}
+
+void __udelay(unsigned long usec)
+{
+	uint64_t cur_tick, end_tick;
+	uint64_t tim_clk;
+	uint64_t periph_clk;
+
+	/* default arm clk is 1GHz, periph_clk=arm_clk/2, tick per usec */
+	periph_clk = 500;
+
+	tim_clk = lldiv(periph_clk,
+			(((readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+				 TIMER_GLB_CTRL_OFFSET) &
+			TIMER_GLB_TIM_CTRL_PRESC_MASK) >> 8) + 1));
+
+	cur_tick = timer_global_read();
+
+	end_tick = tim_clk;
+	end_tick *= usec;
+	end_tick += cur_tick;
+
+	do {
+		cur_tick = timer_global_read();
+
+	} while (cur_tick < end_tick);
+}
+
+void timer_systick_init(uint32_t tick_ms)
+{
+	/* Disable timer and clear interrupt status*/
+	writel(0, IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_CTRL_OFFSET);
+	writel(TIMER_PVT_TIM_INT_STATUS_SET,
+	       IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_STATUS_OFFSET);
+	writel((PLL_AXI_CLK/1000) * tick_ms,
+	       IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_LOAD_OFFSET);
+	writel(TIMER_PVT_TIM_CTRL_INT_EN |
+	       TIMER_PVT_TIM_CTRL_AUTO_RELD |
+	       TIMER_PVT_TIM_CTRL_TIM_EN,
+	       IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_CTRL_OFFSET);
+}
+
+void timer_systick_isr(void *data)
+{
+	writel(TIMER_PVT_TIM_INT_STATUS_SET,
+	       IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_STATUS_OFFSET);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value in msec.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This is used in conjuction with get_ticks, which returns msec as ticks.
+ * Here we just return ticks/sec = msec/sec = 1000
+ */
+ulong get_tbclk(void)
+{
+	return 1000;
+}
diff --git a/arch/arm/cpu/armv7/kona-common/Makefile b/arch/arm/cpu/armv7/kona-common/Makefile
new file mode 100644
index 0000000..56de3d1
--- /dev/null
+++ b/arch/arm/cpu/armv7/kona-common/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2013 Broadcom Corporation.
+
+obj-y	+= s_init.o
+obj-y	+= hwinit-common.o
+obj-y	+= clk-stubs.o
+obj-${CONFIG_KONA_RESET_S} += reset.o
diff --git a/arch/arm/cpu/armv7/kona-common/clk-stubs.c b/arch/arm/cpu/armv7/kona-common/clk-stubs.c
new file mode 100644
index 0000000..2dfa3f7
--- /dev/null
+++ b/arch/arm/cpu/armv7/kona-common/clk-stubs.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <common.h>
+
+/*
+ * These weak functions are available to kona architectures that don't
+ * require clock enables from the driver code.
+ */
+int __weak clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep)
+{
+	return 0;
+}
+
+int __weak clk_bsc_enable(void *base, u32 rate, u32 *actual_ratep)
+{
+	return 0;
+}
+
+int __weak clk_usb_otg_enable(void *base)
+{
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/kona-common/hwinit-common.c b/arch/arm/cpu/armv7/kona-common/hwinit-common.c
new file mode 100644
index 0000000..8783893
--- /dev/null
+++ b/arch/arm/cpu/armv7/kona-common/hwinit-common.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+#include <common.h>
+#include <linux/sizes.h>
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
diff --git a/arch/arm/cpu/armv7/kona-common/reset.S b/arch/arm/cpu/armv7/kona-common/reset.S
new file mode 100644
index 0000000..eea835b
--- /dev/null
+++ b/arch/arm/cpu/armv7/kona-common/reset.S
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2013 Broadcom Corporation.
+ */
+
+.globl reset_cpu
+reset_cpu:
+	ldr	r1, =0x35001f00
+	ldr	r2, [r1]
+	ldr	r4, =0x80000000
+	and	r4, r2, r4
+	ldr	r3, =0xA5A500
+	orr	r4, r4, r3
+	orr	r4, r4, #0x1
+
+	str	r4, [r1]
+
+	ldr	r1, =0x35001f04
+	ldr	r2, [r1]
+	ldr	r4, =0x80000000
+	and	r4, r2, r4
+	str	r4, [r1]
+
+_loop_forever:
+	b	_loop_forever
diff --git a/arch/arm/cpu/armv7/kona-common/s_init.c b/arch/arm/cpu/armv7/kona-common/s_init.c
new file mode 100644
index 0000000..778b917
--- /dev/null
+++ b/arch/arm/cpu/armv7/kona-common/s_init.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Broadcom Corporation.
+ */
+
+/*
+ * Early system init. Currently empty.
+ */
+void s_init(void)
+{
+}
diff --git a/arch/arm/cpu/armv7/lowlevel_init.S b/arch/arm/cpu/armv7/lowlevel_init.S
new file mode 100644
index 0000000..ba4b374
--- /dev/null
+++ b/arch/arm/cpu/armv7/lowlevel_init.S
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * A lowlevel_init function that sets up the stack to call a C function to
+ * perform further init.
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *
+ * Author :
+ *	Aneesh V	<aneesh@ti.com>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+.pushsection .text.s_init, "ax"
+WEAK(s_init)
+	bx	lr
+ENDPROC(s_init)
+.popsection
+
+.pushsection .text.lowlevel_init, "ax"
+WEAK(lowlevel_init)
+	/*
+	 * Setup a temporary stack. Global data is not available yet.
+	 */
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
+	ldr	sp, =CONFIG_SPL_STACK
+#else
+	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR
+#endif
+	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
+#ifdef CONFIG_SPL_DM
+	mov	r9, #0
+#else
+	/*
+	 * Set up global data for boards that still need it. This will be
+	 * removed soon.
+	 */
+#ifdef CONFIG_SPL_BUILD
+	ldr	r9, =gdata
+#else
+	sub	sp, sp, #GD_SIZE
+	bic	sp, sp, #7
+	mov	r9, sp
+#endif
+#endif
+	/*
+	 * Save the old lr(passed in ip) and the current lr to stack
+	 */
+	push	{ip, lr}
+
+	/*
+	 * Call the very early init function. This should do only the
+	 * absolute bare minimum to get started. It should not:
+	 *
+	 * - set up DRAM
+	 * - use global_data
+	 * - clear BSS
+	 * - try to start a console
+	 *
+	 * For boards with SPL this should be empty since SPL can do all of
+	 * this init in the SPL board_init_f() function which is called
+	 * immediately after this.
+	 */
+	bl	s_init
+	pop	{ip, pc}
+ENDPROC(lowlevel_init)
+.popsection
diff --git a/arch/arm/cpu/armv7/ls102xa/Kconfig b/arch/arm/cpu/armv7/ls102xa/Kconfig
new file mode 100644
index 0000000..4ffde9a
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/Kconfig
@@ -0,0 +1,110 @@
+config ARCH_LS1021A
+	bool
+	select SYS_FSL_DDR_BE if SYS_FSL_DDR
+	select SYS_FSL_DDR_VER_50 if SYS_FSL_DDR
+	select SYS_FSL_ERRATUM_A008378
+	select SYS_FSL_ERRATUM_A008407
+	select SYS_FSL_ERRATUM_A008997
+	select SYS_FSL_ERRATUM_A009007
+	select SYS_FSL_ERRATUM_A009008
+	select SYS_FSL_ERRATUM_A009663
+	select SYS_FSL_ERRATUM_A009798
+	select SYS_FSL_ERRATUM_A009942
+	select SYS_FSL_ERRATUM_A010315
+	select SYS_FSL_HAS_CCI400
+	select SYS_FSL_HAS_DDR3 if SYS_FSL_DDR
+	select SYS_FSL_HAS_DDR4 if SYS_FSL_DDR
+	select SYS_FSL_HAS_SEC
+	select SYS_FSL_SEC_COMPAT_5
+	select SYS_FSL_SEC_LE
+	select SYS_FSL_SRDS_1
+	select SYS_HAS_SERDES
+	imply CMD_PCI
+	imply SCSI
+	imply SCSI_AHCI
+
+menu "LS102xA architecture"
+	depends on ARCH_LS1021A
+
+config FSL_PCIE_COMPAT
+	string "PCIe compatible of Kernel DT"
+	depends on PCIE_LAYERSCAPE
+	default "fsl,ls1021a-pcie" if ARCH_LS1021A
+	help
+	  This compatible is used to find pci controller node in Kernel DT
+	  to complete fixup.
+
+config LS1_DEEP_SLEEP
+	bool "Deep sleep"
+	depends on ARCH_LS1021A
+
+config MAX_CPUS
+	int "Maximum number of CPUs permitted for LS102xA"
+	depends on ARCH_LS1021A
+	default 2
+	help
+	  Set this number to the maximum number of possible CPUs in the SoC.
+	  SoCs may have multiple clusters with each cluster may have multiple
+	  ports. If some ports are reserved but higher ports are used for
+	  cores, count the reserved ports. This will allocate enough memory
+	  in spin table to properly handle all cores.
+
+config SECURE_BOOT
+	bool	"Secure Boot"
+	help
+		Enable Freescale Secure Boot feature. Normally selected
+		by defconfig. If unsure, do not change.
+
+config SYS_CCI400_OFFSET
+	hex "Offset for CCI400 base"
+	depends on SYS_FSL_HAS_CCI400
+	default 0x180000
+	help
+	  Offset for CCI400 base.
+	  CCI400 base addr = CCSRBAR + CCI400_OFFSET
+
+config SYS_FSL_ERRATUM_A008997
+	bool
+	help
+	  Workaround for USB PHY erratum A008997
+
+config SYS_FSL_ERRATUM_A009007
+	bool
+	help
+	  Workaround for USB PHY erratum A009007
+
+config SYS_FSL_ERRATUM_A009008
+	bool
+	help
+	  Workaround for USB PHY erratum A009008
+
+config SYS_FSL_ERRATUM_A009798
+	bool
+	help
+	  Workaround for USB PHY erratum A009798
+
+config SYS_FSL_ERRATUM_A010315
+	bool "Workaround for PCIe erratum A010315"
+
+config SYS_FSL_HAS_CCI400
+	bool
+
+config SYS_FSL_SRDS_1
+	bool
+
+config SYS_FSL_SRDS_2
+	bool
+
+config SYS_HAS_SERDES
+	bool
+
+config SYS_FSL_IFC_BANK_COUNT
+	int "Maximum banks of Integrated flash controller"
+	depends on ARCH_LS1021A
+	default 8
+
+config SYS_FSL_ERRATUM_A008407
+	bool
+
+endmenu
+
diff --git a/arch/arm/cpu/armv7/ls102xa/Makefile b/arch/arm/cpu/armv7/ls102xa/Makefile
new file mode 100644
index 0000000..0c1596f
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/Makefile
@@ -0,0 +1,19 @@
+#
+# Copyright 2014 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y	+= cpu.o
+obj-y	+= clock.o
+obj-y	+= timer.o
+obj-y	+= fsl_epu.o
+obj-y	+= soc.o
+
+obj-$(CONFIG_OF_LIBFDT) += fdt.o
+obj-$(CONFIG_SYS_HAS_SERDES) += fsl_ls1_serdes.o ls102xa_serdes.o
+obj-$(CONFIG_SPL) += spl.o
+
+ifdef CONFIG_ARMV7_PSCI
+obj-y  += psci.o ls102xa_psci.o
+endif
diff --git a/arch/arm/cpu/armv7/ls102xa/clock.c b/arch/arm/cpu/armv7/ls102xa/clock.c
new file mode 100644
index 0000000..30c7b37
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/clock.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <asm/arch/clock.h>
+#include <fsl_ifc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
+#define CONFIG_SYS_FSL_NUM_CC_PLLS      2
+#endif
+
+void get_sys_info(struct sys_info *sys_info)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_LS1_CLK_ADDR);
+	unsigned int cpu;
+	const u8 core_cplx_pll[6] = {
+		[0] = 0,	/* CC1 PPL / 1 */
+		[1] = 0,	/* CC1 PPL / 2 */
+		[4] = 1,	/* CC2 PPL / 1 */
+		[5] = 1,	/* CC2 PPL / 2 */
+	};
+
+	const u8 core_cplx_pll_div[6] = {
+		[0] = 1,	/* CC1 PPL / 1 */
+		[1] = 2,	/* CC1 PPL / 2 */
+		[4] = 1,	/* CC2 PPL / 1 */
+		[5] = 2,	/* CC2 PPL / 2 */
+	};
+
+	uint i;
+	uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
+	uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
+	unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
+
+	sys_info->freq_systembus = sysclk;
+#ifdef CONFIG_DDR_CLK_FREQ
+	sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
+#else
+	sys_info->freq_ddrbus = sysclk;
+#endif
+
+	sys_info->freq_systembus *= (in_be32(&gur->rcwsr[0]) >>
+		RCWSR0_SYS_PLL_RAT_SHIFT) & RCWSR0_SYS_PLL_RAT_MASK;
+	sys_info->freq_ddrbus *= (in_be32(&gur->rcwsr[0]) >>
+		RCWSR0_MEM_PLL_RAT_SHIFT) & RCWSR0_MEM_PLL_RAT_MASK;
+
+	for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
+		ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0x3f;
+		if (ratio[i] > 4)
+			freq_c_pll[i] = sysclk * ratio[i];
+		else
+			freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
+	}
+
+	for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) {
+		u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27)
+				& 0xf;
+		u32 cplx_pll = core_cplx_pll[c_pll_sel];
+
+		sys_info->freq_processor[cpu] =
+			freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
+	}
+
+#if defined(CONFIG_FSL_IFC)
+	sys_info->freq_localbus = sys_info->freq_systembus;
+#endif
+}
+
+int get_clocks(void)
+{
+	struct sys_info sys_info;
+
+	get_sys_info(&sys_info);
+	gd->cpu_clk = sys_info.freq_processor[0];
+	gd->bus_clk = sys_info.freq_systembus;
+	gd->mem_clk = sys_info.freq_ddrbus * 2;
+
+#if defined(CONFIG_FSL_ESDHC)
+	gd->arch.sdhc_clk = gd->bus_clk;
+#endif
+
+	return 0;
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+	return gd->bus_clk;
+}
+
+ulong get_ddr_freq(ulong dummy)
+{
+	return gd->mem_clk;
+}
+
+int get_serial_clock(void)
+{
+	return gd->bus_clk / 2;
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_I2C_CLK:
+		return get_bus_freq(0) / 2;
+	case MXC_ESDHC_CLK:
+		return get_bus_freq(0);
+	case MXC_DSPI_CLK:
+		return get_bus_freq(0) / 2;
+	case MXC_UART_CLK:
+		return get_bus_freq(0) / 2;
+	default:
+		printf("Unsupported clock\n");
+	}
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/cpu.c b/arch/arm/cpu/armv7/ls102xa/cpu.c
new file mode 100644
index 0000000..7c4018e
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/cpu.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/io.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <asm/cache.h>
+#include <asm/system.h>
+#include <tsec.h>
+#include <netdev.h>
+#include <fsl_esdhc.h>
+#include <config.h>
+#include <fsl_wdog.h>
+
+#include "fsl_epu.h"
+
+#define DCSR_RCPM2_BLOCK_OFFSET	0x223000
+#define DCSR_RCPM2_CPMFSMCR0	0x400
+#define DCSR_RCPM2_CPMFSMSR0	0x404
+#define DCSR_RCPM2_CPMFSMCR1	0x414
+#define DCSR_RCPM2_CPMFSMSR1	0x418
+#define CPMFSMSR_FSM_STATE_MASK	0x7f
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+
+/*
+ * Bit[1] of the descriptor indicates the descriptor type,
+ * and bit[0] indicates whether the descriptor is valid.
+ */
+#define PMD_TYPE_TABLE		0x3
+#define PMD_TYPE_SECT		0x1
+
+/* AttrIndx[2:0] */
+#define PMD_ATTRINDX(t)		((t) << 2)
+
+/* Section */
+#define PMD_SECT_AF		(1 << 10)
+
+#define BLOCK_SIZE_L1		(1UL << 30)
+#define BLOCK_SIZE_L2		(1UL << 21)
+
+/* TTBCR flags */
+#define TTBCR_EAE		(1 << 31)
+#define TTBCR_T0SZ(x)		((x) << 0)
+#define TTBCR_T1SZ(x)		((x) << 16)
+#define TTBCR_USING_TTBR0	(TTBCR_T0SZ(0) | TTBCR_T1SZ(0))
+#define TTBCR_IRGN0_NC		(0 << 8)
+#define TTBCR_IRGN0_WBWA	(1 << 8)
+#define TTBCR_IRGN0_WT		(2 << 8)
+#define TTBCR_IRGN0_WBNWA	(3 << 8)
+#define TTBCR_IRGN0_MASK	(3 << 8)
+#define TTBCR_ORGN0_NC		(0 << 10)
+#define TTBCR_ORGN0_WBWA	(1 << 10)
+#define TTBCR_ORGN0_WT		(2 << 10)
+#define TTBCR_ORGN0_WBNWA	(3 << 10)
+#define TTBCR_ORGN0_MASK	(3 << 10)
+#define TTBCR_SHARED_NON	(0 << 12)
+#define TTBCR_SHARED_OUTER	(2 << 12)
+#define TTBCR_SHARED_INNER	(3 << 12)
+#define TTBCR_EPD0		(0 << 7)
+#define TTBCR			(TTBCR_SHARED_NON | \
+				 TTBCR_ORGN0_NC	| \
+				 TTBCR_IRGN0_NC	| \
+				 TTBCR_USING_TTBR0 | \
+				 TTBCR_EAE)
+
+/*
+ * Memory region attributes for LPAE (defined in pgtable):
+ *
+ * n = AttrIndx[2:0]
+ *
+ *		              n       MAIR
+ *	UNCACHED              000     00000000
+ *	BUFFERABLE            001     01000100
+ *	DEV_WC                001     01000100
+ *	WRITETHROUGH          010     10101010
+ *	WRITEBACK             011     11101110
+ *	DEV_CACHED            011     11101110
+ *	DEV_SHARED            100     00000100
+ *	DEV_NONSHARED         100     00000100
+ *	unused                101
+ *	unused                110
+ *	WRITEALLOC            111     11111111
+ */
+#define MT_MAIR0		0xeeaa4400
+#define MT_MAIR1		0xff000004
+#define MT_STRONLY_ORDER	0
+#define MT_NORMAL_NC		1
+#define MT_DEVICE_MEM		4
+#define MT_NORMAL		7
+
+/* The phy_addr must be aligned to 4KB */
+static inline void set_pgtable(u32 *page_table, u32 index, u32 phy_addr)
+{
+	u32 value = phy_addr | PMD_TYPE_TABLE;
+
+	page_table[2 * index] = value;
+	page_table[2 * index + 1] = 0;
+}
+
+/* The phy_addr must be aligned to 4KB */
+static inline void set_pgsection(u32 *page_table, u32 index, u64 phy_addr,
+				 u32 memory_type)
+{
+	u64 value;
+
+	value = phy_addr | PMD_TYPE_SECT | PMD_SECT_AF;
+	value |= PMD_ATTRINDX(memory_type);
+	page_table[2 * index] = value & 0xFFFFFFFF;
+	page_table[2 * index + 1] = (value >> 32) & 0xFFFFFFFF;
+}
+
+/*
+ * Start MMU after DDR is available, we create MMU table in DRAM.
+ * The base address of TTLB is gd->arch.tlb_addr. We use two
+ * levels of translation tables here to cover 40-bit address space.
+ *
+ * The TTLBs are located at PHY 2G~4G.
+ *
+ * VA mapping:
+ *
+ *  -------  <---- 0GB
+ * |       |
+ * |       |
+ * |-------| <---- 0x24000000
+ * |///////|  ===> 192MB VA map for PCIe1 with offset 0x40_0000_0000
+ * |-------| <---- 0x300000000
+ * |       |
+ * |-------| <---- 0x34000000
+ * |///////|  ===> 192MB VA map for PCIe2 with offset 0x48_0000_0000
+ * |-------| <---- 0x40000000
+ * |       |
+ * |-------| <---- 0x80000000 DDR0 space start
+ * |\\\\\\\|
+ *.|\\\\\\\|  ===> 2GB VA map for 2GB DDR0 Memory space
+ * |\\\\\\\|
+ *  -------  <---- 4GB DDR0 space end
+ */
+static void mmu_setup(void)
+{
+	u32 *level0_table = (u32 *)gd->arch.tlb_addr;
+	u32 *level1_table = (u32 *)(gd->arch.tlb_addr + 0x1000);
+	u64 va_start = 0;
+	u32 reg;
+	int i;
+
+	/* Level 0 Table 2-3 are used to map DDR */
+	set_pgsection(level0_table, 3, 3 * BLOCK_SIZE_L1, MT_NORMAL);
+	set_pgsection(level0_table, 2, 2 * BLOCK_SIZE_L1, MT_NORMAL);
+	/* Level 0 Table 1 is used to map device */
+	set_pgsection(level0_table, 1, 1 * BLOCK_SIZE_L1, MT_DEVICE_MEM);
+	/* Level 0 Table 0 is used to map device including PCIe MEM */
+	set_pgtable(level0_table, 0, (u32)level1_table);
+
+	/* Level 1 has 512 entries */
+	for (i = 0; i < 512; i++) {
+		/* Mapping for PCIe 1 */
+		if (va_start >= CONFIG_SYS_PCIE1_VIRT_ADDR &&
+		    va_start < (CONFIG_SYS_PCIE1_VIRT_ADDR +
+				 CONFIG_SYS_PCIE_MMAP_SIZE))
+			set_pgsection(level1_table, i,
+				      CONFIG_SYS_PCIE1_PHYS_BASE + va_start,
+				      MT_DEVICE_MEM);
+		/* Mapping for PCIe 2 */
+		else if (va_start >= CONFIG_SYS_PCIE2_VIRT_ADDR &&
+			 va_start < (CONFIG_SYS_PCIE2_VIRT_ADDR +
+				     CONFIG_SYS_PCIE_MMAP_SIZE))
+			set_pgsection(level1_table, i,
+				      CONFIG_SYS_PCIE2_PHYS_BASE + va_start,
+				      MT_DEVICE_MEM);
+		else
+			set_pgsection(level1_table, i,
+				      va_start,
+				      MT_DEVICE_MEM);
+		va_start += BLOCK_SIZE_L2;
+	}
+
+	asm volatile("dsb sy;isb");
+	asm volatile("mcr p15, 0, %0, c2, c0, 2" /* Write RT to TTBCR */
+			: : "r" (TTBCR) : "memory");
+	asm volatile("mcrr p15, 0, %0, %1, c2" /* TTBR 0 */
+			: : "r" ((u32)level0_table), "r" (0) : "memory");
+	asm volatile("mcr p15, 0, %0, c10, c2, 0" /* write MAIR 0 */
+			: : "r" (MT_MAIR0) : "memory");
+	asm volatile("mcr p15, 0, %0, c10, c2, 1" /* write MAIR 1 */
+			: : "r" (MT_MAIR1) : "memory");
+
+	/* Set the access control to all-supervisor */
+	asm volatile("mcr p15, 0, %0, c3, c0, 0"
+		     : : "r" (~0));
+
+	/* Enable the mmu */
+	reg = get_cr();
+	set_cr(reg | CR_M);
+}
+
+/*
+ * This function is called from lib/board.c. It recreates MMU
+ * table in main memory. MMU and i/d-cache are enabled here.
+ */
+void enable_caches(void)
+{
+	/* Invalidate all TLB */
+	mmu_page_table_flush(gd->arch.tlb_addr,
+			     gd->arch.tlb_addr +  gd->arch.tlb_size);
+	/* Set up and enable mmu */
+	mmu_setup();
+
+	/* Invalidate & Enable d-cache */
+	invalidate_dcache_all();
+	set_cr(get_cr() | CR_C);
+}
+#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
+
+
+uint get_svr(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+	return in_be32(&gur->svr);
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	char buf1[32], buf2[32];
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	unsigned int svr, major, minor, ver, i;
+
+	svr = in_be32(&gur->svr);
+	major = SVR_MAJ(svr);
+	minor = SVR_MIN(svr);
+
+	puts("CPU:   Freescale LayerScape ");
+
+	ver = SVR_SOC_VER(svr);
+	switch (ver) {
+	case SOC_VER_SLS1020:
+		puts("SLS1020");
+		break;
+	case SOC_VER_LS1020:
+		puts("LS1020");
+		break;
+	case SOC_VER_LS1021:
+		puts("LS1021");
+		break;
+	case SOC_VER_LS1022:
+		puts("LS1022");
+		break;
+	default:
+		puts("Unknown");
+		break;
+	}
+
+	if (IS_E_PROCESSOR(svr) && (ver != SOC_VER_SLS1020))
+		puts("E");
+
+	printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+
+	puts("Clock Configuration:");
+
+	printf("\n       CPU0(ARMV7):%-4s MHz, ", strmhz(buf1, gd->cpu_clk));
+	printf("\n       Bus:%-4s MHz, ", strmhz(buf1, gd->bus_clk));
+	printf("DDR:%-4s MHz (%s MT/s data rate), ",
+	       strmhz(buf1, gd->mem_clk/2), strmhz(buf2, gd->mem_clk));
+	puts("\n");
+
+	/* Display the RCW, so that no one gets confused as to what RCW
+	 * we're actually using for this boot.
+	 */
+	puts("Reset Configuration Word (RCW):");
+	for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) {
+		u32 rcw = in_be32(&gur->rcwsr[i]);
+
+		if ((i % 4) == 0)
+			printf("\n       %08x:", i * 4);
+		printf(" %08x", rcw);
+	}
+	puts("\n");
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FSL_ESDHC
+int cpu_mmc_init(bd_t *bis)
+{
+	return fsl_esdhc_mmc_init(bis);
+}
+#endif
+
+int cpu_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_TSEC_ENET
+	tsec_standard_init(bis);
+#endif
+
+	return 0;
+}
+
+int arch_cpu_init(void)
+{
+	void *epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET);
+	void *rcpm2_base =
+		(void *)(CONFIG_SYS_DCSRBAR + DCSR_RCPM2_BLOCK_OFFSET);
+	struct ccsr_scfg *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+	u32 state;
+
+	/*
+	 * The RCPM FSM state may not be reset after power-on.
+	 * So, reset them.
+	 */
+	state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR0) &
+		CPMFSMSR_FSM_STATE_MASK;
+	if (state != 0) {
+		out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x80);
+		out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x0);
+	}
+
+	state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR1) &
+		CPMFSMSR_FSM_STATE_MASK;
+	if (state != 0) {
+		out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x80);
+		out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x0);
+	}
+
+	/*
+	 * After wakeup from deep sleep, Clear EPU registers
+	 * as early as possible to prevent from possible issue.
+	 * It's also safe to clear at normal boot.
+	 */
+	fsl_epu_clean(epu_base);
+
+	setbits_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SEC_RD_WR);
+
+	return 0;
+}
+
+#ifdef CONFIG_ARMV7_NONSEC
+/* Set the address at which the secondary core starts from.*/
+void smp_set_core_boot_addr(unsigned long addr, int corenr)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+	out_be32(&gur->scratchrw[0], addr);
+}
+
+/* Release the secondary core from holdoff state and kick it */
+void smp_kick_all_cpus(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+	out_be32(&gur->brrl, 0x2);
+
+	/*
+	 * LS1 STANDBYWFE is not captured outside the ARM module in the soc.
+	 * So add a delay to wait bootrom execute WFE.
+	 */
+	udelay(1);
+
+	asm volatile("sev");
+}
+#endif
+
+void reset_cpu(ulong addr)
+{
+	struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
+
+	clrbits_be16(&wdog->wcr, WCR_SRS);
+
+	while (1) {
+		/*
+		 * Let the watchdog trigger
+		 */
+	}
+}
+
+void arch_preboot_os(void)
+{
+	unsigned long ctrl;
+
+	/* Disable PL1 Physical Timer */
+	asm("mrc p15, 0, %0, c14, c2, 1" : "=r" (ctrl));
+	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
+	asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl));
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/fdt.c b/arch/arm/cpu/armv7/ls102xa/fdt.c
new file mode 100644
index 0000000..8bf9c42
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/fdt.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/arch/clock.h>
+#include <linux/ctype.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+#include <tsec.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <fsl_sec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void ft_fixup_enet_phy_connect_type(void *fdt)
+{
+	struct eth_device *dev;
+	struct tsec_private *priv;
+	const char *enet_path, *phy_path;
+	char enet[16];
+	char phy[16];
+	int phy_node;
+	int i = 0;
+	uint32_t ph;
+	char *name[3] = { "eTSEC1", "eTSEC2", "eTSEC3" };
+
+	for (; i < ARRAY_SIZE(name); i++) {
+		dev = eth_get_dev_by_name(name[i]);
+		if (dev) {
+			sprintf(enet, "ethernet%d", i);
+			sprintf(phy, "enet%d_rgmii_phy", i);
+		} else {
+			continue;
+		}
+
+		priv = dev->priv;
+		if (priv->flags & TSEC_SGMII)
+			continue;
+
+		enet_path = fdt_get_alias(fdt, enet);
+		if (!enet_path)
+			continue;
+
+		phy_path = fdt_get_alias(fdt, phy);
+		if (!phy_path)
+			continue;
+
+		phy_node = fdt_path_offset(fdt, phy_path);
+		if (phy_node < 0)
+			continue;
+
+		ph = fdt_create_phandle(fdt, phy_node);
+		if (ph)
+			do_fixup_by_path_u32(fdt, enet_path,
+					     "phy-handle", ph, 1);
+
+		do_fixup_by_path(fdt, enet_path, "phy-connection-type",
+				 phy_string_for_interface(
+				 PHY_INTERFACE_MODE_RGMII_ID),
+				 strlen(phy_string_for_interface(
+				 PHY_INTERFACE_MODE_RGMII_ID)) + 1,
+				 1);
+	}
+}
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	int off;
+	int val;
+	const char *sysclk_path;
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	unsigned int svr;
+	svr = in_be32(&gur->svr);
+
+	unsigned long busclk = get_bus_freq(0);
+
+	/* delete crypto node if not on an E-processor */
+	if (!IS_E_PROCESSOR(svr))
+		fdt_fixup_crypto_node(blob, 0);
+#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
+	else {
+		ccsr_sec_t __iomem *sec;
+
+		sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+		fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
+	}
+#endif
+
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+	while (off != -FDT_ERR_NOTFOUND) {
+		val = gd->cpu_clk;
+		fdt_setprop(blob, off, "clock-frequency", &val, 4);
+		off = fdt_node_offset_by_prop_value(blob, off,
+						    "device_type", "cpu", 4);
+	}
+
+	do_fixup_by_prop_u32(blob, "device_type", "soc",
+			     4, "bus-frequency", busclk, 1);
+
+	ft_fixup_enet_phy_connect_type(blob);
+
+#ifdef CONFIG_SYS_NS16550
+	do_fixup_by_compat_u32(blob, "fsl,16550-FIFO64",
+			       "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+	sysclk_path = fdt_get_alias(blob, "sysclk");
+	if (sysclk_path)
+		do_fixup_by_path_u32(blob, sysclk_path, "clock-frequency",
+				     CONFIG_SYS_CLK_FREQ, 1);
+	do_fixup_by_compat_u32(blob, "fsl,qoriq-sysclk-2.0",
+			       "clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
+
+#if defined(CONFIG_DEEP_SLEEP) && defined(CONFIG_SD_BOOT)
+#define UBOOT_HEAD_LEN	0x1000
+	/*
+	 * Reserved memory in SD boot deep sleep case.
+	 * Second stage uboot binary and malloc space should be reserved.
+	 * If the memory they occupied has not been reserved, then this
+	 * space would be used by kernel and overwritten in uboot when
+	 * deep sleep resume, which cause deep sleep failed.
+	 * Since second uboot binary has a head, that space need to be
+	 * reserved either(assuming its size is less than 0x1000).
+	 */
+	off = fdt_add_mem_rsv(blob, CONFIG_SYS_TEXT_BASE - UBOOT_HEAD_LEN,
+			CONFIG_SYS_MONITOR_LEN + CONFIG_SYS_SPL_MALLOC_SIZE +
+			UBOOT_HEAD_LEN);
+	if (off < 0)
+		printf("Failed to reserve memory for SD boot deep sleep: %s\n",
+		       fdt_strerror(off));
+#endif
+
+#if defined(CONFIG_FSL_ESDHC)
+	fdt_fixup_esdhc(blob, bd);
+#endif
+
+	/*
+	 * platform bus clock = system bus clock/2
+	 * Here busclk = system bus clock
+	 * We are using the platform bus clock as 1588 Timer reference
+	 * clock source select
+	 */
+	do_fixup_by_compat_u32(blob, "fsl, gianfar-ptp-timer",
+			       "timer-frequency", busclk / 2, 1);
+
+	/*
+	 * clock-freq should change to clock-frequency and
+	 * flexcan-v1.0 should change to p1010-flexcan respectively
+	 * in the future.
+	 */
+	do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0",
+			       "clock_freq", busclk / 2, 1);
+
+	do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0",
+			       "clock-frequency", busclk / 2, 1);
+
+	do_fixup_by_compat_u32(blob, "fsl, ls1021a-flexcan",
+			       "clock-frequency", busclk / 2, 1);
+
+#if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI)
+	off = fdt_node_offset_by_compat_reg(blob, FSL_IFC_COMPAT,
+					    CONFIG_SYS_IFC_ADDR);
+	fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
+#else
+	off = fdt_node_offset_by_compat_reg(blob, FSL_QSPI_COMPAT,
+					    QSPI0_BASE_ADDR);
+	fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
+	off = fdt_node_offset_by_compat_reg(blob, FSL_DSPI_COMPAT,
+					    DSPI1_BASE_ADDR);
+	fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
+#endif
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_epu.c b/arch/arm/cpu/armv7/ls102xa/fsl_epu.c
new file mode 100644
index 0000000..e31a4fb
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/fsl_epu.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#include "fsl_epu.h"
+
+struct fsm_reg_vals epu_default_val[] = {
+	/* EPGCR (Event Processor Global Control Register) */
+	{EPGCR, 0},
+	/* EPECR (Event Processor Event Control Registers) */
+	{EPECR0 + EPECR_STRIDE * 0, 0},
+	{EPECR0 + EPECR_STRIDE * 1, 0},
+	{EPECR0 + EPECR_STRIDE * 2, 0xF0004004},
+	{EPECR0 + EPECR_STRIDE * 3, 0x80000084},
+	{EPECR0 + EPECR_STRIDE * 4, 0x20000084},
+	{EPECR0 + EPECR_STRIDE * 5, 0x08000004},
+	{EPECR0 + EPECR_STRIDE * 6, 0x80000084},
+	{EPECR0 + EPECR_STRIDE * 7, 0x80000084},
+	{EPECR0 + EPECR_STRIDE * 8, 0x60000084},
+	{EPECR0 + EPECR_STRIDE * 9, 0x08000084},
+	{EPECR0 + EPECR_STRIDE * 10, 0x42000084},
+	{EPECR0 + EPECR_STRIDE * 11, 0x90000084},
+	{EPECR0 + EPECR_STRIDE * 12, 0x80000084},
+	{EPECR0 + EPECR_STRIDE * 13, 0x08000084},
+	{EPECR0 + EPECR_STRIDE * 14, 0x02000084},
+	{EPECR0 + EPECR_STRIDE * 15, 0x00000004},
+	/*
+	 * EPEVTCR (Event Processor EVT Pin Control Registers)
+	 * SCU8 triger EVT2, and SCU11 triger EVT9
+	 */
+	{EPEVTCR0 + EPEVTCR_STRIDE * 0, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 1, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x80000001},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 3, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 4, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 5, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 6, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 7, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 8, 0},
+	{EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB0000001},
+	/* EPCMPR (Event Processor Counter Compare Registers) */
+	{EPCMPR0 + EPCMPR_STRIDE * 0, 0},
+	{EPCMPR0 + EPCMPR_STRIDE * 1, 0},
+	{EPCMPR0 + EPCMPR_STRIDE * 2, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 3, 0},
+	{EPCMPR0 + EPCMPR_STRIDE * 4, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 5, 0x00000020},
+	{EPCMPR0 + EPCMPR_STRIDE * 6, 0},
+	{EPCMPR0 + EPCMPR_STRIDE * 7, 0},
+	{EPCMPR0 + EPCMPR_STRIDE * 8, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 9, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 10, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 11, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 12, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 13, 0},
+	{EPCMPR0 + EPCMPR_STRIDE * 14, 0x000000FF},
+	{EPCMPR0 + EPCMPR_STRIDE * 15, 0x000000FF},
+	/* EPCCR (Event Processor Counter Control Registers) */
+	{EPCCR0 + EPCCR_STRIDE * 0, 0},
+	{EPCCR0 + EPCCR_STRIDE * 1, 0},
+	{EPCCR0 + EPCCR_STRIDE * 2, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 3, 0},
+	{EPCCR0 + EPCCR_STRIDE * 4, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 5, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 6, 0},
+	{EPCCR0 + EPCCR_STRIDE * 7, 0},
+	{EPCCR0 + EPCCR_STRIDE * 8, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 9, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 10, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 11, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 12, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 13, 0},
+	{EPCCR0 + EPCCR_STRIDE * 14, 0x92840000},
+	{EPCCR0 + EPCCR_STRIDE * 15, 0x92840000},
+	/* EPSMCR (Event Processor SCU Mux Control Registers) */
+	{EPSMCR0 + EPSMCR_STRIDE * 0, 0},
+	{EPSMCR0 + EPSMCR_STRIDE * 1, 0},
+	{EPSMCR0 + EPSMCR_STRIDE * 2, 0x6C700000},
+	{EPSMCR0 + EPSMCR_STRIDE * 3, 0x2F000000},
+	{EPSMCR0 + EPSMCR_STRIDE * 4, 0x002F0000},
+	{EPSMCR0 + EPSMCR_STRIDE * 5, 0x00002E00},
+	{EPSMCR0 + EPSMCR_STRIDE * 6, 0x7C000000},
+	{EPSMCR0 + EPSMCR_STRIDE * 7, 0x30000000},
+	{EPSMCR0 + EPSMCR_STRIDE * 8, 0x64300000},
+	{EPSMCR0 + EPSMCR_STRIDE * 9, 0x00003000},
+	{EPSMCR0 + EPSMCR_STRIDE * 10, 0x65000030},
+	{EPSMCR0 + EPSMCR_STRIDE * 11, 0x31740000},
+	{EPSMCR0 + EPSMCR_STRIDE * 12, 0x7F000000},
+	{EPSMCR0 + EPSMCR_STRIDE * 13, 0x00003100},
+	{EPSMCR0 + EPSMCR_STRIDE * 14, 0x00000031},
+	{EPSMCR0 + EPSMCR_STRIDE * 15, 0x76000000},
+	/* EPACR (Event Processor Action Control Registers) */
+	{EPACR0 + EPACR_STRIDE * 0, 0},
+	{EPACR0 + EPACR_STRIDE * 1, 0},
+	{EPACR0 + EPACR_STRIDE * 2, 0},
+	{EPACR0 + EPACR_STRIDE * 3, 0x00000080},
+	{EPACR0 + EPACR_STRIDE * 4, 0},
+	{EPACR0 + EPACR_STRIDE * 5, 0x00000040},
+	{EPACR0 + EPACR_STRIDE * 6, 0},
+	{EPACR0 + EPACR_STRIDE * 7, 0},
+	{EPACR0 + EPACR_STRIDE * 8, 0},
+	{EPACR0 + EPACR_STRIDE * 9, 0x0000001C},
+	{EPACR0 + EPACR_STRIDE * 10, 0x00000020},
+	{EPACR0 + EPACR_STRIDE * 11, 0},
+	{EPACR0 + EPACR_STRIDE * 12, 0x00000003},
+	{EPACR0 + EPACR_STRIDE * 13, 0x06000000},
+	{EPACR0 + EPACR_STRIDE * 14, 0x04000000},
+	{EPACR0 + EPACR_STRIDE * 15, 0x02000000},
+	/* EPIMCR (Event Processor Input Mux Control Registers) */
+	{EPIMCR0 + EPIMCR_STRIDE * 0, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 1, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 2, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 3, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 4, 0x44000000},
+	{EPIMCR0 + EPIMCR_STRIDE * 5, 0x40000000},
+	{EPIMCR0 + EPIMCR_STRIDE * 6, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 7, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 8, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 9, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 10, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 11, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 12, 0x44000000},
+	{EPIMCR0 + EPIMCR_STRIDE * 13, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 14, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 15, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 16, 0x6A000000},
+	{EPIMCR0 + EPIMCR_STRIDE * 17, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 18, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 19, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 20, 0x48000000},
+	{EPIMCR0 + EPIMCR_STRIDE * 21, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 22, 0x6C000000},
+	{EPIMCR0 + EPIMCR_STRIDE * 23, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 24, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 25, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 26, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 27, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 28, 0x76000000},
+	{EPIMCR0 + EPIMCR_STRIDE * 29, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 30, 0},
+	{EPIMCR0 + EPIMCR_STRIDE * 31, 0x76000000},
+	/* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
+	{EPXTRIGCR, 0x0000FFDF},
+	/* end */
+	{FSM_END_FLAG, 0},
+};
+
+/**
+ * fsl_epu_setup - Setup EPU registers to default values
+ */
+void fsl_epu_setup(void *epu_base)
+{
+	struct fsm_reg_vals *data = epu_default_val;
+
+	if (!epu_base || !data)
+		return;
+
+	while (data->offset != FSM_END_FLAG) {
+		out_be32(epu_base + data->offset, data->value);
+		data++;
+	}
+}
+
+/**
+ * fsl_epu_clean - Clear EPU registers
+ */
+void fsl_epu_clean(void *epu_base)
+{
+	u32 offset;
+
+	/* follow the exact sequence to clear the registers */
+	/* Clear EPACRn */
+	for (offset = EPACR0; offset <= EPACR15; offset += EPACR_STRIDE)
+		out_be32(epu_base + offset, 0);
+
+	/* Clear EPEVTCRn */
+	for (offset = EPEVTCR0; offset <= EPEVTCR9; offset += EPEVTCR_STRIDE)
+		out_be32(epu_base + offset, 0);
+
+	/* Clear EPGCR */
+	out_be32(epu_base + EPGCR, 0);
+
+	/* Clear EPSMCRn */
+	for (offset = EPSMCR0; offset <= EPSMCR15; offset += EPSMCR_STRIDE)
+		out_be32(epu_base + offset, 0);
+
+	/* Clear EPCCRn */
+	for (offset = EPCCR0; offset <= EPCCR31; offset += EPCCR_STRIDE)
+		out_be32(epu_base + offset, 0);
+
+	/* Clear EPCMPRn */
+	for (offset = EPCMPR0; offset <= EPCMPR31; offset += EPCMPR_STRIDE)
+		out_be32(epu_base + offset, 0);
+
+	/* Clear EPCTRn */
+	for (offset = EPCTR0; offset <= EPCTR31; offset += EPCTR_STRIDE)
+		out_be32(epu_base + offset, 0);
+
+	/* Clear EPIMCRn */
+	for (offset = EPIMCR0; offset <= EPIMCR31; offset += EPIMCR_STRIDE)
+		out_be32(epu_base + offset, 0);
+
+	/* Clear EPXTRIGCRn */
+	out_be32(epu_base + EPXTRIGCR, 0);
+
+	/* Clear EPECRn */
+	for (offset = EPECR0; offset <= EPECR15; offset += EPECR_STRIDE)
+		out_be32(epu_base + offset, 0);
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_epu.h b/arch/arm/cpu/armv7/ls102xa/fsl_epu.h
new file mode 100644
index 0000000..711eea5
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/fsl_epu.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#ifndef __FSL_EPU_H
+#define __FSL_EPU_H
+
+#include <asm/types.h>
+
+#define FSL_STRIDE_4B	4
+#define FSL_STRIDE_8B	8
+
+/* Block offsets */
+#define EPU_BLOCK_OFFSET	0x00000000
+
+/* EPGCR (Event Processor Global Control Register) */
+#define EPGCR		0x000
+
+/* EPEVTCR0-9 (Event Processor EVT Pin Control Registers) */
+#define EPEVTCR0	0x050
+#define EPEVTCR9	0x074
+#define EPEVTCR_STRIDE	FSL_STRIDE_4B
+
+/* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
+#define EPXTRIGCR	0x090
+
+/* EPIMCR0-31 (Event Processor Input Mux Control Registers) */
+#define EPIMCR0		0x100
+#define EPIMCR31	0x17C
+#define EPIMCR_STRIDE	FSL_STRIDE_4B
+
+/* EPSMCR0-15 (Event Processor SCU Mux Control Registers) */
+#define EPSMCR0		0x200
+#define EPSMCR15	0x278
+#define EPSMCR_STRIDE	FSL_STRIDE_8B
+
+/* EPECR0-15 (Event Processor Event Control Registers) */
+#define EPECR0		0x300
+#define EPECR15		0x33C
+#define EPECR_STRIDE	FSL_STRIDE_4B
+
+/* EPACR0-15 (Event Processor Action Control Registers) */
+#define EPACR0		0x400
+#define EPACR15		0x43C
+#define EPACR_STRIDE	FSL_STRIDE_4B
+
+/* EPCCRi0-15 (Event Processor Counter Control Registers) */
+#define EPCCR0		0x800
+#define EPCCR15		0x83C
+#define EPCCR31		0x87C
+#define EPCCR_STRIDE	FSL_STRIDE_4B
+
+/* EPCMPR0-15 (Event Processor Counter Compare Registers) */
+#define EPCMPR0		0x900
+#define EPCMPR15	0x93C
+#define EPCMPR31	0x97C
+#define EPCMPR_STRIDE	FSL_STRIDE_4B
+
+/* EPCTR0-31 (Event Processor Counter Register) */
+#define EPCTR0		0xA00
+#define EPCTR31		0xA7C
+#define EPCTR_STRIDE	FSL_STRIDE_4B
+
+#define FSM_END_FLAG	0xFFFFFFFFUL
+
+struct fsm_reg_vals {
+	u32 offset;
+	u32 value;
+};
+
+void fsl_epu_setup(void *epu_base);
+void fsl_epu_clean(void *epu_base);
+
+#endif
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
new file mode 100644
index 0000000..caf51e1
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include "fsl_ls1_serdes.h"
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+static u64 serdes1_prtcl_map;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+static u64 serdes2_prtcl_map;
+#endif
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+	u64 ret = 0;
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	if (!(serdes1_prtcl_map & (1ULL << NONE)))
+		fsl_serdes_init();
+
+	ret |= (1ULL << device) & serdes1_prtcl_map;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	if (!(serdes2_prtcl_map & (1ULL << NONE)))
+		fsl_serdes_init();
+
+	ret |= (1ULL << device) & serdes2_prtcl_map;
+#endif
+
+	return !!ret;
+}
+
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 cfg = in_be32(&gur->rcwsr[4]);
+	int i;
+
+	switch (sd) {
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	case FSL_SRDS_1:
+		cfg &= RCWSR4_SRDS1_PRTCL_MASK;
+		cfg >>= RCWSR4_SRDS1_PRTCL_SHIFT;
+		break;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	case FSL_SRDS_2:
+		cfg &= RCWSR4_SRDS2_PRTCL_MASK;
+		cfg >>= RCWSR4_SRDS2_PRTCL_SHIFT;
+		break;
+#endif
+	default:
+		printf("invalid SerDes%d\n", sd);
+		break;
+	}
+	/* Is serdes enabled at all? */
+	if (unlikely(cfg == 0))
+		return -ENODEV;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (serdes_get_prtcl(sd, cfg, i) == device)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u64 serdes_prtcl_map = 0;
+	u32 cfg;
+	int lane;
+
+	cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask;
+	cfg >>= sd_prctl_shift;
+	printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
+
+	if (!is_serdes_prtcl_valid(sd, cfg))
+		printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
+
+	for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+		enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
+
+		serdes_prtcl_map |= (1ULL << lane_prtcl);
+	}
+
+	/* Set the first bit to indicate serdes has been initialized */
+	serdes_prtcl_map |= (1ULL << NONE);
+
+	return serdes_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	if (!(serdes1_prtcl_map & (1ULL << NONE)))
+		serdes1_prtcl_map = serdes_init(FSL_SRDS_1,
+					CONFIG_SYS_FSL_SERDES_ADDR,
+					RCWSR4_SRDS1_PRTCL_MASK,
+					RCWSR4_SRDS1_PRTCL_SHIFT);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	if (!(serdes2_prtcl_map & (1ULL << NONE)))
+		serdes2_prtcl_map = serdes_init(FSL_SRDS_2,
+					CONFIG_SYS_FSL_SERDES_ADDR +
+					FSL_SRDS_2 * 0x1000,
+					RCWSR4_SRDS2_PRTCL_MASK,
+					RCWSR4_SRDS2_PRTCL_SHIFT);
+#endif
+}
+
+const char *serdes_clock_to_string(u32 clock)
+{
+	switch (clock) {
+	case SRDS_PLLCR0_RFCK_SEL_100:
+		return "100";
+	case SRDS_PLLCR0_RFCK_SEL_125:
+		return "125";
+	default:
+		return "100";
+	}
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.h b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.h
new file mode 100644
index 0000000..7382aef
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#ifndef __FSL_LS1_SERDES_H
+#define __FSL_LS1_SERDES_H
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl);
+int serdes_lane_enabled(int lane);
+#endif /* __FSL_LS1_SERDES_H */
diff --git a/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c b/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c
new file mode 100644
index 0000000..bb169aa
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Author: Hongbo Zhang <hongbo.zhang@nxp.com>
+ * This file implements LS102X platform PSCI SYSTEM-SUSPEND function
+ */
+
+#include <config.h>
+#include <asm/io.h>
+#include <asm/psci.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <fsl_immap.h>
+#include "fsl_epu.h"
+
+#define __secure __attribute__((section("._secure.text")))
+
+#define CCSR_GICD_CTLR			0x1000
+#define CCSR_GICC_CTLR			0x2000
+#define DCSR_RCPM_CG1CR0		0x31c
+#define DCSR_RCPM_CSTTACR0		0xb00
+#define DCFG_CRSTSR_WDRFR		0x8
+#define DDR_RESV_LEN			128
+
+#ifdef CONFIG_LS1_DEEP_SLEEP
+/*
+ * DDR controller initialization training breaks the first 128 bytes of DDR,
+ * save them so that the bootloader can restore them while resuming.
+ */
+static void __secure ls1_save_ddr_head(void)
+{
+	const char *src = (const char *)CONFIG_SYS_SDRAM_BASE;
+	char *dest = (char *)(OCRAM_BASE_S_ADDR + OCRAM_S_SIZE - DDR_RESV_LEN);
+	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+	int i;
+
+	out_le32(&scfg->sparecr[2], dest);
+
+	for (i = 0; i < DDR_RESV_LEN; i++)
+		*dest++ = *src++;
+}
+
+static void __secure ls1_fsm_setup(void)
+{
+	void *dcsr_epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET);
+	void *dcsr_rcpm_base = (void *)SYS_FSL_DCSR_RCPM_ADDR;
+
+	out_be32(dcsr_rcpm_base + DCSR_RCPM_CSTTACR0, 0x00001001);
+	out_be32(dcsr_rcpm_base + DCSR_RCPM_CG1CR0, 0x00000001);
+
+	fsl_epu_setup((void *)dcsr_epu_base);
+
+	/* Pull MCKE signal low before enabling deep sleep signal in FPGA */
+	out_be32(dcsr_epu_base + EPECR0, 0x5);
+	out_be32(dcsr_epu_base + EPSMCR15, 0x76300000);
+}
+
+static void __secure ls1_deepsleep_irq_cfg(void)
+{
+	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+	struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR;
+	u32 ippdexpcr0, ippdexpcr1, pmcintecr = 0;
+
+	/* Mask interrupts from GIC */
+	out_be32(&rcpm->nfiqoutr, 0x0ffffffff);
+	out_be32(&rcpm->nirqoutr, 0x0ffffffff);
+	/* Mask deep sleep wake-up interrupts while entering deep sleep */
+	out_be32(&rcpm->dsimskr, 0x0ffffffff);
+
+	ippdexpcr0 = in_be32(&rcpm->ippdexpcr0);
+	/*
+	 * Workaround: There is bug of register ippdexpcr1, when read it always
+	 * returns zero, so its value is saved to a scrachpad register to be
+	 * read, that is why we don't read it from register ippdexpcr1 itself.
+	 */
+	ippdexpcr1 = in_le32(&scfg->sparecr[7]);
+	out_be32(&rcpm->ippdexpcr1, ippdexpcr1);
+
+	if (ippdexpcr0 & RCPM_IPPDEXPCR0_ETSEC)
+		pmcintecr |= SCFG_PMCINTECR_ETSECRXG0 |
+			     SCFG_PMCINTECR_ETSECRXG1 |
+			     SCFG_PMCINTECR_ETSECERRG0 |
+			     SCFG_PMCINTECR_ETSECERRG1;
+
+	if (ippdexpcr0 & RCPM_IPPDEXPCR0_GPIO)
+		pmcintecr |= SCFG_PMCINTECR_GPIO;
+
+	if (ippdexpcr1 & RCPM_IPPDEXPCR1_LPUART)
+		pmcintecr |= SCFG_PMCINTECR_LPUART;
+
+	if (ippdexpcr1 & RCPM_IPPDEXPCR1_FLEXTIMER)
+		pmcintecr |= SCFG_PMCINTECR_FTM;
+
+	/* Always set external IRQ pins as wakeup source */
+	pmcintecr |= SCFG_PMCINTECR_IRQ0 | SCFG_PMCINTECR_IRQ1;
+
+	out_be32(&scfg->pmcintlecr, 0);
+	/* Clear PMC interrupt status */
+	out_be32(&scfg->pmcintsr, 0xffffffff);
+	/* Enable wakeup interrupt during deep sleep */
+	out_be32(&scfg->pmcintecr, pmcintecr);
+}
+
+static void __secure ls1_delay(unsigned int loop)
+{
+	while (loop--) {
+		int i = 1000;
+		while (i--)
+			;
+	}
+}
+
+static void __secure ls1_start_fsm(void)
+{
+	void *dcsr_epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET);
+	void *ccsr_gic_base = (void *)SYS_FSL_GIC_ADDR;
+	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+	struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+
+	/* Set HRSTCR */
+	setbits_be32(&scfg->hrstcr, 0x80000000);
+
+	/* Place DDR controller in self refresh mode */
+	setbits_be32(&ddr->sdram_cfg_2, 0x80000000);
+
+	ls1_delay(2000);
+
+	/* Set EVT4_B to lock the signal MCKE down */
+	out_be32(dcsr_epu_base + EPECR0, 0x0);
+
+	ls1_delay(2000);
+
+	out_be32(ccsr_gic_base + CCSR_GICD_CTLR, 0x0);
+	out_be32(ccsr_gic_base + CCSR_GICC_CTLR, 0x0);
+
+	/* Enable all EPU Counters */
+	setbits_be32(dcsr_epu_base + EPGCR, 0x80000000);
+
+	/* Enable SCU15 */
+	setbits_be32(dcsr_epu_base + EPECR15, 0x90000004);
+
+	/* Enter WFI mode, and EPU FSM will start */
+	__asm__ __volatile__ ("wfi" : : : "memory");
+
+	/* NEVER ENTER HERE */
+	while (1)
+		;
+}
+
+static void __secure ls1_deep_sleep(u32 entry_point)
+{
+	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+	struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+	struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR;
+#ifdef QIXIS_BASE
+	u32 tmp;
+	void *qixis_base = (void *)QIXIS_BASE;
+#endif
+
+	/* Enable cluster to enter the PCL10 state */
+	out_be32(&scfg->clusterpmcr, SCFG_CLUSTERPMCR_WFIL2EN);
+
+	/* Save the first 128 bytes of DDR data */
+	ls1_save_ddr_head();
+
+	/* Save the kernel resume entry */
+	out_le32(&scfg->sparecr[3], entry_point);
+
+	/* Request to put cluster 0 in PCL10 state */
+	setbits_be32(&rcpm->clpcl10setr, RCPM_CLPCL10SETR_C0);
+
+	/* Setup the registers of the EPU FSM for deep sleep */
+	ls1_fsm_setup();
+
+#ifdef QIXIS_BASE
+	/* Connect the EVENT button to IRQ in FPGA */
+	tmp = in_8(qixis_base + QIXIS_CTL_SYS);
+	tmp &= ~QIXIS_CTL_SYS_EVTSW_MASK;
+	tmp |= QIXIS_CTL_SYS_EVTSW_IRQ;
+	out_8(qixis_base + QIXIS_CTL_SYS, tmp);
+
+	/* Enable deep sleep signals in FPGA */
+	tmp = in_8(qixis_base + QIXIS_PWR_CTL2);
+	tmp |= QIXIS_PWR_CTL2_PCTL;
+	out_8(qixis_base + QIXIS_PWR_CTL2, tmp);
+
+	/* Pull down PCIe RST# */
+	tmp = in_8(qixis_base + QIXIS_RST_FORCE_3);
+	tmp |= QIXIS_RST_FORCE_3_PCIESLOT1;
+	out_8(qixis_base + QIXIS_RST_FORCE_3, tmp);
+#endif
+
+	/* Enable Warm Device Reset */
+	setbits_be32(&scfg->dpslpcr, SCFG_DPSLPCR_WDRR_EN);
+	setbits_be32(&gur->crstsr, DCFG_CRSTSR_WDRFR);
+
+	/* Disable QE */
+	setbits_be32(&gur->devdisr, CCSR_DEVDISR1_QE);
+
+	ls1_deepsleep_irq_cfg();
+
+	psci_v7_flush_dcache_all();
+
+	ls1_start_fsm();
+}
+
+#else
+static void __secure ls1_sleep(void)
+{
+	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+	struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR;
+
+#ifdef QIXIS_BASE
+	u32 tmp;
+	void *qixis_base = (void *)QIXIS_BASE;
+
+	/* Connect the EVENT button to IRQ in FPGA */
+	tmp = in_8(qixis_base + QIXIS_CTL_SYS);
+	tmp &= ~QIXIS_CTL_SYS_EVTSW_MASK;
+	tmp |= QIXIS_CTL_SYS_EVTSW_IRQ;
+	out_8(qixis_base + QIXIS_CTL_SYS, tmp);
+#endif
+
+	/* Enable cluster to enter the PCL10 state */
+	out_be32(&scfg->clusterpmcr, SCFG_CLUSTERPMCR_WFIL2EN);
+
+	setbits_be32(&rcpm->powmgtcsr, RCPM_POWMGTCSR_LPM20_REQ);
+
+	__asm__ __volatile__ ("wfi" : : : "memory");
+}
+#endif
+
+void __secure ls1_system_suspend(u32 fn, u32 entry_point, u32 context_id)
+{
+#ifdef CONFIG_LS1_DEEP_SLEEP
+	ls1_deep_sleep(entry_point);
+#else
+	ls1_sleep();
+#endif
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/ls102xa_serdes.c b/arch/arm/cpu/armv7/ls102xa/ls102xa_serdes.c
new file mode 100644
index 0000000..8c030be
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/ls102xa_serdes.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_ls102xa.h>
+
+static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = {
+	[0x00] = {PCIE1, PCIE1, PCIE1, PCIE1},
+	[0x10] = {PCIE1, SATA1, PCIE2, PCIE2},
+	[0x20] = {PCIE1, SGMII_TSEC1, PCIE2, SGMII_TSEC2},
+	[0x30] = {PCIE1, SATA1, SGMII_TSEC1, SGMII_TSEC2},
+	[0x40] = {PCIE1, PCIE1, SATA1, SGMII_TSEC2},
+	[0x50] = {PCIE1, PCIE1, PCIE2, SGMII_TSEC2},
+	[0x60] = {PCIE1, PCIE1, SGMII_TSEC1, SGMII_TSEC2},
+	[0x70] = {PCIE1, SATA1, PCIE2, SGMII_TSEC2},
+	[0x80] = {PCIE2, PCIE2, PCIE2, PCIE2},
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	return serdes_cfg_tbl[cfg][lane];
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+
+	if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (serdes_cfg_tbl[prtcl][i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/psci.S b/arch/arm/cpu/armv7/ls102xa/psci.S
new file mode 100644
index 0000000..531cfb0
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/psci.S
@@ -0,0 +1,257 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+#include <asm/armv7.h>
+#include <asm/arch-armv7/generictimer.h>
+#include <asm/psci.h>
+
+#define RCPM_TWAITSR		0x04C
+
+#define SCFG_CORE0_SFT_RST      0x130
+#define SCFG_CORESRENCR         0x204
+
+#define DCFG_CCSR_RSTCR			0x0B0
+#define DCFG_CCSR_RSTCR_RESET_REQ	0x2
+#define DCFG_CCSR_BRR			0x0E4
+#define DCFG_CCSR_SCRATCHRW1		0x200
+
+#define PSCI_FN_PSCI_VERSION_FEATURE_MASK	0x0
+#define PSCI_FN_CPU_SUSPEND_FEATURE_MASK	0x0
+#define PSCI_FN_CPU_OFF_FEATURE_MASK		0x0
+#define PSCI_FN_CPU_ON_FEATURE_MASK		0x0
+#define PSCI_FN_AFFINITY_INFO_FEATURE_MASK	0x0
+#define PSCI_FN_SYSTEM_OFF_FEATURE_MASK		0x0
+#define PSCI_FN_SYSTEM_RESET_FEATURE_MASK	0x0
+#define PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK	0x0
+
+	.pushsection ._secure.text, "ax"
+
+	.arch_extension sec
+
+	.align	5
+
+#define	ONE_MS		(COUNTER_FREQUENCY / 1000)
+#define	RESET_WAIT	(30 * ONE_MS)
+
+.globl	psci_version
+psci_version:
+	movw	r0, #0
+	movt	r0, #1
+
+	bx	lr
+
+_ls102x_psci_supported_table:
+	.word	ARM_PSCI_0_2_FN_PSCI_VERSION
+	.word	PSCI_FN_PSCI_VERSION_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_CPU_SUSPEND
+	.word	PSCI_FN_CPU_SUSPEND_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_CPU_OFF
+	.word	PSCI_FN_CPU_OFF_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_CPU_ON
+	.word	PSCI_FN_CPU_ON_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_AFFINITY_INFO
+	.word	PSCI_FN_AFFINITY_INFO_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_SYSTEM_OFF
+	.word	PSCI_FN_SYSTEM_OFF_FEATURE_MASK
+	.word	ARM_PSCI_0_2_FN_SYSTEM_RESET
+	.word	PSCI_FN_SYSTEM_RESET_FEATURE_MASK
+	.word	ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
+	.word	PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK
+	.word	0
+	.word	ARM_PSCI_RET_NI
+
+.globl	psci_features
+psci_features:
+	adr	r2, _ls102x_psci_supported_table
+1:	ldr	r3, [r2]
+	cmp	r3, #0
+	beq	out_psci_features
+	cmp	r1, r3
+	addne	r2, r2, #8
+	bne	1b
+
+out_psci_features:
+	ldr	r0, [r2, #4]
+	bx	lr
+
+@ r0: return value ARM_PSCI_RET_SUCCESS or ARM_PSCI_RET_INVAL
+@ r1: input target CPU ID in MPIDR format, original value in r1 may be dropped
+@ r4: output validated CPU ID if ARM_PSCI_RET_SUCCESS returns, meaningless for
+@ ARM_PSCI_RET_INVAL,suppose caller saves r4 before calling
+LENTRY(psci_check_target_cpu_id)
+	@ Get the real CPU number
+	and	r4, r1, #0xff
+	mov	r0, #ARM_PSCI_RET_INVAL
+
+	@ Bit[31:24], bits must be zero.
+	tst	r1, #0xff000000
+	bxne	lr
+
+	@ Affinity level 2 - Cluster: only one cluster in LS1021xa.
+	tst	r1, #0xff0000
+	bxne	lr
+
+	@ Affinity level 1 - Processors: should be in 0xf00 format.
+	lsr	r1, r1, #8
+	teq	r1, #0xf
+	bxne	lr
+
+	@ Affinity level 0 - CPU: only 0, 1 are valid in LS1021xa.
+	cmp	r4, #2
+	bxge	lr
+
+	mov	r0, #ARM_PSCI_RET_SUCCESS
+	bx	lr
+ENDPROC(psci_check_target_cpu_id)
+
+	@ r1 = target CPU
+	@ r2 = target PC
+.globl	psci_cpu_on
+psci_cpu_on:
+	push	{r4, r5, r6, lr}
+
+	@ Clear and Get the correct CPU number
+	@ r1 = 0xf01
+	bl	psci_check_target_cpu_id
+	cmp	r0, #ARM_PSCI_RET_INVAL
+	beq	out_psci_cpu_on
+
+	mov	r0, r4
+	mov	r1, r2
+	mov	r2, r3
+	bl	psci_save
+	mov	r1, r4
+
+	@ Get DCFG base address
+	movw	r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
+	movt	r4, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16)
+
+	@ Detect target CPU state
+	ldr	r2, [r4, #DCFG_CCSR_BRR]
+	rev	r2, r2
+	lsr	r2, r2, r1
+	ands	r2, r2, #1
+	beq	holdoff_release
+
+	@ Reset target CPU
+	@ Get SCFG base address
+	movw	r0, #(CONFIG_SYS_FSL_SCFG_ADDR & 0xffff)
+	movt	r0, #(CONFIG_SYS_FSL_SCFG_ADDR >> 16)
+
+	@ Enable CORE Soft Reset
+	movw	r5, #0
+	movt	r5, #(1 << 15)
+	rev	r5, r5
+	str	r5, [r0, #SCFG_CORESRENCR]
+
+	@ Get CPUx offset register
+	mov	r6, #0x4
+	mul	r6, r6, r1
+	add	r2, r0, r6
+
+	@ Do reset on target CPU
+	movw	r5, #0
+	movt	r5, #(1 << 15)
+	rev	r5, r5
+	str	r5, [r2, #SCFG_CORE0_SFT_RST]
+
+	@ Wait target CPU up
+	timer_wait	r2, RESET_WAIT
+
+	@ Disable CORE soft reset
+	mov	r5, #0
+	str	r5, [r0, #SCFG_CORESRENCR]
+
+holdoff_release:
+	@ Release on target CPU
+	ldr	r2, [r4, #DCFG_CCSR_BRR]
+	mov	r6, #1
+	lsl	r6, r6, r1	@ 32 bytes per CPU
+
+	rev	r6, r6
+	orr	r2, r2, r6
+	str	r2, [r4, #DCFG_CCSR_BRR]
+
+	@ Set secondary boot entry
+	ldr	r6, =psci_cpu_entry
+	rev	r6, r6
+	str	r6, [r4, #DCFG_CCSR_SCRATCHRW1]
+
+	isb
+	dsb
+
+	@ Return
+	mov	r0, #ARM_PSCI_RET_SUCCESS
+
+out_psci_cpu_on:
+	pop	{r4, r5, r6, lr}
+	bx	lr
+
+.globl	psci_cpu_off
+psci_cpu_off:
+	bl	psci_cpu_off_common
+
+1:	wfi
+	b	1b
+
+.globl	psci_affinity_info
+psci_affinity_info:
+	push	{lr}
+
+	mov	r0, #ARM_PSCI_RET_INVAL
+
+	@ Verify Affinity level
+	cmp	r2, #0
+	bne	out_affinity_info
+
+	bl	psci_check_target_cpu_id
+	cmp	r0, #ARM_PSCI_RET_INVAL
+	beq	out_affinity_info
+	mov	r1, r4
+
+	@ Get RCPM base address
+	movw	r4, #(CONFIG_SYS_FSL_RCPM_ADDR & 0xffff)
+	movt	r4, #(CONFIG_SYS_FSL_RCPM_ADDR >> 16)
+
+	mov	r0, #PSCI_AFFINITY_LEVEL_ON
+
+	@ Detect target CPU state
+	ldr	r2, [r4, #RCPM_TWAITSR]
+	rev	r2, r2
+	lsr	r2, r2, r1
+	ands	r2, r2, #1
+	beq	out_affinity_info
+
+	mov	r0, #PSCI_AFFINITY_LEVEL_OFF
+
+out_affinity_info:
+	pop	{pc}
+
+.globl	psci_system_reset
+psci_system_reset:
+	@ Get DCFG base address
+	movw	r1, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
+	movt	r1, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16)
+
+	mov	r2, #DCFG_CCSR_RSTCR_RESET_REQ
+	rev	r2, r2
+	str	r2, [r1, #DCFG_CCSR_RSTCR]
+
+1:	wfi
+	b	1b
+
+.globl	psci_system_suspend
+psci_system_suspend:
+	push	{lr}
+
+	bl	ls1_system_suspend
+
+	pop	{pc}
+
+	.popsection
diff --git a/arch/arm/cpu/armv7/ls102xa/soc.c b/arch/arm/cpu/armv7/ls102xa/soc.c
new file mode 100644
index 0000000..448d951
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/soc.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/io.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <asm/arch/ls102xa_soc.h>
+#include <asm/arch/ls102xa_stream_id.h>
+#include <fsl_csu.h>
+
+struct liodn_id_table sec_liodn_tbl[] = {
+	SET_SEC_JR_LIODN_ENTRY(0, 0x10, 0x10),
+	SET_SEC_JR_LIODN_ENTRY(1, 0x10, 0x10),
+	SET_SEC_JR_LIODN_ENTRY(2, 0x10, 0x10),
+	SET_SEC_JR_LIODN_ENTRY(3, 0x10, 0x10),
+	SET_SEC_RTIC_LIODN_ENTRY(a, 0x10),
+	SET_SEC_RTIC_LIODN_ENTRY(b, 0x10),
+	SET_SEC_RTIC_LIODN_ENTRY(c, 0x10),
+	SET_SEC_RTIC_LIODN_ENTRY(d, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(0, 0x10, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(1, 0x10, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(2, 0x10, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(3, 0x10, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(4, 0x10, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(5, 0x10, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(6, 0x10, 0x10),
+	SET_SEC_DECO_LIODN_ENTRY(7, 0x10, 0x10),
+};
+
+struct smmu_stream_id dev_stream_id[] = {
+	{ 0x100, 0x01, "ETSEC MAC1" },
+	{ 0x104, 0x02, "ETSEC MAC2" },
+	{ 0x108, 0x03, "ETSEC MAC3" },
+	{ 0x10c, 0x04, "PEX1" },
+	{ 0x110, 0x05, "PEX2" },
+	{ 0x114, 0x06, "qDMA" },
+	{ 0x118, 0x07, "SATA" },
+	{ 0x11c, 0x08, "USB3" },
+	{ 0x120, 0x09, "QE" },
+	{ 0x124, 0x0a, "eSDHC" },
+	{ 0x128, 0x0b, "eMA" },
+	{ 0x14c, 0x0c, "2D-ACE" },
+	{ 0x150, 0x0d, "USB2" },
+	{ 0x18c, 0x0e, "DEBUG" },
+};
+
+unsigned int get_soc_major_rev(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	unsigned int svr, major;
+
+	svr = in_be32(&gur->svr);
+	major = SVR_MAJ(svr);
+
+	return major;
+}
+
+static void erratum_a009008(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009008
+	u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
+
+	clrsetbits_be32(scfg + SCFG_USB3PRM1CR / 4,
+			0xF << 6,
+			SCFG_USB_TXVREFTUNE << 6);
+#endif /* CONFIG_SYS_FSL_ERRATUM_A009008 */
+}
+
+static void erratum_a009798(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009798
+	u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
+
+	clrbits_be32(scfg + SCFG_USB3PRM1CR / 4,
+			SCFG_USB_SQRXTUNE_MASK << 23);
+#endif /* CONFIG_SYS_FSL_ERRATUM_A009798 */
+}
+
+static void erratum_a008997(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008997
+	u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
+
+	clrsetbits_be32(scfg + SCFG_USB3PRM2CR / 4,
+			SCFG_USB_PCSTXSWINGFULL_MASK,
+			SCFG_USB_PCSTXSWINGFULL_VAL);
+#endif /* CONFIG_SYS_FSL_ERRATUM_A008997 */
+}
+
+static void erratum_a009007(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009007
+	void __iomem *usb_phy = (void __iomem *)USB_PHY_BASE;
+
+	out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1);
+	out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_2);
+	out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_3);
+	out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_4);
+#endif /* CONFIG_SYS_FSL_ERRATUM_A009007 */
+}
+
+void s_init(void)
+{
+}
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A010315
+void erratum_a010315(void)
+{
+	int i;
+
+	for (i = PCIE1; i <= PCIE2; i++)
+		if (!is_serdes_configured(i)) {
+			debug("PCIe%d: disabled all R/W permission!\n", i);
+			set_pcie_ns_access(i, 0);
+		}
+}
+#endif
+
+int arch_soc_init(void)
+{
+	struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
+	struct ccsr_cci400 *cci = (struct ccsr_cci400 *)(CONFIG_SYS_IMMR +
+					CONFIG_SYS_CCI400_OFFSET);
+	unsigned int major;
+
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+
+#ifdef CONFIG_FSL_QSPI
+	out_be32(&scfg->qspi_cfg, SCFG_QSPI_CLKSEL);
+#endif
+
+#ifdef CONFIG_VIDEO_FSL_DCU_FB
+	out_be32(&scfg->pixclkcr, SCFG_PIXCLKCR_PXCKEN);
+#endif
+
+	/* Configure Little endian for SAI, ASRC and SPDIF */
+	out_be32(&scfg->endiancr, SCFG_ENDIANCR_LE);
+
+	/*
+	 * Enable snoop requests and DVM message requests for
+	 * All the slave insterfaces.
+	 */
+	out_le32(&cci->slave[0].snoop_ctrl,
+		 CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+	out_le32(&cci->slave[1].snoop_ctrl,
+		 CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+	out_le32(&cci->slave[2].snoop_ctrl,
+		 CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+	out_le32(&cci->slave[4].snoop_ctrl,
+		 CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+
+	major = get_soc_major_rev();
+	if (major == SOC_MAJOR_VER_1_0) {
+		/*
+		 * Set CCI-400 Slave interface S1, S2 Shareable Override
+		 * Register All transactions are treated as non-shareable
+		 */
+		out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
+		out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
+
+		/* Workaround for the issue that DDR could not respond to
+		 * barrier transaction which is generated by executing DSB/ISB
+		 * instruction. Set CCI-400 control override register to
+		 * terminate the barrier transaction. After DDR is initialized,
+		 * allow barrier transaction to DDR again */
+		out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
+	}
+
+	/* Enable all the snoop signal for various masters */
+	out_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SEC_RD_WR |
+				SCFG_SNPCNFGCR_DCU_RD_WR |
+				SCFG_SNPCNFGCR_SATA_RD_WR |
+				SCFG_SNPCNFGCR_USB3_RD_WR |
+				SCFG_SNPCNFGCR_DBG_RD_WR |
+				SCFG_SNPCNFGCR_EDMA_SNP);
+
+	/*
+	 * Memory controller require a register write before being enabled.
+	 * Affects: DDR
+	 * Register: EDDRTQCFG
+	 * Description: Memory controller performance is not optimal with
+	 *		default internal target queue register values.
+	 * Workaround: Write a value of 63b2_0042h to address: 157_020Ch.
+	 */
+	out_be32(&scfg->eddrtqcfg, 0x63b20042);
+
+	/* Erratum */
+	erratum_a009008();
+	erratum_a009798();
+	erratum_a008997();
+	erratum_a009007();
+
+	return 0;
+}
+
+int ls102xa_smmu_stream_id_init(void)
+{
+	ls1021x_config_caam_stream_id(sec_liodn_tbl,
+				      ARRAY_SIZE(sec_liodn_tbl));
+
+	ls102xa_config_smmu_stream_id(dev_stream_id,
+				      ARRAY_SIZE(dev_stream_id));
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/spl.c b/arch/arm/cpu/armv7/ls102xa/spl.c
new file mode 100644
index 0000000..308536c
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/spl.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <spl.h>
+
+u32 spl_boot_device(void)
+{
+#ifdef CONFIG_SPL_MMC_SUPPORT
+	return BOOT_DEVICE_MMC1;
+#endif
+	return BOOT_DEVICE_NAND;
+}
diff --git a/arch/arm/cpu/armv7/ls102xa/timer.c b/arch/arm/cpu/armv7/ls102xa/timer.c
new file mode 100644
index 0000000..e79360a
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/timer.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <div64.h>
+#include <asm/arch/immap_ls102xa.h>
+#include <asm/arch/clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This function is intended for SHORT delays only.
+ * It will overflow at around 10 seconds @ 400MHz,
+ * or 20 seconds @ 200MHz.
+ */
+unsigned long usec2ticks(unsigned long usec)
+{
+	ulong ticks;
+
+	if (usec < 1000)
+		ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
+	else
+		ticks = ((usec / 10) * (get_tbclk() / 100000));
+
+	return ticks;
+}
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	unsigned long freq;
+
+	asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq));
+
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, freq);
+
+	return tick;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long usec)
+{
+	unsigned long freq;
+
+	asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq));
+
+	usec = usec * freq  + 999999;
+	do_div(usec, 1000000);
+
+	return usec;
+}
+
+int timer_init(void)
+{
+	struct sctr_regs *sctr = (struct sctr_regs *)SCTR_BASE_ADDR;
+	unsigned long ctrl, freq;
+	unsigned long long val;
+
+	/* Enable System Counter */
+	writel(SYS_COUNTER_CTRL_ENABLE, &sctr->cntcr);
+
+	freq = COUNTER_FREQUENCY;
+	asm("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
+
+	/* Set PL1 Physical Timer Ctrl */
+	ctrl = ARCH_TIMER_CTRL_ENABLE;
+	asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl));
+
+	/* Set PL1 Physical Comp Value */
+	val = TIMER_COMP_VAL;
+	asm("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val));
+
+	gd->arch.tbl = 0;
+	gd->arch.tbu = 0;
+
+	return 0;
+}
+
+unsigned long long get_ticks(void)
+{
+	unsigned long long now;
+
+	asm("mrrc p15, 0, %Q0, %R0, c14" : "=r" (now));
+
+	gd->arch.tbl = (unsigned long)(now & 0xffffffff);
+	gd->arch.tbu = (unsigned long)(now >> 32);
+
+	return now;
+}
+
+unsigned long get_timer(ulong base)
+{
+	return tick_to_time(get_ticks()) - base;
+}
+
+/* delay x useconds and preserve advance timstamp value */
+void __udelay(unsigned long usec)
+{
+	unsigned long long start;
+	unsigned long tmo;
+
+	start = get_ticks();			/* get current timestamp */
+	tmo = us_to_tick(usec);			/* convert usecs to ticks */
+
+	while ((get_ticks() - start) < tmo)
+		;				/* loop till time has passed */
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+unsigned long get_tbclk(void)
+{
+	unsigned long freq;
+
+	asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq));
+
+	return freq;
+}
diff --git a/arch/arm/cpu/armv7/mpu_v7r.c b/arch/arm/cpu/armv7/mpu_v7r.c
new file mode 100644
index 0000000..7adecff
--- /dev/null
+++ b/arch/arm/cpu/armv7/mpu_v7r.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Cortex-R Memory Protection Unit specific code
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *	Lokesh Vutla <lokeshvutla@ti.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/armv7.h>
+#include <asm/system.h>
+#include <asm/barriers.h>
+#include <linux/compiler.h>
+
+#include <asm/armv7_mpu.h>
+
+/* MPU Type register definitions */
+#define MPUIR_S_SHIFT		0
+#define MPUIR_S_MASK		BIT(MPUIR_S_SHIFT)
+#define MPUIR_DREGION_SHIFT	8
+#define MPUIR_DREGION_MASK	(0xff << 8)
+
+/**
+ * Note:
+ * The Memory Protection Unit(MPU) allows to partition memory into regions
+ * and set individual protection attributes for each region. In absence
+ * of MPU a default map[1] will take effect. make sure to run this code
+ * from a region which has execution permissions by default.
+ * [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0460d/I1002400.html
+ */
+
+void disable_mpu(void)
+{
+	u32 reg;
+
+	reg = get_cr();
+	reg &= ~CR_M;
+	dsb();
+	set_cr(reg);
+	isb();
+}
+
+void enable_mpu(void)
+{
+	u32 reg;
+
+	reg = get_cr();
+	reg |= CR_M;
+	dsb();
+	set_cr(reg);
+	isb();
+}
+
+int mpu_enabled(void)
+{
+	return get_cr() & CR_M;
+}
+
+void mpu_config(struct mpu_region_config *rgn)
+{
+	u32 attr, val;
+
+	attr = get_attr_encoding(rgn->mr_attr);
+
+	/* MPU Region Number Register */
+	asm volatile ("mcr p15, 0, %0, c6, c2, 0" : : "r" (rgn->region_no));
+
+	/* MPU Region Base Address Register */
+	asm volatile ("mcr p15, 0, %0, c6, c1, 0" : : "r" (rgn->start_addr));
+
+	/* MPU Region Size and Enable Register */
+	if (rgn->reg_size)
+		val = (rgn->reg_size << REGION_SIZE_SHIFT) | ENABLE_REGION;
+	else
+		val = DISABLE_REGION;
+	asm volatile ("mcr p15, 0, %0, c6, c1, 2" : : "r" (val));
+
+	/* MPU Region Access Control Register */
+	val = rgn->xn << XN_SHIFT | rgn->ap << AP_SHIFT | attr;
+	asm volatile ("mcr p15, 0, %0, c6, c1, 4" : : "r" (val));
+}
+
+void setup_mpu_regions(struct mpu_region_config *rgns, u32 num_rgns)
+{
+	u32 num, i;
+
+	asm volatile ("mrc p15, 0, %0, c0, c0, 4" : "=r" (num));
+	num = (num & MPUIR_DREGION_MASK) >> MPUIR_DREGION_SHIFT;
+	/* Regions to be configured cannot be greater than available regions */
+	if (num < num_rgns)
+		num_rgns = num;
+	/**
+	 * Assuming dcache might not be enabled at this point, disabling
+	 * and invalidating only icache.
+	 */
+	icache_disable();
+	invalidate_icache_all();
+
+	disable_mpu();
+
+	for (i = 0; i < num_rgns; i++)
+		mpu_config(&rgns[i]);
+
+	enable_mpu();
+
+	icache_enable();
+}
+
+void enable_caches(void)
+{
+	/*
+	 * setup_mpu_regions() might have enabled Icache. So add a check
+	 * before enabling Icache
+	 */
+	if (!icache_status())
+		icache_enable();
+	dcache_enable();
+}
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
new file mode 100644
index 0000000..1773fae
--- /dev/null
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -0,0 +1,225 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * code for switching cores into non-secure state and into HYP mode
+ *
+ * Copyright (c) 2013	Andre Przywara <andre.przywara@linaro.org>
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/gic.h>
+#include <asm/armv7.h>
+#include <asm/proc-armv/ptrace.h>
+
+.arch_extension sec
+.arch_extension virt
+
+	.pushsection ._secure.text, "ax"
+
+	.align	5
+/* the vector table for secure state and HYP mode */
+_monitor_vectors:
+	.word 0	/* reset */
+	.word 0 /* undef */
+	adr pc, _secure_monitor
+	.word 0
+	.word 0
+	.word 0
+	.word 0
+	.word 0
+
+.macro is_cpu_virt_capable	tmp
+	mrc	p15, 0, \tmp, c0, c1, 1		@ read ID_PFR1
+	and	\tmp, \tmp, #CPUID_ARM_VIRT_MASK	@ mask virtualization bits
+	cmp	\tmp, #(1 << CPUID_ARM_VIRT_SHIFT)
+.endm
+
+/*
+ * secure monitor handler
+ * U-Boot calls this "software interrupt" in start.S
+ * This is executed on a "smc" instruction, we use a "smc #0" to switch
+ * to non-secure state.
+ * r0, r1, r2: passed to the callee
+ * ip: target PC
+ */
+_secure_monitor:
+#ifdef CONFIG_ARMV7_PSCI
+	ldr	r5, =_psci_vectors		@ Switch to the next monitor
+	mcr	p15, 0, r5, c12, c0, 1
+	isb
+
+	@ Obtain a secure stack
+	bl	psci_stack_setup
+
+	@ Configure the PSCI backend
+	push	{r0, r1, r2, ip}
+	bl	psci_arch_init
+	pop	{r0, r1, r2, ip}
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_773022
+	mrc	p15, 0, r5, c1, c0, 1
+	orr	r5, r5, #(1 << 1)
+	mcr	p15, 0, r5, c1, c0, 1
+	isb
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_774769
+	mrc	p15, 0, r5, c1, c0, 1
+	orr	r5, r5, #(1 << 25)
+	mcr	p15, 0, r5, c1, c0, 1
+	isb
+#endif
+
+	mrc	p15, 0, r5, c1, c1, 0		@ read SCR
+	bic	r5, r5, #0x4a			@ clear IRQ, EA, nET bits
+	orr	r5, r5, #0x31			@ enable NS, AW, FW bits
+						@ FIQ preserved for secure mode
+	mov	r6, #SVC_MODE			@ default mode is SVC
+	is_cpu_virt_capable r4
+#ifdef CONFIG_ARMV7_VIRT
+	orreq	r5, r5, #0x100			@ allow HVC instruction
+	moveq	r6, #HYP_MODE			@ Enter the kernel as HYP
+	mrseq	r3, sp_svc
+	msreq	sp_hyp, r3			@ migrate SP
+#endif
+
+	mcr	p15, 0, r5, c1, c1, 0		@ write SCR (with NS bit set)
+	isb
+
+	bne	1f
+
+	@ Reset CNTVOFF to 0 before leaving monitor mode
+	mrc	p15, 0, r4, c0, c1, 1		@ read ID_PFR1
+	ands	r4, r4, #CPUID_ARM_GENTIMER_MASK	@ test arch timer bits
+	movne	r4, #0
+	mcrrne	p15, 4, r4, r4, c14		@ Reset CNTVOFF to zero
+1:
+	mov	lr, ip
+	mov	ip, #(F_BIT | I_BIT | A_BIT)	@ Set A, I and F
+	tst	lr, #1				@ Check for Thumb PC
+	orrne	ip, ip, #T_BIT			@ Set T if Thumb
+	orr	ip, ip, r6			@ Slot target mode in
+	msr	spsr_cxfs, ip			@ Set full SPSR
+	movs	pc, lr				@ ERET to non-secure
+
+ENTRY(_do_nonsec_entry)
+	mov	ip, r0
+	mov	r0, r1
+	mov	r1, r2
+	mov	r2, r3
+	smc	#0
+ENDPROC(_do_nonsec_entry)
+
+.macro get_cbar_addr	addr
+#ifdef CONFIG_ARM_GIC_BASE_ADDRESS
+	ldr	\addr, =CONFIG_ARM_GIC_BASE_ADDRESS
+#else
+	mrc	p15, 4, \addr, c15, c0, 0	@ read CBAR
+	bfc	\addr, #0, #15			@ clear reserved bits
+#endif
+.endm
+
+.macro get_gicd_addr	addr
+	get_cbar_addr	\addr
+	add	\addr, \addr, #GIC_DIST_OFFSET	@ GIC dist i/f offset
+.endm
+
+.macro get_gicc_addr	addr, tmp
+	get_cbar_addr	\addr
+	is_cpu_virt_capable \tmp
+	movne	\tmp, #GIC_CPU_OFFSET_A9	@ GIC CPU offset for A9
+	moveq	\tmp, #GIC_CPU_OFFSET_A15	@ GIC CPU offset for A15/A7
+	add	\addr, \addr, \tmp
+.endm
+
+#ifndef CONFIG_ARMV7_PSCI
+/*
+ * Secondary CPUs start here and call the code for the core specific parts
+ * of the non-secure and HYP mode transition. The GIC distributor specific
+ * code has already been executed by a C function before.
+ * Then they go back to wfi and wait to be woken up by the kernel again.
+ */
+ENTRY(_smp_pen)
+	cpsid	i
+	cpsid	f
+
+	bl	_nonsec_init
+
+	adr	r0, _smp_pen			@ do not use this address again
+	b	smp_waitloop			@ wait for IPIs, board specific
+ENDPROC(_smp_pen)
+#endif
+
+/*
+ * Switch a core to non-secure state.
+ *
+ *  1. initialize the GIC per-core interface
+ *  2. allow coprocessor access in non-secure modes
+ *
+ * Called from smp_pen by secondary cores and directly by the BSP.
+ * Do not assume that the stack is available and only use registers
+ * r0-r3 and r12.
+ *
+ * PERIPHBASE is used to get the GIC address. This could be 40 bits long,
+ * though, but we check this in C before calling this function.
+ */
+ENTRY(_nonsec_init)
+	get_gicd_addr	r3
+
+	mvn	r1, #0				@ all bits to 1
+	str	r1, [r3, #GICD_IGROUPRn]	@ allow private interrupts
+
+	get_gicc_addr	r3, r1
+
+	mov	r1, #3				@ Enable both groups
+	str	r1, [r3, #GICC_CTLR]		@ and clear all other bits
+	mov	r1, #0xff
+	str	r1, [r3, #GICC_PMR]		@ set priority mask register
+
+	mrc	p15, 0, r0, c1, c1, 2
+	movw	r1, #0x3fff
+	movt	r1, #0x0004
+	orr	r0, r0, r1
+	mcr	p15, 0, r0, c1, c1, 2		@ NSACR = all copros to non-sec
+
+/* The CNTFRQ register of the generic timer needs to be
+ * programmed in secure state. Some primary bootloaders / firmware
+ * omit this, so if the frequency is provided in the configuration,
+ * we do this here instead.
+ * But first check if we have the generic timer.
+ */
+#ifdef COUNTER_FREQUENCY
+	mrc	p15, 0, r0, c0, c1, 1		@ read ID_PFR1
+	and	r0, r0, #CPUID_ARM_GENTIMER_MASK	@ mask arch timer bits
+	cmp	r0, #(1 << CPUID_ARM_GENTIMER_SHIFT)
+	ldreq	r1, =COUNTER_FREQUENCY
+	mcreq	p15, 0, r1, c14, c0, 0		@ write CNTFRQ
+#endif
+
+	adr	r1, _monitor_vectors
+	mcr	p15, 0, r1, c12, c0, 1		@ set MVBAR to secure vectors
+	isb
+
+	mov	r0, r3				@ return GICC address
+	bx	lr
+ENDPROC(_nonsec_init)
+
+#ifdef CONFIG_SMP_PEN_ADDR
+/* void __weak smp_waitloop(unsigned previous_address); */
+ENTRY(smp_waitloop)
+	wfi
+	ldr	r1, =CONFIG_SMP_PEN_ADDR	@ load start address
+	ldr	r1, [r1]
+#ifdef CONFIG_PEN_ADDR_BIG_ENDIAN
+	rev	r1, r1
+#endif
+	cmp	r0, r1			@ make sure we dont execute this code
+	beq	smp_waitloop		@ again (due to a spurious wakeup)
+	mov	r0, r1
+	b	_do_nonsec_entry
+ENDPROC(smp_waitloop)
+.weak smp_waitloop
+#endif
+
+	.popsection
diff --git a/arch/arm/cpu/armv7/psci-common.c b/arch/arm/cpu/armv7/psci-common.c
new file mode 100644
index 0000000..a328b2b
--- /dev/null
+++ b/arch/arm/cpu/armv7/psci-common.c
@@ -0,0 +1,46 @@
+/*
+ * Common PSCI functions
+ *
+ * Copyright (C) 2016 Chen-Yu Tsai
+ * Author: Chen-Yu Tsai <wens@csie.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <asm/armv7.h>
+#include <asm/macro.h>
+#include <asm/psci.h>
+#include <asm/secure.h>
+#include <linux/linkage.h>
+
+static u32 psci_target_pc[CONFIG_ARMV7_PSCI_NR_CPUS] __secure_data = { 0 };
+static u32 psci_context_id[CONFIG_ARMV7_PSCI_NR_CPUS] __secure_data = { 0 };
+
+void __secure psci_save(int cpu, u32 pc, u32 context_id)
+{
+	psci_target_pc[cpu] = pc;
+	psci_context_id[cpu] = context_id;
+	dsb();
+}
+
+u32 __secure psci_get_target_pc(int cpu)
+{
+	return psci_target_pc[cpu];
+}
+
+u32 __secure psci_get_context_id(int cpu)
+{
+	return psci_context_id[cpu];
+}
+
diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S
new file mode 100644
index 0000000..983cd90
--- /dev/null
+++ b/arch/arm/cpu/armv7/psci.S
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2013,2014 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/macro.h>
+#include <asm/psci.h>
+
+	.pushsection ._secure.text, "ax"
+
+	.arch_extension	sec
+
+	.align	5
+	.globl _psci_vectors
+_psci_vectors:
+	b	default_psci_vector	@ reset
+	b	default_psci_vector	@ undef
+	b	_smc_psci		@ smc
+	b	default_psci_vector	@ pabort
+	b	default_psci_vector	@ dabort
+	b	default_psci_vector	@ hyp
+	b	default_psci_vector	@ irq
+	b	psci_fiq_enter		@ fiq
+
+ENTRY(psci_fiq_enter)
+	movs	pc, lr
+ENDPROC(psci_fiq_enter)
+.weak psci_fiq_enter
+
+ENTRY(default_psci_vector)
+	movs	pc, lr
+ENDPROC(default_psci_vector)
+.weak default_psci_vector
+
+ENTRY(psci_version)
+ENTRY(psci_cpu_suspend)
+ENTRY(psci_cpu_off)
+ENTRY(psci_cpu_on)
+ENTRY(psci_affinity_info)
+ENTRY(psci_migrate)
+ENTRY(psci_migrate_info_type)
+ENTRY(psci_migrate_info_up_cpu)
+ENTRY(psci_system_off)
+ENTRY(psci_system_reset)
+ENTRY(psci_features)
+ENTRY(psci_cpu_freeze)
+ENTRY(psci_cpu_default_suspend)
+ENTRY(psci_node_hw_state)
+ENTRY(psci_system_suspend)
+ENTRY(psci_set_suspend_mode)
+ENTRY(psi_stat_residency)
+ENTRY(psci_stat_count)
+	mov	r0, #ARM_PSCI_RET_NI	@ Return -1 (Not Implemented)
+	mov	pc, lr
+ENDPROC(psci_stat_count)
+ENDPROC(psi_stat_residency)
+ENDPROC(psci_set_suspend_mode)
+ENDPROC(psci_system_suspend)
+ENDPROC(psci_node_hw_state)
+ENDPROC(psci_cpu_default_suspend)
+ENDPROC(psci_cpu_freeze)
+ENDPROC(psci_features)
+ENDPROC(psci_system_reset)
+ENDPROC(psci_system_off)
+ENDPROC(psci_migrate_info_up_cpu)
+ENDPROC(psci_migrate_info_type)
+ENDPROC(psci_migrate)
+ENDPROC(psci_affinity_info)
+ENDPROC(psci_cpu_on)
+ENDPROC(psci_cpu_off)
+ENDPROC(psci_cpu_suspend)
+ENDPROC(psci_version)
+.weak psci_version
+.weak psci_cpu_suspend
+.weak psci_cpu_off
+.weak psci_cpu_on
+.weak psci_affinity_info
+.weak psci_migrate
+.weak psci_migrate_info_type
+.weak psci_migrate_info_up_cpu
+.weak psci_system_off
+.weak psci_system_reset
+.weak psci_features
+.weak psci_cpu_freeze
+.weak psci_cpu_default_suspend
+.weak psci_node_hw_state
+.weak psci_system_suspend
+.weak psci_set_suspend_mode
+.weak psi_stat_residency
+.weak psci_stat_count
+
+_psci_table:
+	.word	ARM_PSCI_FN_CPU_SUSPEND
+	.word	psci_cpu_suspend
+	.word	ARM_PSCI_FN_CPU_OFF
+	.word	psci_cpu_off
+	.word	ARM_PSCI_FN_CPU_ON
+	.word	psci_cpu_on
+	.word	ARM_PSCI_FN_MIGRATE
+	.word	psci_migrate
+	.word	ARM_PSCI_0_2_FN_PSCI_VERSION
+	.word	psci_version
+	.word	ARM_PSCI_0_2_FN_CPU_SUSPEND
+	.word	psci_cpu_suspend
+	.word	ARM_PSCI_0_2_FN_CPU_OFF
+	.word	psci_cpu_off
+	.word	ARM_PSCI_0_2_FN_CPU_ON
+	.word	psci_cpu_on
+	.word	ARM_PSCI_0_2_FN_AFFINITY_INFO
+	.word	psci_affinity_info
+	.word	ARM_PSCI_0_2_FN_MIGRATE
+	.word	psci_migrate
+	.word	ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE
+	.word	psci_migrate_info_type
+	.word	ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU
+	.word	psci_migrate_info_up_cpu
+	.word	ARM_PSCI_0_2_FN_SYSTEM_OFF
+	.word	psci_system_off
+	.word	ARM_PSCI_0_2_FN_SYSTEM_RESET
+	.word	psci_system_reset
+	.word	ARM_PSCI_1_0_FN_PSCI_FEATURES
+	.word	psci_features
+	.word	ARM_PSCI_1_0_FN_CPU_FREEZE
+	.word	psci_cpu_freeze
+	.word	ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND
+	.word	psci_cpu_default_suspend
+	.word	ARM_PSCI_1_0_FN_NODE_HW_STATE
+	.word	psci_node_hw_state
+	.word	ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
+	.word	psci_system_suspend
+	.word	ARM_PSCI_1_0_FN_SET_SUSPEND_MODE
+	.word	psci_set_suspend_mode
+	.word	ARM_PSCI_1_0_FN_STAT_RESIDENCY
+	.word	psi_stat_residency
+	.word	ARM_PSCI_1_0_FN_STAT_COUNT
+	.word	psci_stat_count
+	.word	0
+	.word	0
+
+_smc_psci:
+	push	{r4-r7,lr}
+
+	@ Switch to secure
+	mrc	p15, 0, r7, c1, c1, 0
+	bic	r4, r7, #1
+	mcr	p15, 0, r4, c1, c1, 0
+	isb
+
+	adr	r4, _psci_table
+1:	ldr	r5, [r4]		@ Load PSCI function ID
+	ldr	r6, [r4, #4]		@ Load target PC
+	cmp	r5, #0			@ If reach the end, bail out
+	moveq	r0, #ARM_PSCI_RET_INVAL	@ Return -2 (Invalid)
+	beq	2f
+	cmp	r0, r5			@ If not matching, try next entry
+	addne	r4, r4, #8
+	bne	1b
+
+	blx	r6			@ Execute PSCI function
+
+	@ Switch back to non-secure
+2:	mcr	p15, 0, r7, c1, c1, 0
+
+	pop	{r4-r7, lr}
+	movs	pc, lr			@ Return to the kernel
+
+@ Requires dense and single-cluster CPU ID space
+ENTRY(psci_get_cpu_id)
+	mrc	p15, 0, r0, c0, c0, 5	/* read MPIDR */
+	and	r0, r0, #0xff		/* return CPU ID in cluster */
+	bx	lr
+ENDPROC(psci_get_cpu_id)
+.weak psci_get_cpu_id
+
+/* Imported from Linux kernel */
+ENTRY(psci_v7_flush_dcache_all)
+	stmfd	sp!, {r4-r5, r7, r9-r11, lr}
+	dmb					@ ensure ordering with previous memory accesses
+	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
+	ands	r3, r0, #0x7000000		@ extract loc from clidr
+	mov	r3, r3, lsr #23			@ left align loc bit field
+	beq	finished			@ if loc is 0, then no need to clean
+	mov	r10, #0				@ start clean at cache level 0
+flush_levels:
+	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
+	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
+	and	r1, r1, #7			@ mask of the bits for current cache only
+	cmp	r1, #2				@ see what cache we have at this level
+	blt	skip				@ skip if no cache, or just i-cache
+	mrs     r9, cpsr			@ make cssr&csidr read atomic
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	isb					@ isb to sych the new cssr&csidr
+	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
+	msr     cpsr_c, r9
+	and	r2, r1, #7			@ extract the length of the cache lines
+	add	r2, r2, #4			@ add 4 (line length offset)
+	ldr	r4, =0x3ff
+	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
+	clz	r5, r4				@ find bit position of way size increment
+	ldr	r7, =0x7fff
+	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
+loop1:
+	mov	r9, r7				@ create working copy of max index
+loop2:
+	orr	r11, r10, r4, lsl r5		@ factor way and cache number into r11
+	orr	r11, r11, r9, lsl r2		@ factor index number into r11
+	mcr	p15, 0, r11, c7, c14, 2		@ clean & invalidate by set/way
+	subs	r9, r9, #1			@ decrement the index
+	bge	loop2
+	subs	r4, r4, #1			@ decrement the way
+	bge	loop1
+skip:
+	add	r10, r10, #2			@ increment cache number
+	cmp	r3, r10
+	bgt	flush_levels
+finished:
+	mov	r10, #0				@ swith back to cache level 0
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	dsb	st
+	isb
+	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}
+	bx	lr
+ENDPROC(psci_v7_flush_dcache_all)
+
+ENTRY(psci_disable_smp)
+	mrc	p15, 0, r0, c1, c0, 1		@ ACTLR
+	bic	r0, r0, #(1 << 6)		@ Clear SMP bit
+	mcr	p15, 0, r0, c1, c0, 1		@ ACTLR
+	isb
+	dsb
+	bx	lr
+ENDPROC(psci_disable_smp)
+.weak psci_disable_smp
+
+ENTRY(psci_enable_smp)
+	mrc	p15, 0, r0, c1, c0, 1		@ ACTLR
+	orr	r0, r0, #(1 << 6)		@ Set SMP bit
+	mcr	p15, 0, r0, c1, c0, 1		@ ACTLR
+	isb
+	bx	lr
+ENDPROC(psci_enable_smp)
+.weak psci_enable_smp
+
+ENTRY(psci_cpu_off_common)
+	push	{lr}
+
+	bl	psci_v7_flush_dcache_all
+
+	clrex					@ Why???
+
+	mrc	p15, 0, r0, c1, c0, 0		@ SCTLR
+	bic	r0, r0, #(1 << 2)		@ Clear C bit
+	mcr	p15, 0, r0, c1, c0, 0		@ SCTLR
+	isb
+	dsb
+
+	bl	psci_v7_flush_dcache_all
+
+	clrex					@ Why???
+
+	bl	psci_disable_smp
+
+	pop	{lr}
+	bx	lr
+ENDPROC(psci_cpu_off_common)
+
+@ The stacks are allocated in reverse order, i.e.
+@ the stack for CPU0 has the highest memory address.
+@
+@ --------------------  __secure_stack_end
+@ |  CPU0 target PC  |
+@ |------------------|
+@ |                  |
+@ |    CPU0 stack    |
+@ |                  |
+@ |------------------|  __secure_stack_end - 1KB
+@ |        .         |
+@ |        .         |
+@ |        .         |
+@ |        .         |
+@ --------------------  __secure_stack_start
+@
+@ This expects CPU ID in r0 and returns stack top in r0
+LENTRY(psci_get_cpu_stack_top)
+	@ stack top = __secure_stack_end - (cpuid << ARM_PSCI_STACK_SHIFT)
+	ldr	r3, =__secure_stack_end
+	sub	r0, r3, r0, LSL #ARM_PSCI_STACK_SHIFT
+	sub	r0, r0, #4		@ Save space for target PC
+	bx	lr
+ENDPROC(psci_get_cpu_stack_top)
+
+@ {r0, r1, r2, ip} from _do_nonsec_entry(kernel_entry, 0, machid, r2) in
+@ arch/arm/lib/bootm.c:boot_jump_linux() must remain unchanged across
+@ this function.
+ENTRY(psci_stack_setup)
+	mov	r6, lr
+	mov	r7, r0
+	bl	psci_get_cpu_id		@ CPU ID => r0
+	bl	psci_get_cpu_stack_top	@ stack top => r0
+	mov	sp, r0
+	mov	r0, r7
+	bx	r6
+ENDPROC(psci_stack_setup)
+
+ENTRY(psci_arch_init)
+	mov	pc, lr
+ENDPROC(psci_arch_init)
+.weak psci_arch_init
+
+ENTRY(psci_arch_cpu_entry)
+	mov	pc, lr
+ENDPROC(psci_arch_cpu_entry)
+.weak psci_arch_cpu_entry
+
+ENTRY(psci_cpu_entry)
+	bl	psci_enable_smp
+
+	bl	_nonsec_init
+
+	bl	psci_stack_setup
+
+	bl	psci_arch_cpu_entry
+
+	bl	psci_get_cpu_id			@ CPU ID => r0
+	mov	r2, r0				@ CPU ID => r2
+	bl	psci_get_context_id		@ context id => r0
+	mov	r1, r0				@ context id => r1
+	mov	r0, r2				@ CPU ID => r0
+	bl	psci_get_target_pc		@ target PC => r0
+	b	_do_nonsec_entry
+ENDPROC(psci_cpu_entry)
+
+	.popsection
diff --git a/arch/arm/cpu/armv7/s5p-common/Makefile b/arch/arm/cpu/armv7/s5p-common/Makefile
new file mode 100644
index 0000000..12cf804
--- /dev/null
+++ b/arch/arm/cpu/armv7/s5p-common/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2009 Samsung Electronics
+# Minkyu Kang <mk7.kang@samsung.com>
+
+obj-y		+= cpu_info.o
+ifndef CONFIG_SPL_BUILD
+obj-y		+= timer.o
+obj-y		+= sromc.o
+obj-$(CONFIG_PWM)	+= pwm.o
+endif
diff --git a/arch/arm/cpu/armv7/s5p-common/cpu_info.c b/arch/arm/cpu/armv7/s5p-common/cpu_info.c
new file mode 100644
index 0000000..5f4076d
--- /dev/null
+++ b/arch/arm/cpu/armv7/s5p-common/cpu_info.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2009 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ */
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/arch/clk.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Default is s5pc100 */
+unsigned int s5p_cpu_id = 0xC100;
+/* Default is EVT1 */
+unsigned int s5p_cpu_rev = 1;
+
+#ifdef CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+	s5p_set_cpu_id();
+
+	return 0;
+}
+#endif
+
+u32 get_device_type(void)
+{
+	return s5p_cpu_id;
+}
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+int print_cpuinfo(void)
+{
+	const char *cpu_model;
+	int len;
+
+	/* For SoC with no real CPU ID in naming convention. */
+	cpu_model = fdt_getprop(gd->fdt_blob, 0, "cpu-model", &len);
+	if (cpu_model)
+		printf("CPU:   %.*s @ ", len, cpu_model);
+	else
+		printf("CPU:   %s%X @ ", s5p_get_cpu_name(), s5p_cpu_id);
+
+	print_freq(get_arm_clk(), "\n");
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c
new file mode 100644
index 0000000..6b9e865
--- /dev/null
+++ b/arch/arm/cpu/armv7/s5p-common/pwm.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Donghwa Lee <dh09.lee@samsung.com>
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <pwm.h>
+#include <asm/io.h>
+#include <asm/arch/pwm.h>
+#include <asm/arch/clk.h>
+
+int pwm_enable(int pwm_id)
+{
+	const struct s5p_timer *pwm =
+			(struct s5p_timer *)samsung_get_base_timer();
+	unsigned long tcon;
+
+	tcon = readl(&pwm->tcon);
+	tcon |= TCON_START(pwm_id);
+
+	writel(tcon, &pwm->tcon);
+
+	return 0;
+}
+
+void pwm_disable(int pwm_id)
+{
+	const struct s5p_timer *pwm =
+			(struct s5p_timer *)samsung_get_base_timer();
+	unsigned long tcon;
+
+	tcon = readl(&pwm->tcon);
+	tcon &= ~TCON_START(pwm_id);
+
+	writel(tcon, &pwm->tcon);
+}
+
+static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq)
+{
+	unsigned long tin_parent_rate;
+	unsigned int div;
+
+	tin_parent_rate = get_pwm_clk();
+
+	for (div = 2; div <= 16; div *= 2) {
+		if ((tin_parent_rate / (div << 16)) < freq)
+			return tin_parent_rate / div;
+	}
+
+	return tin_parent_rate / 16;
+}
+
+#define NS_IN_SEC 1000000000UL
+
+int pwm_config(int pwm_id, int duty_ns, int period_ns)
+{
+	const struct s5p_timer *pwm =
+			(struct s5p_timer *)samsung_get_base_timer();
+	unsigned int offset;
+	unsigned long tin_rate;
+	unsigned long tin_ns;
+	unsigned long frequency;
+	unsigned long tcon;
+	unsigned long tcnt;
+	unsigned long tcmp;
+
+	/*
+	 * We currently avoid using 64bit arithmetic by using the
+	 * fact that anything faster than 1GHz is easily representable
+	 * by 32bits.
+	 */
+	if (period_ns > NS_IN_SEC || duty_ns > NS_IN_SEC || period_ns == 0)
+		return -ERANGE;
+
+	if (duty_ns > period_ns)
+		return -EINVAL;
+
+	frequency = NS_IN_SEC / period_ns;
+
+	/* Check to see if we are changing the clock rate of the PWM */
+	tin_rate = pwm_calc_tin(pwm_id, frequency);
+
+	tin_ns = NS_IN_SEC / tin_rate;
+	tcnt = period_ns / tin_ns;
+
+	/* Note, counters count down */
+	tcmp = duty_ns / tin_ns;
+	tcmp = tcnt - tcmp;
+
+	/* Update the PWM register block. */
+	offset = pwm_id * 3;
+	if (pwm_id < 4) {
+		writel(tcnt, &pwm->tcntb0 + offset);
+		writel(tcmp, &pwm->tcmpb0 + offset);
+	}
+
+	tcon = readl(&pwm->tcon);
+	tcon |= TCON_UPDATE(pwm_id);
+	if (pwm_id < 4)
+		tcon |= TCON_AUTO_RELOAD(pwm_id);
+	else
+		tcon |= TCON4_AUTO_RELOAD;
+	writel(tcon, &pwm->tcon);
+
+	tcon &= ~TCON_UPDATE(pwm_id);
+	writel(tcon, &pwm->tcon);
+
+	return 0;
+}
+
+int pwm_init(int pwm_id, int div, int invert)
+{
+	u32 val;
+	const struct s5p_timer *pwm =
+			(struct s5p_timer *)samsung_get_base_timer();
+	unsigned long ticks_per_period;
+	unsigned int offset, prescaler;
+
+	/*
+	 * Timer Freq(HZ) =
+	 *	PWM_CLK / { (prescaler_value + 1) * (divider_value) }
+	 */
+
+	val = readl(&pwm->tcfg0);
+	if (pwm_id < 2) {
+		prescaler = PRESCALER_0;
+		val &= ~0xff;
+		val |= (prescaler & 0xff);
+	} else {
+		prescaler = PRESCALER_1;
+		val &= ~(0xff << 8);
+		val |= (prescaler & 0xff) << 8;
+	}
+	writel(val, &pwm->tcfg0);
+	val = readl(&pwm->tcfg1);
+	val &= ~(0xf << MUX_DIV_SHIFT(pwm_id));
+	val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id);
+	writel(val, &pwm->tcfg1);
+
+	if (pwm_id == 4) {
+		/*
+		 * TODO(sjg): Use this as a countdown timer for now. We count
+		 * down from the maximum value to 0, then reset.
+		 */
+		ticks_per_period = -1UL;
+	} else {
+		const unsigned long pwm_hz = 1000;
+		unsigned long timer_rate_hz = get_pwm_clk() /
+			((prescaler + 1) * (1 << div));
+
+		ticks_per_period = timer_rate_hz / pwm_hz;
+	}
+
+	/* set count value */
+	offset = pwm_id * 3;
+
+	writel(ticks_per_period, &pwm->tcntb0 + offset);
+
+	val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id));
+	if (invert && (pwm_id < 4))
+		val |= TCON_INVERTER(pwm_id);
+	writel(val, &pwm->tcon);
+
+	pwm_enable(pwm_id);
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/s5p-common/sromc.c b/arch/arm/cpu/armv7/s5p-common/sromc.c
new file mode 100644
index 0000000..0fc1709
--- /dev/null
+++ b/arch/arm/cpu/armv7/s5p-common/sromc.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ * Naveen Krishna Ch <ch.naveen@samsung.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sromc.h>
+
+/*
+ * s5p_config_sromc() - select the proper SROMC Bank and configure the
+ * band width control and bank control registers
+ * srom_bank	- SROM
+ * srom_bw_conf  - SMC Band witdh reg configuration value
+ * srom_bc_conf  - SMC Bank Control reg configuration value
+ */
+void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf)
+{
+	u32 tmp;
+	struct s5p_sromc *srom =
+		(struct s5p_sromc *)samsung_get_base_sromc();
+
+	/* Configure SMC_BW register to handle proper SROMC bank */
+	tmp = srom->bw;
+	tmp &= ~(0xF << (srom_bank * 4));
+	tmp |= srom_bw_conf;
+	srom->bw = tmp;
+
+	/* Configure SMC_BC register */
+	srom->bc[srom_bank] = srom_bc_conf;
+}
diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c
new file mode 100644
index 0000000..0048cd8
--- /dev/null
+++ b/arch/arm/cpu/armv7/s5p-common/timer.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2009 Samsung Electronics
+ * Heungjun Kim <riverful.kim@samsung.com>
+ * Inki Dae <inki.dae@samsung.com>
+ * Minkyu Kang <mk7.kang@samsung.com>
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <asm/arch/pwm.h>
+#include <asm/arch/clk.h>
+
+/* Use the old PWM interface for now */
+#undef CONFIG_DM_PWM
+#include <pwm.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned long get_current_tick(void);
+static void reset_timer_masked(void);
+
+/* macro to read the 16 bit timer */
+static inline struct s5p_timer *s5p_get_base_timer(void)
+{
+	return (struct s5p_timer *)samsung_get_base_timer();
+}
+
+/**
+ * Read the countdown timer.
+ *
+ * This operates at 1MHz and counts downwards. It will wrap about every
+ * hour (2^32 microseconds).
+ *
+ * @return current value of timer
+ */
+static unsigned long timer_get_us_down(void)
+{
+	struct s5p_timer *const timer = s5p_get_base_timer();
+
+	return readl(&timer->tcnto4);
+}
+
+int timer_init(void)
+{
+	/* PWM Timer 4 */
+	pwm_init(4, MUX_DIV_4, 0);
+	pwm_config(4, 100000, 100000);
+	pwm_enable(4);
+
+	/* Use this as the current monotonic time in us */
+	gd->arch.timer_reset_value = 0;
+
+	/* Use this as the last timer value we saw */
+	gd->arch.lastinc = timer_get_us_down();
+	reset_timer_masked();
+
+	return 0;
+}
+
+/*
+ * timer without interrupts
+ */
+unsigned long get_timer(unsigned long base)
+{
+	unsigned long long time_ms;
+
+	ulong now = timer_get_us_down();
+
+	/*
+	 * Increment the time by the amount elapsed since the last read.
+	 * The timer may have wrapped around, but it makes no difference to
+	 * our arithmetic here.
+	 */
+	gd->arch.timer_reset_value += gd->arch.lastinc - now;
+	gd->arch.lastinc = now;
+
+	/* Divide by 1000 to convert from us to ms */
+	time_ms = gd->arch.timer_reset_value;
+	do_div(time_ms, 1000);
+	return time_ms - base;
+}
+
+unsigned long __attribute__((no_instrument_function)) timer_get_us(void)
+{
+	static unsigned long base_time_us;
+
+	struct s5p_timer *const timer =
+		(struct s5p_timer *)samsung_get_base_timer();
+	unsigned long now_downward_us = readl(&timer->tcnto4);
+
+	if (!base_time_us)
+		base_time_us = now_downward_us;
+
+	/* Note that this timer counts downward. */
+	return base_time_us - now_downward_us;
+}
+
+/* delay x useconds */
+void __udelay(unsigned long usec)
+{
+	unsigned long count_value;
+
+	count_value = timer_get_us_down();
+	while ((int)(count_value - timer_get_us_down()) < (int)usec)
+		;
+}
+
+static void reset_timer_masked(void)
+{
+	struct s5p_timer *const timer = s5p_get_base_timer();
+
+	/* reset time */
+	gd->arch.lastinc = readl(&timer->tcnto4);
+	gd->arch.tbl = 0;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+unsigned long get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/cpu/armv7/sctlr.S b/arch/arm/cpu/armv7/sctlr.S
new file mode 100644
index 0000000..bd56e41
--- /dev/null
+++ b/arch/arm/cpu/armv7/sctlr.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ *  Routines to access the system control register
+ *
+ *  Copyright (c) 2018 Heinrich Schuchardt
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * void allow_unaligned(void) - allow unaligned access
+ *
+ * This routine clears the aligned flag in the system control register.
+ * After calling this routine unaligned access does no longer lead to a
+ * data abort but is handled by the CPU.
+ */
+ENTRY(allow_unaligned)
+	mrc	p15, 0, r0, c1, c0, 0	@ load system control register
+	bic	r0, r0, #2		@ clear aligned flag
+	mcr	p15, 0, r0, c1, c0, 0	@ write system control register
+	bx	lr			@ return
+ENDPROC(allow_unaligned)
diff --git a/arch/arm/cpu/armv7/smccc-call.S b/arch/arm/cpu/armv7/smccc-call.S
new file mode 100644
index 0000000..eae69e3
--- /dev/null
+++ b/arch/arm/cpu/armv7/smccc-call.S
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2015, Linaro Limited
+ */
+#include <linux/linkage.h>
+
+#include <asm/opcodes-sec.h>
+#include <asm/opcodes-virt.h>
+
+	.section	.text.efi_runtime
+
+#define UNWIND(x...)
+	/*
+	 * Wrap c macros in asm macros to delay expansion until after the
+	 * SMCCC asm macro is expanded.
+	 */
+	.macro SMCCC_SMC
+	__SMC(0)
+	.endm
+
+	.macro SMCCC_HVC
+	__HVC(0)
+	.endm
+
+	.macro SMCCC instr
+UNWIND(	.fnstart)
+	mov	r12, sp
+	push	{r4-r7}
+UNWIND(	.save	{r4-r7})
+	ldm	r12, {r4-r7}
+	\instr
+	pop	{r4-r7}
+	ldr	r12, [sp, #(4 * 4)]
+	stm	r12, {r0-r3}
+	bx	lr
+UNWIND(	.fnend)
+	.endm
+
+/*
+ * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+ *		  unsigned long a3, unsigned long a4, unsigned long a5,
+ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ *		  struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_smc)
+	SMCCC SMCCC_SMC
+ENDPROC(__arm_smccc_smc)
+
+/*
+ * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
+ *		  unsigned long a3, unsigned long a4, unsigned long a5,
+ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ *		  struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_hvc)
+	SMCCC SMCCC_HVC
+ENDPROC(__arm_smccc_hvc)
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
new file mode 100644
index 0000000..0cb6dd3
--- /dev/null
+++ b/arch/arm/cpu/armv7/start.S
@@ -0,0 +1,342 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
+ *
+ * Copyright (c) 2004	Texas Instruments <r-woodruff2@ti.com>
+ *
+ * Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
+ * Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
+ * Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ * Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ * Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/system.h>
+#include <linux/linkage.h>
+#include <asm/armv7.h>
+
+/*************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * Do important init only if we don't start from memory!
+ * Setup memory and board specific bits prior to relocation.
+ * Relocate armboot to ram. Setup stack.
+ *
+ *************************************************************************/
+
+	.globl	reset
+	.globl	save_boot_params_ret
+	.type   save_boot_params_ret,%function
+#ifdef CONFIG_ARMV7_LPAE
+	.global	switch_to_hypervisor_ret
+#endif
+
+reset:
+	/* Allow the board to save important registers */
+	b	save_boot_params
+save_boot_params_ret:
+#ifdef CONFIG_ARMV7_LPAE
+/*
+ * check for Hypervisor support
+ */
+	mrc	p15, 0, r0, c0, c1, 1		@ read ID_PFR1
+	and	r0, r0, #CPUID_ARM_VIRT_MASK	@ mask virtualization bits
+	cmp	r0, #(1 << CPUID_ARM_VIRT_SHIFT)
+	beq	switch_to_hypervisor
+switch_to_hypervisor_ret:
+#endif
+	/*
+	 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
+	 * except if in HYP mode already
+	 */
+	mrs	r0, cpsr
+	and	r1, r0, #0x1f		@ mask mode bits
+	teq	r1, #0x1a		@ test for HYP mode
+	bicne	r0, r0, #0x1f		@ clear all mode bits
+	orrne	r0, r0, #0x13		@ set SVC mode
+	orr	r0, r0, #0xc0		@ disable FIQ and IRQ
+	msr	cpsr,r0
+
+/*
+ * Setup vector:
+ * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
+ * Continue to use ROM code vector only in OMAP4 spl)
+ */
+#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
+	/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
+	mrc	p15, 0, r0, c1, c0, 0	@ Read CP15 SCTLR Register
+	bic	r0, #CR_V		@ V = 0
+	mcr	p15, 0, r0, c1, c0, 0	@ Write CP15 SCTLR Register
+
+#ifdef CONFIG_HAS_VBAR
+	/* Set vector address in CP15 VBAR register */
+	ldr	r0, =_start
+	mcr	p15, 0, r0, c12, c0, 0	@Set VBAR
+#endif
+#endif
+
+	/* the mask ROM code should have PLL and others stable */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+#ifdef CONFIG_CPU_V7A
+	bl	cpu_init_cp15
+#endif
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+	bl	cpu_init_crit
+#endif
+#endif
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+ENTRY(c_runtime_cpu_setup)
+/*
+ * If I-cache is enabled invalidate it
+ */
+#ifndef CONFIG_SYS_ICACHE_OFF
+	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache
+	mcr     p15, 0, r0, c7, c10, 4	@ DSB
+	mcr     p15, 0, r0, c7, c5, 4	@ ISB
+#endif
+
+	bx	lr
+
+ENDPROC(c_runtime_cpu_setup)
+
+/*************************************************************************
+ *
+ * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
+ *	__attribute__((weak));
+ *
+ * Stack pointer is not yet initialized at this moment
+ * Don't save anything to stack even if compiled with -O0
+ *
+ *************************************************************************/
+ENTRY(save_boot_params)
+	b	save_boot_params_ret		@ back to my caller
+ENDPROC(save_boot_params)
+	.weak	save_boot_params
+
+#ifdef CONFIG_ARMV7_LPAE
+ENTRY(switch_to_hypervisor)
+	b	switch_to_hypervisor_ret
+ENDPROC(switch_to_hypervisor)
+	.weak	switch_to_hypervisor
+#endif
+
+/*************************************************************************
+ *
+ * cpu_init_cp15
+ *
+ * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
+ * CONFIG_SYS_ICACHE_OFF is defined.
+ *
+ *************************************************************************/
+ENTRY(cpu_init_cp15)
+	/*
+	 * Invalidate L1 I/D
+	 */
+	mov	r0, #0			@ set up for MCR
+	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs
+	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache
+	mcr	p15, 0, r0, c7, c5, 6	@ invalidate BP array
+	mcr     p15, 0, r0, c7, c10, 4	@ DSB
+	mcr     p15, 0, r0, c7, c5, 4	@ ISB
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002000	@ clear bits 13 (--V-)
+	bic	r0, r0, #0x00000007	@ clear bits 2:0 (-CAM)
+	orr	r0, r0, #0x00000002	@ set bit 1 (--A-) Align
+	orr	r0, r0, #0x00000800	@ set bit 11 (Z---) BTB
+#ifdef CONFIG_SYS_ICACHE_OFF
+	bic	r0, r0, #0x00001000	@ clear bit 12 (I) I-cache
+#else
+	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-cache
+#endif
+	mcr	p15, 0, r0, c1, c0, 0
+
+#ifdef CONFIG_ARM_ERRATA_716044
+	mrc	p15, 0, r0, c1, c0, 0	@ read system control register
+	orr	r0, r0, #1 << 11	@ set bit #11
+	mcr	p15, 0, r0, c1, c0, 0	@ write system control register
+#endif
+
+#if (defined(CONFIG_ARM_ERRATA_742230) || defined(CONFIG_ARM_ERRATA_794072))
+	mrc	p15, 0, r0, c15, c0, 1	@ read diagnostic register
+	orr	r0, r0, #1 << 4		@ set bit #4
+	mcr	p15, 0, r0, c15, c0, 1	@ write diagnostic register
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_743622
+	mrc	p15, 0, r0, c15, c0, 1	@ read diagnostic register
+	orr	r0, r0, #1 << 6		@ set bit #6
+	mcr	p15, 0, r0, c15, c0, 1	@ write diagnostic register
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_751472
+	mrc	p15, 0, r0, c15, c0, 1	@ read diagnostic register
+	orr	r0, r0, #1 << 11	@ set bit #11
+	mcr	p15, 0, r0, c15, c0, 1	@ write diagnostic register
+#endif
+#ifdef CONFIG_ARM_ERRATA_761320
+	mrc	p15, 0, r0, c15, c0, 1	@ read diagnostic register
+	orr	r0, r0, #1 << 21	@ set bit #21
+	mcr	p15, 0, r0, c15, c0, 1	@ write diagnostic register
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_845369
+	mrc     p15, 0, r0, c15, c0, 1	@ read diagnostic register
+	orr     r0, r0, #1 << 22	@ set bit #22
+	mcr     p15, 0, r0, c15, c0, 1	@ write diagnostic register
+#endif
+
+	mov	r5, lr			@ Store my Caller
+	mrc	p15, 0, r1, c0, c0, 0	@ r1 has Read Main ID Register (MIDR)
+	mov	r3, r1, lsr #20		@ get variant field
+	and	r3, r3, #0xf		@ r3 has CPU variant
+	and	r4, r1, #0xf		@ r4 has CPU revision
+	mov	r2, r3, lsl #4		@ shift variant field for combined value
+	orr	r2, r4, r2		@ r2 has combined CPU variant + revision
+
+/* Early stack for ERRATA that needs into call C code */
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
+	ldr	r0, =(CONFIG_SPL_STACK)
+#else
+	ldr	r0, =(CONFIG_SYS_INIT_SP_ADDR)
+#endif
+	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
+	mov	sp, r0
+
+#ifdef CONFIG_ARM_ERRATA_798870
+	cmp	r2, #0x30		@ Applies to lower than R3p0
+	bge	skip_errata_798870      @ skip if not affected rev
+	cmp	r2, #0x20		@ Applies to including and above R2p0
+	blt	skip_errata_798870      @ skip if not affected rev
+
+	mrc	p15, 1, r0, c15, c0, 0  @ read l2 aux ctrl reg
+	orr	r0, r0, #1 << 7         @ Enable hazard-detect timeout
+	push	{r1-r5}			@ Save the cpu info registers
+	bl	v7_arch_cp15_set_l2aux_ctrl
+	isb				@ Recommended ISB after l2actlr update
+	pop	{r1-r5}			@ Restore the cpu info - fall through
+skip_errata_798870:
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_801819
+	cmp	r2, #0x24		@ Applies to lt including R2p4
+	bgt	skip_errata_801819      @ skip if not affected rev
+	cmp	r2, #0x20		@ Applies to including and above R2p0
+	blt	skip_errata_801819      @ skip if not affected rev
+	mrc	p15, 0, r0, c0, c0, 6	@ pick up REVIDR reg
+	and	r0, r0, #1 << 3		@ check REVIDR[3]
+	cmp	r0, #1 << 3
+	beq	skip_errata_801819	@ skip erratum if REVIDR[3] is set
+
+	mrc	p15, 0, r0, c1, c0, 1	@ read auxilary control register
+	orr	r0, r0, #3 << 27	@ Disables streaming. All write-allocate
+					@ lines allocate in the L1 or L2 cache.
+	orr	r0, r0, #3 << 25	@ Disables streaming. All write-allocate
+					@ lines allocate in the L1 cache.
+	push	{r1-r5}			@ Save the cpu info registers
+	bl	v7_arch_cp15_set_acr
+	pop	{r1-r5}			@ Restore the cpu info - fall through
+skip_errata_801819:
+#endif
+
+#ifdef CONFIG_ARM_CORTEX_A15_CVE_2017_5715
+	mrc	p15, 0, r0, c1, c0, 1	@ read auxilary control register
+	orr	r0, r0, #1 << 0		@ Enable invalidates of BTB
+	push	{r1-r5}			@ Save the cpu info registers
+	bl	v7_arch_cp15_set_acr
+	pop	{r1-r5}			@ Restore the cpu info - fall through
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_454179
+	mrc	p15, 0, r0, c1, c0, 1	@ Read ACR
+
+	cmp	r2, #0x21		@ Only on < r2p1
+	orrlt	r0, r0, #(0x3 << 6)	@ Set DBSM(BIT7) and IBE(BIT6) bits
+
+	push	{r1-r5}			@ Save the cpu info registers
+	bl	v7_arch_cp15_set_acr
+	pop	{r1-r5}			@ Restore the cpu info - fall through
+#endif
+
+#if defined(CONFIG_ARM_ERRATA_430973) || defined (CONFIG_ARM_CORTEX_A8_CVE_2017_5715)
+	mrc	p15, 0, r0, c1, c0, 1	@ Read ACR
+
+#ifdef CONFIG_ARM_CORTEX_A8_CVE_2017_5715
+	orr	r0, r0, #(0x1 << 6)	@ Set IBE bit always to enable OS WA
+#else
+	cmp	r2, #0x21		@ Only on < r2p1
+	orrlt	r0, r0, #(0x1 << 6)	@ Set IBE bit
+#endif
+	push	{r1-r5}			@ Save the cpu info registers
+	bl	v7_arch_cp15_set_acr
+	pop	{r1-r5}			@ Restore the cpu info - fall through
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_621766
+	mrc	p15, 0, r0, c1, c0, 1	@ Read ACR
+
+	cmp	r2, #0x21		@ Only on < r2p1
+	orrlt	r0, r0, #(0x1 << 5)	@ Set L1NEON bit
+
+	push	{r1-r5}			@ Save the cpu info registers
+	bl	v7_arch_cp15_set_acr
+	pop	{r1-r5}			@ Restore the cpu info - fall through
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_725233
+	mrc	p15, 1, r0, c9, c0, 2	@ Read L2ACR
+
+	cmp	r2, #0x21		@ Only on < r2p1 (Cortex A8)
+	orrlt	r0, r0, #(0x1 << 27)	@ L2 PLD data forwarding disable
+
+	push	{r1-r5}			@ Save the cpu info registers
+	bl	v7_arch_cp15_set_l2aux_ctrl
+	pop	{r1-r5}			@ Restore the cpu info - fall through
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_852421
+	mrc	p15, 0, r0, c15, c0, 1	@ read diagnostic register
+	orr	r0, r0, #1 << 24	@ set bit #24
+	mcr	p15, 0, r0, c15, c0, 1	@ write diagnostic register
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_852423
+	mrc	p15, 0, r0, c15, c0, 1	@ read diagnostic register
+	orr	r0, r0, #1 << 12	@ set bit #12
+	mcr	p15, 0, r0, c15, c0, 1	@ write diagnostic register
+#endif
+
+	mov	pc, r5			@ back to my caller
+ENDPROC(cpu_init_cp15)
+
+#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && \
+	!defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY)
+/*************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************/
+ENTRY(cpu_init_crit)
+	/*
+	 * Jump to board specific initialization...
+	 * The Mask ROM will have already initialized
+	 * basic memory. Go here to bump up clock rate and handle
+	 * wake up conditions.
+	 */
+	b	lowlevel_init		@ go setup pll,mux,memory
+ENDPROC(cpu_init_crit)
+#endif
diff --git a/arch/arm/cpu/armv7/stv0991/Makefile b/arch/arm/cpu/armv7/stv0991/Makefile
new file mode 100644
index 0000000..3be5eba
--- /dev/null
+++ b/arch/arm/cpu/armv7/stv0991/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2014, STMicroelectronics - All Rights Reserved
+# Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+
+obj-y	:= timer.o clock.o pinmux.o reset.o
+obj-y	+= lowlevel.o
diff --git a/arch/arm/cpu/armv7/stv0991/clock.c b/arch/arm/cpu/armv7/stv0991/clock.c
new file mode 100644
index 0000000..1e35dee
--- /dev/null
+++ b/arch/arm/cpu/armv7/stv0991/clock.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/stv0991_cgu.h>
+#include<asm/arch/stv0991_periph.h>
+
+static struct stv0991_cgu_regs *const stv0991_cgu_regs = \
+				(struct stv0991_cgu_regs *) (CGU_BASE_ADDR);
+
+void enable_pll1(void)
+{
+	/* pll1 already configured for 1000Mhz, just need to enable it */
+	writel(readl(&stv0991_cgu_regs->pll1_ctrl) & ~(0x01),
+			&stv0991_cgu_regs->pll1_ctrl);
+}
+
+void clock_setup(int peripheral)
+{
+	switch (peripheral) {
+	case UART_CLOCK_CFG:
+		writel(UART_CLK_CFG, &stv0991_cgu_regs->uart_freq);
+		break;
+	case ETH_CLOCK_CFG:
+		enable_pll1();
+		writel(ETH_CLK_CFG, &stv0991_cgu_regs->eth_freq);
+
+		/* Clock selection for ethernet tx_clk & rx_clk*/
+		writel((readl(&stv0991_cgu_regs->eth_ctrl) & ETH_CLK_MASK)
+				| ETH_CLK_CTRL, &stv0991_cgu_regs->eth_ctrl);
+		break;
+	case QSPI_CLOCK_CFG:
+		writel(QSPI_CLK_CTRL, &stv0991_cgu_regs->qspi_freq);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/arch/arm/cpu/armv7/stv0991/lowlevel.S b/arch/arm/cpu/armv7/stv0991/lowlevel.S
new file mode 100644
index 0000000..218ac70
--- /dev/null
+++ b/arch/arm/cpu/armv7/stv0991/lowlevel.S
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014 stmicroelectronics
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+ENTRY(lowlevel_init)
+	mov	pc, lr
+ENDPROC(lowlevel_init)
diff --git a/arch/arm/cpu/armv7/stv0991/pinmux.c b/arch/arm/cpu/armv7/stv0991/pinmux.c
new file mode 100644
index 0000000..6c44ffe
--- /dev/null
+++ b/arch/arm/cpu/armv7/stv0991/pinmux.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#include <asm/io.h>
+#include <asm/arch/stv0991_creg.h>
+#include <asm/arch/stv0991_periph.h>
+#include <asm/arch/hardware.h>
+
+static struct stv0991_creg *const stv0991_creg = \
+			(struct stv0991_creg *)CREG_BASE_ADDR;
+
+int stv0991_pinmux_config(int peripheral)
+{
+	switch (peripheral) {
+	case UART_GPIOC_30_31:
+		/* SSDA/SSCL pad muxing to UART Rx/Dx */
+		writel((readl(&stv0991_creg->mux12) & GPIOC_31_MUX_MASK) |
+				CFG_GPIOC_31_UART_RX,
+				&stv0991_creg->mux12);
+		writel((readl(&stv0991_creg->mux12) & GPIOC_30_MUX_MASK) |
+				CFG_GPIOC_30_UART_TX,
+				&stv0991_creg->mux12);
+		/* SSDA/SSCL pad config to push pull*/
+		writel((readl(&stv0991_creg->cfg_pad6) & GPIOC_31_MODE_MASK) |
+				CFG_GPIOC_31_MODE_PP,
+				&stv0991_creg->cfg_pad6);
+		writel((readl(&stv0991_creg->cfg_pad6) & GPIOC_30_MODE_MASK) |
+				CFG_GPIOC_30_MODE_HIGH,
+				&stv0991_creg->cfg_pad6);
+		break;
+	case UART_GPIOB_16_17:
+		/* ethernet rx_6/7 to UART Rx/Dx */
+		writel((readl(&stv0991_creg->mux7) & GPIOB_17_MUX_MASK) |
+				CFG_GPIOB_17_UART_RX,
+				&stv0991_creg->mux7);
+		writel((readl(&stv0991_creg->mux7) & GPIOB_16_MUX_MASK) |
+				CFG_GPIOB_16_UART_TX,
+				&stv0991_creg->mux7);
+		break;
+	case ETH_GPIOB_10_31_C_0_4:
+		writel(readl(&stv0991_creg->mux6) & 0x000000FF,
+				&stv0991_creg->mux6);
+		writel(0x00000000, &stv0991_creg->mux7);
+		writel(0x00000000, &stv0991_creg->mux8);
+		writel(readl(&stv0991_creg->mux9) & 0xFFF00000,
+				&stv0991_creg->mux9);
+		/* Ethernet Voltage configuration to 1.8V*/
+		writel((readl(&stv0991_creg->vdd_pad1) & VDD_ETH_PS_MASK) |
+				ETH_VDD_CFG, &stv0991_creg->vdd_pad1);
+		writel((readl(&stv0991_creg->vdd_pad1) & VDD_ETH_PS_MASK) |
+				ETH_M_VDD_CFG, &stv0991_creg->vdd_pad1);
+
+		break;
+	case QSPI_CS_CLK_PAD:
+		writel((readl(&stv0991_creg->mux13) & FLASH_CS_NC_MASK) |
+				CFG_FLASH_CS_NC, &stv0991_creg->mux13);
+		writel((readl(&stv0991_creg->mux13) & FLASH_CLK_MASK) |
+				CFG_FLASH_CLK, &stv0991_creg->mux13);
+	default:
+		break;
+	}
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/stv0991/reset.c b/arch/arm/cpu/armv7/stv0991/reset.c
new file mode 100644
index 0000000..d4b3ab7
--- /dev/null
+++ b/arch/arm/cpu/armv7/stv0991/reset.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/stv0991_wdru.h>
+void reset_cpu(ulong ignored)
+{
+	puts("System is going to reboot ...\n");
+	/*
+	 * This 1 second delay will allow the above message
+	 * to be printed before reset
+	 */
+	udelay((1000 * 1000));
+
+	/* Setting bit 1 of the WDRU unit will reset the SoC */
+	writel(WDRU_RST_SYS, &stv0991_wd_ru_ptr->wdru_ctrl1);
+
+	/* system will restart */
+	while (1)
+		;
+}
diff --git a/arch/arm/cpu/armv7/stv0991/timer.c b/arch/arm/cpu/armv7/stv0991/timer.c
new file mode 100644
index 0000000..d1b763d
--- /dev/null
+++ b/arch/arm/cpu/armv7/stv0991/timer.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch-stv0991/hardware.h>
+#include <asm/arch-stv0991/stv0991_cgu.h>
+#include <asm/arch-stv0991/stv0991_gpt.h>
+
+static struct stv0991_cgu_regs *const stv0991_cgu_regs = \
+				(struct stv0991_cgu_regs *) (CGU_BASE_ADDR);
+
+#define READ_TIMER()	(readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING)
+#define GPT_RESOLUTION	(CONFIG_STV0991_HZ_CLOCK / CONFIG_STV0991_HZ)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp gd->arch.tbl
+#define lastdec gd->arch.lastinc
+
+static ulong get_timer_masked(void);
+
+int timer_init(void)
+{
+	/* Timer1 clock configuration */
+	writel(TIMER1_CLK_CFG, &stv0991_cgu_regs->tim_freq);
+	writel(readl(&stv0991_cgu_regs->cgu_enable_2) |
+			TIMER1_CLK_EN, &stv0991_cgu_regs->cgu_enable_2);
+
+	/* Stop the timer */
+	writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1);
+	writel(GPT_PRESCALER_128, &gpt1_regs_ptr->psc);
+	/* Configure timer for auto-reload */
+	writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD,
+			&gpt1_regs_ptr->cr1);
+
+	/* load value for free running */
+	writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr);
+
+	/* start timer */
+	writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN,
+			&gpt1_regs_ptr->cr1);
+
+	/* Reset the timer */
+	lastdec = READ_TIMER();
+	timestamp = 0;
+
+	return 0;
+}
+
+/*
+ * timer without interrupts
+ */
+ulong get_timer(ulong base)
+{
+	return (get_timer_masked() / GPT_RESOLUTION) - base;
+}
+
+void __udelay(unsigned long usec)
+{
+	ulong tmo;
+	ulong start = get_timer_masked();
+	ulong tenudelcnt = CONFIG_STV0991_HZ_CLOCK / (1000 * 100);
+	ulong rndoff;
+
+	rndoff = (usec % 10) ? 1 : 0;
+
+	/* tenudelcnt timer tick gives 10 microsecconds delay */
+	tmo = ((usec / 10) + rndoff) * tenudelcnt;
+
+	while ((ulong) (get_timer_masked() - start) < tmo)
+		;
+}
+
+static ulong get_timer_masked(void)
+{
+	ulong now = READ_TIMER();
+
+	if (now >= lastdec) {
+		/* normal mode */
+		timestamp += now - lastdec;
+	} else {
+		/* we have an overflow ... */
+		timestamp += now + GPT_FREE_RUNNING - lastdec;
+	}
+	lastdec = now;
+
+	return timestamp;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_STV0991_HZ;
+}
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
new file mode 100644
index 0000000..1d40d6a
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+#
+# Based on some other Makefile
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+obj-y	+= timer.o
+
+obj-$(CONFIG_MACH_SUN6I)	+= tzpc.o
+obj-$(CONFIG_MACH_SUN8I_H3)	+= tzpc.o
+
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_ARMV7_PSCI)	+= psci.o
+endif
+
+ifdef CONFIG_SPL_BUILD
+obj-y	+= fel_utils.o
+endif
diff --git a/arch/arm/cpu/armv7/sunxi/fel_utils.S b/arch/arm/cpu/armv7/sunxi/fel_utils.S
new file mode 100644
index 0000000..b231075
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/fel_utils.S
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Utility functions for FEL mode.
+ *
+ * Copyright (c) 2015 Google, Inc
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/system.h>
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+	ldr	r0, =fel_stash
+	str	sp, [r0, #0]
+	str	lr, [r0, #4]
+	mrs	lr, cpsr		@ Read CPSR
+	str	lr, [r0, #8]
+	mrc	p15, 0, lr, c1, c0, 0	@ Read CP15 SCTLR Register
+	str	lr, [r0, #12]
+	mrc	p15, 0, lr, c12, c0, 0	@ Read VBAR
+	str	lr, [r0, #16]
+	mrc	p15, 0, lr, c1, c0, 0	@ Read CP15 Control Register
+	str	lr, [r0, #20]
+	b	save_boot_params_ret
+ENDPROC(save_boot_params)
+
+ENTRY(return_to_fel)
+	mov	sp, r0
+	mov	lr, r1
+	ldr	r0, =fel_stash
+	ldr	r1, [r0, #20]
+	mcr	p15, 0, r1, c1, c0, 0	@ Write CP15 Control Register
+	ldr	r1, [r0, #16]
+	mcr	p15, 0, r1, c12, c0, 0	@ Write VBAR
+	ldr	r1, [r0, #12]
+	mcr	p15, 0, r1, c1, c0, 0	@ Write CP15 SCTLR Register
+	ldr	r1, [r0, #8]
+	msr	cpsr, r1		@ Write CPSR
+	bx	lr
+ENDPROC(return_to_fel)
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
new file mode 100644
index 0000000..f3e8f99
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016
+ * Author: Chen-Yu Tsai <wens@csie.org>
+ *
+ * Based on assembly code by Marc Zyngier <marc.zyngier@arm.com>,
+ * which was based on code by Carl van Schaik <carl@ok-labs.com>.
+ */
+#include <config.h>
+#include <common.h>
+
+#include <asm/arch/cpu.h>
+#include <asm/arch/cpucfg.h>
+#include <asm/arch/prcm.h>
+#include <asm/armv7.h>
+#include <asm/gic.h>
+#include <asm/io.h>
+#include <asm/psci.h>
+#include <asm/secure.h>
+#include <asm/system.h>
+
+#include <linux/bitops.h>
+
+#define __irq		__attribute__ ((interrupt ("IRQ")))
+
+#define	GICD_BASE	(SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
+#define	GICC_BASE	(SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
+
+/*
+ * R40 is different from other single cluster SoCs.
+ *
+ * The power clamps are located in the unused space after the per-core
+ * reset controls for core 3. The secondary core entry address register
+ * is in the SRAM controller address range.
+ */
+#define SUN8I_R40_PWROFF			(0x110)
+#define SUN8I_R40_PWR_CLAMP(cpu)		(0x120 + (cpu) * 0x4)
+#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0		(0xbc)
+
+static void __secure cp15_write_cntp_tval(u32 tval)
+{
+	asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
+}
+
+static void __secure cp15_write_cntp_ctl(u32 val)
+{
+	asm volatile ("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
+}
+
+static u32 __secure cp15_read_cntp_ctl(void)
+{
+	u32 val;
+
+	asm volatile ("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
+
+	return val;
+}
+
+#define ONE_MS (COUNTER_FREQUENCY / 1000)
+
+static void __secure __mdelay(u32 ms)
+{
+	u32 reg = ONE_MS * ms;
+
+	cp15_write_cntp_tval(reg);
+	isb();
+	cp15_write_cntp_ctl(3);
+
+	do {
+		isb();
+		reg = cp15_read_cntp_ctl();
+	} while (!(reg & BIT(2)));
+
+	cp15_write_cntp_ctl(0);
+	isb();
+}
+
+static void __secure clamp_release(u32 __maybe_unused *clamp)
+{
+#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
+	defined(CONFIG_MACH_SUN8I_H3) || \
+	defined(CONFIG_MACH_SUN8I_R40)
+	u32 tmp = 0x1ff;
+	do {
+		tmp >>= 1;
+		writel(tmp, clamp);
+	} while (tmp);
+
+	__mdelay(10);
+#endif
+}
+
+static void __secure clamp_set(u32 __maybe_unused *clamp)
+{
+#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
+	defined(CONFIG_MACH_SUN8I_H3) || \
+	defined(CONFIG_MACH_SUN8I_R40)
+	writel(0xff, clamp);
+#endif
+}
+
+static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
+					int cpu)
+{
+	if (on) {
+		/* Release power clamp */
+		clamp_release(clamp);
+
+		/* Clear power gating */
+		clrbits_le32(pwroff, BIT(cpu));
+	} else {
+		/* Set power gating */
+		setbits_le32(pwroff, BIT(cpu));
+
+		/* Activate power clamp */
+		clamp_set(clamp);
+	}
+}
+
+#ifdef CONFIG_MACH_SUN8I_R40
+/* secondary core entry address is programmed differently on R40 */
+static void __secure sunxi_set_entry_address(void *entry)
+{
+	writel((u32)entry,
+	       SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
+}
+#else
+static void __secure sunxi_set_entry_address(void *entry)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+	writel((u32)entry, &cpucfg->priv0);
+}
+#endif
+
+#ifdef CONFIG_MACH_SUN7I
+/* sun7i (A20) is different from other single cluster SoCs */
+static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+	sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
+			   on, 0);
+}
+#elif defined CONFIG_MACH_SUN8I_R40
+static void __secure sunxi_cpu_set_power(int cpu, bool on)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+	sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu),
+			   (void *)cpucfg + SUN8I_R40_PWROFF,
+			   on, 0);
+}
+#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
+static void __secure sunxi_cpu_set_power(int cpu, bool on)
+{
+	struct sunxi_prcm_reg *prcm =
+		(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+
+	sunxi_power_switch(&prcm->cpu_pwr_clamp[cpu], &prcm->cpu_pwroff,
+			   on, cpu);
+}
+#endif /* CONFIG_MACH_SUN7I */
+
+void __secure sunxi_cpu_power_off(u32 cpuid)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+	u32 cpu = cpuid & 0x3;
+
+	/* Wait for the core to enter WFI */
+	while (1) {
+		if (readl(&cpucfg->cpu[cpu].status) & BIT(2))
+			break;
+		__mdelay(1);
+	}
+
+	/* Assert reset on target CPU */
+	writel(0, &cpucfg->cpu[cpu].rst);
+
+	/* Lock CPU (Disable external debug access) */
+	clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+
+	/* Power down CPU */
+	sunxi_cpu_set_power(cpuid, false);
+
+	/* Unlock CPU (Disable external debug access) */
+	setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+}
+
+static u32 __secure cp15_read_scr(void)
+{
+	u32 scr;
+
+	asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (scr));
+
+	return scr;
+}
+
+static void __secure cp15_write_scr(u32 scr)
+{
+	asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (scr));
+	isb();
+}
+
+/*
+ * Although this is an FIQ handler, the FIQ is processed in monitor mode,
+ * which means there's no FIQ banked registers. This is the same as IRQ
+ * mode, so use the IRQ attribute to ask the compiler to handler entry
+ * and return.
+ */
+void __secure __irq psci_fiq_enter(void)
+{
+	u32 scr, reg, cpu;
+
+	/* Switch to secure mode */
+	scr = cp15_read_scr();
+	cp15_write_scr(scr & ~BIT(0));
+
+	/* Validate reason based on IAR and acknowledge */
+	reg = readl(GICC_BASE + GICC_IAR);
+
+	/* Skip spurious interrupts 1022 and 1023 */
+	if (reg == 1023 || reg == 1022)
+		goto out;
+
+	/* End of interrupt */
+	writel(reg, GICC_BASE + GICC_EOIR);
+	dsb();
+
+	/* Get CPU number */
+	cpu = (reg >> 10) & 0x7;
+
+	/* Power off the CPU */
+	sunxi_cpu_power_off(cpu);
+
+out:
+	/* Restore security level */
+	cp15_write_scr(scr);
+}
+
+int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
+			 u32 context_id)
+{
+	struct sunxi_cpucfg_reg *cpucfg =
+		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+	u32 cpu = (mpidr & 0x3);
+
+	/* store target PC and context id */
+	psci_save(cpu, pc, context_id);
+
+	/* Set secondary core power on PC */
+	sunxi_set_entry_address(&psci_cpu_entry);
+
+	/* Assert reset on target CPU */
+	writel(0, &cpucfg->cpu[cpu].rst);
+
+	/* Invalidate L1 cache */
+	clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+
+	/* Lock CPU (Disable external debug access) */
+	clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+
+	/* Power up target CPU */
+	sunxi_cpu_set_power(cpu, true);
+
+	/* De-assert reset on target CPU */
+	writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst);
+
+	/* Unlock CPU (Disable external debug access) */
+	setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+
+	return ARM_PSCI_RET_SUCCESS;
+}
+
+void __secure psci_cpu_off(void)
+{
+	psci_cpu_off_common();
+
+	/* Ask CPU0 via SGI15 to pull the rug... */
+	writel(BIT(16) | 15, GICD_BASE + GICD_SGIR);
+	dsb();
+
+	/* Wait to be turned off */
+	while (1)
+		wfi();
+}
+
+void __secure psci_arch_init(void)
+{
+	u32 reg;
+
+	/* SGI15 as Group-0 */
+	clrbits_le32(GICD_BASE + GICD_IGROUPRn, BIT(15));
+
+	/* Set SGI15 priority to 0 */
+	writeb(0, GICD_BASE + GICD_IPRIORITYRn + 15);
+
+	/* Be cool with non-secure */
+	writel(0xff, GICC_BASE + GICC_PMR);
+
+	/* Switch FIQEn on */
+	setbits_le32(GICC_BASE + GICC_CTLR, BIT(3));
+
+	reg = cp15_read_scr();
+	reg |= BIT(2);  /* Enable FIQ in monitor mode */
+	reg &= ~BIT(0); /* Secure mode */
+	cp15_write_scr(reg);
+}
diff --git a/arch/arm/cpu/armv7/sunxi/start.c b/arch/arm/cpu/armv7/sunxi/start.c
new file mode 100644
index 0000000..6b392fa
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/start.c
@@ -0,0 +1 @@
+/* Intentionally empty. Only needed to get FEL SPL link line right */
diff --git a/arch/arm/cpu/armv7/sunxi/timer.c b/arch/arm/cpu/armv7/sunxi/timer.c
new file mode 100644
index 0000000..304c1ac
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/timer.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define TIMER_MODE   (0x0 << 7)	/* continuous mode */
+#define TIMER_DIV    (0x0 << 4)	/* pre scale 1 */
+#define TIMER_SRC    (0x1 << 2)	/* osc24m */
+#define TIMER_RELOAD (0x1 << 1)	/* reload internal value */
+#define TIMER_EN     (0x1 << 0)	/* enable timer */
+
+#define TIMER_CLOCK		(24 * 1000 * 1000)
+#define COUNT_TO_USEC(x)	((x) / 24)
+#define USEC_TO_COUNT(x)	((x) * 24)
+#define TICKS_PER_HZ		(TIMER_CLOCK / CONFIG_SYS_HZ)
+#define TICKS_TO_HZ(x)		((x) / TICKS_PER_HZ)
+
+#define TIMER_LOAD_VAL		0xffffffff
+
+#define TIMER_NUM		0	/* we use timer 0 */
+
+/* read the 32-bit timer */
+static ulong read_timer(void)
+{
+	struct sunxi_timer_reg *timers =
+		(struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
+	struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
+
+	/*
+	 * The hardware timer counts down, therefore we invert to
+	 * produce an incrementing timer.
+	 */
+	return ~readl(&timer->val);
+}
+
+/* init timer register */
+int timer_init(void)
+{
+	struct sunxi_timer_reg *timers =
+		(struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
+	struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
+	writel(TIMER_LOAD_VAL, &timer->inter);
+	writel(TIMER_MODE | TIMER_DIV | TIMER_SRC | TIMER_RELOAD | TIMER_EN,
+	       &timer->ctl);
+
+	return 0;
+}
+
+/* timer without interrupts */
+static ulong get_timer_masked(void)
+{
+	/* current tick value */
+	ulong now = TICKS_TO_HZ(read_timer());
+
+	if (now >= gd->arch.lastinc)	/* normal (non rollover) */
+		gd->arch.tbl += (now - gd->arch.lastinc);
+	else {
+		/* rollover */
+		gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL)
+				- gd->arch.lastinc) + now;
+	}
+	gd->arch.lastinc = now;
+
+	return gd->arch.tbl;
+}
+
+ulong get_timer(ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+/* delay x useconds */
+void __udelay(unsigned long usec)
+{
+	long tmo = USEC_TO_COUNT(usec);
+	ulong now, last = read_timer();
+
+	while (tmo > 0) {
+		now = read_timer();
+		if (now > last)	/* normal (non rollover) */
+			tmo -= now - last;
+		else		/* rollover */
+			tmo -= TIMER_LOAD_VAL - last + now;
+		last = now;
+	}
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/cpu/armv7/sunxi/tzpc.c b/arch/arm/cpu/armv7/sunxi/tzpc.c
new file mode 100644
index 0000000..0c86a21
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/tzpc.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Chen-Yu Tsai <wens@csie.org>
+ */
+
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/tzpc.h>
+
+/* Configure Trust Zone Protection Controller */
+void tzpc_init(void)
+{
+	struct sunxi_tzpc *tzpc = (struct sunxi_tzpc *)SUNXI_TZPC_BASE;
+
+#ifdef CONFIG_MACH_SUN6I
+	/* Enable non-secure access to the RTC */
+	writel(SUN6I_TZPC_DECPORT0_RTC, &tzpc->decport0_set);
+#endif
+
+#ifdef CONFIG_MACH_SUN8I_H3
+	/* Enable non-secure access to all peripherals */
+	writel(SUN8I_H3_TZPC_DECPORT0_ALL, &tzpc->decport0_set);
+	writel(SUN8I_H3_TZPC_DECPORT1_ALL, &tzpc->decport1_set);
+	writel(SUN8I_H3_TZPC_DECPORT2_ALL, &tzpc->decport2_set);
+#endif
+}
diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
new file mode 100644
index 0000000..5d7f3f5
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Based on omap-common/u-boot-spl.lds:
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *	Aneesh V <aneesh@ti.com>
+ */
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+		LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	.text      :
+	{
+		__start = .;
+		*(.vectors)
+		arch/arm/cpu/armv7/start.o	(.text)
+		*(.text*)
+	} > .sram
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+	. = ALIGN(4);
+	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	} > .sram
+
+	. = ALIGN(4);
+	__image_copy_end = .;
+	_end = .;
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} > .sdram
+}
diff --git a/arch/arm/cpu/armv7/syslib.c b/arch/arm/cpu/armv7/syslib.c
new file mode 100644
index 0000000..7e29636
--- /dev/null
+++ b/arch/arm/cpu/armv7/syslib.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ *
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Syed Mohammed Khasim <khasim@ti.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+/************************************************************
+ * sdelay() - simple spin loop.  Will be constant time as
+ *  its generally used in bypass conditions only.  This
+ *  is necessary until timers are accessible.
+ *
+ *  not inline to increase chances its in cache when called
+ *************************************************************/
+void sdelay(unsigned long loops)
+{
+	__asm__ volatile ("1:\n" "subs %0, %1, #1\n"
+			  "bne 1b":"=r" (loops):"0"(loops));
+}
+
+/*********************************************************************
+ * wait_on_value() - common routine to allow waiting for changes in
+ *   volatile regs.
+ *********************************************************************/
+u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
+		  u32 bound)
+{
+	u32 i = 0, val;
+	do {
+		++i;
+		val = readl((u32)read_addr) & read_bit_mask;
+		if (val == match_value)
+			return 1;
+		if (i == bound)
+			return 0;
+	} while (1);
+}
diff --git a/arch/arm/cpu/armv7/vf610/Kconfig b/arch/arm/cpu/armv7/vf610/Kconfig
new file mode 100644
index 0000000..764d1fb
--- /dev/null
+++ b/arch/arm/cpu/armv7/vf610/Kconfig
@@ -0,0 +1,37 @@
+if ARCH_VF610
+
+config VF610
+	bool
+	default y
+
+choice
+	prompt "Vybrid board select"
+
+config TARGET_VF610TWR
+	bool "TWR-VF65GS10-DS5"
+
+config TARGET_COLIBRI_VF
+	bool "Colibri VF50/61"
+	select BOARD_LATE_INIT
+
+config TARGET_PCM052
+	bool "PCM-052"
+	select SYS_FSL_ERRATUM_ESDHC135
+	select SYS_FSL_ERRATUM_ESDHC_A001
+
+config TARGET_BK4R1
+	bool "BK4r1"
+	select SYS_FSL_ERRATUM_ESDHC135
+	select SYS_FSL_ERRATUM_ESDHC_A001
+
+endchoice
+
+config SYS_SOC
+	default "vf610"
+
+source "board/freescale/vf610twr/Kconfig"
+source "board/phytec/pcm052/Kconfig"
+source "board/toradex/colibri_vf/Kconfig"
+
+endif
+
diff --git a/arch/arm/cpu/armv7/vf610/Makefile b/arch/arm/cpu/armv7/vf610/Makefile
new file mode 100644
index 0000000..b5b479b
--- /dev/null
+++ b/arch/arm/cpu/armv7/vf610/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2013 Freescale Semiconductor, Inc.
+
+obj-y	+= generic.o
+obj-y	+= timer.o
+
+MKIMAGEFLAGS_u-boot.vyb = -T vybridimage
+
+u-boot.vyb: u-boot.imx
+	$(call if_changed,mkimage)
diff --git a/arch/arm/cpu/armv7/vf610/generic.c b/arch/arm/cpu/armv7/vf610/generic.c
new file mode 100644
index 0000000..cbd3391
--- /dev/null
+++ b/arch/arm/cpu/armv7/vf610/generic.c
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/mach-imx/sys_proto.h>
+#include <netdev.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+
+#ifdef CONFIG_FSL_ESDHC
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+static char soc_type[] = "xx0";
+
+#ifdef CONFIG_MXC_OCOTP
+void enable_ocotp_clk(unsigned char enable)
+{
+	struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	u32 reg;
+
+	reg = readl(&ccm->ccgr6);
+	if (enable)
+		reg |= CCM_CCGR6_OCOTP_CTRL_MASK;
+	else
+		reg &= ~CCM_CCGR6_OCOTP_CTRL_MASK;
+	writel(reg, &ccm->ccgr6);
+}
+#endif
+
+static u32 get_mcu_main_clk(void)
+{
+	struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	u32 ccm_ccsr, ccm_cacrr, armclk_div;
+	u32 sysclk_sel, pll_pfd_sel = 0;
+	u32 freq = 0;
+
+	ccm_ccsr = readl(&ccm->ccsr);
+	sysclk_sel = ccm_ccsr & CCM_CCSR_SYS_CLK_SEL_MASK;
+	sysclk_sel >>= CCM_CCSR_SYS_CLK_SEL_OFFSET;
+
+	ccm_cacrr = readl(&ccm->cacrr);
+	armclk_div = ccm_cacrr & CCM_CACRR_ARM_CLK_DIV_MASK;
+	armclk_div >>= CCM_CACRR_ARM_CLK_DIV_OFFSET;
+	armclk_div += 1;
+
+	switch (sysclk_sel) {
+	case 0:
+		freq = FASE_CLK_FREQ;
+		break;
+	case 1:
+		freq = SLOW_CLK_FREQ;
+		break;
+	case 2:
+		pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL2_PFD_CLK_SEL_MASK;
+		pll_pfd_sel >>= CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET;
+		if (pll_pfd_sel == 0)
+			freq = PLL2_MAIN_FREQ;
+		else if (pll_pfd_sel == 1)
+			freq = PLL2_PFD1_FREQ;
+		else if (pll_pfd_sel == 2)
+			freq = PLL2_PFD2_FREQ;
+		else if (pll_pfd_sel == 3)
+			freq = PLL2_PFD3_FREQ;
+		else if (pll_pfd_sel == 4)
+			freq = PLL2_PFD4_FREQ;
+		break;
+	case 3:
+		freq = PLL2_MAIN_FREQ;
+		break;
+	case 4:
+		pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL1_PFD_CLK_SEL_MASK;
+		pll_pfd_sel >>= CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET;
+		if (pll_pfd_sel == 0)
+			freq = PLL1_MAIN_FREQ;
+		else if (pll_pfd_sel == 1)
+			freq = PLL1_PFD1_FREQ;
+		else if (pll_pfd_sel == 2)
+			freq = PLL1_PFD2_FREQ;
+		else if (pll_pfd_sel == 3)
+			freq = PLL1_PFD3_FREQ;
+		else if (pll_pfd_sel == 4)
+			freq = PLL1_PFD4_FREQ;
+		break;
+	case 5:
+		freq = PLL3_MAIN_FREQ;
+		break;
+	default:
+		printf("unsupported system clock select\n");
+	}
+
+	return freq / armclk_div;
+}
+
+static u32 get_bus_clk(void)
+{
+	struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	u32 ccm_cacrr, busclk_div;
+
+	ccm_cacrr = readl(&ccm->cacrr);
+
+	busclk_div = ccm_cacrr & CCM_CACRR_BUS_CLK_DIV_MASK;
+	busclk_div >>= CCM_CACRR_BUS_CLK_DIV_OFFSET;
+	busclk_div += 1;
+
+	return get_mcu_main_clk() / busclk_div;
+}
+
+static u32 get_ipg_clk(void)
+{
+	struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	u32 ccm_cacrr, ipgclk_div;
+
+	ccm_cacrr = readl(&ccm->cacrr);
+
+	ipgclk_div = ccm_cacrr & CCM_CACRR_IPG_CLK_DIV_MASK;
+	ipgclk_div >>= CCM_CACRR_IPG_CLK_DIV_OFFSET;
+	ipgclk_div += 1;
+
+	return get_bus_clk() / ipgclk_div;
+}
+
+static u32 get_uart_clk(void)
+{
+	return get_ipg_clk();
+}
+
+static u32 get_sdhc_clk(void)
+{
+	struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	u32 ccm_cscmr1, ccm_cscdr2, sdhc_clk_sel, sdhc_clk_div;
+	u32 freq = 0;
+
+	ccm_cscmr1 = readl(&ccm->cscmr1);
+	sdhc_clk_sel = ccm_cscmr1 & CCM_CSCMR1_ESDHC1_CLK_SEL_MASK;
+	sdhc_clk_sel >>= CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET;
+
+	ccm_cscdr2 = readl(&ccm->cscdr2);
+	sdhc_clk_div = ccm_cscdr2 & CCM_CSCDR2_ESDHC1_CLK_DIV_MASK;
+	sdhc_clk_div >>= CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET;
+	sdhc_clk_div += 1;
+
+	switch (sdhc_clk_sel) {
+	case 0:
+		freq = PLL3_MAIN_FREQ;
+		break;
+	case 1:
+		freq = PLL3_PFD3_FREQ;
+		break;
+	case 2:
+		freq = PLL1_PFD3_FREQ;
+		break;
+	case 3:
+		freq = get_bus_clk();
+		break;
+	}
+
+	return freq / sdhc_clk_div;
+}
+
+u32 get_fec_clk(void)
+{
+	struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	u32 ccm_cscmr2, rmii_clk_sel;
+	u32 freq = 0;
+
+	ccm_cscmr2 = readl(&ccm->cscmr2);
+	rmii_clk_sel = ccm_cscmr2 & CCM_CSCMR2_RMII_CLK_SEL_MASK;
+	rmii_clk_sel >>= CCM_CSCMR2_RMII_CLK_SEL_OFFSET;
+
+	switch (rmii_clk_sel) {
+	case 0:
+		freq = ENET_EXTERNAL_CLK;
+		break;
+	case 1:
+		freq = AUDIO_EXTERNAL_CLK;
+		break;
+	case 2:
+		freq = PLL5_MAIN_FREQ;
+		break;
+	case 3:
+		freq = PLL5_MAIN_FREQ / 2;
+		break;
+	}
+
+	return freq;
+}
+
+static u32 get_i2c_clk(void)
+{
+	return get_ipg_clk();
+}
+
+static u32 get_dspi_clk(void)
+{
+	return get_ipg_clk();
+}
+
+u32 get_lpuart_clk(void)
+{
+	return get_uart_clk();
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return get_mcu_main_clk();
+	case MXC_BUS_CLK:
+		return get_bus_clk();
+	case MXC_IPG_CLK:
+		return get_ipg_clk();
+	case MXC_UART_CLK:
+		return get_uart_clk();
+	case MXC_ESDHC_CLK:
+		return get_sdhc_clk();
+	case MXC_FEC_CLK:
+		return get_fec_clk();
+	case MXC_I2C_CLK:
+		return get_i2c_clk();
+	case MXC_DSPI_CLK:
+		return get_dspi_clk();
+	default:
+		break;
+	}
+	return -1;
+}
+
+/* Dump some core clocks */
+int do_vf610_showclocks(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char * const argv[])
+{
+	printf("\n");
+	printf("cpu clock : %8d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("bus clock : %8d MHz\n", mxc_get_clock(MXC_BUS_CLK) / 1000000);
+	printf("ipg clock : %8d MHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000000);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	clocks, CONFIG_SYS_MAXARGS, 1, do_vf610_showclocks,
+	"display clocks",
+	""
+);
+
+#ifdef CONFIG_FEC_MXC
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+	struct fuse_bank *bank = &ocotp->bank[4];
+	struct fuse_bank4_regs *fuse =
+		(struct fuse_bank4_regs *)bank->fuse_regs;
+
+	u32 value = readl(&fuse->mac_addr0);
+	mac[0] = (value >> 8);
+	mac[1] = value;
+
+	value = readl(&fuse->mac_addr1);
+	mac[2] = value >> 24;
+	mac[3] = value >> 16;
+	mac[4] = value >> 8;
+	mac[5] = value;
+}
+#endif
+
+u32 get_cpu_rev(void)
+{
+	return MXC_CPU_VF610 << 12;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+static char *get_reset_cause(void)
+{
+	u32 cause;
+	struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+
+	cause = readl(&src_regs->srsr);
+	writel(cause, &src_regs->srsr);
+
+	if (cause & SRC_SRSR_POR_RST)
+		return "POWER ON RESET";
+	else if (cause & SRC_SRSR_WDOG_A5)
+		return "WDOG A5";
+	else if (cause & SRC_SRSR_WDOG_M4)
+		return "WDOG M4";
+	else if (cause & SRC_SRSR_JTAG_RST)
+		return "JTAG HIGH-Z";
+	else if (cause & SRC_SRSR_SW_RST)
+		return "SW RESET";
+	else if (cause & SRC_SRSR_RESETB)
+		return "EXTERNAL RESET";
+	else
+		return "unknown reset";
+}
+
+int print_cpuinfo(void)
+{
+	printf("CPU: Freescale Vybrid VF%s at %d MHz\n",
+	       soc_type, mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("Reset cause: %s\n", get_reset_cause());
+
+	return 0;
+}
+#endif
+
+int arch_cpu_init(void)
+{
+	struct mscm *mscm = (struct mscm *)MSCM_BASE_ADDR;
+
+	soc_type[0] = mscm->cpxcount ? '6' : '5'; /*Dual Core => VF6x0 */
+	soc_type[1] = mscm->cpxcfg1 ? '1' : '0'; /* L2 Cache => VFx10 */
+
+	return 0;
+}
+
+#ifdef CONFIG_ARCH_MISC_INIT
+int arch_misc_init(void)
+{
+	char soc[6];
+
+	strcpy(soc, "vf");
+	strcat(soc, soc_type);
+	env_set("soc", soc);
+
+	return 0;
+}
+#endif
+
+int cpu_eth_init(bd_t *bis)
+{
+	int rc = -ENODEV;
+
+#if defined(CONFIG_FEC_MXC)
+	rc = fecmxc_initialize(bis);
+#endif
+
+	return rc;
+}
+
+#ifdef CONFIG_FSL_ESDHC
+int cpu_mmc_init(bd_t *bis)
+{
+	return fsl_esdhc_mmc_init(bis);
+}
+#endif
+
+int get_clocks(void)
+{
+#ifdef CONFIG_FSL_ESDHC
+	gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+#endif
+	return 0;
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
+	enum dcache_option option = DCACHE_WRITETHROUGH;
+#else
+	enum dcache_option option = DCACHE_WRITEBACK;
+#endif
+	dcache_enable();
+	icache_enable();
+
+    /* Enable caching on OCRAM */
+	mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, IRAM_SIZE, option);
+}
+#endif
diff --git a/arch/arm/cpu/armv7/vf610/timer.c b/arch/arm/cpu/armv7/vf610/timer.c
new file mode 100644
index 0000000..821a279
--- /dev/null
+++ b/arch/arm/cpu/armv7/vf610/timer.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <div64.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+static struct pit_reg *cur_pit = (struct pit_reg *)PIT_BASE_ADDR;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define TIMER_LOAD_VAL	0xffffffff
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, mxc_get_clock(MXC_IPG_CLK));
+
+	return tick;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long usec)
+{
+	usec = usec * mxc_get_clock(MXC_IPG_CLK)  + 999999;
+	do_div(usec, 1000000);
+
+	return usec;
+}
+
+int timer_init(void)
+{
+	__raw_writel(0, &cur_pit->mcr);
+
+	__raw_writel(TIMER_LOAD_VAL, &cur_pit->ldval1);
+	__raw_writel(0, &cur_pit->tctrl1);
+	__raw_writel(1, &cur_pit->tctrl1);
+
+	gd->arch.tbl = 0;
+	gd->arch.tbu = 0;
+
+	return 0;
+}
+
+unsigned long long get_ticks(void)
+{
+	ulong now = TIMER_LOAD_VAL - __raw_readl(&cur_pit->cval1);
+
+	/* increment tbu if tbl has rolled over */
+	if (now < gd->arch.tbl)
+		gd->arch.tbu++;
+	gd->arch.tbl = now;
+
+	return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
+}
+
+ulong get_timer(ulong base)
+{
+	return tick_to_time(get_ticks()) - base;
+}
+
+/* delay x useconds AND preserve advance timstamp value */
+void __udelay(unsigned long usec)
+{
+	unsigned long long start;
+	ulong tmo;
+
+	start = get_ticks();			/* get current timestamp */
+	tmo = us_to_tick(usec);			/* convert usecs to ticks */
+	while ((get_ticks() - start) < tmo)
+		;				/* loop till time has passed */
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return mxc_get_clock(MXC_IPG_CLK);
+}
diff --git a/arch/arm/cpu/armv7/virt-dt.c b/arch/arm/cpu/armv7/virt-dt.c
new file mode 100644
index 0000000..204187c
--- /dev/null
+++ b/arch/arm/cpu/armv7/virt-dt.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <stdio_dev.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <asm/global_data.h>
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+#include <asm/armv7.h>
+#include <asm/psci.h>
+
+int armv7_apply_memory_carveout(u64 *start, u64 *size)
+{
+#ifdef CONFIG_ARMV7_SECURE_RESERVE_SIZE
+	if (*start + *size < CONFIG_ARMV7_SECURE_BASE ||
+	    *start >= (u64)CONFIG_ARMV7_SECURE_BASE +
+		      CONFIG_ARMV7_SECURE_RESERVE_SIZE)
+		return 0;
+
+	/* carveout must be at the beginning or the end of the bank */
+	if (*start == CONFIG_ARMV7_SECURE_BASE ||
+	    *start + *size == (u64)CONFIG_ARMV7_SECURE_BASE +
+			      CONFIG_ARMV7_SECURE_RESERVE_SIZE) {
+		if (*size < CONFIG_ARMV7_SECURE_RESERVE_SIZE) {
+			debug("Secure monitor larger than RAM bank!?\n");
+			return -EINVAL;
+		}
+		*size -= CONFIG_ARMV7_SECURE_RESERVE_SIZE;
+		if (*start == CONFIG_ARMV7_SECURE_BASE)
+			*start += CONFIG_ARMV7_SECURE_RESERVE_SIZE;
+		return 0;
+	}
+	debug("Secure monitor not located at beginning or end of RAM bank\n");
+	return -EINVAL;
+#else /* !CONFIG_ARMV7_SECURE_RESERVE_SIZE */
+	return 0;
+#endif
+}
+
+int psci_update_dt(void *fdt)
+{
+#ifdef CONFIG_ARMV7_NONSEC
+	if (!armv7_boot_nonsec())
+		return 0;
+#endif
+#ifndef CONFIG_ARMV7_SECURE_BASE
+	/* secure code lives in RAM, keep it alive */
+	fdt_add_mem_rsv(fdt, (unsigned long)__secure_start,
+			__secure_end - __secure_start);
+#endif
+
+	return fdt_psci(fdt);
+}
diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
new file mode 100644
index 0000000..be14eb9
--- /dev/null
+++ b/arch/arm/cpu/armv7/virt-v7.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013
+ * Andre Przywara, Linaro <andre.przywara@linaro.org>
+ *
+ * Routines to transition ARMv7 processors from secure into non-secure state
+ * and from non-secure SVC into HYP mode
+ * needed to enable ARMv7 virtualization for current hypervisors
+ */
+
+#include <common.h>
+#include <asm/armv7.h>
+#include <asm/gic.h>
+#include <asm/io.h>
+#include <asm/secure.h>
+
+static unsigned int read_id_pfr1(void)
+{
+	unsigned int reg;
+
+	asm("mrc p15, 0, %0, c0, c1, 1\n" : "=r"(reg));
+	return reg;
+}
+
+static unsigned long get_gicd_base_address(void)
+{
+#ifdef CONFIG_ARM_GIC_BASE_ADDRESS
+	return CONFIG_ARM_GIC_BASE_ADDRESS + GIC_DIST_OFFSET;
+#else
+	unsigned periphbase;
+
+	/* get the GIC base address from the CBAR register */
+	asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase));
+
+	/* the PERIPHBASE can be mapped above 4 GB (lower 8 bits used to
+	 * encode this). Bail out here since we cannot access this without
+	 * enabling paging.
+	 */
+	if ((periphbase & 0xff) != 0) {
+		printf("nonsec: PERIPHBASE is above 4 GB, no access.\n");
+		return -1;
+	}
+
+	return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET;
+#endif
+}
+
+/* Define a specific version of this function to enable any available
+ * hardware protections for the reserved region */
+void __weak protect_secure_section(void) {}
+
+static void relocate_secure_section(void)
+{
+#ifdef CONFIG_ARMV7_SECURE_BASE
+	size_t sz = __secure_end - __secure_start;
+	unsigned long szflush = ALIGN(sz + 1, CONFIG_SYS_CACHELINE_SIZE);
+
+	memcpy((void *)CONFIG_ARMV7_SECURE_BASE, __secure_start, sz);
+
+	flush_dcache_range(CONFIG_ARMV7_SECURE_BASE,
+			   CONFIG_ARMV7_SECURE_BASE + szflush);
+	protect_secure_section();
+	invalidate_icache_all();
+#endif
+}
+
+static void kick_secondary_cpus_gic(unsigned long gicdaddr)
+{
+	/* kick all CPUs (except this one) by writing to GICD_SGIR */
+	writel(1U << 24, gicdaddr + GICD_SGIR);
+}
+
+void __weak smp_kick_all_cpus(void)
+{
+	unsigned long gic_dist_addr;
+
+	gic_dist_addr = get_gicd_base_address();
+	if (gic_dist_addr == -1)
+		return;
+
+	kick_secondary_cpus_gic(gic_dist_addr);
+}
+
+__weak void psci_board_init(void)
+{
+}
+
+int armv7_init_nonsec(void)
+{
+	unsigned int reg;
+	unsigned itlinesnr, i;
+	unsigned long gic_dist_addr;
+
+	/* check whether the CPU supports the security extensions */
+	reg = read_id_pfr1();
+	if ((reg & 0xF0) == 0) {
+		printf("nonsec: Security extensions not implemented.\n");
+		return -1;
+	}
+
+	/* the SCR register will be set directly in the monitor mode handler,
+	 * according to the spec one should not tinker with it in secure state
+	 * in SVC mode. Do not try to read it once in non-secure state,
+	 * any access to it will trap.
+	 */
+
+	gic_dist_addr = get_gicd_base_address();
+	if (gic_dist_addr == -1)
+		return -1;
+
+	/* enable the GIC distributor */
+	writel(readl(gic_dist_addr + GICD_CTLR) | 0x03,
+	       gic_dist_addr + GICD_CTLR);
+
+	/* TYPER[4:0] contains an encoded number of available interrupts */
+	itlinesnr = readl(gic_dist_addr + GICD_TYPER) & 0x1f;
+
+	/* set all bits in the GIC group registers to one to allow access
+	 * from non-secure state. The first 32 interrupts are private per
+	 * CPU and will be set later when enabling the GIC for each core
+	 */
+	for (i = 1; i <= itlinesnr; i++)
+		writel((unsigned)-1, gic_dist_addr + GICD_IGROUPRn + 4 * i);
+
+	psci_board_init();
+
+	/*
+	 * Relocate secure section before any cpu runs in secure ram.
+	 * smp_kick_all_cpus may enable other cores and runs into secure
+	 * ram, so need to relocate secure section before enabling other
+	 * cores.
+	 */
+	relocate_secure_section();
+
+#ifndef CONFIG_ARMV7_PSCI
+	smp_set_core_boot_addr((unsigned long)secure_ram_addr(_smp_pen), -1);
+	smp_kick_all_cpus();
+#endif
+
+	/* call the non-sec switching code on this CPU also */
+	secure_ram_addr(_nonsec_init)();
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile
new file mode 100644
index 0000000..baeac93
--- /dev/null
+++ b/arch/arm/cpu/armv7m/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y := start.o
+obj-y += cpu.o cache.o
+obj-$(CONFIG_SYS_ARM_MPU) += mpu.o
+obj-$(CONFIG_SYS_ARCH_TIMER) += systick-timer.o
diff --git a/arch/arm/cpu/armv7m/cache.c b/arch/arm/cpu/armv7m/cache.c
new file mode 100644
index 0000000..815e623
--- /dev/null
+++ b/arch/arm/cpu/armv7m/cache.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/armv7m.h>
+#include <asm/io.h>
+
+/* Cache maintenance operation registers */
+
+#define V7M_CACHE_REG_ICIALLU		((u32 *)(V7M_CACHE_MAINT_BASE + 0x00))
+#define INVAL_ICACHE_POU		0
+#define V7M_CACHE_REG_ICIMVALU		((u32 *)(V7M_CACHE_MAINT_BASE + 0x08))
+#define V7M_CACHE_REG_DCIMVAC		((u32 *)(V7M_CACHE_MAINT_BASE + 0x0C))
+#define V7M_CACHE_REG_DCISW		((u32 *)(V7M_CACHE_MAINT_BASE + 0x10))
+#define V7M_CACHE_REG_DCCMVAU		((u32 *)(V7M_CACHE_MAINT_BASE + 0x14))
+#define V7M_CACHE_REG_DCCMVAC		((u32 *)(V7M_CACHE_MAINT_BASE + 0x18))
+#define V7M_CACHE_REG_DCCSW		((u32 *)(V7M_CACHE_MAINT_BASE + 0x1C))
+#define V7M_CACHE_REG_DCCIMVAC		((u32 *)(V7M_CACHE_MAINT_BASE + 0x20))
+#define V7M_CACHE_REG_DCCISW		((u32 *)(V7M_CACHE_MAINT_BASE + 0x24))
+#define WAYS_SHIFT			30
+#define SETS_SHIFT			5
+
+/* armv7m processor feature registers */
+
+#define V7M_PROC_REG_CLIDR		((u32 *)(V7M_PROC_FTR_BASE + 0x00))
+#define V7M_PROC_REG_CTR		((u32 *)(V7M_PROC_FTR_BASE + 0x04))
+#define V7M_PROC_REG_CCSIDR		((u32 *)(V7M_PROC_FTR_BASE + 0x08))
+#define MASK_NUM_WAYS			GENMASK(12, 3)
+#define MASK_NUM_SETS			GENMASK(27, 13)
+#define CLINE_SIZE_MASK			GENMASK(2, 0)
+#define NUM_WAYS_SHIFT			3
+#define NUM_SETS_SHIFT			13
+#define V7M_PROC_REG_CSSELR		((u32 *)(V7M_PROC_FTR_BASE + 0x0C))
+#define SEL_I_OR_D			BIT(0)
+
+enum cache_type {
+	DCACHE,
+	ICACHE,
+};
+
+/* PoU : Point of Unification, Poc: Point of Coherency */
+enum cache_action {
+	INVALIDATE_POU,		/* i-cache invalidate by address */
+	INVALIDATE_POC,		/* d-cache invalidate by address */
+	INVALIDATE_SET_WAY,	/* d-cache invalidate by sets/ways */
+	FLUSH_POU,		/* d-cache clean by address to the PoU */
+	FLUSH_POC,		/* d-cache clean by address to the PoC */
+	FLUSH_SET_WAY,		/* d-cache clean by sets/ways */
+	FLUSH_INVAL_POC,	/* d-cache clean & invalidate by addr to PoC */
+	FLUSH_INVAL_SET_WAY,	/* d-cache clean & invalidate by set/ways */
+};
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+struct dcache_config {
+	u32 ways;
+	u32 sets;
+};
+
+static void get_cache_ways_sets(struct dcache_config *cache)
+{
+	u32 cache_size_id = readl(V7M_PROC_REG_CCSIDR);
+
+	cache->ways = (cache_size_id & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT;
+	cache->sets = (cache_size_id & MASK_NUM_SETS) >> NUM_SETS_SHIFT;
+}
+
+/*
+ * Return the io register to perform required cache action like clean or clean
+ * & invalidate by sets/ways.
+ */
+static u32 *get_action_reg_set_ways(enum cache_action action)
+{
+	switch (action) {
+	case INVALIDATE_SET_WAY:
+		return V7M_CACHE_REG_DCISW;
+	case FLUSH_SET_WAY:
+		return V7M_CACHE_REG_DCCSW;
+	case FLUSH_INVAL_SET_WAY:
+		return V7M_CACHE_REG_DCCISW;
+	default:
+		break;
+	};
+
+	return NULL;
+}
+
+/*
+ * Return the io register to perform required cache action like clean or clean
+ * & invalidate by adddress or range.
+ */
+static u32 *get_action_reg_range(enum cache_action action)
+{
+	switch (action) {
+	case INVALIDATE_POU:
+		return V7M_CACHE_REG_ICIMVALU;
+	case INVALIDATE_POC:
+		return V7M_CACHE_REG_DCIMVAC;
+	case FLUSH_POU:
+		return V7M_CACHE_REG_DCCMVAU;
+	case FLUSH_POC:
+		return V7M_CACHE_REG_DCCMVAC;
+	case FLUSH_INVAL_POC:
+		return V7M_CACHE_REG_DCCIMVAC;
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
+static u32 get_cline_size(enum cache_type type)
+{
+	u32 size;
+
+	if (type == DCACHE)
+		clrbits_le32(V7M_PROC_REG_CSSELR, BIT(SEL_I_OR_D));
+	else if (type == ICACHE)
+		setbits_le32(V7M_PROC_REG_CSSELR, BIT(SEL_I_OR_D));
+	/* Make sure cache selection is effective for next memory access */
+	dsb();
+
+	size = readl(V7M_PROC_REG_CCSIDR) & CLINE_SIZE_MASK;
+	/* Size enocoded as 2 less than log(no_of_words_in_cache_line) base 2 */
+	size = 1 << (size + 2);
+	debug("cache line size is %d\n", size);
+
+	return size;
+}
+
+/* Perform the action like invalidate/clean on a range of cache addresses */
+static int action_cache_range(enum cache_action action, u32 start_addr,
+			      int64_t size)
+{
+	u32 cline_size;
+	u32 *action_reg;
+	enum cache_type type;
+
+	action_reg = get_action_reg_range(action);
+	if (!action_reg)
+		return -EINVAL;
+	if (action == INVALIDATE_POU)
+		type = ICACHE;
+	else
+		type = DCACHE;
+
+	/* Cache line size is minium size for the cache action */
+	cline_size = get_cline_size(type);
+	/* Align start address to cache line boundary */
+	start_addr &= ~(cline_size - 1);
+	debug("total size for cache action = %llx\n", size);
+	do {
+		writel(start_addr, action_reg);
+		size -= cline_size;
+		start_addr += cline_size;
+	} while (size > cline_size);
+
+	/* Make sure cache action is effective for next memory access */
+	dsb();
+	isb();	/* Make sure instruction stream sees it */
+	debug("cache action on range done\n");
+
+	return 0;
+}
+
+/* Perform the action like invalidate/clean on all cached addresses */
+static int action_dcache_all(enum cache_action action)
+{
+	struct dcache_config cache;
+	u32 *action_reg;
+	int i, j;
+
+	action_reg = get_action_reg_set_ways(action);
+	if (!action_reg)
+		return -EINVAL;
+
+	clrbits_le32(V7M_PROC_REG_CSSELR, BIT(SEL_I_OR_D));
+	/* Make sure cache selection is effective for next memory access */
+	dsb();
+
+	get_cache_ways_sets(&cache);	/* Get number of ways & sets */
+	debug("cache: ways= %d, sets= %d\n", cache.ways + 1, cache.sets + 1);
+	for (i = cache.sets; i >= 0; i--) {
+		for (j = cache.ways; j >= 0; j--) {
+			writel((j << WAYS_SHIFT) | (i << SETS_SHIFT),
+			       action_reg);
+		}
+	}
+
+	/* Make sure cache action is effective for next memory access */
+	dsb();
+	isb();	/* Make sure instruction stream sees it */
+
+	return 0;
+}
+
+void dcache_enable(void)
+{
+	if (dcache_status())	/* return if cache already enabled */
+		return;
+
+	if (action_dcache_all(INVALIDATE_SET_WAY)) {
+		printf("ERR: D-cache not enabled\n");
+		return;
+	}
+
+	setbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_DCACHE));
+
+	/* Make sure cache action is effective for next memory access */
+	dsb();
+	isb();	/* Make sure instruction stream sees it */
+}
+
+void dcache_disable(void)
+{
+	if (!dcache_status())
+		return;
+
+	/* if dcache is enabled-> dcache disable & then flush */
+	if (action_dcache_all(FLUSH_SET_WAY)) {
+		printf("ERR: D-cache not flushed\n");
+		return;
+	}
+
+	clrbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_DCACHE));
+
+	/* Make sure cache action is effective for next memory access */
+	dsb();
+	isb();	/* Make sure instruction stream sees it */
+}
+
+int dcache_status(void)
+{
+	return (readl(&V7M_SCB->ccr) & BIT(V7M_CCR_DCACHE)) != 0;
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+	if (action_cache_range(INVALIDATE_POC, start, stop - start)) {
+		printf("ERR: D-cache not invalidated\n");
+		return;
+	}
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+	if (action_cache_range(FLUSH_POC, start, stop - start)) {
+		printf("ERR: D-cache not flushed\n");
+		return;
+	}
+}
+void flush_dcache_all(void)
+{
+	if (action_dcache_all(FLUSH_SET_WAY)) {
+		printf("ERR: D-cache not flushed\n");
+		return;
+	}
+}
+
+void invalidate_dcache_all(void)
+{
+	if (action_dcache_all(INVALIDATE_SET_WAY)) {
+		printf("ERR: D-cache not invalidated\n");
+		return;
+	}
+}
+#else
+void dcache_enable(void)
+{
+	return;
+}
+
+void dcache_disable(void)
+{
+	return;
+}
+
+int dcache_status(void)
+{
+	return 0;
+}
+
+void flush_dcache_all(void)
+{
+}
+
+void invalidate_dcache_all(void)
+{
+}
+#endif
+
+#ifndef CONFIG_SYS_ICACHE_OFF
+
+void invalidate_icache_all(void)
+{
+	writel(INVAL_ICACHE_POU, V7M_CACHE_REG_ICIALLU);
+
+	/* Make sure cache action is effective for next memory access */
+	dsb();
+	isb();	/* Make sure instruction stream sees it */
+}
+
+void icache_enable(void)
+{
+	if (icache_status())
+		return;
+
+	invalidate_icache_all();
+	setbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_ICACHE));
+
+	/* Make sure cache action is effective for next memory access */
+	dsb();
+	isb();	/* Make sure instruction stream sees it */
+}
+
+int icache_status(void)
+{
+	return (readl(&V7M_SCB->ccr) & BIT(V7M_CCR_ICACHE)) != 0;
+}
+
+void icache_disable(void)
+{
+	if (!icache_status())
+		return;
+
+	isb();	/* flush pipeline */
+	clrbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_ICACHE));
+	isb();	/* subsequent instructions fetch see cache disable effect */
+}
+#else
+void icache_enable(void)
+{
+	return;
+}
+
+void icache_disable(void)
+{
+	return;
+}
+
+int icache_status(void)
+{
+	return 0;
+}
+#endif
+
+void enable_caches(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+	icache_enable();
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+	dcache_enable();
+#endif
+}
diff --git a/arch/arm/cpu/armv7m/config.mk b/arch/arm/cpu/armv7m/config.mk
new file mode 100644
index 0000000..f50964c
--- /dev/null
+++ b/arch/arm/cpu/armv7m/config.mk
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2015
+# Kamil Lulko, <kamil.lulko@gmail.com>
+
+PLATFORM_CPPFLAGS += -mno-unaligned-access
diff --git a/arch/arm/cpu/armv7m/cpu.c b/arch/arm/cpu/armv7m/cpu.c
new file mode 100644
index 0000000..55ea078
--- /dev/null
+++ b/arch/arm/cpu/armv7m/cpu.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010,2011
+ * Vladimir Khusainov, Emcraft Systems, vlad@emcraft.com
+ *
+ * (C) Copyright 2015
+ * Kamil Lulko, <kamil.lulko@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/armv7m.h>
+
+/*
+ * This is called right before passing control to
+ * the Linux kernel point.
+ */
+int cleanup_before_linux(void)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * disable interrupt and turn off caches etc ...
+	 */
+	disable_interrupts();
+	/*
+	 * turn off D-cache
+	 * dcache_disable() in turn flushes the d-cache
+	 * MPU is still enabled & can't be disabled as the u-boot
+	 * code might be running in sdram which by default is not
+	 * executable area.
+	 */
+	dcache_disable();
+	/* invalidate to make sure no cache line gets dirty between
+	 * dcache flushing and disabling dcache */
+	invalidate_dcache_all();
+
+	icache_disable();
+	invalidate_icache_all();
+
+	return 0;
+}
+
+/*
+ * Perform the low-level reset.
+ */
+void reset_cpu(ulong addr)
+{
+	/*
+	 * Perform reset but keep priority group unchanged.
+	 */
+	writel((V7M_AIRCR_VECTKEY << V7M_AIRCR_VECTKEY_SHIFT)
+		| (V7M_SCB->aircr & V7M_AIRCR_PRIGROUP_MSK)
+		| V7M_AIRCR_SYSRESET, &V7M_SCB->aircr);
+}
diff --git a/arch/arm/cpu/armv7m/mpu.c b/arch/arm/cpu/armv7m/mpu.c
new file mode 100644
index 0000000..81e7492
--- /dev/null
+++ b/arch/arm/cpu/armv7m/mpu.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#include <linux/bitops.h>
+#include <asm/armv7m.h>
+#include <asm/armv7_mpu.h>
+#include <asm/io.h>
+
+#define V7M_MPU_CTRL_ENABLE		BIT(0)
+#define V7M_MPU_CTRL_DISABLE		(0 << 0)
+#define V7M_MPU_CTRL_HFNMIENA		BIT(1)
+#define V7M_MPU_CTRL_PRIVDEFENA		BIT(2)
+#define VALID_REGION			BIT(4)
+
+void disable_mpu(void)
+{
+	writel(0, &V7M_MPU->ctrl);
+}
+
+void enable_mpu(void)
+{
+	writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_PRIVDEFENA, &V7M_MPU->ctrl);
+
+	/* Make sure new mpu config is effective for next memory access */
+	dsb();
+	isb();	/* Make sure instruction stream sees it */
+}
+
+void mpu_config(struct mpu_region_config *reg_config)
+{
+	uint32_t attr;
+
+	attr = get_attr_encoding(reg_config->mr_attr);
+
+	writel(reg_config->start_addr | VALID_REGION | reg_config->region_no,
+	       &V7M_MPU->rbar);
+
+	writel(reg_config->xn << XN_SHIFT | reg_config->ap << AP_SHIFT | attr
+		| reg_config->reg_size << REGION_SIZE_SHIFT | ENABLE_REGION
+	       , &V7M_MPU->rasr);
+}
diff --git a/arch/arm/cpu/armv7m/start.S b/arch/arm/cpu/armv7m/start.S
new file mode 100644
index 0000000..0c07f21
--- /dev/null
+++ b/arch/arm/cpu/armv7m/start.S
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2015
+ * Kamil Lulko, <kamil.lulko@gmail.com>
+ */
+
+#include <asm/assembler.h>
+
+.globl	reset
+.type reset, %function
+reset:
+	W(b)	_main
+
+.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+	mov	pc, lr
diff --git a/arch/arm/cpu/armv7m/systick-timer.c b/arch/arm/cpu/armv7m/systick-timer.c
new file mode 100644
index 0000000..d04f67a
--- /dev/null
+++ b/arch/arm/cpu/armv7m/systick-timer.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ARM Cortex M3/M4/M7 SysTick timer driver
+ * (C) Copyright 2017 Renesas Electronics Europe Ltd
+ *
+ * Based on arch/arm/mach-stm32/stm32f1/timer.c
+ * (C) Copyright 2015
+ * Kamil Lulko, <kamil.lulko@gmail.com>
+ *
+ * Copyright 2015 ATS Advanced Telematics Systems GmbH
+ * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
+ *
+ * The SysTick timer is a 24-bit count down timer. The clock can be either the
+ * CPU clock or a reference clock. Since the timer will wrap around very quickly
+ * when using the CPU clock, and we do not handle the timer interrupts, it is
+ * expected that this driver is only ever used with a slow reference clock.
+ *
+ * The number of reference clock ticks that correspond to 10ms is normally
+ * defined in the SysTick Calibration register's TENMS field. However, on some
+ * devices this is wrong, so this driver allows the clock rate to be defined
+ * using CONFIG_SYS_HZ_CLOCK.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* SysTick Base Address - fixed for all Cortex M3, M4 and M7 devices */
+#define SYSTICK_BASE		0xE000E010
+
+struct cm3_systick {
+	uint32_t ctrl;
+	uint32_t reload_val;
+	uint32_t current_val;
+	uint32_t calibration;
+};
+
+#define TIMER_MAX_VAL		0x00FFFFFF
+#define SYSTICK_CTRL_EN		BIT(0)
+/* Clock source: 0 = Ref clock, 1 = CPU clock */
+#define SYSTICK_CTRL_CPU_CLK	BIT(2)
+#define SYSTICK_CAL_NOREF	BIT(31)
+#define SYSTICK_CAL_SKEW	BIT(30)
+#define SYSTICK_CAL_TENMS_MASK	0x00FFFFFF
+
+/* read the 24-bit timer */
+static ulong read_timer(void)
+{
+	struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
+
+	/* The timer counts down, therefore convert to an incrementing timer */
+	return TIMER_MAX_VAL - readl(&systick->current_val);
+}
+
+int timer_init(void)
+{
+	struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
+	u32 cal;
+
+	writel(TIMER_MAX_VAL, &systick->reload_val);
+	/* Any write to current_val reg clears it to 0 */
+	writel(0, &systick->current_val);
+
+	cal = readl(&systick->calibration);
+	if (cal & SYSTICK_CAL_NOREF)
+		/* Use CPU clock, no interrupts */
+		writel(SYSTICK_CTRL_EN | SYSTICK_CTRL_CPU_CLK, &systick->ctrl);
+	else
+		/* Use external clock, no interrupts */
+		writel(SYSTICK_CTRL_EN, &systick->ctrl);
+
+	/*
+	 * If the TENMS field is inexact or wrong, specify the clock rate using
+	 * CONFIG_SYS_HZ_CLOCK.
+	 */
+#if defined(CONFIG_SYS_HZ_CLOCK)
+	gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK;
+#else
+	gd->arch.timer_rate_hz = (cal & SYSTICK_CAL_TENMS_MASK) * 100;
+#endif
+
+	gd->arch.tbl = 0;
+	gd->arch.tbu = 0;
+	gd->arch.lastinc = read_timer();
+
+	return 0;
+}
+
+/* return milli-seconds timer value */
+ulong get_timer(ulong base)
+{
+	unsigned long long t = get_ticks() * 1000;
+
+	return (ulong)((t / gd->arch.timer_rate_hz)) - base;
+}
+
+unsigned long long get_ticks(void)
+{
+	u32 now = read_timer();
+
+	if (now >= gd->arch.lastinc)
+		gd->arch.tbl += (now - gd->arch.lastinc);
+	else
+		gd->arch.tbl += (TIMER_MAX_VAL - gd->arch.lastinc) + now;
+
+	gd->arch.lastinc = now;
+
+	return gd->arch.tbl;
+}
+
+ulong get_tbclk(void)
+{
+	return gd->arch.timer_rate_hz;
+}
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
new file mode 100644
index 0000000..d5a9158
--- /dev/null
+++ b/arch/arm/cpu/armv8/Kconfig
@@ -0,0 +1,169 @@
+if ARM64
+
+config ARMV8_SPL_EXCEPTION_VECTORS
+	bool "Install crash dump exception vectors"
+	depends on SPL
+	default y
+	help
+	  The default exception vector table is only used for the crash
+	  dump, but still takes quite a lot of space in the image size.
+
+	  Say N here if you are running out of code space in the image
+	  and want to save some space at the cost of less debugging info.
+
+config ARMV8_MULTIENTRY
+        bool "Enable multiple CPUs to enter into U-Boot"
+
+config ARMV8_SET_SMPEN
+        bool "Enable data coherency with other cores in cluster"
+        help
+	  Say Y here if there is not any trust firmware to set
+	  CPUECTLR_EL1.SMPEN bit before U-Boot.
+
+	  For A53, it enables data coherency with other cores in the
+	  cluster, and for A57/A72, it enables receiving of instruction
+	  cache and TLB maintenance operations.
+	  Cortex A53/57/72 cores require CPUECTLR_EL1.SMPEN set even
+	  for single core systems. Unfortunately write access to this
+	  register may be controlled by EL3/EL2 firmware. To be more
+	  precise, by default (if there is EL2/EL3 firmware running)
+	  this register is RO for NS EL1.
+	  This switch can be used to avoid writing to CPUECTLR_EL1,
+	  it can be safely enabled when EL2/EL3 initialized SMPEN bit
+	  or when CPU implementation doesn't include that register.
+
+config ARMV8_SPIN_TABLE
+	bool "Support spin-table enable method"
+	depends on ARMV8_MULTIENTRY && OF_LIBFDT
+	help
+	  Say Y here to support "spin-table" enable method for booting Linux.
+
+	  To use this feature, you must do:
+	    - Specify enable-method = "spin-table" in each CPU node in the
+	      Device Tree you are using to boot the kernel
+	    - Bring secondary CPUs into U-Boot proper in a board specific
+	      manner.  This must be done *after* relocation.  Otherwise, the
+	      secondary CPUs will spin in unprotected memory area because the
+	      master CPU protects the relocated spin code.
+
+	  U-Boot automatically does:
+	    - Set "cpu-release-addr" property of each CPU node
+	      (overwrites it if already exists).
+	    - Reserve the code for the spin-table and the release address
+	      via a /memreserve/ region in the Device Tree.
+
+menu "ARMv8 secure monitor firmware"
+config ARMV8_SEC_FIRMWARE_SUPPORT
+	bool "Enable ARMv8 secure monitor firmware framework support"
+	select FIT
+	select OF_LIBFDT
+	help
+	  This framework is aimed at making secure monitor firmware load
+	  process brief.
+	  Note: Only FIT format image is supported.
+	  You should prepare and provide the below information:
+	    - Address of secure firmware.
+	    - Address to hold the return address from secure firmware.
+	    - Secure firmware FIT image related information.
+	      Such as: SEC_FIRMWARE_FIT_IMAGE and SEC_FIRMEWARE_FIT_CNF_NAME
+	    - The target exception level that secure monitor firmware will
+	      return to.
+
+config SPL_ARMV8_SEC_FIRMWARE_SUPPORT
+	bool "Enable ARMv8 secure monitor firmware framework support for SPL"
+	select SPL_FIT
+	select SPL_OF_LIBFDT
+	help
+	  Say Y here to support this framework in SPL phase.
+
+config SEC_FIRMWARE_ARMV8_PSCI
+	bool "PSCI implementation in secure monitor firmware"
+	depends on ARMV8_SEC_FIRMWARE_SUPPORT || SPL_ARMV8_SEC_FIRMWARE_SUPPORT
+	help
+	  This config enables the ARMv8 PSCI implementation in secure monitor
+	  firmware. This is a private PSCI implementation and different from
+	  those implemented under the common ARMv8 PSCI framework.
+
+config ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT
+	bool "ARMv8 secure monitor firmware ERET address byteorder swap"
+	depends on ARMV8_SEC_FIRMWARE_SUPPORT || SPL_ARMV8_SEC_FIRMWARE_SUPPORT
+	help
+	  Say Y here when the endianness of the register or memory holding the
+	  Secure firmware exception return address is different with core's.
+
+endmenu
+
+config PSCI_RESET
+	bool "Use PSCI for reset and shutdown"
+	default n
+	select ARM_SMCCC if OF_CONTROL
+	depends on !ARCH_EXYNOS7 && !ARCH_BCM283X && \
+		   !TARGET_LS2080A_SIMU && !TARGET_LS2080AQDS && \
+		   !TARGET_LS2080ARDB && !TARGET_LS2080A_EMU && \
+		   !TARGET_LS1088ARDB && !TARGET_LS1088AQDS && \
+		   !TARGET_LS1012ARDB && !TARGET_LS1012AFRDM && \
+		   !TARGET_LS1012A2G5RDB && !TARGET_LS1012AQDS && \
+		   !TARGET_LS1012AFRWY && \
+		   !TARGET_LS1043ARDB && !TARGET_LS1043AQDS && \
+		   !TARGET_LS1046ARDB && !TARGET_LS1046AQDS && \
+		   !TARGET_LS2081ARDB && \
+		   !ARCH_UNIPHIER && !TARGET_S32V234EVB
+	help
+	  Most armv8 systems have PSCI support enabled in EL3, either through
+	  ARM Trusted Firmware or other firmware.
+
+	  On these systems, we do not need to implement system reset manually,
+	  but can instead rely on higher level firmware to deal with it.
+
+	  Select Y here to make use of PSCI calls for system reset
+
+config ARMV8_PSCI
+	bool "Enable PSCI support" if EXPERT
+	default n
+	help
+	  PSCI is Power State Coordination Interface defined by ARM.
+	  The PSCI in U-boot provides a general framework and each platform
+	  can implement their own specific PSCI functions.
+	  Say Y here to enable PSCI support on ARMv8 platform.
+
+config ARMV8_PSCI_NR_CPUS
+	int "Maximum supported CPUs for PSCI"
+	depends on ARMV8_PSCI
+	default 4
+	help
+	  The maximum number of CPUs supported in the PSCI firmware.
+	  It is no problem to set a larger value than the number of CPUs in
+	  the actual hardware implementation.
+
+config ARMV8_PSCI_CPUS_PER_CLUSTER
+	int "Number of CPUs per cluster"
+	depends on ARMV8_PSCI
+	default 0
+	help
+	  The number of CPUs per cluster, suppose each cluster has same number
+	  of CPU cores, platforms with asymmetric clusters don't apply here.
+	  A value 0 or no definition of it works for single cluster system.
+	  System with multi-cluster should difine their own exact value.
+
+config ARMV8_EA_EL3_FIRST
+	bool "External aborts and SError interrupt exception are taken in EL3"
+	default n
+	help
+	  Exception handling at all exception levels for External Abort and
+	  SError interrupt exception are taken in EL3.
+
+if SYS_HAS_ARMV8_SECURE_BASE
+
+config ARMV8_SECURE_BASE
+	hex "Secure address for PSCI image"
+	depends on ARMV8_PSCI
+	help
+	  Address for placing the PSCI text, data and stack sections.
+	  If not defined, the PSCI sections are placed together with the u-boot
+	  but platform can choose to place PSCI code image separately in other
+	  places such as some secure RAM built-in SOC etc.
+
+endif
+
+endif
+
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
new file mode 100644
index 0000000..a807d1f
--- /dev/null
+++ b/arch/arm/cpu/armv8/Makefile
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	:= start.o
+
+obj-y	+= cpu.o
+ifndef CONFIG_$(SPL_TPL_)TIMER
+obj-$(CONFIG_SYS_ARCH_TIMER) += generic_timer.o
+endif
+obj-y	+= cache_v8.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) += exceptions.o
+else
+obj-y	+= exceptions.o
+endif
+obj-y	+= cache.o
+obj-y	+= tlb.o
+obj-y	+= transition.o
+obj-y	+= fwcall.o
+obj-y	+= cpu-dt.o
+obj-$(CONFIG_ARM_SMCCC)		+= smccc-call.o
+
+obj-y	+= a32_kernel_pre_entry.o
+
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
+endif
+obj-$(CONFIG_$(SPL_)ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o
+
+obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/
+obj-$(CONFIG_S32V234) += s32v234/
+obj-$(CONFIG_ARCH_ZYNQMP) += zynqmp/
+obj-$(CONFIG_TARGET_HIKEY) += hisilicon/
+obj-$(CONFIG_ARMV8_PSCI) += psci.o
+obj-$(CONFIG_ARCH_SUNXI) += lowlevel_init.o
diff --git a/arch/arm/cpu/armv8/a32_kernel_pre_entry.S b/arch/arm/cpu/armv8/a32_kernel_pre_entry.S
new file mode 100644
index 0000000..ac4220e
--- /dev/null
+++ b/arch/arm/cpu/armv8/a32_kernel_pre_entry.S
@@ -0,0 +1,85 @@
+#include <asm-offsets.h>
+#include <config.h>
+#include <version.h>
+#include <asm/macro.h>
+#include <linux/linkage.h>
+
+#define HCR_RW		(1 << 31)
+#define HCR_TGE		(1 << 27)
+#define HCR_E2H		(1 << 34)
+
+
+/* AArch32 SPSR*/
+#define AARCH32_SPSR_MODE      (3 << 0)
+#define AARCH32_SPSR_STATE     (1 << 4)
+#define AARCH32_SPSR_DAIF      (7 << 6)
+
+/*
+ * void jump_to_a32_kernel(kernel_ep, machid, dtb pointer)
+*/
+ENTRY(jump_to_a32_kernel)
+	mov x20, x0
+	mov x21, x1
+	mov x22, x2
+
+	mrs	x0, sctlr_el2
+	bic	x0, x0, #(1 << 25)
+	msr	sctlr_el2, x0
+
+	mov	x2, xzr
+
+	/* sctlr_el1 */
+	mov	x0, #0x0878			// Set/clear RES{1,0} bits
+	movk	x0, #0x00c5, lsl #16	// Clear EE and E0E on LE systems
+	msr	sctlr_el1, x0
+
+#if 0
+	/* Generic timers. */
+	mrs	x0, cnthctl_el2
+	orr	x0, x0, #3			// Enable EL1 physical timers
+	msr	cnthctl_el2, x0
+	msr	cntvoff_el2, xzr		// Clear virtual offset
+
+	/* Populate ID registers. */
+	mrs	x0, midr_el1
+	mrs	x1, mpidr_el1
+	msr	vpidr_el2, x0
+	msr	vmpidr_el2, x1
+
+	/* Coprocessor traps. */
+	mov	x0, #0x33ff
+	msr	cptr_el2, x0			// Disable copro. traps to EL2
+
+	msr	hstr_el2, xzr			// Disable CP15 traps to EL2
+
+	/* EL2 debug */
+	mrs	x0, id_aa64dfr0_el1		// Check ID_AA64DFR0_EL1 PMUVer
+	sbfx	x0, x0, #8, #4
+	cmp	x0, #1
+	b.lt	4f				// Skip if no PMU present
+	mrs	x0, pmcr_el0			// Disable debug access traps
+	ubfx	x0, x0, #11, #5			// to EL2 and allow access to
+4:
+	csel	x0, xzr, x0, lt			// all PMU counters from EL1
+	msr	mdcr_el2, x0			// (if they exist)
+
+	/* Stage-2 translation */
+	msr	vttbr_el2, xzr
+#endif
+
+	/* Hyp configuration. */
+	mov	x0, #0			// 32-bit EL1 HCR_EL2.RW=0
+	msr	hcr_el2, x0
+	isb
+
+	/* spsr */
+	mov x0, #(AARCH32_SPSR_MODE | \
+				AARCH32_SPSR_STATE  | \
+				AARCH32_SPSR_DAIF)
+	msr	spsr_el2, x0
+	msr	elr_el2, x20
+	mov x0, #0
+	mov x1, x21
+	mov x2, x22
+	eret
+ENDPROC(jump_to_a32_kernel)
diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
new file mode 100644
index 0000000..443d94c
--- /dev/null
+++ b/arch/arm/cpu/armv8/cache.S
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ *
+ * This file is based on sample code from ARMv8 ARM.
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/macro.h>
+#include <asm/system.h>
+#include <linux/linkage.h>
+
+/*
+ * void __asm_dcache_level(level)
+ *
+ * flush or invalidate one level cache.
+ *
+ * x0: cache level
+ * x1: 0 clean & invalidate, 1 invalidate only
+ * x2~x9: clobbered
+ */
+.pushsection .text.__asm_dcache_level, "ax"
+ENTRY(__asm_dcache_level)
+	lsl	x12, x0, #1
+	msr	csselr_el1, x12		/* select cache level */
+	isb				/* sync change of cssidr_el1 */
+	mrs	x6, ccsidr_el1		/* read the new cssidr_el1 */
+	and	x2, x6, #7		/* x2 <- log2(cache line size)-4 */
+	add	x2, x2, #4		/* x2 <- log2(cache line size) */
+	mov	x3, #0x3ff
+	and	x3, x3, x6, lsr #3	/* x3 <- max number of #ways */
+	clz	w5, w3			/* bit position of #ways */
+	mov	x4, #0x7fff
+	and	x4, x4, x6, lsr #13	/* x4 <- max number of #sets */
+	/* x12 <- cache level << 1 */
+	/* x2 <- line length offset */
+	/* x3 <- number of cache ways - 1 */
+	/* x4 <- number of cache sets - 1 */
+	/* x5 <- bit position of #ways */
+
+loop_set:
+	mov	x6, x3			/* x6 <- working copy of #ways */
+loop_way:
+	lsl	x7, x6, x5
+	orr	x9, x12, x7		/* map way and level to cisw value */
+	lsl	x7, x4, x2
+	orr	x9, x9, x7		/* map set number to cisw value */
+	tbz	w1, #0, 1f
+	dc	isw, x9
+	b	2f
+1:	dc	cisw, x9		/* clean & invalidate by set/way */
+2:	subs	x6, x6, #1		/* decrement the way */
+	b.ge	loop_way
+	subs	x4, x4, #1		/* decrement the set */
+	b.ge	loop_set
+
+	ret
+ENDPROC(__asm_dcache_level)
+.popsection
+
+/*
+ * void __asm_flush_dcache_all(int invalidate_only)
+ *
+ * x0: 0 clean & invalidate, 1 invalidate only
+ *
+ * flush or invalidate all data cache by SET/WAY.
+ */
+.pushsection .text.__asm_dcache_all, "ax"
+ENTRY(__asm_dcache_all)
+	mov	x1, x0
+	dsb	sy
+	mrs	x10, clidr_el1		/* read clidr_el1 */
+	lsr	x11, x10, #24
+	and	x11, x11, #0x7		/* x11 <- loc */
+	cbz	x11, finished		/* if loc is 0, exit */
+	mov	x15, lr
+	mov	x0, #0			/* start flush at cache level 0 */
+	/* x0  <- cache level */
+	/* x10 <- clidr_el1 */
+	/* x11 <- loc */
+	/* x15 <- return address */
+
+loop_level:
+	lsl	x12, x0, #1
+	add	x12, x12, x0		/* x0 <- tripled cache level */
+	lsr	x12, x10, x12
+	and	x12, x12, #7		/* x12 <- cache type */
+	cmp	x12, #2
+	b.lt	skip			/* skip if no cache or icache */
+	bl	__asm_dcache_level	/* x1 = 0 flush, 1 invalidate */
+skip:
+	add	x0, x0, #1		/* increment cache level */
+	cmp	x11, x0
+	b.gt	loop_level
+
+	mov	x0, #0
+	msr	csselr_el1, x0		/* restore csselr_el1 */
+	dsb	sy
+	isb
+	mov	lr, x15
+
+finished:
+	ret
+ENDPROC(__asm_dcache_all)
+.popsection
+
+.pushsection .text.__asm_flush_dcache_all, "ax"
+ENTRY(__asm_flush_dcache_all)
+	mov	x0, #0
+	b	__asm_dcache_all
+ENDPROC(__asm_flush_dcache_all)
+.popsection
+
+.pushsection .text.__asm_invalidate_dcache_all, "ax"
+ENTRY(__asm_invalidate_dcache_all)
+	mov	x0, #0x1
+	b	__asm_dcache_all
+ENDPROC(__asm_invalidate_dcache_all)
+.popsection
+
+/*
+ * void __asm_flush_dcache_range(start, end)
+ *
+ * clean & invalidate data cache in the range
+ *
+ * x0: start address
+ * x1: end address
+ */
+.pushsection .text.__asm_flush_dcache_range, "ax"
+ENTRY(__asm_flush_dcache_range)
+	mrs	x3, ctr_el0
+	lsr	x3, x3, #16
+	and	x3, x3, #0xf
+	mov	x2, #4
+	lsl	x2, x2, x3		/* cache line size */
+
+	/* x2 <- minimal cache line size in cache system */
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+1:	dc	civac, x0	/* clean & invalidate data or unified cache */
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	ret
+ENDPROC(__asm_flush_dcache_range)
+.popsection
+/*
+ * void __asm_invalidate_dcache_range(start, end)
+ *
+ * invalidate data cache in the range
+ *
+ * x0: start address
+ * x1: end address
+ */
+.pushsection .text.__asm_invalidate_dcache_range, "ax"
+ENTRY(__asm_invalidate_dcache_range)
+	mrs	x3, ctr_el0
+	ubfm	x3, x3, #16, #19
+	mov	x2, #4
+	lsl	x2, x2, x3		/* cache line size */
+
+	/* x2 <- minimal cache line size in cache system */
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+1:	dc	ivac, x0	/* invalidate data or unified cache */
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	ret
+ENDPROC(__asm_invalidate_dcache_range)
+.popsection
+
+/*
+ * void __asm_invalidate_icache_all(void)
+ *
+ * invalidate all tlb entries.
+ */
+.pushsection .text.__asm_invalidate_icache_all, "ax"
+ENTRY(__asm_invalidate_icache_all)
+	ic	ialluis
+	isb	sy
+	ret
+ENDPROC(__asm_invalidate_icache_all)
+.popsection
+
+.pushsection .text.__asm_invalidate_l3_dcache, "ax"
+ENTRY(__asm_invalidate_l3_dcache)
+	mov	x0, #0			/* return status as success */
+	ret
+ENDPROC(__asm_invalidate_l3_dcache)
+	.weak	__asm_invalidate_l3_dcache
+.popsection
+
+.pushsection .text.__asm_flush_l3_dcache, "ax"
+ENTRY(__asm_flush_l3_dcache)
+	mov	x0, #0			/* return status as success */
+	ret
+ENDPROC(__asm_flush_l3_dcache)
+	.weak	__asm_flush_l3_dcache
+.popsection
+
+.pushsection .text.__asm_invalidate_l3_icache, "ax"
+ENTRY(__asm_invalidate_l3_icache)
+	mov	x0, #0			/* return status as success */
+	ret
+ENDPROC(__asm_invalidate_l3_icache)
+	.weak	__asm_invalidate_l3_icache
+.popsection
+
+/*
+ * void __asm_switch_ttbr(ulong new_ttbr)
+ *
+ * Safely switches to a new page table.
+ */
+.pushsection .text.__asm_switch_ttbr, "ax"
+ENTRY(__asm_switch_ttbr)
+	/* x2 = SCTLR (alive throghout the function) */
+	switch_el x4, 3f, 2f, 1f
+3:	mrs	x2, sctlr_el3
+	b	0f
+2:	mrs	x2, sctlr_el2
+	b	0f
+1:	mrs	x2, sctlr_el1
+0:
+
+	/* Unset CR_M | CR_C | CR_I from SCTLR to disable all caches */
+	movn	x1, #(CR_M | CR_C | CR_I)
+	and	x1, x2, x1
+	switch_el x4, 3f, 2f, 1f
+3:	msr	sctlr_el3, x1
+	b	0f
+2:	msr	sctlr_el2, x1
+	b	0f
+1:	msr	sctlr_el1, x1
+0:	isb
+
+	/* This call only clobbers x30 (lr) and x9 (unused) */
+	mov	x3, x30
+	bl	__asm_invalidate_tlb_all
+
+	/* From here on we're running safely with caches disabled */
+
+	/* Set TTBR to our first argument */
+	switch_el x4, 3f, 2f, 1f
+3:	msr	ttbr0_el3, x0
+	b	0f
+2:	msr	ttbr0_el2, x0
+	b	0f
+1:	msr	ttbr0_el1, x0
+0:	isb
+
+	/* Restore original SCTLR and thus enable caches again */
+	switch_el x4, 3f, 2f, 1f
+3:	msr	sctlr_el3, x2
+	b	0f
+2:	msr	sctlr_el2, x2
+	b	0f
+1:	msr	sctlr_el1, x2
+0:	isb
+
+	ret	x3
+ENDPROC(__asm_switch_ttbr)
+.popsection
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
new file mode 100644
index 0000000..0384051
--- /dev/null
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -0,0 +1,742 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ *
+ * (C) Copyright 2016
+ * Alexander Graf <agraf@suse.de>
+ */
+
+#include <common.h>
+#include <asm/system.h>
+#include <asm/armv8/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+
+/*
+ *  With 4k page granule, a virtual address is split into 4 lookup parts
+ *  spanning 9 bits each:
+ *
+ *    _______________________________________________
+ *   |       |       |       |       |       |       |
+ *   |   0   |  Lv0  |  Lv1  |  Lv2  |  Lv3  |  off  |
+ *   |_______|_______|_______|_______|_______|_______|
+ *     63-48   47-39   38-30   29-21   20-12   11-00
+ *
+ *             mask        page size
+ *
+ *    Lv0: FF8000000000       --
+ *    Lv1:   7FC0000000       1G
+ *    Lv2:     3FE00000       2M
+ *    Lv3:       1FF000       4K
+ *    off:          FFF
+ */
+
+u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
+{
+	u64 max_addr = 0;
+	u64 ips, va_bits;
+	u64 tcr;
+	int i;
+
+	/* Find the largest address we need to support */
+	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++)
+		max_addr = max(max_addr, mem_map[i].virt + mem_map[i].size);
+
+	/* Calculate the maximum physical (and thus virtual) address */
+	if (max_addr > (1ULL << 44)) {
+		ips = 5;
+		va_bits = 48;
+	} else  if (max_addr > (1ULL << 42)) {
+		ips = 4;
+		va_bits = 44;
+	} else  if (max_addr > (1ULL << 40)) {
+		ips = 3;
+		va_bits = 42;
+	} else  if (max_addr > (1ULL << 36)) {
+		ips = 2;
+		va_bits = 40;
+	} else  if (max_addr > (1ULL << 32)) {
+		ips = 1;
+		va_bits = 36;
+	} else {
+		ips = 0;
+		va_bits = 32;
+	}
+
+	if (el == 1) {
+		tcr = TCR_EL1_RSVD | (ips << 32) | TCR_EPD1_DISABLE;
+	} else if (el == 2) {
+		tcr = TCR_EL2_RSVD | (ips << 16);
+	} else {
+		tcr = TCR_EL3_RSVD | (ips << 16);
+	}
+
+	/* PTWs cacheable, inner/outer WBWA and inner shareable */
+	tcr |= TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA;
+	tcr |= TCR_T0SZ(va_bits);
+
+	if (pips)
+		*pips = ips;
+	if (pva_bits)
+		*pva_bits = va_bits;
+
+	return tcr;
+}
+
+#define MAX_PTE_ENTRIES 512
+
+static int pte_type(u64 *pte)
+{
+	return *pte & PTE_TYPE_MASK;
+}
+
+/* Returns the LSB number for a PTE on level <level> */
+static int level2shift(int level)
+{
+	/* Page is 12 bits wide, every level translates 9 bits */
+	return (12 + 9 * (3 - level));
+}
+
+static u64 *find_pte(u64 addr, int level)
+{
+	int start_level = 0;
+	u64 *pte;
+	u64 idx;
+	u64 va_bits;
+	int i;
+
+	debug("addr=%llx level=%d\n", addr, level);
+
+	get_tcr(0, NULL, &va_bits);
+	if (va_bits < 39)
+		start_level = 1;
+
+	if (level < start_level)
+		return NULL;
+
+	/* Walk through all page table levels to find our PTE */
+	pte = (u64*)gd->arch.tlb_addr;
+	for (i = start_level; i < 4; i++) {
+		idx = (addr >> level2shift(i)) & 0x1FF;
+		pte += idx;
+		debug("idx=%llx PTE %p at level %d: %llx\n", idx, pte, i, *pte);
+
+		/* Found it */
+		if (i == level)
+			return pte;
+		/* PTE is no table (either invalid or block), can't traverse */
+		if (pte_type(pte) != PTE_TYPE_TABLE)
+			return NULL;
+		/* Off to the next level */
+		pte = (u64*)(*pte & 0x0000fffffffff000ULL);
+	}
+
+	/* Should never reach here */
+	return NULL;
+}
+
+/* Returns and creates a new full table (512 entries) */
+static u64 *create_table(void)
+{
+	u64 *new_table = (u64*)gd->arch.tlb_fillptr;
+	u64 pt_len = MAX_PTE_ENTRIES * sizeof(u64);
+
+	/* Allocate MAX_PTE_ENTRIES pte entries */
+	gd->arch.tlb_fillptr += pt_len;
+
+	if (gd->arch.tlb_fillptr - gd->arch.tlb_addr > gd->arch.tlb_size)
+		panic("Insufficient RAM for page table: 0x%lx > 0x%lx. "
+		      "Please increase the size in get_page_table_size()",
+			gd->arch.tlb_fillptr - gd->arch.tlb_addr,
+			gd->arch.tlb_size);
+
+	/* Mark all entries as invalid */
+	memset(new_table, 0, pt_len);
+
+	return new_table;
+}
+
+static void set_pte_table(u64 *pte, u64 *table)
+{
+	/* Point *pte to the new table */
+	debug("Setting %p to addr=%p\n", pte, table);
+	*pte = PTE_TYPE_TABLE | (ulong)table;
+}
+
+/* Splits a block PTE into table with subpages spanning the old block */
+static void split_block(u64 *pte, int level)
+{
+	u64 old_pte = *pte;
+	u64 *new_table;
+	u64 i = 0;
+	/* level describes the parent level, we need the child ones */
+	int levelshift = level2shift(level + 1);
+
+	if (pte_type(pte) != PTE_TYPE_BLOCK)
+		panic("PTE %p (%llx) is not a block. Some driver code wants to "
+		      "modify dcache settings for an range not covered in "
+		      "mem_map.", pte, old_pte);
+
+	new_table = create_table();
+	debug("Splitting pte %p (%llx) into %p\n", pte, old_pte, new_table);
+
+	for (i = 0; i < MAX_PTE_ENTRIES; i++) {
+		new_table[i] = old_pte | (i << levelshift);
+
+		/* Level 3 block PTEs have the table type */
+		if ((level + 1) == 3)
+			new_table[i] |= PTE_TYPE_TABLE;
+
+		debug("Setting new_table[%lld] = %llx\n", i, new_table[i]);
+	}
+
+	/* Set the new table into effect */
+	set_pte_table(pte, new_table);
+}
+
+/* Add one mm_region map entry to the page tables */
+static void add_map(struct mm_region *map)
+{
+	u64 *pte;
+	u64 virt = map->virt;
+	u64 phys = map->phys;
+	u64 size = map->size;
+	u64 attrs = map->attrs | PTE_TYPE_BLOCK | PTE_BLOCK_AF;
+	u64 blocksize;
+	int level;
+	u64 *new_table;
+
+	while (size) {
+		pte = find_pte(virt, 0);
+		if (pte && (pte_type(pte) == PTE_TYPE_FAULT)) {
+			debug("Creating table for virt 0x%llx\n", virt);
+			new_table = create_table();
+			set_pte_table(pte, new_table);
+		}
+
+		for (level = 1; level < 4; level++) {
+			pte = find_pte(virt, level);
+			if (!pte)
+				panic("pte not found\n");
+
+			blocksize = 1ULL << level2shift(level);
+			debug("Checking if pte fits for virt=%llx size=%llx blocksize=%llx\n",
+			      virt, size, blocksize);
+			if (size >= blocksize && !(virt & (blocksize - 1))) {
+				/* Page fits, create block PTE */
+				debug("Setting PTE %p to block virt=%llx\n",
+				      pte, virt);
+				if (level == 3)
+					*pte = phys | attrs | PTE_TYPE_PAGE;
+				else
+					*pte = phys | attrs;
+				virt += blocksize;
+				phys += blocksize;
+				size -= blocksize;
+				break;
+			} else if (pte_type(pte) == PTE_TYPE_FAULT) {
+				/* Page doesn't fit, create subpages */
+				debug("Creating subtable for virt 0x%llx blksize=%llx\n",
+				      virt, blocksize);
+				new_table = create_table();
+				set_pte_table(pte, new_table);
+			} else if (pte_type(pte) == PTE_TYPE_BLOCK) {
+				debug("Split block into subtable for virt 0x%llx blksize=0x%llx\n",
+				      virt, blocksize);
+				split_block(pte, level);
+			}
+		}
+	}
+}
+
+enum pte_type {
+	PTE_INVAL,
+	PTE_BLOCK,
+	PTE_LEVEL,
+};
+
+/*
+ * This is a recursively called function to count the number of
+ * page tables we need to cover a particular PTE range. If you
+ * call this with level = -1 you basically get the full 48 bit
+ * coverage.
+ */
+static int count_required_pts(u64 addr, int level, u64 maxaddr)
+{
+	int levelshift = level2shift(level);
+	u64 levelsize = 1ULL << levelshift;
+	u64 levelmask = levelsize - 1;
+	u64 levelend = addr + levelsize;
+	int r = 0;
+	int i;
+	enum pte_type pte_type = PTE_INVAL;
+
+	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++) {
+		struct mm_region *map = &mem_map[i];
+		u64 start = map->virt;
+		u64 end = start + map->size;
+
+		/* Check if the PTE would overlap with the map */
+		if (max(addr, start) <= min(levelend, end)) {
+			start = max(addr, start);
+			end = min(levelend, end);
+
+			/* We need a sub-pt for this level */
+			if ((start & levelmask) || (end & levelmask)) {
+				pte_type = PTE_LEVEL;
+				break;
+			}
+
+			/* Lv0 can not do block PTEs, so do levels here too */
+			if (level <= 0) {
+				pte_type = PTE_LEVEL;
+				break;
+			}
+
+			/* PTE is active, but fits into a block */
+			pte_type = PTE_BLOCK;
+		}
+	}
+
+	/*
+	 * Block PTEs at this level are already covered by the parent page
+	 * table, so we only need to count sub page tables.
+	 */
+	if (pte_type == PTE_LEVEL) {
+		int sublevel = level + 1;
+		u64 sublevelsize = 1ULL << level2shift(sublevel);
+
+		/* Account for the new sub page table ... */
+		r = 1;
+
+		/* ... and for all child page tables that one might have */
+		for (i = 0; i < MAX_PTE_ENTRIES; i++) {
+			r += count_required_pts(addr, sublevel, maxaddr);
+			addr += sublevelsize;
+
+			if (addr >= maxaddr) {
+				/*
+				 * We reached the end of address space, no need
+				 * to look any further.
+				 */
+				break;
+			}
+		}
+	}
+
+	return r;
+}
+
+/* Returns the estimated required size of all page tables */
+__weak u64 get_page_table_size(void)
+{
+	u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
+	u64 size = 0;
+	u64 va_bits;
+	int start_level = 0;
+
+	get_tcr(0, NULL, &va_bits);
+	if (va_bits < 39)
+		start_level = 1;
+
+	/* Account for all page tables we would need to cover our memory map */
+	size = one_pt * count_required_pts(0, start_level - 1, 1ULL << va_bits);
+
+	/*
+	 * We need to duplicate our page table once to have an emergency pt to
+	 * resort to when splitting page tables later on
+	 */
+	size *= 2;
+
+	/*
+	 * We may need to split page tables later on if dcache settings change,
+	 * so reserve up to 4 (random pick) page tables for that.
+	 */
+	size += one_pt * 4;
+
+	return size;
+}
+
+void setup_pgtables(void)
+{
+	int i;
+
+	if (!gd->arch.tlb_fillptr || !gd->arch.tlb_addr)
+		panic("Page table pointer not setup.");
+
+	/*
+	 * Allocate the first level we're on with invalidate entries.
+	 * If the starting level is 0 (va_bits >= 39), then this is our
+	 * Lv0 page table, otherwise it's the entry Lv1 page table.
+	 */
+	create_table();
+
+	/* Now add all MMU table entries one after another to the table */
+	for (i = 0; mem_map[i].size || mem_map[i].attrs; i++)
+		add_map(&mem_map[i]);
+}
+
+static void setup_all_pgtables(void)
+{
+	u64 tlb_addr = gd->arch.tlb_addr;
+	u64 tlb_size = gd->arch.tlb_size;
+
+	/* Reset the fill ptr */
+	gd->arch.tlb_fillptr = tlb_addr;
+
+	/* Create normal system page tables */
+	setup_pgtables();
+
+	/* Create emergency page tables */
+	gd->arch.tlb_size -= (uintptr_t)gd->arch.tlb_fillptr -
+			     (uintptr_t)gd->arch.tlb_addr;
+	gd->arch.tlb_addr = gd->arch.tlb_fillptr;
+	setup_pgtables();
+	gd->arch.tlb_emerg = gd->arch.tlb_addr;
+	gd->arch.tlb_addr = tlb_addr;
+	gd->arch.tlb_size = tlb_size;
+}
+
+/* to activate the MMU we need to set up virtual memory */
+__weak void mmu_setup(void)
+{
+	int el;
+
+	/* Set up page tables only once */
+	if (!gd->arch.tlb_fillptr)
+		setup_all_pgtables();
+
+	el = current_el();
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
+			  MEMORY_ATTRIBUTES);
+
+	/* enable the mmu */
+	set_sctlr(get_sctlr() | CR_M);
+}
+
+/*
+ * Performs a invalidation of the entire data cache at all levels
+ */
+void invalidate_dcache_all(void)
+{
+	__asm_invalidate_dcache_all();
+	__asm_invalidate_l3_dcache();
+}
+
+/*
+ * Performs a clean & invalidation of the entire data cache at all levels.
+ * This function needs to be inline to avoid using stack.
+ * __asm_flush_l3_dcache return status of timeout
+ */
+inline void flush_dcache_all(void)
+{
+	int ret;
+
+	__asm_flush_dcache_all();
+	ret = __asm_flush_l3_dcache();
+	if (ret)
+		debug("flushing dcache returns 0x%x\n", ret);
+	else
+		debug("flushing dcache successfully.\n");
+}
+
+/*
+ * Invalidates range in all levels of D-cache/unified cache
+ */
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+	__asm_invalidate_dcache_range(start, stop);
+}
+
+/*
+ * Flush range(clean & invalidate) from all levels of D-cache/unified cache
+ */
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+	__asm_flush_dcache_range(start, stop);
+}
+
+void dcache_enable(void)
+{
+	/* The data cache is not active unless the mmu is enabled */
+	if (!(get_sctlr() & CR_M)) {
+		invalidate_dcache_all();
+		__asm_invalidate_tlb_all();
+		mmu_setup();
+	}
+
+	set_sctlr(get_sctlr() | CR_C);
+}
+
+void dcache_disable(void)
+{
+	uint32_t sctlr;
+
+	sctlr = get_sctlr();
+
+	/* if cache isn't enabled no need to disable */
+	if (!(sctlr & CR_C))
+		return;
+
+	set_sctlr(sctlr & ~(CR_C|CR_M));
+
+	flush_dcache_all();
+	__asm_invalidate_tlb_all();
+}
+
+int dcache_status(void)
+{
+	return (get_sctlr() & CR_C) != 0;
+}
+
+u64 *__weak arch_get_page_table(void) {
+	puts("No page table offset defined\n");
+
+	return NULL;
+}
+
+static bool is_aligned(u64 addr, u64 size, u64 align)
+{
+	return !(addr & (align - 1)) && !(size & (align - 1));
+}
+
+/* Use flag to indicate if attrs has more than d-cache attributes */
+static u64 set_one_region(u64 start, u64 size, u64 attrs, bool flag, int level)
+{
+	int levelshift = level2shift(level);
+	u64 levelsize = 1ULL << levelshift;
+	u64 *pte = find_pte(start, level);
+
+	/* Can we can just modify the current level block PTE? */
+	if (is_aligned(start, size, levelsize)) {
+		if (flag) {
+			*pte &= ~PMD_ATTRMASK;
+			*pte |= attrs & PMD_ATTRMASK;
+		} else {
+			*pte &= ~PMD_ATTRINDX_MASK;
+			*pte |= attrs & PMD_ATTRINDX_MASK;
+		}
+		debug("Set attrs=%llx pte=%p level=%d\n", attrs, pte, level);
+
+		return levelsize;
+	}
+
+	/* Unaligned or doesn't fit, maybe split block into table */
+	debug("addr=%llx level=%d pte=%p (%llx)\n", start, level, pte, *pte);
+
+	/* Maybe we need to split the block into a table */
+	if (pte_type(pte) == PTE_TYPE_BLOCK)
+		split_block(pte, level);
+
+	/* And then double-check it became a table or already is one */
+	if (pte_type(pte) != PTE_TYPE_TABLE)
+		panic("PTE %p (%llx) for addr=%llx should be a table",
+		      pte, *pte, start);
+
+	/* Roll on to the next page table level */
+	return 0;
+}
+
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
+				     enum dcache_option option)
+{
+	u64 attrs = PMD_ATTRINDX(option);
+	u64 real_start = start;
+	u64 real_size = size;
+
+	debug("start=%lx size=%lx\n", (ulong)start, (ulong)size);
+
+	if (!gd->arch.tlb_emerg)
+		panic("Emergency page table not setup.");
+
+	/*
+	 * We can not modify page tables that we're currently running on,
+	 * so we first need to switch to the "emergency" page tables where
+	 * we can safely modify our primary page tables and then switch back
+	 */
+	__asm_switch_ttbr(gd->arch.tlb_emerg);
+
+	/*
+	 * Loop through the address range until we find a page granule that fits
+	 * our alignment constraints, then set it to the new cache attributes
+	 */
+	while (size > 0) {
+		int level;
+		u64 r;
+
+		for (level = 1; level < 4; level++) {
+			/* Set d-cache attributes only */
+			r = set_one_region(start, size, attrs, false, level);
+			if (r) {
+				/* PTE successfully replaced */
+				size -= r;
+				start += r;
+				break;
+			}
+		}
+
+	}
+
+	/* We're done modifying page tables, switch back to our primary ones */
+	__asm_switch_ttbr(gd->arch.tlb_addr);
+
+	/*
+	 * Make sure there's nothing stale in dcache for a region that might
+	 * have caches off now
+	 */
+	flush_dcache_range(real_start, real_start + real_size);
+}
+
+/*
+ * Modify MMU table for a region with updated PXN/UXN/Memory type/valid bits.
+ * The procecess is break-before-make. The target region will be marked as
+ * invalid during the process of changing.
+ */
+void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs)
+{
+	int level;
+	u64 r, size, start;
+
+	start = addr;
+	size = siz;
+	/*
+	 * Loop through the address range until we find a page granule that fits
+	 * our alignment constraints, then set it to "invalid".
+	 */
+	while (size > 0) {
+		for (level = 1; level < 4; level++) {
+			/* Set PTE to fault */
+			r = set_one_region(start, size, PTE_TYPE_FAULT, true,
+					   level);
+			if (r) {
+				/* PTE successfully invalidated */
+				size -= r;
+				start += r;
+				break;
+			}
+		}
+	}
+
+	flush_dcache_range(gd->arch.tlb_addr,
+			   gd->arch.tlb_addr + gd->arch.tlb_size);
+	__asm_invalidate_tlb_all();
+
+	/*
+	 * Loop through the address range until we find a page granule that fits
+	 * our alignment constraints, then set it to the new cache attributes
+	 */
+	start = addr;
+	size = siz;
+	while (size > 0) {
+		for (level = 1; level < 4; level++) {
+			/* Set PTE to new attributes */
+			r = set_one_region(start, size, attrs, true, level);
+			if (r) {
+				/* PTE successfully updated */
+				size -= r;
+				start += r;
+				break;
+			}
+		}
+	}
+	flush_dcache_range(gd->arch.tlb_addr,
+			   gd->arch.tlb_addr + gd->arch.tlb_size);
+	__asm_invalidate_tlb_all();
+}
+
+#else	/* CONFIG_SYS_DCACHE_OFF */
+
+/*
+ * For SPL builds, we may want to not have dcache enabled. Any real U-Boot
+ * running however really wants to have dcache and the MMU active. Check that
+ * everything is sane and give the developer a hint if it isn't.
+ */
+#ifndef CONFIG_SPL_BUILD
+#error Please describe your MMU layout in CONFIG_SYS_MEM_MAP and enable dcache.
+#endif
+
+void invalidate_dcache_all(void)
+{
+}
+
+void flush_dcache_all(void)
+{
+}
+
+void dcache_enable(void)
+{
+}
+
+void dcache_disable(void)
+{
+}
+
+int dcache_status(void)
+{
+	return 0;
+}
+
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
+				     enum dcache_option option)
+{
+}
+
+#endif	/* CONFIG_SYS_DCACHE_OFF */
+
+#ifndef CONFIG_SYS_ICACHE_OFF
+
+void icache_enable(void)
+{
+	invalidate_icache_all();
+	set_sctlr(get_sctlr() | CR_I);
+}
+
+void icache_disable(void)
+{
+	set_sctlr(get_sctlr() & ~CR_I);
+}
+
+int icache_status(void)
+{
+	return (get_sctlr() & CR_I) != 0;
+}
+
+void invalidate_icache_all(void)
+{
+	__asm_invalidate_icache_all();
+	__asm_invalidate_l3_icache();
+}
+
+#else	/* CONFIG_SYS_ICACHE_OFF */
+
+void icache_enable(void)
+{
+}
+
+void icache_disable(void)
+{
+}
+
+int icache_status(void)
+{
+	return 0;
+}
+
+void invalidate_icache_all(void)
+{
+}
+
+#endif	/* CONFIG_SYS_ICACHE_OFF */
+
+/*
+ * Enable dCache & iCache, whether cache is actually enabled
+ * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF
+ */
+void __weak enable_caches(void)
+{
+	icache_enable();
+	dcache_enable();
+}
diff --git a/arch/arm/cpu/armv8/config.mk b/arch/arm/cpu/armv8/config.mk
new file mode 100644
index 0000000..6f90931
--- /dev/null
+++ b/arch/arm/cpu/armv8/config.mk
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+PLATFORM_RELFLAGS += -fno-common -ffixed-x18
+
+PF_NO_UNALIGNED := $(call cc-option, -mstrict-align)
+PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED)
+
+EFI_LDS := elf_aarch64_efi.lds
+EFI_CRT0 := crt0_aarch64_efi.o
+EFI_RELOC := reloc_aarch64_efi.o
diff --git a/arch/arm/cpu/armv8/cpu-dt.c b/arch/arm/cpu/armv8/cpu-dt.c
new file mode 100644
index 0000000..267abb8
--- /dev/null
+++ b/arch/arm/cpu/armv8/cpu-dt.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/psci.h>
+#include <asm/system.h>
+#include <asm/armv8/sec_firmware.h>
+
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+int psci_update_dt(void *fdt)
+{
+	/*
+	 * If the PSCI in SEC Firmware didn't work, avoid to update the
+	 * device node of PSCI. But still return 0 instead of an error
+	 * number to support detecting PSCI dynamically and then switching
+	 * the SMP boot method between PSCI and spin-table.
+	 */
+	if (sec_firmware_support_psci_version() == PSCI_INVALID_VER)
+		return 0;
+	fdt_psci(fdt);
+
+#if defined(CONFIG_ARMV8_PSCI) && !defined(CONFIG_ARMV8_SECURE_BASE)
+	/* secure code lives in RAM, keep it alive */
+	fdt_add_mem_rsv(fdt, (unsigned long)__secure_start,
+			__secure_end - __secure_start);
+#endif
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/armv8/cpu.c b/arch/arm/cpu/armv8/cpu.c
new file mode 100644
index 0000000..b312b3b
--- /dev/null
+++ b/arch/arm/cpu/armv8/cpu.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008 Texas Insturments
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+#include <asm/secure.h>
+#include <linux/compiler.h>
+
+/*
+ * sdelay() - simple spin loop.
+ *
+ * Will delay execution by roughly (@loops * 2) cycles.
+ * This is necessary to be used before timers are accessible.
+ *
+ * A value of "0" will results in 2^64 loops.
+ */
+void sdelay(unsigned long loops)
+{
+	__asm__ volatile ("1:\n" "subs %0, %0, #1\n"
+			  "b.ne 1b" : "=r" (loops) : "0"(loops) : "cc");
+}
+
+int cleanup_before_linux(void)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * disable interrupt and turn off caches etc ...
+	 */
+	disable_interrupts();
+
+	/*
+	 * Turn off I-cache and invalidate it
+	 */
+	icache_disable();
+	invalidate_icache_all();
+
+	/*
+	 * turn off D-cache
+	 * dcache_disable() in turn flushes the d-cache and disables MMU
+	 */
+	dcache_disable();
+	invalidate_dcache_all();
+
+	return 0;
+}
+
+#ifdef CONFIG_ARMV8_PSCI
+static void relocate_secure_section(void)
+{
+#ifdef CONFIG_ARMV8_SECURE_BASE
+	size_t sz = __secure_end - __secure_start;
+
+	memcpy((void *)CONFIG_ARMV8_SECURE_BASE, __secure_start, sz);
+	flush_dcache_range(CONFIG_ARMV8_SECURE_BASE,
+			   CONFIG_ARMV8_SECURE_BASE + sz + 1);
+	invalidate_icache_all();
+#endif
+}
+
+void armv8_setup_psci(void)
+{
+	relocate_secure_section();
+	secure_ram_addr(psci_setup_vectors)();
+	secure_ram_addr(psci_arch_init)();
+}
+#endif
diff --git a/arch/arm/cpu/armv8/exceptions.S b/arch/arm/cpu/armv8/exceptions.S
new file mode 100644
index 0000000..a15af72
--- /dev/null
+++ b/arch/arm/cpu/armv8/exceptions.S
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/ptrace.h>
+#include <asm/macro.h>
+#include <linux/linkage.h>
+
+/*
+ * AArch64 exception vectors:
+ * We have four types of exceptions:
+ * - synchronous: traps, data aborts, undefined instructions, ...
+ * - IRQ: group 1 (normal) interrupts
+ * - FIQ: group 0 or secure interrupts
+ * - SError: fatal system errors
+ * There are entries for all four of those for different contexts:
+ * - from same exception level, when using the SP_EL0 stack pointer
+ * - from same exception level, when using the SP_ELx stack pointer
+ * - from lower exception level, when this is AArch64
+ * - from lower exception level, when this is AArch32
+ * Each of those 16 entries have space for 32 instructions, each entry must
+ * be 128 byte aligned, the whole table must be 2K aligned.
+ * The 32 instructions are not enough to save and restore all registers and
+ * to branch to the actual handler, so we split this up:
+ * Each entry saves the LR, branches to the save routine, then to the actual
+ * handler, then to the restore routine. The save and restore routines are
+ * each split in half and stuffed in the unused gap between the entries.
+ * Also as we do not run anything in a lower exception level, we just provide
+ * the first 8 entries for exceptions from the same EL.
+ */
+	.align	11
+	.globl	vectors
+vectors:
+	.align	7		/* Current EL Synchronous Thread */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_bad_sync
+	b	exception_exit
+
+/*
+ * Save (most of) the GP registers to the stack frame.
+ * This is the first part of the shared routine called into from all entries.
+ */
+_exception_entry:
+	stp	x27, x28, [sp, #-16]!
+	stp	x25, x26, [sp, #-16]!
+	stp	x23, x24, [sp, #-16]!
+	stp	x21, x22, [sp, #-16]!
+	stp	x19, x20, [sp, #-16]!
+	stp	x17, x18, [sp, #-16]!
+	stp	x15, x16, [sp, #-16]!
+	stp	x13, x14, [sp, #-16]!
+	stp	x11, x12, [sp, #-16]!
+	stp	x9, x10, [sp, #-16]!
+	stp	x7, x8, [sp, #-16]!
+	stp	x5, x6, [sp, #-16]!
+	stp	x3, x4, [sp, #-16]!
+	stp	x1, x2, [sp, #-16]!
+	b	_save_el_regs			/* jump to the second part */
+
+	.align	7		/* Current EL IRQ Thread */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_bad_irq
+	b	exception_exit
+
+/*
+ * Save exception specific context: ESR and ELR, for all exception levels.
+ * This is the second part of the shared routine called into from all entries.
+ */
+_save_el_regs:
+	/* Could be running at EL3/EL2/EL1 */
+	switch_el x11, 3f, 2f, 1f
+3:	mrs	x1, esr_el3
+	mrs	x2, elr_el3
+	b	0f
+2:	mrs	x1, esr_el2
+	mrs	x2, elr_el2
+	b	0f
+1:	mrs	x1, esr_el1
+	mrs	x2, elr_el1
+0:
+	stp	x2, x0, [sp, #-16]!
+	mov	x0, sp
+	ret
+
+	.align	7		/* Current EL FIQ Thread */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_bad_fiq
+				/* falling through to _exception_exit */
+/*
+ * Restore the exception return address, for all exception levels.
+ * This is the first part of the shared routine called into from all entries.
+ */
+exception_exit:
+	ldp	x2, x0, [sp],#16
+	switch_el x11, 3f, 2f, 1f
+3:	msr	elr_el3, x2
+	b	_restore_regs
+2:	msr	elr_el2, x2
+	b	_restore_regs
+1:	msr	elr_el1, x2
+	b	_restore_regs		/* jump to the second part */
+
+	.align	7		/* Current EL Error Thread */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_bad_error
+	b	exception_exit
+
+/*
+ * Restore the general purpose registers from the exception stack, then return.
+ * This is the second part of the shared routine called into from all entries.
+ */
+_restore_regs:
+	ldp	x1, x2, [sp],#16
+	ldp	x3, x4, [sp],#16
+	ldp	x5, x6, [sp],#16
+	ldp	x7, x8, [sp],#16
+	ldp	x9, x10, [sp],#16
+	ldp	x11, x12, [sp],#16
+	ldp	x13, x14, [sp],#16
+	ldp	x15, x16, [sp],#16
+	ldp	x17, x18, [sp],#16
+	ldp	x19, x20, [sp],#16
+	ldp	x21, x22, [sp],#16
+	ldp	x23, x24, [sp],#16
+	ldp	x25, x26, [sp],#16
+	ldp	x27, x28, [sp],#16
+	ldp	x29, x30, [sp],#16
+	eret
+
+	.align	7		 /* Current EL (SP_ELx) Synchronous Handler */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_sync
+	b	exception_exit
+
+	.align	7		 /* Current EL (SP_ELx) IRQ Handler */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_irq
+	b	exception_exit
+
+	.align	7		 /* Current EL (SP_ELx) FIQ Handler */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_fiq
+	b	exception_exit
+
+	.align	7		 /* Current EL (SP_ELx) Error Handler */
+	stp	x29, x30, [sp, #-16]!
+	bl	_exception_entry
+	bl	do_error
+	b	exception_exit
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
new file mode 100644
index 0000000..b55b36c
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -0,0 +1,574 @@
+config ARCH_LS1012A
+	bool
+	select ARMV8_SET_SMPEN
+	select ARM_ERRATA_855873 if !TFABOOT
+	select FSL_LSCH2
+	select SYS_FSL_SRDS_1
+	select SYS_HAS_SERDES
+	select SYS_FSL_DDR_BE
+	select SYS_FSL_MMDC
+	select SYS_FSL_ERRATUM_A010315
+	select SYS_FSL_ERRATUM_A009798
+	select SYS_FSL_ERRATUM_A008997
+	select SYS_FSL_ERRATUM_A009007
+	select SYS_FSL_ERRATUM_A009008
+	select ARCH_EARLY_INIT_R
+	select BOARD_EARLY_INIT_F
+	select SYS_I2C_MXC
+	select SYS_I2C_MXC_I2C1
+	select SYS_I2C_MXC_I2C2
+	imply PANIC_HANG
+
+config ARCH_LS1043A
+	bool
+	select ARMV8_SET_SMPEN
+	select ARM_ERRATA_855873 if !TFABOOT
+	select FSL_LSCH2
+	select SYS_FSL_SRDS_1
+	select SYS_HAS_SERDES
+	select SYS_FSL_DDR
+	select SYS_FSL_DDR_BE
+	select SYS_FSL_DDR_VER_50
+	select SYS_FSL_ERRATUM_A008850 if !TFABOOT
+	select SYS_FSL_ERRATUM_A008997
+	select SYS_FSL_ERRATUM_A009007
+	select SYS_FSL_ERRATUM_A009008
+	select SYS_FSL_ERRATUM_A009660 if !TFABOOT
+	select SYS_FSL_ERRATUM_A009663 if !TFABOOT
+	select SYS_FSL_ERRATUM_A009798
+	select SYS_FSL_ERRATUM_A009929
+	select SYS_FSL_ERRATUM_A009942 if !TFABOOT
+	select SYS_FSL_ERRATUM_A010315
+	select SYS_FSL_ERRATUM_A010539
+	select SYS_FSL_HAS_DDR3
+	select SYS_FSL_HAS_DDR4
+	select ARCH_EARLY_INIT_R
+	select BOARD_EARLY_INIT_F
+	select SYS_I2C_MXC
+	select SYS_I2C_MXC_I2C1
+	select SYS_I2C_MXC_I2C2
+	select SYS_I2C_MXC_I2C3
+	select SYS_I2C_MXC_I2C4
+	imply SCSI
+	imply SCSI_AHCI
+	imply CMD_PCI
+
+config ARCH_LS1046A
+	bool
+	select ARMV8_SET_SMPEN
+	select FSL_LSCH2
+	select SYS_FSL_SRDS_1
+	select SYS_HAS_SERDES
+	select SYS_FSL_DDR
+	select SYS_FSL_DDR_BE
+	select SYS_FSL_DDR_VER_50
+	select SYS_FSL_ERRATUM_A008336 if !TFABOOT
+	select SYS_FSL_ERRATUM_A008511 if !TFABOOT
+	select SYS_FSL_ERRATUM_A008850 if !TFABOOT
+	select SYS_FSL_ERRATUM_A008997
+	select SYS_FSL_ERRATUM_A009007
+	select SYS_FSL_ERRATUM_A009008
+	select SYS_FSL_ERRATUM_A009798
+	select SYS_FSL_ERRATUM_A009801
+	select SYS_FSL_ERRATUM_A009803 if !TFABOOT
+	select SYS_FSL_ERRATUM_A009942 if !TFABOOT
+	select SYS_FSL_ERRATUM_A010165 if !TFABOOT
+	select SYS_FSL_ERRATUM_A010539
+	select SYS_FSL_HAS_DDR4
+	select SYS_FSL_SRDS_2
+	select ARCH_EARLY_INIT_R
+	select BOARD_EARLY_INIT_F
+	select SYS_I2C_MXC
+	select SYS_I2C_MXC_I2C1
+	select SYS_I2C_MXC_I2C2
+	select SYS_I2C_MXC_I2C3
+	select SYS_I2C_MXC_I2C4
+	imply SCSI
+	imply SCSI_AHCI
+
+config ARCH_LS1088A
+	bool
+	select ARMV8_SET_SMPEN
+	select ARM_ERRATA_855873
+	select FSL_LSCH3
+	select SYS_FSL_SRDS_1
+	select SYS_HAS_SERDES
+	select SYS_FSL_DDR
+	select SYS_FSL_DDR_LE
+	select SYS_FSL_DDR_VER_50
+	select SYS_FSL_EC1
+	select SYS_FSL_EC2
+	select SYS_FSL_ERRATUM_A009803
+	select SYS_FSL_ERRATUM_A009942
+	select SYS_FSL_ERRATUM_A010165
+	select SYS_FSL_ERRATUM_A008511
+	select SYS_FSL_ERRATUM_A008850
+	select SYS_FSL_ERRATUM_A009007
+	select SYS_FSL_HAS_CCI400
+	select SYS_FSL_HAS_DDR4
+	select SYS_FSL_HAS_RGMII
+	select SYS_FSL_HAS_SEC
+	select SYS_FSL_SEC_COMPAT_5
+	select SYS_FSL_SEC_LE
+	select SYS_FSL_SRDS_1
+	select SYS_FSL_SRDS_2
+	select FSL_TZASC_1
+	select ARCH_EARLY_INIT_R
+	select BOARD_EARLY_INIT_F
+	select SYS_I2C_MXC
+	select SYS_I2C_MXC_I2C1
+	select SYS_I2C_MXC_I2C2
+	select SYS_I2C_MXC_I2C3
+	select SYS_I2C_MXC_I2C4
+	imply SCSI
+	imply PANIC_HANG
+
+config ARCH_LS2080A
+	bool
+	select ARMV8_SET_SMPEN
+	select ARM_ERRATA_826974
+	select ARM_ERRATA_828024
+	select ARM_ERRATA_829520
+	select ARM_ERRATA_833471
+	select FSL_LSCH3
+	select SYS_FSL_SRDS_1
+	select SYS_HAS_SERDES
+	select SYS_FSL_DDR
+	select SYS_FSL_DDR_LE
+	select SYS_FSL_DDR_VER_50
+	select SYS_FSL_HAS_CCN504
+	select SYS_FSL_HAS_DP_DDR
+	select SYS_FSL_HAS_SEC
+	select SYS_FSL_HAS_DDR4
+	select SYS_FSL_SEC_COMPAT_5
+	select SYS_FSL_SEC_LE
+	select SYS_FSL_SRDS_2
+	select FSL_TZASC_1
+	select FSL_TZASC_2
+	select SYS_FSL_ERRATUM_A008336
+	select SYS_FSL_ERRATUM_A008511
+	select SYS_FSL_ERRATUM_A008514
+	select SYS_FSL_ERRATUM_A008585
+	select SYS_FSL_ERRATUM_A008997
+	select SYS_FSL_ERRATUM_A009007
+	select SYS_FSL_ERRATUM_A009008
+	select SYS_FSL_ERRATUM_A009635
+	select SYS_FSL_ERRATUM_A009663
+	select SYS_FSL_ERRATUM_A009798
+	select SYS_FSL_ERRATUM_A009801
+	select SYS_FSL_ERRATUM_A009803
+	select SYS_FSL_ERRATUM_A009942
+	select SYS_FSL_ERRATUM_A010165
+	select SYS_FSL_ERRATUM_A009203
+	select ARCH_EARLY_INIT_R
+	select BOARD_EARLY_INIT_F
+	select SYS_I2C_MXC
+	select SYS_I2C_MXC_I2C1
+	select SYS_I2C_MXC_I2C2
+	select SYS_I2C_MXC_I2C3
+	select SYS_I2C_MXC_I2C4
+	imply DISTRO_DEFAULTS
+	imply PANIC_HANG
+
+config ARCH_LX2160A
+	bool
+	select ARMV8_SET_SMPEN
+	select FSL_LSCH3
+	select NXP_LSCH3_2
+	select SYS_HAS_SERDES
+	select SYS_FSL_SRDS_1
+	select SYS_FSL_SRDS_2
+	select SYS_NXP_SRDS_3
+	select SYS_FSL_DDR
+	select SYS_FSL_DDR_LE
+	select SYS_FSL_DDR_VER_50
+	select SYS_FSL_EC1
+	select SYS_FSL_EC2
+	select SYS_FSL_HAS_RGMII
+	select SYS_FSL_HAS_SEC
+	select SYS_FSL_HAS_CCN508
+	select SYS_FSL_HAS_DDR4
+	select SYS_FSL_SEC_COMPAT_5
+	select SYS_FSL_SEC_LE
+	select ARCH_EARLY_INIT_R
+	select BOARD_EARLY_INIT_F
+	select SYS_I2C_MXC
+	select SYS_I2C_MXC_I2C1
+	select SYS_I2C_MXC_I2C2
+	select SYS_I2C_MXC_I2C3
+	select SYS_I2C_MXC_I2C4
+	select SYS_I2C_MXC_I2C5
+	select SYS_I2C_MXC_I2C6
+	select SYS_I2C_MXC_I2C7
+	select SYS_I2C_MXC_I2C8
+	imply DISTRO_DEFAULTS
+	imply PANIC_HANG
+	imply SCSI
+	imply SCSI_AHCI
+
+config FSL_LSCH2
+	bool
+	select SYS_FSL_HAS_CCI400
+	select SYS_FSL_HAS_SEC
+	select SYS_FSL_SEC_COMPAT_5
+	select SYS_FSL_SEC_BE
+
+config FSL_LSCH3
+	bool
+
+config NXP_LSCH3_2
+	bool
+
+config FSL_MC_ENET
+	bool "Management Complex network"
+	depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
+	default y
+	select RESV_RAM
+	help
+	  Enable Management Complex (MC) network
+
+menu "Layerscape architecture"
+	depends on FSL_LSCH2 || FSL_LSCH3
+
+config FSL_PCIE_COMPAT
+	string "PCIe compatible of Kernel DT"
+	depends on PCIE_LAYERSCAPE
+	default "fsl,ls1012a-pcie" if ARCH_LS1012A
+	default "fsl,ls1043a-pcie" if ARCH_LS1043A
+	default "fsl,ls1046a-pcie" if ARCH_LS1046A
+	default "fsl,ls2080a-pcie" if ARCH_LS2080A
+	default "fsl,ls1088a-pcie" if ARCH_LS1088A
+	default "fsl,lx2160a-pcie" if ARCH_LX2160A
+	help
+	  This compatible is used to find pci controller node in Kernel DT
+	  to complete fixup.
+
+config HAS_FEATURE_GIC64K_ALIGN
+	bool
+	default y if ARCH_LS1043A
+
+config HAS_FEATURE_ENHANCED_MSI
+	bool
+	default y if ARCH_LS1043A
+
+menu "Layerscape PPA"
+config FSL_LS_PPA
+	bool "FSL Layerscape PPA firmware support"
+	depends on !ARMV8_PSCI
+	select ARMV8_SEC_FIRMWARE_SUPPORT
+	select SEC_FIRMWARE_ARMV8_PSCI
+	select ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT if FSL_LSCH2
+	help
+	  The FSL Primary Protected Application (PPA) is a software component
+	  which is loaded during boot stage, and then remains resident in RAM
+	  and runs in the TrustZone after boot.
+	  Say y to enable it.
+
+config SPL_FSL_LS_PPA
+	bool "FSL Layerscape PPA firmware support for SPL build"
+	depends on !ARMV8_PSCI
+	select SPL_ARMV8_SEC_FIRMWARE_SUPPORT
+	select SEC_FIRMWARE_ARMV8_PSCI
+	select ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT if FSL_LSCH2
+	help
+	  The FSL Primary Protected Application (PPA) is a software component
+	  which is loaded during boot stage, and then remains resident in RAM
+	  and runs in the TrustZone after boot. This is to load PPA during SPL
+	  stage instead of the RAM version of U-Boot. Once PPA is initialized,
+	  the rest of U-Boot (including RAM version) runs at EL2.
+choice
+	prompt "FSL Layerscape PPA firmware loading-media select"
+	depends on FSL_LS_PPA
+	default SYS_LS_PPA_FW_IN_MMC if SD_BOOT
+	default SYS_LS_PPA_FW_IN_NAND if NAND_BOOT
+	default SYS_LS_PPA_FW_IN_XIP
+
+config SYS_LS_PPA_FW_IN_XIP
+	bool "XIP"
+	help
+	  Say Y here if the PPA firmware locate at XIP flash, such
+	  as NOR or QSPI flash.
+
+config SYS_LS_PPA_FW_IN_MMC
+	bool "eMMC or SD Card"
+	help
+	  Say Y here if the PPA firmware locate at eMMC/SD card.
+
+config SYS_LS_PPA_FW_IN_NAND
+	bool "NAND"
+	help
+	  Say Y here if the PPA firmware locate at NAND flash.
+
+endchoice
+
+config LS_PPA_ESBC_HDR_SIZE
+	hex "Length of PPA ESBC header"
+	depends on FSL_LS_PPA && CHAIN_OF_TRUST && !SYS_LS_PPA_FW_IN_XIP
+	default 0x2000
+	help
+	  Length (in bytes) of PPA ESBC header to be copied from MMC/SD or
+	  NAND to memory to validate PPA image.
+
+endmenu
+
+config SYS_FSL_ERRATUM_A008997
+	bool "Workaround for USB PHY erratum A008997"
+
+config SYS_FSL_ERRATUM_A009007
+	bool
+	help
+	  Workaround for USB PHY erratum A009007
+
+config SYS_FSL_ERRATUM_A009008
+	bool "Workaround for USB PHY erratum A009008"
+
+config SYS_FSL_ERRATUM_A009798
+	bool "Workaround for USB PHY erratum A009798"
+
+config SYS_FSL_ERRATUM_A010315
+	bool "Workaround for PCIe erratum A010315"
+
+config SYS_FSL_ERRATUM_A010539
+	bool "Workaround for PIN MUX erratum A010539"
+
+config MAX_CPUS
+	int "Maximum number of CPUs permitted for Layerscape"
+	default 4 if ARCH_LS1043A
+	default 4 if ARCH_LS1046A
+	default 16 if ARCH_LS2080A
+	default 8 if ARCH_LS1088A
+	default 16 if ARCH_LX2160A
+	default 1
+	help
+	  Set this number to the maximum number of possible CPUs in the SoC.
+	  SoCs may have multiple clusters with each cluster may have multiple
+	  ports. If some ports are reserved but higher ports are used for
+	  cores, count the reserved ports. This will allocate enough memory
+	  in spin table to properly handle all cores.
+
+config SECURE_BOOT
+	bool "Secure Boot"
+	help
+		Enable Freescale Secure Boot feature
+
+config QSPI_AHB_INIT
+	bool "Init the QSPI AHB bus"
+	help
+	  The default setting for QSPI AHB bus just support 3bytes addressing.
+	  But some QSPI flash size up to 64MBytes, so initialize the QSPI AHB
+	  bus for those flashes to support the full QSPI flash size.
+
+config SYS_CCI400_OFFSET
+	hex "Offset for CCI400 base"
+	depends on SYS_FSL_HAS_CCI400
+	default 0x3090000 if ARCH_LS1088A
+	default 0x180000 if FSL_LSCH2
+	help
+	  Offset for CCI400 base
+	  CCI400 base addr = CCSRBAR + CCI400_OFFSET
+
+config SYS_FSL_IFC_BANK_COUNT
+	int "Maximum banks of Integrated flash controller"
+	depends on ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A || ARCH_LS1088A
+	default 4 if ARCH_LS1043A
+	default 4 if ARCH_LS1046A
+	default 8 if ARCH_LS2080A || ARCH_LS1088A
+
+config SYS_FSL_HAS_CCI400
+	bool
+
+config SYS_FSL_HAS_CCN504
+	bool
+
+config SYS_FSL_HAS_CCN508
+	bool
+
+config SYS_FSL_HAS_DP_DDR
+	bool
+
+config SYS_FSL_SRDS_1
+	bool
+
+config SYS_FSL_SRDS_2
+	bool
+
+config SYS_NXP_SRDS_3
+	bool
+
+config SYS_HAS_SERDES
+	bool
+
+config FSL_TZASC_1
+	bool
+
+config FSL_TZASC_2
+	bool
+
+endmenu
+
+menu "Layerscape clock tree configuration"
+	depends on FSL_LSCH2 || FSL_LSCH3
+
+config SYS_FSL_CLK
+	bool "Enable clock tree initialization"
+	default y
+
+config CLUSTER_CLK_FREQ
+	int "Reference clock of core cluster"
+	depends on ARCH_LS1012A
+	default 100000000
+	help
+	  This number is the reference clock frequency of core PLL.
+	  For most platforms, the core PLL and Platform PLL have the same
+	  reference clock, but for some platforms, LS1012A for instance,
+	  they are provided sepatately.
+
+config SYS_FSL_PCLK_DIV
+	int "Platform clock divider"
+	default 1 if ARCH_LS1043A
+	default 1 if ARCH_LS1046A
+	default 1 if ARCH_LS1088A
+	default 2
+	help
+	  This is the divider that is used to derive Platform clock from
+	  Platform PLL, in another word:
+		Platform_clk = Platform_PLL_freq / this_divider
+
+config SYS_FSL_DSPI_CLK_DIV
+	int "DSPI clock divider"
+	default 1 if ARCH_LS1043A
+	default 2
+	help
+	  This is the divider that is used to derive DSPI clock from Platform
+	  clock, in another word DSPI_clk = Platform_clk / this_divider.
+
+config SYS_FSL_DUART_CLK_DIV
+	int "DUART clock divider"
+	default 1 if ARCH_LS1043A
+	default 4 if ARCH_LX2160A
+	default 2
+	help
+	  This is the divider that is used to derive DUART clock from Platform
+	  clock, in another word DUART_clk = Platform_clk / this_divider.
+
+config SYS_FSL_I2C_CLK_DIV
+	int "I2C clock divider"
+	default 1 if ARCH_LS1043A
+	default 2
+	help
+	  This is the divider that is used to derive I2C clock from Platform
+	  clock, in another word I2C_clk = Platform_clk / this_divider.
+
+config SYS_FSL_IFC_CLK_DIV
+	int "IFC clock divider"
+	default 1 if ARCH_LS1043A
+	default 2
+	help
+	  This is the divider that is used to derive IFC clock from Platform
+	  clock, in another word IFC_clk = Platform_clk / this_divider.
+
+config SYS_FSL_LPUART_CLK_DIV
+	int "LPUART clock divider"
+	default 1 if ARCH_LS1043A
+	default 2
+	help
+	  This is the divider that is used to derive LPUART clock from Platform
+	  clock, in another word LPUART_clk = Platform_clk / this_divider.
+
+config SYS_FSL_SDHC_CLK_DIV
+	int "SDHC clock divider"
+	default 1 if ARCH_LS1043A
+	default 1 if ARCH_LS1012A
+	default 2
+	help
+	  This is the divider that is used to derive SDHC clock from Platform
+	  clock, in another word SDHC_clk = Platform_clk / this_divider.
+
+config SYS_FSL_QMAN_CLK_DIV
+	int "QMAN clock divider"
+	default 1 if ARCH_LS1043A
+	default 2
+	help
+	  This is the divider that is used to derive QMAN clock from Platform
+	  clock, in another word QMAN_clk = Platform_clk / this_divider.
+endmenu
+
+config RESV_RAM
+	bool
+	help
+	  Reserve memory from the top, tracked by gd->arch.resv_ram. This
+	  reserved RAM can be used by special driver that resides in memory
+	  after U-Boot exits. It's up to implementation to allocate and allow
+	  access to this reserved memory. For example, the reserved RAM can
+	  be at the high end of physical memory. The reserve RAM may be
+	  excluded from memory bank(s) passed to OS, or marked as reserved.
+
+config SYS_FSL_EC1
+	bool
+	help
+	  Ethernet controller 1, this is connected to
+	  MAC17 for LX2160A or to MAC3 for other SoCs
+	  Provides DPAA2 capabilities
+
+config SYS_FSL_EC2
+	bool
+	help
+	  Ethernet controller 2, this is connected to
+	  MAC18 for LX2160A or to MAC4 for other SoCs
+	  Provides DPAA2 capabilities
+
+config SYS_FSL_ERRATUM_A008336
+	bool
+
+config SYS_FSL_ERRATUM_A008514
+	bool
+
+config SYS_FSL_ERRATUM_A008585
+	bool
+
+config SYS_FSL_ERRATUM_A008850
+	bool
+
+config SYS_FSL_ERRATUM_A009203
+	bool
+
+config SYS_FSL_ERRATUM_A009635
+	bool
+
+config SYS_FSL_ERRATUM_A009660
+	bool
+
+config SYS_FSL_ERRATUM_A009929
+	bool
+
+
+config SYS_FSL_HAS_RGMII
+	bool
+	depends on SYS_FSL_EC1 || SYS_FSL_EC2
+
+
+config SYS_MC_RSV_MEM_ALIGN
+	hex "Management Complex reserved memory alignment"
+	depends on RESV_RAM
+	default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
+	help
+	  Reserved memory needs to be aligned for MC to use. Default value
+	  is 512MB.
+
+config SPL_LDSCRIPT
+	default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A
+
+config HAS_FSL_XHCI_USB
+	bool
+	default y if ARCH_LS1043A || ARCH_LS1046A
+	help
+	  For some SoC(such as LS1043A and LS1046A), USB and QE-HDLC multiplex use
+	  pins, select it when the pins are assigned to USB.
+
+config TFABOOT
+       bool "Support for booting from TFA"
+       default n
+       help
+         Enabling this will make a U-Boot binary that is capable of being
+         booted via TFA.
+
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
new file mode 100644
index 0000000..e9bc987
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2016-2018 NXP
+# Copyright 2014-2015, Freescale Semiconductor
+
+obj-y += cpu.o
+obj-y += lowlevel.o
+obj-y += soc.o
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_MP) += mp.o
+obj-$(CONFIG_OF_LIBFDT) += fdt.o
+endif
+obj-$(CONFIG_SPL) += spl.o
+obj-$(CONFIG_$(SPL_)FSL_LS_PPA) += ppa.o
+
+ifneq ($(CONFIG_FSL_LSCH3),)
+obj-y += fsl_lsch3_speed.o
+obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch3_serdes.o
+else
+ifneq ($(CONFIG_FSL_LSCH2),)
+obj-y += fsl_lsch2_speed.o
+obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch2_serdes.o
+endif
+endif
+
+ifneq ($(CONFIG_ARCH_LX2160A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += lx2160a_serdes.o
+endif
+
+ifneq ($(CONFIG_ARCH_LS2080A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls2080a_serdes.o
+endif
+
+ifneq ($(CONFIG_ARCH_LS1043A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1043a_serdes.o
+obj-$(CONFIG_ARMV8_PSCI) += ls1043a_psci.o
+obj-y += icid.o ls1043_ids.o
+endif
+
+ifneq ($(CONFIG_ARCH_LS1012A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1012a_serdes.o
+endif
+
+ifneq ($(CONFIG_ARCH_LS1046A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1046a_serdes.o
+obj-y += icid.o ls1046_ids.o
+endif
+
+ifneq ($(CONFIG_ARCH_LS1088A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1088a_serdes.o
+endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
new file mode 100644
index 0000000..1fc025b
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -0,0 +1,1580 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2017 NXP
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <fsl_ddr_sdram.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+#include <fm_eth.h>
+#include <asm/armv8/mmu.h>
+#include <asm/io.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/speed.h>
+#include <fsl_immap.h>
+#include <asm/arch/mp.h>
+#include <efi_loader.h>
+#include <fsl-mc/fsl_mc.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+#include <asm/armv8/sec_firmware.h>
+#ifdef CONFIG_SYS_FSL_DDR
+#include <fsl_ddr.h>
+#endif
+#include <asm/arch/clock.h>
+#include <hwconfig.h>
+#include <fsl_qbman.h>
+
+#ifdef CONFIG_TFABOOT
+#include <environment.h>
+#ifdef CONFIG_CHAIN_OF_TRUST
+#include <fsl_validate.h>
+#endif
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct cpu_type cpu_type_list[] = {
+	CPU_TYPE_ENTRY(LS2080A, LS2080A, 8),
+	CPU_TYPE_ENTRY(LS2085A, LS2085A, 8),
+	CPU_TYPE_ENTRY(LS2045A, LS2045A, 4),
+	CPU_TYPE_ENTRY(LS2088A, LS2088A, 8),
+	CPU_TYPE_ENTRY(LS2084A, LS2084A, 8),
+	CPU_TYPE_ENTRY(LS2048A, LS2048A, 4),
+	CPU_TYPE_ENTRY(LS2044A, LS2044A, 4),
+	CPU_TYPE_ENTRY(LS2081A, LS2081A, 8),
+	CPU_TYPE_ENTRY(LS2041A, LS2041A, 4),
+	CPU_TYPE_ENTRY(LS1043A, LS1043A, 4),
+	CPU_TYPE_ENTRY(LS1023A, LS1023A, 2),
+	CPU_TYPE_ENTRY(LS1046A, LS1046A, 4),
+	CPU_TYPE_ENTRY(LS1026A, LS1026A, 2),
+	CPU_TYPE_ENTRY(LS2040A, LS2040A, 4),
+	CPU_TYPE_ENTRY(LS1012A, LS1012A, 1),
+	CPU_TYPE_ENTRY(LS1088A, LS1088A, 8),
+	CPU_TYPE_ENTRY(LS1084A, LS1084A, 8),
+	CPU_TYPE_ENTRY(LS1048A, LS1048A, 4),
+	CPU_TYPE_ENTRY(LS1044A, LS1044A, 4),
+	CPU_TYPE_ENTRY(LX2160A, LX2160A, 16),
+	CPU_TYPE_ENTRY(LX2120A, LX2120A, 12),
+	CPU_TYPE_ENTRY(LX2080A, LX2080A, 8),
+};
+
+#define EARLY_PGTABLE_SIZE 0x5000
+static struct mm_region early_map[] = {
+#ifdef CONFIG_FSL_LSCH3
+	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
+	  SYS_FSL_OCRAM_SPACE_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
+	{ CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_BASE1,
+	  CONFIG_SYS_FSL_QSPI_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE},
+#ifdef CONFIG_FSL_IFC
+	/* For IFC Region #1, only the first 4MB is cache-enabled */
+	{ CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_BASE1,
+	  CONFIG_SYS_FSL_IFC_SIZE1_1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
+	{ CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
+	  CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
+	  CONFIG_SYS_FSL_IFC_SIZE1 - CONFIG_SYS_FSL_IFC_SIZE1_1,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
+	{ CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FSL_IFC_BASE1,
+	  CONFIG_SYS_FSL_IFC_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
+#endif
+	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+#if defined(CONFIG_TFABOOT) || \
+	(defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+#else	/* Start with nGnRnE and PXN and UXN to prevent speculative access */
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
+#endif
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+#ifdef CONFIG_FSL_IFC
+	/* Map IFC region #2 up to CONFIG_SYS_FLASH_BASE for NAND boot */
+	{ CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
+	  CONFIG_SYS_FLASH_BASE - CONFIG_SYS_FSL_IFC_BASE2,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
+#endif
+	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+#ifdef CONFIG_SYS_FSL_DRAM_BASE3
+	{ CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
+	  CONFIG_SYS_FSL_DRAM_SIZE3,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+#endif
+#elif defined(CONFIG_FSL_LSCH2)
+	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
+	  SYS_FSL_OCRAM_SPACE_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
+	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE,
+	  CONFIG_SYS_FSL_QSPI_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
+#ifdef CONFIG_FSL_IFC
+	{ CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
+	  CONFIG_SYS_FSL_IFC_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
+#endif
+	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+#if defined(CONFIG_TFABOOT) || \
+	(defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+#else	/* Start with nGnRnE and PXN and UXN to prevent speculative access */
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
+#endif
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+#endif
+	{},	/* list terminator */
+};
+
+static struct mm_region final_map[] = {
+#ifdef CONFIG_FSL_LSCH3
+	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
+	  SYS_FSL_OCRAM_SPACE_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
+	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+	{ CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_BASE1,
+	  CONFIG_SYS_FSL_QSPI_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_QSPI_BASE2, CONFIG_SYS_FSL_QSPI_BASE2,
+	  CONFIG_SYS_FSL_QSPI_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+#ifdef CONFIG_FSL_IFC
+	{ CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
+	  CONFIG_SYS_FSL_IFC_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+#endif
+	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_MC_BASE, CONFIG_SYS_FSL_MC_BASE,
+	  CONFIG_SYS_FSL_MC_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_NI_BASE, CONFIG_SYS_FSL_NI_BASE,
+	  CONFIG_SYS_FSL_NI_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	/* For QBMAN portal, only the first 64MB is cache-enabled */
+	{ CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
+	  CONFIG_SYS_FSL_QBMAN_SIZE_1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_NS
+	},
+	{ CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
+	  CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
+	  CONFIG_SYS_FSL_QBMAN_SIZE - CONFIG_SYS_FSL_QBMAN_SIZE_1,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR,
+	  CONFIG_SYS_PCIE1_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR,
+	  CONFIG_SYS_PCIE2_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
+	  CONFIG_SYS_PCIE3_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LX2160A)
+	{ CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_ADDR,
+	  CONFIG_SYS_PCIE4_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+#endif
+	{ CONFIG_SYS_FSL_WRIOP1_BASE, CONFIG_SYS_FSL_WRIOP1_BASE,
+	  CONFIG_SYS_FSL_WRIOP1_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_AIOP1_BASE, CONFIG_SYS_FSL_AIOP1_BASE,
+	  CONFIG_SYS_FSL_AIOP1_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_PEBUF_BASE, CONFIG_SYS_FSL_PEBUF_BASE,
+	  CONFIG_SYS_FSL_PEBUF_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+#ifdef CONFIG_SYS_FSL_DRAM_BASE3
+	{ CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
+	  CONFIG_SYS_FSL_DRAM_SIZE3,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+#endif
+#elif defined(CONFIG_FSL_LSCH2)
+	{ CONFIG_SYS_FSL_BOOTROM_BASE, CONFIG_SYS_FSL_BOOTROM_BASE,
+	  CONFIG_SYS_FSL_BOOTROM_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
+	  CONFIG_SYS_FSL_CCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE,
+	  SYS_FSL_OCRAM_SPACE_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
+	},
+	{ CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
+	  CONFIG_SYS_FSL_DCSR_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE,
+	  CONFIG_SYS_FSL_QSPI_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+#ifdef CONFIG_FSL_IFC
+	{ CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
+	  CONFIG_SYS_FSL_IFC_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
+	},
+#endif
+	{ CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
+	  CONFIG_SYS_FSL_DRAM_SIZE1,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+	{ CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
+	  CONFIG_SYS_FSL_QBMAN_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
+	  CONFIG_SYS_FSL_DRAM_SIZE2,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+	{ CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR,
+	  CONFIG_SYS_PCIE1_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR,
+	  CONFIG_SYS_PCIE2_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR,
+	  CONFIG_SYS_PCIE3_PHYS_SIZE,
+	  PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+	  PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{ CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
+	  CONFIG_SYS_FSL_DRAM_SIZE3,
+	  PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+	  PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
+	},
+#endif
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	{},	/* space holder for secure mem */
+#endif
+	{},
+};
+
+struct mm_region *mem_map = early_map;
+
+void cpu_name(char *name)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	unsigned int i, svr, ver;
+
+	svr = gur_in32(&gur->svr);
+	ver = SVR_SOC_VER(svr);
+
+	for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++)
+		if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) {
+			strcpy(name, cpu_type_list[i].name);
+#ifdef CONFIG_ARCH_LX2160A
+			if (IS_C_PROCESSOR(svr))
+				strcat(name, "C");
+#endif
+
+			if (IS_E_PROCESSOR(svr))
+				strcat(name, "E");
+
+			sprintf(name + strlen(name), " Rev%d.%d",
+				SVR_MAJ(svr), SVR_MIN(svr));
+			break;
+		}
+
+	if (i == ARRAY_SIZE(cpu_type_list))
+		strcpy(name, "unknown");
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+/*
+ * To start MMU before DDR is available, we create MMU table in SRAM.
+ * The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three
+ * levels of translation tables here to cover 40-bit address space.
+ * We use 4KB granule size, with 40 bits physical address, T0SZ=24
+ * Address above EARLY_PGTABLE_SIZE (0x5000) is free for other purpose.
+ * Note, the debug print in cache_v8.c is not usable for debugging
+ * these early MMU tables because UART is not yet available.
+ */
+static inline void early_mmu_setup(void)
+{
+	unsigned int el = current_el();
+
+	/* global data is already setup, no allocation yet */
+	if (el == 3)
+		gd->arch.tlb_addr = CONFIG_SYS_FSL_OCRAM_BASE;
+	else
+		gd->arch.tlb_addr = CONFIG_SYS_DDR_SDRAM_BASE;
+	gd->arch.tlb_fillptr = gd->arch.tlb_addr;
+	gd->arch.tlb_size = EARLY_PGTABLE_SIZE;
+
+	/* Create early page tables */
+	setup_pgtables();
+
+	/* point TTBR to the new table */
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
+			  get_tcr(el, NULL, NULL) &
+			  ~(TCR_ORGN_MASK | TCR_IRGN_MASK),
+			  MEMORY_ATTRIBUTES);
+
+	set_sctlr(get_sctlr() | CR_M);
+}
+
+static void fix_pcie_mmu_map(void)
+{
+#ifdef CONFIG_ARCH_LS2080A
+	unsigned int i;
+	u32 svr, ver;
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+	svr = gur_in32(&gur->svr);
+	ver = SVR_SOC_VER(svr);
+
+	/* Fix PCIE base and size for LS2088A */
+	if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) ||
+	    (ver == SVR_LS2048A) || (ver == SVR_LS2044A) ||
+	    (ver == SVR_LS2081A) || (ver == SVR_LS2041A)) {
+		for (i = 0; i < ARRAY_SIZE(final_map); i++) {
+			switch (final_map[i].phys) {
+			case CONFIG_SYS_PCIE1_PHYS_ADDR:
+				final_map[i].phys = 0x2000000000ULL;
+				final_map[i].virt = 0x2000000000ULL;
+				final_map[i].size = 0x800000000ULL;
+				break;
+			case CONFIG_SYS_PCIE2_PHYS_ADDR:
+				final_map[i].phys = 0x2800000000ULL;
+				final_map[i].virt = 0x2800000000ULL;
+				final_map[i].size = 0x800000000ULL;
+				break;
+			case CONFIG_SYS_PCIE3_PHYS_ADDR:
+				final_map[i].phys = 0x3000000000ULL;
+				final_map[i].virt = 0x3000000000ULL;
+				final_map[i].size = 0x800000000ULL;
+				break;
+			case CONFIG_SYS_PCIE4_PHYS_ADDR:
+				final_map[i].phys = 0x3800000000ULL;
+				final_map[i].virt = 0x3800000000ULL;
+				final_map[i].size = 0x800000000ULL;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+#endif
+}
+
+/*
+ * The final tables look similar to early tables, but different in detail.
+ * These tables are in DRAM. Sub tables are added to enable cache for
+ * QBMan and OCRAM.
+ *
+ * Put the MMU table in secure memory if gd->arch.secure_ram is valid.
+ * OCRAM will be not used for this purpose so gd->arch.secure_ram can't be 0.
+ */
+static inline void final_mmu_setup(void)
+{
+	u64 tlb_addr_save = gd->arch.tlb_addr;
+	unsigned int el = current_el();
+	int index;
+
+	/* fix the final_map before filling in the block entries */
+	fix_pcie_mmu_map();
+
+	mem_map = final_map;
+
+	/* Update mapping for DDR to actual size */
+	for (index = 0; index < ARRAY_SIZE(final_map) - 2; index++) {
+		/*
+		 * Find the entry for DDR mapping and update the address and
+		 * size. Zero-sized mapping will be skipped when creating MMU
+		 * table.
+		 */
+		switch (final_map[index].virt) {
+		case CONFIG_SYS_FSL_DRAM_BASE1:
+			final_map[index].virt = gd->bd->bi_dram[0].start;
+			final_map[index].phys = gd->bd->bi_dram[0].start;
+			final_map[index].size = gd->bd->bi_dram[0].size;
+			break;
+#ifdef CONFIG_SYS_FSL_DRAM_BASE2
+		case CONFIG_SYS_FSL_DRAM_BASE2:
+#if (CONFIG_NR_DRAM_BANKS >= 2)
+			final_map[index].virt = gd->bd->bi_dram[1].start;
+			final_map[index].phys = gd->bd->bi_dram[1].start;
+			final_map[index].size = gd->bd->bi_dram[1].size;
+#else
+			final_map[index].size = 0;
+#endif
+		break;
+#endif
+#ifdef CONFIG_SYS_FSL_DRAM_BASE3
+		case CONFIG_SYS_FSL_DRAM_BASE3:
+#if (CONFIG_NR_DRAM_BANKS >= 3)
+			final_map[index].virt = gd->bd->bi_dram[2].start;
+			final_map[index].phys = gd->bd->bi_dram[2].start;
+			final_map[index].size = gd->bd->bi_dram[2].size;
+#else
+			final_map[index].size = 0;
+#endif
+		break;
+#endif
+		default:
+			break;
+		}
+	}
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
+		if (el == 3) {
+			/*
+			 * Only use gd->arch.secure_ram if the address is
+			 * recalculated. Align to 4KB for MMU table.
+			 */
+			/* put page tables in secure ram */
+			index = ARRAY_SIZE(final_map) - 2;
+			gd->arch.tlb_addr = gd->arch.secure_ram & ~0xfff;
+			final_map[index].virt = gd->arch.secure_ram & ~0x3;
+			final_map[index].phys = final_map[index].virt;
+			final_map[index].size = CONFIG_SYS_MEM_RESERVE_SECURE;
+			final_map[index].attrs = PTE_BLOCK_OUTER_SHARE;
+			gd->arch.secure_ram |= MEM_RESERVE_SECURE_SECURED;
+			tlb_addr_save = gd->arch.tlb_addr;
+		} else {
+			/* Use allocated (board_f.c) memory for TLB */
+			tlb_addr_save = gd->arch.tlb_allocated;
+			gd->arch.tlb_addr = tlb_addr_save;
+		}
+	}
+#endif
+
+	/* Reset the fill ptr */
+	gd->arch.tlb_fillptr = tlb_addr_save;
+
+	/* Create normal system page tables */
+	setup_pgtables();
+
+	/* Create emergency page tables */
+	gd->arch.tlb_addr = gd->arch.tlb_fillptr;
+	gd->arch.tlb_emerg = gd->arch.tlb_addr;
+	setup_pgtables();
+	gd->arch.tlb_addr = tlb_addr_save;
+
+	/* Disable cache and MMU */
+	dcache_disable();	/* TLBs are invalidated */
+	invalidate_icache_all();
+
+	/* point TTBR to the new table */
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
+			  MEMORY_ATTRIBUTES);
+
+	set_sctlr(get_sctlr() | CR_M);
+}
+
+u64 get_page_table_size(void)
+{
+	return 0x10000;
+}
+
+int arch_cpu_init(void)
+{
+	/*
+	 * This function is called before U-Boot relocates itself to speed up
+	 * on system running. It is not necessary to run if performance is not
+	 * critical. Skip if MMU is already enabled by SPL or other means.
+	 */
+	if (get_sctlr() & CR_M)
+		return 0;
+
+	icache_enable();
+	__asm_invalidate_dcache_all();
+	__asm_invalidate_tlb_all();
+	early_mmu_setup();
+	set_sctlr(get_sctlr() | CR_C);
+	return 0;
+}
+
+void mmu_setup(void)
+{
+	final_mmu_setup();
+}
+
+/*
+ * This function is called from common/board_r.c.
+ * It recreates MMU table in main memory.
+ */
+void enable_caches(void)
+{
+	mmu_setup();
+	__asm_invalidate_tlb_all();
+	icache_enable();
+	dcache_enable();
+}
+#endif	/* CONFIG_SYS_DCACHE_OFF */
+
+#ifdef CONFIG_TFABOOT
+enum boot_src __get_boot_src(u32 porsr1)
+{
+	enum boot_src src = BOOT_SOURCE_RESERVED;
+	u32 rcw_src = (porsr1 & RCW_SRC_MASK) >> RCW_SRC_BIT;
+#if !defined(CONFIG_NXP_LSCH3_2)
+	u32 val;
+#endif
+	debug("%s: rcw_src 0x%x\n", __func__, rcw_src);
+
+#if defined(CONFIG_FSL_LSCH3)
+#if defined(CONFIG_NXP_LSCH3_2)
+	switch (rcw_src) {
+	case RCW_SRC_SDHC1_VAL:
+		src = BOOT_SOURCE_SD_MMC;
+	break;
+	case RCW_SRC_SDHC2_VAL:
+		src = BOOT_SOURCE_SD_MMC2;
+	break;
+	case RCW_SRC_I2C1_VAL:
+		src = BOOT_SOURCE_I2C1_EXTENDED;
+	break;
+	case RCW_SRC_FLEXSPI_NAND2K_VAL:
+		src = BOOT_SOURCE_XSPI_NAND;
+	break;
+	case RCW_SRC_FLEXSPI_NAND4K_VAL:
+		src = BOOT_SOURCE_XSPI_NAND;
+	break;
+	case RCW_SRC_RESERVED_1_VAL:
+		src = BOOT_SOURCE_RESERVED;
+	break;
+	case RCW_SRC_FLEXSPI_NOR_24B:
+		src = BOOT_SOURCE_XSPI_NOR;
+	break;
+	default:
+		src = BOOT_SOURCE_RESERVED;
+	}
+#else
+	val = rcw_src & RCW_SRC_TYPE_MASK;
+	if (val == RCW_SRC_NOR_VAL) {
+		val = rcw_src & NOR_TYPE_MASK;
+
+		switch (val) {
+		case NOR_16B_VAL:
+		case NOR_32B_VAL:
+			src = BOOT_SOURCE_IFC_NOR;
+		break;
+		default:
+			src = BOOT_SOURCE_RESERVED;
+		}
+	} else {
+		/* RCW SRC Serial Flash */
+		val = rcw_src & RCW_SRC_SERIAL_MASK;
+		switch (val) {
+		case RCW_SRC_QSPI_VAL:
+		/* RCW SRC Serial NOR (QSPI) */
+			src = BOOT_SOURCE_QSPI_NOR;
+			break;
+		case RCW_SRC_SD_CARD_VAL:
+		/* RCW SRC SD Card */
+			src = BOOT_SOURCE_SD_MMC;
+			break;
+		case RCW_SRC_EMMC_VAL:
+		/* RCW SRC EMMC */
+			src = BOOT_SOURCE_SD_MMC2;
+			break;
+		case RCW_SRC_I2C1_VAL:
+		/* RCW SRC I2C1 Extended */
+			src = BOOT_SOURCE_I2C1_EXTENDED;
+			break;
+		default:
+			src = BOOT_SOURCE_RESERVED;
+		}
+	}
+#endif
+#elif defined(CONFIG_FSL_LSCH2)
+	/* RCW SRC NAND */
+	val = rcw_src & RCW_SRC_NAND_MASK;
+	if (val == RCW_SRC_NAND_VAL) {
+		val = rcw_src & NAND_RESERVED_MASK;
+		if (val != NAND_RESERVED_1 && val != NAND_RESERVED_2)
+			src = BOOT_SOURCE_IFC_NAND;
+
+	} else {
+		/* RCW SRC NOR */
+		val = rcw_src & RCW_SRC_NOR_MASK;
+		if (val == NOR_8B_VAL || val == NOR_16B_VAL) {
+			src = BOOT_SOURCE_IFC_NOR;
+		} else {
+			switch (rcw_src) {
+			case QSPI_VAL1:
+			case QSPI_VAL2:
+				src = BOOT_SOURCE_QSPI_NOR;
+				break;
+			case SD_VAL:
+				src = BOOT_SOURCE_SD_MMC;
+				break;
+			default:
+				src = BOOT_SOURCE_RESERVED;
+			}
+		}
+	}
+#endif
+
+	if (CONFIG_IS_ENABLED(SYS_FSL_ERRATUM_A010539) && !rcw_src)
+		src = BOOT_SOURCE_QSPI_NOR;
+
+	debug("%s: src 0x%x\n", __func__, src);
+	return src;
+}
+
+enum boot_src get_boot_src(void)
+{
+	struct pt_regs regs;
+	u32 porsr1 = 0;
+
+#if defined(CONFIG_FSL_LSCH3)
+	u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE;
+#elif defined(CONFIG_FSL_LSCH2)
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+#endif
+
+	if (current_el() == 2) {
+		regs.regs[0] = SIP_SVC_RCW;
+
+		smc_call(&regs);
+		if (!regs.regs[0])
+			porsr1 = regs.regs[1];
+	}
+
+	if (current_el() == 3 || !porsr1) {
+#ifdef CONFIG_FSL_LSCH3
+		porsr1 = in_le32(dcfg_ccsr + DCFG_PORSR1 / 4);
+#elif defined(CONFIG_FSL_LSCH2)
+		porsr1 = in_be32(&gur->porsr1);
+#endif
+	}
+
+	debug("%s: porsr1 0x%x\n", __func__, porsr1);
+
+	return __get_boot_src(porsr1);
+}
+
+#ifdef CONFIG_ENV_IS_IN_MMC
+int mmc_get_env_dev(void)
+{
+	enum boot_src src = get_boot_src();
+	int dev = CONFIG_SYS_MMC_ENV_DEV;
+
+	switch (src) {
+	case BOOT_SOURCE_SD_MMC:
+		dev = 0;
+		break;
+	case BOOT_SOURCE_SD_MMC2:
+		dev = 1;
+		break;
+	default:
+		break;
+	}
+
+	return dev;
+}
+#endif
+
+enum env_location env_get_location(enum env_operation op, int prio)
+{
+	enum boot_src src = get_boot_src();
+	enum env_location env_loc = ENVL_NOWHERE;
+
+	if (prio)
+		return ENVL_UNKNOWN;
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+	/* Check Boot Mode
+	 * If Boot Mode is Secure, return ENVL_NOWHERE
+	 */
+	if (fsl_check_boot_mode_secure() == 1)
+		goto done;
+#endif
+
+	switch (src) {
+	case BOOT_SOURCE_IFC_NOR:
+		env_loc = ENVL_FLASH;
+		break;
+	case BOOT_SOURCE_QSPI_NOR:
+		/* FALLTHROUGH */
+	case BOOT_SOURCE_XSPI_NOR:
+		env_loc = ENVL_SPI_FLASH;
+		break;
+	case BOOT_SOURCE_IFC_NAND:
+		/* FALLTHROUGH */
+	case BOOT_SOURCE_QSPI_NAND:
+		/* FALLTHROUGH */
+	case BOOT_SOURCE_XSPI_NAND:
+		env_loc = ENVL_NAND;
+		break;
+	case BOOT_SOURCE_SD_MMC:
+		/* FALLTHROUGH */
+	case BOOT_SOURCE_SD_MMC2:
+		env_loc =  ENVL_MMC;
+		break;
+	case BOOT_SOURCE_I2C1_EXTENDED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+done:
+#endif
+	return env_loc;
+}
+#endif	/* CONFIG_TFABOOT */
+
+u32 initiator_type(u32 cluster, int init_id)
+{
+	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK;
+	u32 type = 0;
+
+	type = gur_in32(&gur->tp_ityp[idx]);
+	if (type & TP_ITYP_AV)
+		return type;
+
+	return 0;
+}
+
+u32 cpu_pos_mask(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int i = 0;
+	u32 cluster, type, mask = 0;
+
+	do {
+		int j;
+
+		cluster = gur_in32(&gur->tp_cluster[i].lower);
+		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+			type = initiator_type(cluster, j);
+			if (type && (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM))
+				mask |= 1 << (i * TP_INIT_PER_CLUSTER + j);
+		}
+		i++;
+	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
+
+	return mask;
+}
+
+u32 cpu_mask(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int i = 0, count = 0;
+	u32 cluster, type, mask = 0;
+
+	do {
+		int j;
+
+		cluster = gur_in32(&gur->tp_cluster[i].lower);
+		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+			type = initiator_type(cluster, j);
+			if (type) {
+				if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)
+					mask |= 1 << count;
+				count++;
+			}
+		}
+		i++;
+	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
+
+	return mask;
+}
+
+/*
+ * Return the number of cores on this SOC.
+ */
+int cpu_numcores(void)
+{
+	return hweight32(cpu_mask());
+}
+
+int fsl_qoriq_core_to_cluster(unsigned int core)
+{
+	struct ccsr_gur __iomem *gur =
+		(void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int i = 0, count = 0;
+	u32 cluster;
+
+	do {
+		int j;
+
+		cluster = gur_in32(&gur->tp_cluster[i].lower);
+		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+			if (initiator_type(cluster, j)) {
+				if (count == core)
+					return i;
+				count++;
+			}
+		}
+		i++;
+	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
+
+	return -1;      /* cannot identify the cluster */
+}
+
+u32 fsl_qoriq_core_to_type(unsigned int core)
+{
+	struct ccsr_gur __iomem *gur =
+		(void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int i = 0, count = 0;
+	u32 cluster, type;
+
+	do {
+		int j;
+
+		cluster = gur_in32(&gur->tp_cluster[i].lower);
+		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+			type = initiator_type(cluster, j);
+			if (type) {
+				if (count == core)
+					return type;
+				count++;
+			}
+		}
+		i++;
+	} while ((cluster & TP_CLUSTER_EOC) == 0x0);
+
+	return -1;      /* cannot identify the cluster */
+}
+
+#ifndef CONFIG_FSL_LSCH3
+uint get_svr(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+
+	return gur_in32(&gur->svr);
+}
+#endif
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+int print_cpuinfo(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	struct sys_info sysinfo;
+	char buf[32];
+	unsigned int i, core;
+	u32 type, rcw, svr = gur_in32(&gur->svr);
+
+	puts("SoC: ");
+
+	cpu_name(buf);
+	printf(" %s (0x%x)\n", buf, svr);
+	memset((u8 *)buf, 0x00, ARRAY_SIZE(buf));
+	get_sys_info(&sysinfo);
+	puts("Clock Configuration:");
+	for_each_cpu(i, core, cpu_numcores(), cpu_mask()) {
+		if (!(i % 3))
+			puts("\n       ");
+		type = TP_ITYP_VER(fsl_qoriq_core_to_type(core));
+		printf("CPU%d(%s):%-4s MHz  ", core,
+		       type == TY_ITYP_VER_A7 ? "A7 " :
+		       (type == TY_ITYP_VER_A53 ? "A53" :
+		       (type == TY_ITYP_VER_A57 ? "A57" :
+		       (type == TY_ITYP_VER_A72 ? "A72" : "   "))),
+		       strmhz(buf, sysinfo.freq_processor[core]));
+	}
+	/* Display platform clock as Bus frequency. */
+	printf("\n       Bus:      %-4s MHz  ",
+	       strmhz(buf, sysinfo.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV));
+	printf("DDR:      %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus));
+#ifdef CONFIG_SYS_DPAA_FMAN
+	printf("  FMAN:     %-4s MHz", strmhz(buf, sysinfo.freq_fman[0]));
+#endif
+#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
+	if (soc_has_dp_ddr()) {
+		printf("     DP-DDR:   %-4s MT/s",
+		       strmhz(buf, sysinfo.freq_ddrbus2));
+	}
+#endif
+	puts("\n");
+
+	/*
+	 * Display the RCW, so that no one gets confused as to what RCW
+	 * we're actually using for this boot.
+	 */
+	puts("Reset Configuration Word (RCW):");
+	for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) {
+		rcw = gur_in32(&gur->rcwsr[i]);
+		if ((i % 4) == 0)
+			printf("\n       %08x:", i * 4);
+		printf(" %08x", rcw);
+	}
+	puts("\n");
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FSL_ESDHC
+int cpu_mmc_init(bd_t *bis)
+{
+	return fsl_esdhc_mmc_init(bis);
+}
+#endif
+
+int cpu_eth_init(bd_t *bis)
+{
+	int error = 0;
+
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+	error = fsl_mc_ldpaa_init(bis);
+#endif
+#ifdef CONFIG_FMAN_ENET
+	fm_standard_init(bis);
+#endif
+	return error;
+}
+
+static inline int check_psci(void)
+{
+	unsigned int psci_ver;
+
+	psci_ver = sec_firmware_support_psci_version();
+	if (psci_ver == PSCI_INVALID_VER)
+		return 1;
+
+	return 0;
+}
+
+static void config_core_prefetch(void)
+{
+	char *buf = NULL;
+	char buffer[HWCONFIG_BUFFER_SIZE];
+	const char *prefetch_arg = NULL;
+	size_t arglen;
+	unsigned int mask;
+	struct pt_regs regs;
+
+	if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0)
+		buf = buffer;
+
+	prefetch_arg = hwconfig_subarg_f("core_prefetch", "disable",
+					 &arglen, buf);
+
+	if (prefetch_arg) {
+		mask = simple_strtoul(prefetch_arg, NULL, 0) & 0xff;
+		if (mask & 0x1) {
+			printf("Core0 prefetch can't be disabled\n");
+			return;
+		}
+
+#define SIP_PREFETCH_DISABLE_64 0xC200FF13
+		regs.regs[0] = SIP_PREFETCH_DISABLE_64;
+		regs.regs[1] = mask;
+		smc_call(&regs);
+
+		if (regs.regs[0])
+			printf("Prefetch disable config failed for mask ");
+		else
+			printf("Prefetch disable config passed for mask ");
+		printf("0x%x\n", mask);
+	}
+}
+
+int arch_early_init_r(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
+	u32 svr_dev_id;
+	/*
+	 * erratum A009635 is valid only for LS2080A SoC and
+	 * its personalitiesi
+	 */
+	svr_dev_id = get_svr();
+	if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A)))
+		erratum_a009635();
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR)
+	erratum_a009942_check_cpo();
+#endif
+	if (check_psci()) {
+		debug("PSCI: PSCI does not exist.\n");
+
+		/* if PSCI does not exist, boot secondary cores here */
+		if (fsl_layerscape_wake_seconday_cores())
+			printf("Did not wake secondary cores\n");
+	}
+
+#ifdef CONFIG_SYS_FSL_HAS_RGMII
+	fsl_rgmii_init();
+#endif
+
+	config_core_prefetch();
+
+#ifdef CONFIG_SYS_HAS_SERDES
+	fsl_serdes_init();
+#endif
+#ifdef CONFIG_FMAN_ENET
+	fman_enet_init();
+#endif
+#ifdef CONFIG_SYS_DPAA_QBMAN
+	setup_qbman_portals();
+#endif
+	return 0;
+}
+
+int timer_init(void)
+{
+	u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
+#ifdef CONFIG_FSL_LSCH3
+	u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
+#endif
+#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A)
+	u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET;
+	u32 svr_dev_id;
+#endif
+#ifdef COUNTER_FREQUENCY_REAL
+	unsigned long cntfrq = COUNTER_FREQUENCY_REAL;
+
+	/* Update with accurate clock frequency */
+	if (current_el() == 3)
+		asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
+#endif
+
+#ifdef CONFIG_FSL_LSCH3
+	/* Enable timebase for all clusters.
+	 * It is safe to do so even some clusters are not enabled.
+	 */
+	out_le32(cltbenr, 0xf);
+#endif
+
+#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A)
+	/*
+	 * In certain Layerscape SoCs, the clock for each core's
+	 * has an enable bit in the PMU Physical Core Time Base Enable
+	 * Register (PCTBENR), which allows the watchdog to operate.
+	 */
+	setbits_le32(pctbenr, 0xff);
+	/*
+	 * For LS2080A SoC and its personalities, timer controller
+	 * offset is different
+	 */
+	svr_dev_id = get_svr();
+	if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A)))
+		cntcr = (u32 *)SYS_FSL_LS2080A_LS2085A_TIMER_ADDR;
+
+#endif
+
+	/* Enable clock for timer
+	 * This is a global setting.
+	 */
+	out_le32(cntcr, 0x1);
+
+	return 0;
+}
+
+__efi_runtime_data u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR;
+
+void __efi_runtime reset_cpu(ulong addr)
+{
+	u32 val;
+
+#ifdef CONFIG_ARCH_LX2160A
+	val = in_le32(rstcr);
+	val |= 0x01;
+	out_le32(rstcr, val);
+#else
+	/* Raise RESET_REQ_B */
+	val = scfg_in32(rstcr);
+	val |= 0x02;
+	scfg_out32(rstcr, val);
+#endif
+}
+
+#ifdef CONFIG_EFI_LOADER
+
+void __efi_runtime EFIAPI efi_reset_system(
+		       enum efi_reset_type reset_type,
+		       efi_status_t reset_status,
+		       unsigned long data_size, void *reset_data)
+{
+	switch (reset_type) {
+	case EFI_RESET_COLD:
+	case EFI_RESET_WARM:
+	case EFI_RESET_PLATFORM_SPECIFIC:
+		reset_cpu(0);
+		break;
+	case EFI_RESET_SHUTDOWN:
+		/* Nothing we can do */
+		break;
+	}
+
+	while (1) { }
+}
+
+efi_status_t efi_reset_system_init(void)
+{
+	return efi_add_runtime_mmio(&rstcr, sizeof(*rstcr));
+}
+
+#endif
+
+/*
+ * Calculate reserved memory with given memory bank
+ * Return aligned memory size on success
+ * Return (ram_size + needed size) for failure
+ */
+phys_size_t board_reserve_ram_top(phys_size_t ram_size)
+{
+	phys_size_t ram_top = ram_size;
+
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+	ram_top = mc_get_dram_block_size();
+	if (ram_top > ram_size)
+		return ram_size + ram_top;
+
+	ram_top = ram_size - ram_top;
+	/* The start address of MC reserved memory needs to be aligned. */
+	ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1);
+#endif
+
+	return ram_size - ram_top;
+}
+
+phys_size_t get_effective_memsize(void)
+{
+	phys_size_t ea_size, rem = 0;
+
+	/*
+	 * For ARMv8 SoCs, DDR memory is split into two or three regions. The
+	 * first region is 2GB space at 0x8000_0000. Secure memory needs to
+	 * allocated from first region. If the memory extends to  the second
+	 * region (or the third region if applicable), Management Complex (MC)
+	 * memory should be put into the highest region, i.e. the end of DDR
+	 * memory. CONFIG_MAX_MEM_MAPPED is set to the size of first region so
+	 * U-Boot doesn't relocate itself into higher address. Should DDR be
+	 * configured to skip the first region, this function needs to be
+	 * adjusted.
+	 */
+	if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) {
+		ea_size = CONFIG_MAX_MEM_MAPPED;
+		rem = gd->ram_size - ea_size;
+	} else {
+		ea_size = gd->ram_size;
+	}
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	/* Check if we have enough space for secure memory */
+	if (ea_size > CONFIG_SYS_MEM_RESERVE_SECURE)
+		ea_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
+	else
+		printf("Error: No enough space for secure memory.\n");
+#endif
+	/* Check if we have enough memory for MC */
+	if (rem < board_reserve_ram_top(rem)) {
+		/* Not enough memory in high region to reserve */
+		if (ea_size > board_reserve_ram_top(ea_size))
+			ea_size -= board_reserve_ram_top(ea_size);
+		else
+			printf("Error: No enough space for reserved memory.\n");
+	}
+
+	return ea_size;
+}
+
+#ifdef CONFIG_TFABOOT
+phys_size_t tfa_get_dram_size(void)
+{
+	struct pt_regs regs;
+	phys_size_t dram_size = 0;
+
+	regs.regs[0] = SMC_DRAM_BANK_INFO;
+	regs.regs[1] = -1;
+
+	smc_call(&regs);
+	if (regs.regs[0])
+		return 0;
+
+	dram_size = regs.regs[1];
+	return dram_size;
+}
+
+static int tfa_dram_init_banksize(void)
+{
+	int i = 0, ret = 0;
+	struct pt_regs regs;
+	phys_size_t dram_size = tfa_get_dram_size();
+
+	debug("dram_size %llx\n", dram_size);
+
+	if (!dram_size)
+		return -EINVAL;
+
+	do {
+		regs.regs[0] = SMC_DRAM_BANK_INFO;
+		regs.regs[1] = i;
+
+		smc_call(&regs);
+		if (regs.regs[0]) {
+			ret = -EINVAL;
+			break;
+		}
+
+		debug("bank[%d]: start %lx, size %lx\n", i, regs.regs[1],
+		      regs.regs[2]);
+		gd->bd->bi_dram[i].start = regs.regs[1];
+		gd->bd->bi_dram[i].size = regs.regs[2];
+
+		dram_size -= gd->bd->bi_dram[i].size;
+
+		i++;
+	} while (dram_size);
+
+	if (i > 0)
+		ret = 0;
+
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+	/* Assign memory for MC */
+#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
+	if (gd->bd->bi_dram[2].size >=
+	    board_reserve_ram_top(gd->bd->bi_dram[2].size)) {
+		gd->arch.resv_ram = gd->bd->bi_dram[2].start +
+			    gd->bd->bi_dram[2].size -
+			    board_reserve_ram_top(gd->bd->bi_dram[2].size);
+	} else
+#endif
+	{
+		if (gd->bd->bi_dram[1].size >=
+		    board_reserve_ram_top(gd->bd->bi_dram[1].size)) {
+			gd->arch.resv_ram = gd->bd->bi_dram[1].start +
+				gd->bd->bi_dram[1].size -
+				board_reserve_ram_top(gd->bd->bi_dram[1].size);
+		} else if (gd->bd->bi_dram[0].size >
+			   board_reserve_ram_top(gd->bd->bi_dram[0].size)) {
+			gd->arch.resv_ram = gd->bd->bi_dram[0].start +
+				gd->bd->bi_dram[0].size -
+				board_reserve_ram_top(gd->bd->bi_dram[0].size);
+		}
+	}
+#endif	/* CONFIG_FSL_MC_ENET */
+
+	return ret;
+}
+#endif
+
+int dram_init_banksize(void)
+{
+#ifdef CONFIG_SYS_DP_DDR_BASE_PHY
+	phys_size_t dp_ddr_size;
+#endif
+
+#ifdef CONFIG_TFABOOT
+	if (!tfa_dram_init_banksize())
+		return 0;
+#endif
+	/*
+	 * gd->ram_size has the total size of DDR memory, less reserved secure
+	 * memory. The DDR extends from low region to high region(s) presuming
+	 * no hole is created with DDR configuration. gd->arch.secure_ram tracks
+	 * the location of secure memory. gd->arch.resv_ram tracks the location
+	 * of reserved memory for Management Complex (MC). Because gd->ram_size
+	 * is reduced by this function if secure memory is reserved, checking
+	 * gd->arch.secure_ram should be done to avoid running it repeatedly.
+	 */
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) {
+		debug("No need to run again, skip %s\n", __func__);
+
+		return 0;
+	}
+#endif
+
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	if (gd->ram_size > CONFIG_SYS_DDR_BLOCK1_SIZE) {
+		gd->bd->bi_dram[0].size = CONFIG_SYS_DDR_BLOCK1_SIZE;
+		gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE;
+		gd->bd->bi_dram[1].size = gd->ram_size -
+					  CONFIG_SYS_DDR_BLOCK1_SIZE;
+#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
+		if (gd->bi_dram[1].size > CONFIG_SYS_DDR_BLOCK2_SIZE) {
+			gd->bd->bi_dram[2].start = CONFIG_SYS_DDR_BLOCK3_BASE;
+			gd->bd->bi_dram[2].size = gd->bd->bi_dram[1].size -
+						  CONFIG_SYS_DDR_BLOCK2_SIZE;
+			gd->bd->bi_dram[1].size = CONFIG_SYS_DDR_BLOCK2_SIZE;
+		}
+#endif
+	} else {
+		gd->bd->bi_dram[0].size = gd->ram_size;
+	}
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	if (gd->bd->bi_dram[0].size >
+				CONFIG_SYS_MEM_RESERVE_SECURE) {
+		gd->bd->bi_dram[0].size -=
+				CONFIG_SYS_MEM_RESERVE_SECURE;
+		gd->arch.secure_ram = gd->bd->bi_dram[0].start +
+				      gd->bd->bi_dram[0].size;
+		gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED;
+		gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
+	}
+#endif	/* CONFIG_SYS_MEM_RESERVE_SECURE */
+
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+	/* Assign memory for MC */
+#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
+	if (gd->bd->bi_dram[2].size >=
+	    board_reserve_ram_top(gd->bd->bi_dram[2].size)) {
+		gd->arch.resv_ram = gd->bd->bi_dram[2].start +
+			    gd->bd->bi_dram[2].size -
+			    board_reserve_ram_top(gd->bd->bi_dram[2].size);
+	} else
+#endif
+	{
+		if (gd->bd->bi_dram[1].size >=
+		    board_reserve_ram_top(gd->bd->bi_dram[1].size)) {
+			gd->arch.resv_ram = gd->bd->bi_dram[1].start +
+				gd->bd->bi_dram[1].size -
+				board_reserve_ram_top(gd->bd->bi_dram[1].size);
+		} else if (gd->bd->bi_dram[0].size >
+			   board_reserve_ram_top(gd->bd->bi_dram[0].size)) {
+			gd->arch.resv_ram = gd->bd->bi_dram[0].start +
+				gd->bd->bi_dram[0].size -
+				board_reserve_ram_top(gd->bd->bi_dram[0].size);
+		}
+	}
+#endif	/* CONFIG_FSL_MC_ENET */
+
+#ifdef CONFIG_SYS_DP_DDR_BASE_PHY
+#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
+#error "This SoC shouldn't have DP DDR"
+#endif
+	if (soc_has_dp_ddr()) {
+		/* initialize DP-DDR here */
+		puts("DP-DDR:  ");
+		/*
+		 * DDR controller use 0 as the base address for binding.
+		 * It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access.
+		 */
+		dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY,
+					  CONFIG_DP_DDR_CTRL,
+					  CONFIG_DP_DDR_NUM_CTRLS,
+					  CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR,
+					  NULL, NULL, NULL);
+		if (dp_ddr_size) {
+			gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE;
+			gd->bd->bi_dram[2].size = dp_ddr_size;
+		} else {
+			puts("Not detected");
+		}
+	}
+#endif
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	debug("%s is called. gd->ram_size is reduced to %lu\n",
+	      __func__, (ulong)gd->ram_size);
+#endif
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+void efi_add_known_memory(void)
+{
+	int i;
+	phys_addr_t ram_start, start;
+	phys_size_t ram_size;
+	u64 pages;
+
+	/* Add RAM */
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+#ifdef CONFIG_SYS_DP_DDR_BASE_PHY
+#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
+#error "This SoC shouldn't have DP DDR"
+#endif
+		if (i == 2)
+			continue;	/* skip DP-DDR */
+#endif
+		ram_start = gd->bd->bi_dram[i].start;
+		ram_size = gd->bd->bi_dram[i].size;
+#ifdef CONFIG_RESV_RAM
+		if (gd->arch.resv_ram >= ram_start &&
+		    gd->arch.resv_ram < ram_start + ram_size)
+			ram_size = gd->arch.resv_ram - ram_start;
+#endif
+		start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
+		pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+
+		efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY,
+				   false);
+	}
+}
+#endif
+
+/*
+ * Before DDR size is known, early MMU table have DDR mapped as device memory
+ * to avoid speculative access. To relocate U-Boot to DDR, "normal memory"
+ * needs to be set for these mappings.
+ * If a special case configures DDR with holes in the mapping, the holes need
+ * to be marked as invalid. This is not implemented in this function.
+ */
+void update_early_mmu_table(void)
+{
+	if (!gd->arch.tlb_addr)
+		return;
+
+	if (gd->ram_size <= CONFIG_SYS_FSL_DRAM_SIZE1) {
+		mmu_change_region_attr(
+					CONFIG_SYS_SDRAM_BASE,
+					gd->ram_size,
+					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
+					PTE_BLOCK_OUTER_SHARE		|
+					PTE_BLOCK_NS			|
+					PTE_TYPE_VALID);
+	} else {
+		mmu_change_region_attr(
+					CONFIG_SYS_SDRAM_BASE,
+					CONFIG_SYS_DDR_BLOCK1_SIZE,
+					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
+					PTE_BLOCK_OUTER_SHARE		|
+					PTE_BLOCK_NS			|
+					PTE_TYPE_VALID);
+#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
+#ifndef CONFIG_SYS_DDR_BLOCK2_SIZE
+#error "Missing CONFIG_SYS_DDR_BLOCK2_SIZE"
+#endif
+		if (gd->ram_size - CONFIG_SYS_DDR_BLOCK1_SIZE >
+		    CONFIG_SYS_DDR_BLOCK2_SIZE) {
+			mmu_change_region_attr(
+					CONFIG_SYS_DDR_BLOCK2_BASE,
+					CONFIG_SYS_DDR_BLOCK2_SIZE,
+					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
+					PTE_BLOCK_OUTER_SHARE		|
+					PTE_BLOCK_NS			|
+					PTE_TYPE_VALID);
+			mmu_change_region_attr(
+					CONFIG_SYS_DDR_BLOCK3_BASE,
+					gd->ram_size -
+					CONFIG_SYS_DDR_BLOCK1_SIZE -
+					CONFIG_SYS_DDR_BLOCK2_SIZE,
+					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
+					PTE_BLOCK_OUTER_SHARE		|
+					PTE_BLOCK_NS			|
+					PTE_TYPE_VALID);
+		} else
+#endif
+		{
+			mmu_change_region_attr(
+					CONFIG_SYS_DDR_BLOCK2_BASE,
+					gd->ram_size -
+					CONFIG_SYS_DDR_BLOCK1_SIZE,
+					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
+					PTE_BLOCK_OUTER_SHARE		|
+					PTE_BLOCK_NS			|
+					PTE_TYPE_VALID);
+		}
+	}
+}
+
+__weak int dram_init(void)
+{
+	fsl_initdram();
+#if (!defined(CONFIG_SPL) && !defined(CONFIG_TFABOOT)) || \
+	defined(CONFIG_SPL_BUILD)
+	/* This will break-before-make MMU for DDR */
+	update_early_mmu_table();
+#endif
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.h b/arch/arm/cpu/armv8/fsl-layerscape/cpu.h
new file mode 100644
index 0000000..dca5fd0
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2014-2015, Freescale Semiconductor
+ */
+
+int fsl_qoriq_core_to_cluster(unsigned int core);
+u32 initiator_type(u32 cluster, int init_id);
+u32 cpu_mask(void);
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch
new file mode 100644
index 0000000..85cf6ab
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch
@@ -0,0 +1,20 @@
+Core instruction prefetch disable
+---------------------------------
+To disable instruction prefetch of core; hwconfig needs to be updated.
+for e.g.
+setenv hwconfig 'fsl_ddr:bank_intlv=auto;core_prefetch:disable=0x02'
+
+Here 0x02 can be replaced with any valid value except Mask[0] bit. It
+represents 64 bit mask. The 64-bit Mask has one bit for each core.
+Mask[0] = core0
+Mask[1] = core1
+Mask[2] = core2
+etc
+If the bit is set ('b1) in the mask, then prefetch is disabled for
+that core when it is released from reset.
+
+core0 prefetch should not be disabled i.e. Mask[0] should never be set.
+Setting Mask[0] may lead to undefined behavior.
+
+Once disabled, prefetch remains disabled until the next reset.
+There is no function to re-enable prefetch.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon
new file mode 100644
index 0000000..b3c6693
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon
@@ -0,0 +1,150 @@
+Falcon boot option
+------------------
+Falcon boot is a short cut boot method for SD/eMMC targets. It skips loading the
+RAM version U-Boot. Instead, it loads FIT image and boot directly to Linux.
+CONFIG_SPL_OS_BOOT enables falcon boot. CONFIG_SPL_LOAD_FIT enables the FIT
+image support (also need CONFIG_SPL_OF_LIBFDT, CONFIG_SPL_FIT and optionally
+CONFIG_SPL_GZIP).
+
+To enable falcon boot, a hook function spl_start_uboot() returns 0 to indicate
+booting U-Boot is not the first choice. The kernel FIT image needs to be put
+at CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR. SPL mmc driver reads the header to
+determine if this is a FIT image. If true, FIT image components are parsed and
+copied or decompressed (if applicable) to their destinations. If FIT image is
+not found, normal U-Boot flow will follow.
+
+An important part of falcon boot is to prepare the device tree. A normal U-Boot
+does FDT fixups when booting Linux. For falcon boot, Linux boots directly from
+SPL, skipping the normal U-Boot. The device tree has to be prepared in advance.
+A command "spl export" should be called under the normal RAM version U-Boot.
+It is equivalent to go through "bootm" step-by-step until device tree fixup is
+done. The device tree in memory is the one needed for falcon boot. Falcon boot
+flow suggests to save this image to SD/eMMC at the location pointed by macro
+CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, with maximum size specified by macro
+CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS. However, when FIT image is used for
+Linux, the device tree stored in FIT image overwrites the memory loaded by spl
+driver from these sectors. We could change this loading order to favor the
+stored sectors. But when secure boot is enabled, these sectors are used for
+signature header and needs to be loaded before the FIT image. So it is important
+to understand the device tree in FIT image should be the one actually used, or
+leave it absent to favor the stored sectors. It is easier to deploy the FIT
+image with embedded static device tree to multiple boards.
+
+Macro CONFIG_SYS_SPL_ARGS_ADDR serves two purposes. One is the pointer to load
+the stored sectors to. Normally this is the static device tree. The second
+purpose is the memory location of signature header for secure boot. After the
+FIT image is loaded into memory, it is validated against the signature header
+before individual components are extracted (and optionally decompressed) into
+their final memory locations, respectively. After the validation, the header
+is no longer used. The static device tree is copied into this location. So
+this macro is passed as the location of device tree when booting Linux.
+
+Steps to prepare static device tree
+-----------------------------------
+To prepare the static device tree for Layerscape boards, it is important to
+understand the fixups in U-Boot. Memory size and location, as well as reserved
+memory blocks are added/updated. Ethernet MAC addressed are updated. FMan
+microcode (if used) is embedded in the device tree. Kernel command line and
+initrd information are embedded. Others including CPU status, boot method,
+Ethernet port status, etc. are also updated.
+
+Following normal booting process, all variables are set, all images are loaded
+before "bootm" command would be issued to boot, run command
+
+spl export fdt <address>
+
+where the address is the location of FIT image. U-Boot goes through the booting
+process as if "bootm start", "bootm loados", "bootm ramdisk"... commands but
+stops before "bootm go". There we have the fixed-up device tree in memory.
+We can check the device tree header by these commands
+
+fdt addr <fdt address>
+fdt header
+
+Where the fdt address is the device tree in memory. It is printed by U-Boot.
+It is useful to know the exact size. One way to extract this static device
+tree is to save it to eMMC/SD using command in U-Boot, and extract under Linux
+with these commands, repectively
+
+mmc write <address> <sector> <sectors>
+dd if=/dev/mmcblk0 of=<filename> bs=512 skip=<sector> count=<sectors>
+
+Note, U-Boot takes values as hexadecimals while Linux takes them as decimals by
+default. If using NAND or other storage, the commands are slightly different.
+When we have the static device tree image, we can re-make the FIT image with
+it. It is important to specify the load addresses in FIT image for every
+components. Otherwise U-Boot cannot load them correctly.
+
+Generate FIT image with static device tree
+------------------------------------------
+Example:
+
+/dts-v1/;
+
+/ {
+	description = "Image file for the LS1043A Linux Kernel";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			description = "ARM64 Linux kernel";
+			data = /incbin/("./arch/arm64/boot/Image.gz");
+			type = "kernel";
+			arch = "arm64";
+			os = "linux";
+			compression = "gzip";
+			load = <0x80080000>;
+			entry = <0x80080000>;
+		};
+		fdt-1 {
+			description = "Flattened Device Tree blob";
+			data = /incbin/("./fsl-ls1043ardb-static.dtb");
+			type = "flat_dt";
+			arch = "arm64";
+			compression = "none";
+			load = <0x90000000>;
+		};
+		ramdisk {
+			description = "LS1043 Ramdisk";
+                        data = /incbin/("./rootfs.cpio.gz");
+			type = "ramdisk";
+			arch = "arm64";
+			os = "linux";
+			compression = "none";
+			load = <0xa0000000>;
+		};
+	};
+
+	configurations {
+		default = "config-1";
+		config-1 {
+			description = "Boot Linux kernel";
+			kernel = "kernel";
+			fdt = "fdt-1";
+			ramdisk = "ramdisk";
+			loadables = "fdt", "ramdisk";
+		};
+	};
+};
+
+The "loadables" is not optional. It tells SPL which images to load into memory.
+
+Falcon mode with QSPI boot
+--------------------------
+To use falcon mode with QSPI boot, SPL needs to be enabled. Similar to SD or
+NAND boot, a RAM version full feature U-Boot is needed. Unlike SD or NAND boot,
+SPL with QSPI doesn't need to combine SPL image with RAM version image. Two
+separated images are used, u-boot-spl.pbl and u-boot.img. The former is SPL
+image with RCW and PBI commands to load the SPL payload into On-Chip RAM. The
+latter is RAM version U-Boot in FIT format (or legacy format if FIT is not
+used).
+
+Other things to consider
+-----------------------
+Falcon boot skips a lot of initialization in U-Boot. If Linux expects the
+hardware to be initialized by U-Boot, the related code should be ported to SPL
+build. For example, if Linux expect Ethernet PHY to be initialized in U-Boot
+(which is not a common case), the PHY initialization has to be included in
+falcon boot. This increases the SPL image size and should be handled carefully.
+If Linux has PHY driver enabled, it still depends on the correct MDIO bus setup
+in U-Boot. Normal U-Boot sets the MDC ratio to generate a proper clock signal.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2
new file mode 100644
index 0000000..9583bf7
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2
@@ -0,0 +1,21 @@
+#
+# Copyright 2015 Freescale Semiconductor
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+Freescale LayerScape with Chassis Generation 2
+
+This architecture supports Freescale ARMv8 SoCs with Chassis generation 2,
+for example LS1043A.
+
+Watchdog support Overview
+-------------------
+Support watchdog driver for LSCH2. The driver is disabled in default.
+You can enable it by setting CONFIG_IMX_WATCHDOG.
+Use following config to set watchdog timeout, if this config is not defined,
+the default timeout value is 128s which is the maximum. Set 10 seconds for
+example:
+    #define CONFIG_WATCHDOG_TIMEOUT_MSECS 10000
+Set CONFIG_WATCHDOG_RESET_DISABLE to disable reset watchdog, so that the
+watchdog will not be fed in u-boot.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
new file mode 100644
index 0000000..6c98d99
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
@@ -0,0 +1,400 @@
+#
+# Copyright 2014-2015 Freescale Semiconductor
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+Freescale LayerScape with Chassis Generation 3
+
+This architecture supports Freescale ARMv8 SoCs with Chassis generation 3,
+for example LS2080A.
+
+DDR Layout
+============
+Entire DDR region splits into two regions.
+ - Region 1 is at address 0x8000_0000 to 0xffff_ffff.
+ - Region 2 is at 0x80_8000_0000 to the top of total memory,
+   for example 16GB, 0x83_ffff_ffff.
+
+All DDR memory is marked as cache-enabled.
+
+When MC and Debug server is enabled, they carve 512MB away from the high
+end of DDR. For example, if the total DDR is 16GB, it shrinks to 15.5GB
+with MC and Debug server enabled. Linux only sees 15.5GB.
+
+The reserved 512MB layout looks like
+
+   +---------------+ <-- top/end of memory
+   |    256MB      |  debug server
+   +---------------+
+   |    256MB      |  MC
+   +---------------+
+   |     ...       |
+
+MC requires the memory to be aligned with 512MB, so even debug server is
+not enabled, 512MB is reserved, not 256MB.
+
+Flash Layout
+============
+
+(1) A typical layout of various images (including Linux and other firmware images)
+   is shown below considering a 32MB NOR flash device present on most
+   pre-silicon platforms (simulator and emulator):
+
+	-------------------------
+	| 	FIT Image	|
+	| (linux + DTB + RFS)	|
+	------------------------- ----> 0x0120_0000
+	| 	Debug Server FW |
+	------------------------- ----> 0x00C0_0000
+	|	AIOP FW 	|
+	------------------------- ----> 0x0070_0000
+	|	MC FW 		|
+	------------------------- ----> 0x006C_0000
+	| 	MC DPL Blob 	|
+	------------------------- ----> 0x0020_0000
+	| 	BootLoader + Env|
+	------------------------- ----> 0x0000_1000
+	|	PBI 		|
+	------------------------- ----> 0x0000_0080
+	|	RCW 		|
+	------------------------- ----> 0x0000_0000
+
+	32-MB NOR flash layout for pre-silicon platforms (simulator and emulator)
+
+(2) A typical layout of various images (including Linux and other firmware images)
+    is shown below considering a 128MB NOR flash device present on QDS and RDB
+    boards:
+	----------------------------------------- ----> 0x5_8800_0000 ---
+	|	.. Unused .. (7M)		|			|
+	----------------------------------------- ----> 0x5_8790_0000	|
+	| FIT Image (linux + DTB + RFS)	(40M)	|			|
+	----------------------------------------- ----> 0x5_8510_0000	|
+	|	PHY firmware (2M)	 	|			|
+	----------------------------------------- ----> 0x5_84F0_0000	| 64K
+	|	Debug Server FW (2M)		|			| Alt
+	----------------------------------------- ----> 0x5_84D0_0000	| Bank
+	|	AIOP FW (4M)			|			|
+	----------------------------------------- ----> 0x5_8490_0000 (vbank4)
+	|	MC DPC Blob (1M) 		|			|
+	----------------------------------------- ----> 0x5_8480_0000	|
+	|	MC DPL Blob (1M)		|			|
+	----------------------------------------- ----> 0x5_8470_0000	|
+	| 	MC FW (4M)			|			|
+	----------------------------------------- ----> 0x5_8430_0000	|
+	|	BootLoader Environment (1M) 	|			|
+	----------------------------------------- ----> 0x5_8420_0000	|
+	|	BootLoader (1M)			|			|
+	----------------------------------------- ----> 0x5_8410_0000	|
+	|	RCW and PBI (1M) 		|			|
+	----------------------------------------- ----> 0x5_8400_0000 ---
+	|	.. Unused .. (7M)		|			|
+	----------------------------------------- ----> 0x5_8390_0000	|
+	| FIT Image (linux + DTB + RFS)	(40M)	|			|
+	----------------------------------------- ----> 0x5_8110_0000	|
+	|	PHY firmware (2M)	 	|			|
+	----------------------------------------- ----> 0x5_80F0_0000	| 64K
+	|	Debug Server FW (2M)		|			| Bank
+	----------------------------------------- ----> 0x5_80D0_0000	|
+	|	AIOP FW (4M)			|			|
+	----------------------------------------- ----> 0x5_8090_0000 (vbank0)
+	|	MC DPC Blob (1M) 		|			|
+	----------------------------------------- ----> 0x5_8080_0000	|
+	|	MC DPL Blob (1M)		|			|
+	----------------------------------------- ----> 0x5_8070_0000	|
+	| 	MC FW (4M)			|			|
+	----------------------------------------- ----> 0x5_8030_0000	|
+	|	BootLoader Environment (1M) 	|			|
+	----------------------------------------- ----> 0x5_8020_0000	|
+	|	BootLoader (1M)			|			|
+	----------------------------------------- ----> 0x5_8010_0000	|
+	|	RCW and PBI (1M) 		|			|
+	----------------------------------------- ----> 0x5_8000_0000 ---
+
+	128-MB NOR flash layout for QDS and RDB boards
+
+Environment Variables
+=====================
+mcboottimeout:	MC boot timeout in milliseconds. If this variable is not defined
+		the value CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS will be assumed.
+
+mcmemsize:	MC DRAM block size in hex. If this variable is not defined, the value
+		CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE will be assumed.
+
+mcinitcmd:	This environment variable is defined to initiate MC and DPL deployment
+		from the location where it is stored(NOR, NAND, SD, SATA, USB)during
+		u-boot booting.If this variable is not defined then MC_BOOT_ENV_VAR
+		will be null and MC will not be booted and DPL will not be applied
+		during U-boot booting.However the MC, DPC and DPL can be applied from
+		console independently.
+		The variable needs to be set from the console once and then on
+		rebooting the parameters set in the variable will automatically be
+		executed. The commmand is demostrated taking an example of mc boot
+		using NOR Flash i.e. MC, DPL, and DPC is stored in the NOR flash:
+
+		cp.b 0xa0000000 0x580300000 $filesize
+		cp.b 0x80000000 0x580800000 $filesize
+		cp.b 0x90000000 0x580700000 $filesize
+
+		setenv mcinitcmd 'fsl_mc start mc 0x580300000 0x580800000'
+
+		If only linux is to be booted then the mcinitcmd environment should be set as
+
+		setenv mcinitcmd 'fsl_mc start mc 0x580300000 0x580800000;fsl_mc apply DPL 0x580700000'
+
+		Here the addresses 0xa0000000, 0x80000000, 0x80000000 are of DDR to where
+		MC binary, DPC binary and DPL binary are stored and 0x580300000, 0x580800000
+		and 0x580700000 are addresses in NOR where these are copied. It is to be
+		noted that these addresses in 'fsl_mc start mc 0x580300000 0x580800000;fsl_mc apply DPL 0x580700000'
+		can be replaced with the addresses of DDR to
+		which these will be copied in case of these binaries being stored in other
+		devices like SATA, USB, NAND, SD etc.
+
+Booting from NAND
+-------------------
+Booting from NAND requires two images, RCW and u-boot-with-spl.bin.
+The difference between NAND boot RCW image and NOR boot image is the PBI
+command sequence. Below is one example for PBI commands for LS2085AQDS which
+uses NAND device with 2KB/page, block size 128KB.
+
+1) CCSR 4-byte write to 0x00e00404, data=0x00000000
+2) CCSR 4-byte write to 0x00e00400, data=0x1800a000
+The above two commands set bootloc register to 0x00000000_1800a000 where
+the u-boot code will be running in OCRAM.
+
+3) Block Copy: SRC=0x0107, SRC_ADDR=0x00020000, DEST_ADDR=0x1800a000,
+BLOCK_SIZE=0x00014000
+This command copies u-boot image from NAND device into OCRAM. The values need
+to adjust accordingly.
+
+SRC		should match the cfg_rcw_src, the reset config pins. It depends
+		on the NAND device. See reference manual for cfg_rcw_src.
+SRC_ADDR	is the offset of u-boot-with-spl.bin image in NAND device. In
+		the example above, 128KB. For easy maintenance, we put it at
+		the beginning of next block from RCW.
+DEST_ADDR	is fixed at 0x1800a000, matching bootloc set above.
+BLOCK_SIZE	is the size to be copied by PBI.
+
+RCW image should be written to the beginning of NAND device. Example of using
+u-boot command
+
+nand write <rcw image in memory> 0 <size of rcw image>
+
+To form the NAND image, build u-boot with NAND config, for example,
+ls2080aqds_nand_defconfig. The image needed is u-boot-with-spl.bin.
+The u-boot image should be written to match SRC_ADDR, in above example 0x20000.
+
+nand write <u-boot image in memory> 200000 <size of u-boot image>
+
+With these two images in NAND device, the board can boot from NAND.
+
+Another example for LS2085ARDB boards,
+
+1) CCSR 4-byte write to 0x00e00404, data=0x00000000
+2) CCSR 4-byte write to 0x00e00400, data=0x1800a000
+3) Block Copy: SRC=0x0119, SRC_ADDR=0x00080000, DEST_ADDR=0x1800a000,
+BLOCK_SIZE=0x00014000
+
+nand write <rcw image in memory> 0 <size of rcw image>
+nand write <u-boot image in memory> 80000 <size of u-boot image>
+
+Notice the difference from QDS is SRC, SRC_ADDR and the offset of u-boot image
+to match board NAND device with 4KB/page, block size 512KB.
+
+Note, LS2088A and LS1088A don't support booting from NAND.
+
+Booting from SD/eMMC
+-------------------
+Booting from SD/eMMC requires two images, RCW and u-boot-with-spl.bin.
+The difference between SD boot RCW image and QSPI-NOR boot image is the
+PBI command sequence. Below is one example for PBI commands for RDB
+and QDS which uses SD device with block size 512. Block location can be
+calculated by dividing offset with block size.
+
+1) Block Copy: SRC=0x0040, SRC_ADDR=0x00100000, DEST_ADDR=0x1800a000,
+BLOCK_SIZE=0x00016000
+
+This command copies u-boot image from SD device into OCRAM. The values
+need to adjust accordingly for SD/eMMC
+
+SRC		should match the cfg_rcw_src, the reset config pins.
+		The value for source(SRC) can be 0x0040 or 0x0041
+		depending upon SD or eMMC.
+SRC_ADDR	is the offset of u-boot-with-spl.bin image in SD device.
+		In the example above, 1MB. This is same as QSPI-NOR.
+DEST_ADDR	is configured at 0x1800a000, matching bootloc set above.
+BLOCK_SIZE	is the size to be copied by PBI.
+
+2) CCSR 4-byte write to 0x01e00404, data=0x00000000
+3) CCSR 4-byte write to 0x01e00400, data=0x1800a000
+The above two commands set bootloc register to 0x00000000_1800a000 where
+the u-boot code will be running in OCRAM.
+
+
+RCW image should be written at 8th block of device(SD/eMMC). Example of
+using u-boot command
+
+mmc erase 0x8 0x10
+mmc write <rcw image in memory> 0x8 <size of rcw in block count typical value=10>
+
+To form the SD-Boot image, build u-boot with SD config, for example,
+ls1088ardb_sdcard_qspi_defconfig. The image needed is u-boot-with-spl.bin.
+The u-boot image should be written to match SRC_ADDR, in above example
+offset 0x100000 in other work it means block location 0x800
+
+mmc erase 0x800 0x1800
+mmc write <u-boot image in memory> 0x800 <size of u-boot image in block count>
+
+With these two images in SD/eMMC device, the board can boot from SD/eMMC.
+
+MMU Translation Tables
+======================
+
+(1) Early MMU Tables:
+
+     Level 0                   Level 1                   Level 2
+------------------        ------------------        ------------------
+| 0x00_0000_0000 | -----> | 0x00_0000_0000 | -----> | 0x00_0000_0000 |
+------------------        ------------------        ------------------
+| 0x80_0000_0000 | --|    | 0x00_4000_0000 |        | 0x00_0020_0000 |
+------------------   |    ------------------        ------------------
+|    invalid     |   |    | 0x00_8000_0000 |        | 0x00_0040_0000 |
+------------------   |    ------------------        ------------------
+                     |    | 0x00_c000_0000 |        | 0x00_0060_0000 |
+                     |    ------------------        ------------------
+                     |    | 0x01_0000_0000 |        | 0x00_0080_0000 |
+                     |    ------------------        ------------------
+                     |            ...                      ...
+                     |    ------------------
+                     |    | 0x05_8000_0000 |  --|
+                     |    ------------------    |
+                     |    | 0x05_c000_0000 |    |
+                     |    ------------------    |
+                     |            ...           |
+                     |    ------------------    |   ------------------
+                     |--> | 0x80_0000_0000 |    |-> | 0x00_3000_0000 |
+                          ------------------        ------------------
+                          | 0x80_4000_0000 |        | 0x00_3020_0000 |
+                          ------------------        ------------------
+                          | 0x80_8000_0000 |        | 0x00_3040_0000 |
+                          ------------------        ------------------
+                          | 0x80_c000_0000 |        | 0x00_3060_0000 |
+                          ------------------        ------------------
+                          | 0x81_0000_0000 |        | 0x00_3080_0000 |
+                          ------------------        ------------------
+			         ...	                   ...
+
+(2) Final MMU Tables:
+
+     Level 0                   Level 1                   Level 2
+------------------        ------------------        ------------------
+| 0x00_0000_0000 | -----> | 0x00_0000_0000 | -----> | 0x00_0000_0000 |
+------------------        ------------------        ------------------
+| 0x80_0000_0000 | --|    | 0x00_4000_0000 |        | 0x00_0020_0000 |
+------------------   |    ------------------        ------------------
+|    invalid     |   |    | 0x00_8000_0000 |        | 0x00_0040_0000 |
+------------------   |    ------------------        ------------------
+                     |    | 0x00_c000_0000 |        | 0x00_0060_0000 |
+                     |    ------------------        ------------------
+                     |    | 0x01_0000_0000 |        | 0x00_0080_0000 |
+                     |    ------------------        ------------------
+                     |            ...                      ...
+                     |    ------------------
+                     |    | 0x08_0000_0000 | --|
+                     |    ------------------   |
+                     |    | 0x08_4000_0000 |   |
+                     |    ------------------   |
+                     |            ...          |
+                     |    ------------------   |    ------------------
+                     |--> | 0x80_0000_0000 |   |--> | 0x08_0000_0000 |
+                          ------------------        ------------------
+                          | 0x80_4000_0000 |        | 0x08_0020_0000 |
+                          ------------------        ------------------
+                          | 0x80_8000_0000 |        | 0x08_0040_0000 |
+                          ------------------        ------------------
+                          | 0x80_c000_0000 |        | 0x08_0060_0000 |
+                          ------------------        ------------------
+                          | 0x81_0000_0000 |        | 0x08_0080_0000 |
+                          ------------------        ------------------
+			         ...	                   ...
+
+
+DPAA2 commands to manage Management Complex (MC)
+------------------------------------------------
+DPAA2 commands has been introduced to manage Management Complex
+(MC). These commands are used to start mc, aiop and apply DPL
+from u-boot command prompt.
+
+Please note Management complex Firmware(MC), DPL and DPC are no
+more deployed during u-boot boot-sequence.
+
+Commands:
+a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
+b) fsl_mc apply DPL <DPL_addr> - Apply DPL file
+c) fsl_mc start aiop <FW_addr> - Start AIOP
+
+How to use commands :-
+1. Command sequence for u-boot ethernet:
+   a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
+   b) DPMAC net-devices are now available for use
+
+   Example-
+	Assumption: MC firmware, DPL and DPC dtb is already programmed
+	on NOR flash.
+
+	=> fsl_mc start mc 580300000 580800000
+	=> setenv ethact DPMAC1@xgmii
+	=> ping $serverip
+
+2. Command sequence for Linux boot:
+   a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
+   b) fsl_mc apply DPL <DPL_addr> - Apply DPL file
+   c) No DPMAC net-devices are available for use in u-boot
+   d) boot Linux
+
+   Example-
+	Assumption: MC firmware, DPL and DPC dtb is already programmed
+	on NOR flash.
+
+	=> fsl_mc start mc 580300000 580800000
+	=> setenv ethact DPMAC1@xgmii
+	=> tftp a0000000 kernel.itb
+	=> fsl_mc apply dpl 580700000
+	=> bootm a0000000
+
+3. Command sequence for AIOP boot:
+   a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex
+   b) fsl_mc start aiop <FW_addr> - Start AIOP
+   c) fsl_mc apply DPL <DPL_addr> - Apply DPL file
+   d) No DPMAC net-devices are availabe for use in u-boot
+  Please note actual AIOP start will happen during DPL parsing of
+  Management complex
+
+  Example-
+	Assumption: MC firmware, DPL, DPC dtb and AIOP firmware is already
+	programmed on NOR flash.
+
+	=> fsl_mc start mc 580300000 580800000
+	=> fsl_mc start aiop 0x580900000
+	=> setenv ethact DPMAC1@xgmii
+	=> fsl_mc apply dpl 580700000
+
+Errata A009635
+---------------
+If the core runs at higher than x3 speed of the platform, there is
+possiblity about sev instruction to getting missed by other cores.
+This is because of SoC Run Control block may not able to sample
+the EVENTI(Sev) signals.
+
+Workaround: Configure Run Control and EPU to periodically send out EVENTI signals to
+wake up A57 cores
+
+Errata workaround uses Env variable "a009635_interval_val". It uses decimal
+value.
+- Default value of env variable is platform clock (MHz)
+
+- User can modify default value by updating the env variable
+  setenv a009635_interval_val 600; saveenv;
+  It configure platform clock as 600 MHz
+
+- Env variable as 0 signifies no workaround
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3_2 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3_2
new file mode 100644
index 0000000..6d4bd0b
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3_2
@@ -0,0 +1,27 @@
+#
+# Copyright 2018 NXP
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+NXP LayerScape with Chassis Generation 3.2
+
+This architecture supports NXP ARMv8 SoCs with Chassis generation 3.2
+for example LX2160A.
+
+This architecture is enhancement over Chassis Generation 3 with
+few differences mentioned below
+
+1)DDR Layout
+============
+Entire DDR region splits into three regions.
+ - Region 1 is at address 0x8000_0000 to 0xffff_ffff.
+ - Region 2 is at address 0x20_8000_0000 to 0x3f_ffff_ffff,
+ - Region 3 is at address 0x60_0000_0000 to the top of memory,
+   for example 140GB, 0x63_7fff_ffff.
+
+All DDR memory is marked as cache-enabled.
+
+2)IFC is removed
+
+3)Number of I2C controllers increased to 8
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.qspi b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.qspi
new file mode 100644
index 0000000..de86f4b
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.qspi
@@ -0,0 +1,42 @@
+QSPI Boot source support Overview
+-------------------
+	1. LS1043A
+		LS1043AQDS
+	2. LS2080A
+		LS2080AQDS
+	3. LS1012A
+		LS1012AQDS
+		LS1012ARDB
+	4. LS1046A
+		LS1046AQDS
+		LS1046ARDB
+
+Booting from QSPI
+-------------------
+Booting from QSPI requires two images, RCW and u-boot-dtb.bin.
+The difference between QSPI boot RCW image and NOR boot image is the PBI
+command sequence for setting the boot location pointer. It's should point
+to the address for u-boot in QSPI flash.
+
+RCW image should be written to the beginning of QSPI flash device.
+Example of using u-boot command
+
+=> sf probe 0:0
+SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB
+=> sf erase 0 +<size of rcw image>
+SF: 65536 bytes @ 0x0 Erased: OK
+=> sf write <rcw image in memory> 0 <size of rcw image>
+SF: 164 bytes @ 0x0 Written: OK
+
+To get the QSPI image, build u-boot with QSPI config, for example,
+<board_name>_qspi_defconfig. The image needed is u-boot-dtb.bin.
+The u-boot image should be written to 0x10000(but 0x1000 for LS1043A, LS2080A).
+
+=> sf probe 0:0
+SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB
+=> sf erase 10000 +<size of u-boot image>
+SF: 589824 bytes @ 0x10000 Erased: OK
+=> sf write <u-boot image in memory> 10000 <size of u-boot image>
+SF: 580966 bytes @ 0x10000 Written: OK
+
+With these two images in QSPI flash device, the board can boot from QSPI.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
new file mode 100644
index 0000000..a0e2621
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
@@ -0,0 +1,330 @@
+SoC overview
+
+	1. LS1043A
+	2. LS1088A
+	3. LS2080A
+	4. LS1012A
+	5. LS1046A
+	6. LS2088A
+	7. LS2081A
+	8. LX2160A
+
+LS1043A
+---------
+The LS1043A integrated multicore processor combines four ARM Cortex-A53
+processor cores with datapath acceleration optimized for L2/3 packet
+processing, single pass security offload and robust traffic management
+and quality of service.
+
+The LS1043A SoC includes the following function and features:
+ - Four 64-bit ARM Cortex-A53 CPUs
+ - 1 MB unified L2 Cache
+ - One 32-bit DDR3L/DDR4 SDRAM memory controllers with ECC and interleaving
+   support
+ - Data Path Acceleration Architecture (DPAA) incorporating acceleration the
+   the following functions:
+   - Packet parsing, classification, and distribution (FMan)
+   - Queue management for scheduling, packet sequencing, and congestion
+     management (QMan)
+   - Hardware buffer management for buffer allocation and de-allocation (BMan)
+   - Cryptography acceleration (SEC)
+ - Ethernet interfaces by FMan
+   - Up to 1 x XFI supporting 10G interface
+   - Up to 1 x QSGMII
+   - Up to 4 x SGMII supporting 1000Mbps
+   - Up to 2 x SGMII supporting 2500Mbps
+   - Up to 2 x RGMII supporting 1000Mbps
+ - High-speed peripheral interfaces
+   - Three PCIe 2.0 controllers, one supporting x4 operation
+   - One serial ATA (SATA 3.0) controllers
+ - Additional peripheral interfaces
+   - Three high-speed USB 3.0 controllers with integrated PHY
+   - Enhanced secure digital host controller (eSDXC/eMMC)
+   - Quad Serial Peripheral Interface (QSPI) Controller
+   - Serial peripheral interface (SPI) controller
+   - Four I2C controllers
+   - Two DUARTs
+   - Integrated flash controller supporting NAND and NOR flash
+ - QorIQ platform's trust architecture 2.1
+
+LS1088A
+--------
+The QorIQ LS1088A processor is built on the Layerscape
+architecture combining eight ARM A53 processor cores
+with advanced, high-performance datapath acceleration
+and networks, peripheral interfaces required for
+networking, wireless infrastructure, and general-purpose
+embedded applications.
+
+LS1088A is compliant with the Layerscape Chassis Generation 3.
+
+Features summary:
+ - 8 32-bit / 64-bit ARM v8 Cortex-A53 CPUs
+ - Cores are in 2 cluster of 4-cores each
+ - 1MB L2 - Cache per cluster
+ - Cache coherent interconnect (CCI-400)
+ - 1 64-bit DDR4 SDRAM memory controller with ECC
+ - Data path acceleration architecture 2.0 (DPAA2)
+ - 4-Lane 10GHz SerDes comprising of WRIOP
+ - 4-Lane 10GHz SerDes comprising of PCI, SATA, uQE(TDM/HLDC/UART)
+ - Ethernet interfaces: SGMIIs, RGMIIs, QSGMIIs, XFIs
+ - QSPI, SPI, IFC2.0 supporting NAND, NOR flash
+ - 3 PCIe3.0 , 1 SATA3.0, 2 USB3.0, 1 SDXC, 2 DUARTs etc
+ - 2 DUARTs
+ - 4 I2C, GPIO
+ - Thermal monitor unit(TMU)
+ - 4 Flextimers and 1 generic timer
+ - Support for hardware virtualization and partitioning enforcement
+ - QorIQ platform's trust architecture 3.0
+ - Service processor (SP) provides pre-boot initialization and secure-boot
+   capabilities
+
+LS2080A
+--------
+The LS2080A integrated multicore processor combines eight ARM Cortex-A57
+processor cores with high-performance data path acceleration logic and network
+and peripheral bus interfaces required for networking, telecom/datacom,
+wireless infrastructure, and mil/aerospace applications.
+
+The LS2080A SoC includes the following function and features:
+
+ - Eight 64-bit ARM Cortex-A57 CPUs
+ - 1 MB platform cache with ECC
+ - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support
+ - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by
+  the AIOP
+ - Data path acceleration architecture (DPAA2) incorporating acceleration for
+ the following functions:
+   - Packet parsing, classification, and distribution (WRIOP)
+   - Queue and Hardware buffer management for scheduling, packet sequencing, and
+     congestion management, buffer allocation and de-allocation (QBMan)
+   - Cryptography acceleration (SEC) at up to 10 Gbps
+   - RegEx pattern matching acceleration (PME) at up to 10 Gbps
+   - Decompression/compression acceleration (DCE) at up to 20 Gbps
+   - Accelerated I/O processing (AIOP) at up to 20 Gbps
+   - QDMA engine
+ - 16 SerDes lanes at up to 10.3125 GHz
+ - Ethernet interfaces
+   - Up to eight 10 Gbps Ethernet MACs
+   - Up to eight 1 / 2.5 Gbps Ethernet MACs
+ - High-speed peripheral interfaces
+   - Four PCIe 3.0 controllers, one supporting SR-IOV
+ - Additional peripheral interfaces
+   - Two serial ATA (SATA 3.0) controllers
+   - Two high-speed USB 3.0 controllers with integrated PHY
+   - Enhanced secure digital host controller (eSDXC/eMMC)
+   - Serial peripheral interface (SPI) controller
+   - Quad Serial Peripheral Interface (QSPI) Controller
+   - Four I2C controllers
+   - Two DUARTs
+   - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash
+ - Support for hardware virtualization and partitioning enforcement
+ - QorIQ platform's trust architecture 3.0
+ - Service processor (SP) provides pre-boot initialization and secure-boot
+  capabilities
+
+LS1012A
+--------
+The LS1012A features an advanced 64-bit ARM v8 Cortex-
+A53 processor, with 32 KB of parity protected L1-I cache,
+32 KB of ECC protected L1-D cache, as well as 256 KB of
+ECC protected L2 cache.
+
+The LS1012A SoC includes the following function and features:
+ - One 64-bit ARM v8 Cortex-A53 core with the following capabilities:
+ - ARM v8 cryptography extensions
+ - One 16-bit DDR3L SDRAM memory controller, Up to 1.0 GT/s, Supports
+    16-/8-bit operation (no ECC support)
+ - ARM core-link CCI-400 cache coherent interconnect
+ - Packet Forwarding Engine (PFE)
+ - Cryptography acceleration (SEC)
+ - Ethernet interfaces supported by PFE:
+ - One Configurable x3 SerDes:
+    Two Serdes PLLs supported for usage by any SerDes data lane
+    Support for up to 6 GBaud operation
+ - High-speed peripheral interfaces:
+     - One PCI Express Gen2 controller, supporting x1 operation
+     - One serial ATA (SATA Gen 3.0) controller
+     - One USB 3.0/2.0 controller with integrated PHY
+     - One USB 2.0 controller with ULPI interface. .
+ - Additional peripheral interfaces:
+    - One quad serial peripheral interface (QuadSPI) controller
+    - One serial peripheral interface (SPI) controller
+    - Two enhanced secure digital host controllers
+    - Two I2C controllers
+    - One 16550 compliant DUART (two UART interfaces)
+    - Two general purpose IOs (GPIO)
+    - Two FlexTimers
+    - Five synchronous audio interfaces (SAI)
+    - Pre-boot loader (PBL) provides pre-boot initialization and RCW loading
+    - Single-source clocking solution enabling generation of core, platform,
+    DDR, SerDes, and USB clocks from a single external crystal and internal
+    crystaloscillator
+    - Thermal monitor unit (TMU) with +/- 3C accuracy
+    - Two WatchDog timers
+    - ARM generic timer
+ - QorIQ platform's trust architecture 2.1
+
+LS1046A
+--------
+The LS1046A integrated multicore processor combines four ARM Cortex-A72
+processor cores with datapath acceleration optimized for L2/3 packet
+processing, single pass security offload and robust traffic management
+and quality of service.
+
+The LS1046A SoC includes the following function and features:
+ - Four 64-bit ARM Cortex-A72 CPUs
+ - 2 MB unified L2 Cache
+ - One 64-bit DDR4 SDRAM memory controllers with ECC and interleaving
+   support
+ - Data Path Acceleration Architecture (DPAA) incorporating acceleration the
+   the following functions:
+   - Packet parsing, classification, and distribution (FMan)
+   - Queue management for scheduling, packet sequencing, and congestion
+     management (QMan)
+   - Hardware buffer management for buffer allocation and de-allocation (BMan)
+   - Cryptography acceleration (SEC)
+ - Two Configurable x4 SerDes
+   - Two PLLs per four-lane SerDes
+   - Support for 10G operation
+ - Ethernet interfaces by FMan
+   - Up to 2 x XFI supporting 10G interface (MAC 9, 10)
+   - Up to 1 x QSGMII (MAC 5, 6, 10, 1)
+   - Up to 4 x SGMII supporting 1000Mbps (MAC 5, 6, 9, 10)
+   - Up to 3 x SGMII supporting 2500Mbps (MAC 5, 9, 10)
+   - Up to 2 x RGMII supporting 1000Mbps (MAC 3, 4)
+ - High-speed peripheral interfaces
+   - Three PCIe 3.0 controllers, one supporting x4 operation
+   - One serial ATA (SATA 3.0) controllers
+ - Additional peripheral interfaces
+   - Three high-speed USB 3.0 controllers with integrated PHY
+   - Enhanced secure digital host controller (eSDXC/eMMC)
+   - Quad Serial Peripheral Interface (QSPI) Controller
+   - Serial peripheral interface (SPI) controller
+   - Four I2C controllers
+   - Two DUARTs
+   - Integrated flash controller (IFC) supporting NAND and NOR flash
+ - QorIQ platform's trust architecture 2.1
+
+LS2088A
+--------
+The LS2088A integrated multicore processor combines eight ARM Cortex-A72
+processor cores with high-performance data path acceleration logic and network
+and peripheral bus interfaces required for networking, telecom/datacom,
+wireless infrastructure, and mil/aerospace applications.
+
+The LS2088A SoC includes the following function and features:
+
+ - Eight 64-bit ARM Cortex-A72 CPUs
+ - 1 MB platform cache with ECC
+ - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support
+ - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by
+   the AIOP
+ - Data path acceleration architecture (DPAA2) incorporating acceleration for
+   the following functions:
+   - Packet parsing, classification, and distribution (WRIOP)
+   - Queue and Hardware buffer management for scheduling, packet sequencing, and
+     congestion management, buffer allocation and de-allocation (QBMan)
+   - Cryptography acceleration (SEC) at up to 10 Gbps
+   - RegEx pattern matching acceleration (PME) at up to 10 Gbps
+   - Decompression/compression acceleration (DCE) at up to 20 Gbps
+   - Accelerated I/O processing (AIOP) at up to 20 Gbps
+   - QDMA engine
+ - 16 SerDes lanes at up to 10.3125 GHz
+ - Ethernet interfaces
+   - Up to eight 10 Gbps Ethernet MACs
+   - Up to eight 1 / 2.5 Gbps Ethernet MACs
+ - High-speed peripheral interfaces
+   - Four PCIe 3.0 controllers, one supporting SR-IOV
+ - Additional peripheral interfaces
+   - Two serial ATA (SATA 3.0) controllers
+   - Two high-speed USB 3.0 controllers with integrated PHY
+   - Enhanced secure digital host controller (eSDXC/eMMC)
+   - Serial peripheral interface (SPI) controller
+   - Quad Serial Peripheral Interface (QSPI) Controller
+   - Four I2C controllers
+   - Two DUARTs
+   - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash
+ - Support for hardware virtualization and partitioning enforcement
+ - QorIQ platform's trust architecture 3.0
+ - Service processor (SP) provides pre-boot initialization and secure-boot
+ capabilities
+
+LS2088A SoC has 3 more similar SoC personalities
+1)LS2048A, few difference w.r.t. LS2088A:
+       a) Four 64-bit ARM v8 Cortex-A72 CPUs
+
+2)LS2084A, few difference w.r.t. LS2088A:
+       a) No AIOP
+       b) No 32-bit DDR3 SDRAM memory
+       c) 5 * 1/10G + 5 *1G WRIOP
+       d) No L2 switch
+
+3)LS2044A, few difference w.r.t. LS2084A:
+       a) Four 64-bit ARM v8 Cortex-A72 CPUs
+
+LS2081A
+--------
+LS2081A is 40-pin derivative of LS2084A.
+So feature-wise it is same as LS2084A.
+Refer to LS2084A(LS2088A) section above for details.
+
+It has one more similar SoC personality
+1)LS2041A, few difference w.r.t. LS2081A:
+       a) Four 64-bit ARM v8 Cortex-A72 CPUs
+
+LX2160A
+--------
+The QorIQ LX2160A processor is built in the 16FFC process on
+the Layerscape architecture combining sixteen ARM A72 processor
+cores with advanced, high-performance datapath acceleration and
+network, peripheral interfaces required for networking, wireless
+infrastructure, storage, and general-purpose embedded applications.
+
+LX2160A is compliant with the Layerscape Chassis Generation 3.2.
+
+The LX2160A SoC includes the following function and features:
+  Sixteen 32-bit / 64-bit ARM v8 A72 CPUs
+  Cache Coherent Interconnect Fabric (CCN508 aka “Eliot”)
+  Two 64-bit 3.2GT/s DDR4 SDRAM memory controllers with ECC.
+  Data path acceleration architecture (DPAA2)
+  24 Serdes lanes at up to 25 GHz
+  Ethernet interfaces
+  Single WRIOP tile supporting 130Gbps using 18 MACs
+  Support for 10G-SXGMII (aka USXGMII).
+  Support for SGMII (and 1000Base-KX)
+  Support for XFI (and 10GBase-KR)
+  Support for CAUI4 (100G); CAUI2 (50G) and 25G-AUI(25G).
+  Support for XLAUI (and 40GBase-KR4) for 40G.
+  Support for two RGMII parallel interfaces.
+  Energy efficient Ethernet support (802.3az)
+  IEEE 1588 support.
+  High-speed peripheral interfaces
+	Two PCIe Gen 4.0 8-lane controllers supporting SR-IOV,
+	Four PCIe Gen 4.0 4-lane controllers.
+	Four serial ATA (SATA 3.0) controllers.
+	Two USB 3.0 controllers with integrated PHY
+	Two Enhanced secure digital host controllers
+	Two Controller Area Network (CAN) modules
+	Flexible Serial peripheral interface (FlexSPI) controller.
+	Three Serial peripheral interface (SPI) controllers.
+	Eight I2C Controllers.
+	Four PL011 UARTs supporting two 4-pin UART ports or four 2-pin UART ports.
+	General Purpose IO (GPIO)
+  Support for hardware virtualization and partitioning (ARM MMU-500)
+  Support for GIC (ARM GIC-500)
+  QorIQ platform Trust Architecture 3.0
+  One Secure WatchDog timer and one Non-Secure Watchdog timer.
+  ARM Generic Timer
+  Two Flextimers
+  Debug supporting run control, data acquisition, high-speed trace,
+  performance/event monitoring
+  Thermal Monitor Unit (TMU) with +/- 2C accuracy
+  Support for Voltage ID (VID) for yield improvement
+
+LX2160A SoC has 2 more similar SoC personalities
+1)LX2120A, few difference w.r.t. LX2160A:
+       a) Twelve 64-bit ARM v8 Cortex-A72 CPUs
+
+2)LX2080A, few difference w.r.t. LX2160A:
+       a) Eight 64-bit ARM v8 Cortex-A72 CPUs
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
new file mode 100644
index 0000000..c9c2c3f
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+#include <phy.h>
+#ifdef CONFIG_FSL_LSCH3
+#include <asm/arch/fdt.h>
+#endif
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+#ifdef CONFIG_SYS_DPAA_FMAN
+#include <fsl_fman.h>
+#endif
+#ifdef CONFIG_MP
+#include <asm/arch/mp.h>
+#endif
+#include <fsl_sec.h>
+#include <asm/arch-fsl-layerscape/soc.h>
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#include <asm/armv8/sec_firmware.h>
+#endif
+#include <asm/arch/speed.h>
+#include <fsl_qbman.h>
+
+int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
+{
+	return fdt_setprop_string(blob, offset, "phy-connection-type",
+					 phy_string_for_interface(phyc));
+}
+
+#ifdef CONFIG_MP
+void ft_fixup_cpu(void *blob)
+{
+	int off;
+	__maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr();
+	fdt32_t *reg;
+	int addr_cells;
+	u64 val, core_id;
+	size_t *boot_code_size = &(__secondary_boot_code_size);
+	u32 mask = cpu_pos_mask();
+	int off_prev = -1;
+
+	off = fdt_path_offset(blob, "/cpus");
+	if (off < 0) {
+		puts("couldn't find /cpus node\n");
+		return;
+	}
+
+	fdt_support_default_count_cells(blob, off, &addr_cells, NULL);
+
+	off = fdt_node_offset_by_prop_value(blob, off_prev, "device_type",
+					    "cpu", 4);
+	while (off != -FDT_ERR_NOTFOUND) {
+		reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
+		if (reg) {
+			core_id = fdt_read_number(reg, addr_cells);
+			if (!test_bit(id_to_core(core_id), &mask)) {
+				fdt_del_node(blob, off);
+				off = off_prev;
+			}
+		}
+		off_prev = off;
+		off = fdt_node_offset_by_prop_value(blob, off_prev,
+						    "device_type", "cpu", 4);
+	}
+
+#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \
+	defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI)
+	int node;
+	u32 psci_ver;
+
+	/* Check the psci version to determine if the psci is supported */
+	psci_ver = sec_firmware_support_psci_version();
+	if (psci_ver == 0xffffffff) {
+		/* remove psci DT node */
+		node = fdt_path_offset(blob, "/psci");
+		if (node >= 0)
+			goto remove_psci_node;
+
+		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci");
+		if (node >= 0)
+			goto remove_psci_node;
+
+		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2");
+		if (node >= 0)
+			goto remove_psci_node;
+
+		node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0");
+		if (node >= 0)
+			goto remove_psci_node;
+
+remove_psci_node:
+		if (node >= 0)
+			fdt_del_node(blob, node);
+	} else {
+		return;
+	}
+#endif
+	off = fdt_path_offset(blob, "/cpus");
+	if (off < 0) {
+		puts("couldn't find /cpus node\n");
+		return;
+	}
+	fdt_support_default_count_cells(blob, off, &addr_cells, NULL);
+
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+	while (off != -FDT_ERR_NOTFOUND) {
+		reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
+		if (reg) {
+			core_id = fdt_read_number(reg, addr_cells);
+			if (core_id  == 0 || (is_core_online(core_id))) {
+				val = spin_tbl_addr;
+				val += id_to_core(core_id) *
+				       SPIN_TABLE_ELEM_SIZE;
+				val = cpu_to_fdt64(val);
+				fdt_setprop_string(blob, off, "enable-method",
+						   "spin-table");
+				fdt_setprop(blob, off, "cpu-release-addr",
+					    &val, sizeof(val));
+			} else {
+				debug("skipping offline core\n");
+			}
+		} else {
+			puts("Warning: found cpu node without reg property\n");
+		}
+		off = fdt_node_offset_by_prop_value(blob, off, "device_type",
+						    "cpu", 4);
+	}
+
+	fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code,
+			*boot_code_size);
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+	efi_add_memory_map((uintptr_t)&secondary_boot_code,
+			   ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
+			   EFI_RESERVED_MEMORY_TYPE, false);
+#endif
+}
+#endif
+
+void fsl_fdt_disable_usb(void *blob)
+{
+	int off;
+	/*
+	 * SYSCLK is used as a reference clock for USB. When the USB
+	 * controller is used, SYSCLK must meet the additional requirement
+	 * of 100 MHz.
+	 */
+	if (CONFIG_SYS_CLK_FREQ != 100000000) {
+		off = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3");
+		while (off != -FDT_ERR_NOTFOUND) {
+			fdt_status_disabled(blob, off);
+			off = fdt_node_offset_by_compatible(blob, off,
+							    "snps,dwc3");
+		}
+	}
+}
+
+#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
+static void fdt_fixup_gic(void *blob)
+{
+	int offset, err;
+	u64 reg[8];
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	unsigned int val;
+	struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+	int align_64k = 0;
+
+	val = gur_in32(&gur->svr);
+
+	if (!IS_SVR_DEV(val, SVR_DEV(SVR_LS1043A))) {
+		align_64k = 1;
+	} else if (SVR_REV(val) != REV1_0) {
+		val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT);
+		if (!val)
+			align_64k = 1;
+	}
+
+	offset = fdt_subnode_offset(blob, 0, "interrupt-controller@1400000");
+	if (offset < 0) {
+		printf("WARNING: fdt_subnode_offset can't find node %s: %s\n",
+		       "interrupt-controller@1400000", fdt_strerror(offset));
+		return;
+	}
+
+	/* Fixup gic node align with 64K */
+	if (align_64k) {
+		reg[0] = cpu_to_fdt64(GICD_BASE_64K);
+		reg[1] = cpu_to_fdt64(GICD_SIZE_64K);
+		reg[2] = cpu_to_fdt64(GICC_BASE_64K);
+		reg[3] = cpu_to_fdt64(GICC_SIZE_64K);
+		reg[4] = cpu_to_fdt64(GICH_BASE_64K);
+		reg[5] = cpu_to_fdt64(GICH_SIZE_64K);
+		reg[6] = cpu_to_fdt64(GICV_BASE_64K);
+		reg[7] = cpu_to_fdt64(GICV_SIZE_64K);
+	} else {
+	/* Fixup gic node align with default */
+		reg[0] = cpu_to_fdt64(GICD_BASE);
+		reg[1] = cpu_to_fdt64(GICD_SIZE);
+		reg[2] = cpu_to_fdt64(GICC_BASE);
+		reg[3] = cpu_to_fdt64(GICC_SIZE);
+		reg[4] = cpu_to_fdt64(GICH_BASE);
+		reg[5] = cpu_to_fdt64(GICH_SIZE);
+		reg[6] = cpu_to_fdt64(GICV_BASE);
+		reg[7] = cpu_to_fdt64(GICV_SIZE);
+	}
+
+	err = fdt_setprop(blob, offset, "reg", reg, sizeof(reg));
+	if (err < 0) {
+		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
+		       "reg", "interrupt-controller@1400000",
+		       fdt_strerror(err));
+		return;
+	}
+
+	return;
+}
+#endif
+
+#ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI
+static int _fdt_fixup_msi_node(void *blob, const char *name,
+				  int irq_0, int irq_1, int rev)
+{
+	int err, offset, len;
+	u32 tmp[4][3];
+	void *p;
+
+	offset = fdt_path_offset(blob, name);
+	if (offset < 0) {
+		printf("WARNING: fdt_path_offset can't find path %s: %s\n",
+		       name, fdt_strerror(offset));
+		return 0;
+	}
+
+	/*fixup the property of interrupts*/
+
+	tmp[0][0] = cpu_to_fdt32(0x0);
+	tmp[0][1] = cpu_to_fdt32(irq_0);
+	tmp[0][2] = cpu_to_fdt32(0x4);
+
+	if (rev > REV1_0) {
+		tmp[1][0] = cpu_to_fdt32(0x0);
+		tmp[1][1] = cpu_to_fdt32(irq_1);
+		tmp[1][2] = cpu_to_fdt32(0x4);
+		tmp[2][0] = cpu_to_fdt32(0x0);
+		tmp[2][1] = cpu_to_fdt32(irq_1 + 1);
+		tmp[2][2] = cpu_to_fdt32(0x4);
+		tmp[3][0] = cpu_to_fdt32(0x0);
+		tmp[3][1] = cpu_to_fdt32(irq_1 + 2);
+		tmp[3][2] = cpu_to_fdt32(0x4);
+		len = sizeof(tmp);
+	} else {
+		len = sizeof(tmp[0]);
+	}
+
+	err = fdt_setprop(blob, offset, "interrupts", tmp, len);
+	if (err < 0) {
+		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
+		       "interrupts", name, fdt_strerror(err));
+		return 0;
+	}
+
+	/*fixup the property of reg*/
+	p = (char *)fdt_getprop(blob, offset, "reg", &len);
+	if (!p) {
+		printf("WARNING: fdt_getprop can't get %s from node %s\n",
+		       "reg", name);
+		return 0;
+	}
+
+	memcpy((char *)tmp, p, len);
+
+	if (rev > REV1_0)
+		*((u32 *)tmp + 3) = cpu_to_fdt32(0x1000);
+	else
+		*((u32 *)tmp + 3) = cpu_to_fdt32(0x8);
+
+	err = fdt_setprop(blob, offset, "reg", tmp, len);
+	if (err < 0) {
+		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
+		       "reg", name, fdt_strerror(err));
+		return 0;
+	}
+
+	/*fixup the property of compatible*/
+	if (rev > REV1_0)
+		err = fdt_setprop_string(blob, offset, "compatible",
+					 "fsl,ls1043a-v1.1-msi");
+	else
+		err = fdt_setprop_string(blob, offset, "compatible",
+					 "fsl,ls1043a-msi");
+	if (err < 0) {
+		printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
+		       "compatible", name, fdt_strerror(err));
+		return 0;
+	}
+
+	return 1;
+}
+
+static int _fdt_fixup_pci_msi(void *blob, const char *name, int rev)
+{
+	int offset, len, err;
+	void *p;
+	int val;
+	u32 tmp[4][8];
+
+	offset = fdt_path_offset(blob, name);
+	if (offset < 0) {
+		printf("WARNING: fdt_path_offset can't find path %s: %s\n",
+		       name, fdt_strerror(offset));
+		return 0;
+	}
+
+	p = (char *)fdt_getprop(blob, offset, "interrupt-map", &len);
+	if (!p || len != sizeof(tmp)) {
+		printf("WARNING: fdt_getprop can't get %s from node %s\n",
+		       "interrupt-map", name);
+		return 0;
+	}
+
+	memcpy((char *)tmp, p, len);
+
+	val = fdt32_to_cpu(tmp[0][6]);
+	if (rev > REV1_0) {
+		tmp[1][6] = cpu_to_fdt32(val + 1);
+		tmp[2][6] = cpu_to_fdt32(val + 2);
+		tmp[3][6] = cpu_to_fdt32(val + 3);
+	} else {
+		tmp[1][6] = cpu_to_fdt32(val);
+		tmp[2][6] = cpu_to_fdt32(val);
+		tmp[3][6] = cpu_to_fdt32(val);
+	}
+
+	err = fdt_setprop(blob, offset, "interrupt-map", tmp, sizeof(tmp));
+	if (err < 0) {
+		printf("WARNING: fdt_setprop can't set %s from node %s: %s.\n",
+		       "interrupt-map", name, fdt_strerror(err));
+		return 0;
+	}
+	return 1;
+}
+
+/* Fixup msi node for ls1043a rev1.1*/
+
+static void fdt_fixup_msi(void *blob)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	unsigned int rev;
+
+	rev = gur_in32(&gur->svr);
+
+	if (!IS_SVR_DEV(rev, SVR_DEV(SVR_LS1043A)))
+		return;
+
+	rev = SVR_REV(rev);
+
+	_fdt_fixup_msi_node(blob, "/soc/msi-controller1@1571000",
+			    116, 111, rev);
+	_fdt_fixup_msi_node(blob, "/soc/msi-controller2@1572000",
+			    126, 121, rev);
+	_fdt_fixup_msi_node(blob, "/soc/msi-controller3@1573000",
+			    160, 155, rev);
+
+	_fdt_fixup_pci_msi(blob, "/soc/pcie@3400000", rev);
+	_fdt_fixup_pci_msi(blob, "/soc/pcie@3500000", rev);
+	_fdt_fixup_pci_msi(blob, "/soc/pcie@3600000", rev);
+}
+#endif
+
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+/* Remove JR node used by SEC firmware */
+void fdt_fixup_remove_jr(void *blob)
+{
+	int jr_node, addr_cells, len;
+	int crypto_node = fdt_path_offset(blob, "crypto");
+	u64 jr_offset, used_jr;
+	fdt32_t *reg;
+
+	used_jr = sec_firmware_used_jobring_offset();
+	fdt_support_default_count_cells(blob, crypto_node, &addr_cells, NULL);
+
+	jr_node = fdt_node_offset_by_compatible(blob, crypto_node,
+						"fsl,sec-v4.0-job-ring");
+
+	while (jr_node != -FDT_ERR_NOTFOUND) {
+		reg = (fdt32_t *)fdt_getprop(blob, jr_node, "reg", &len);
+		jr_offset = fdt_read_number(reg, addr_cells);
+		if (jr_offset == used_jr) {
+			fdt_del_node(blob, jr_node);
+			break;
+		}
+		jr_node = fdt_node_offset_by_compatible(blob, jr_node,
+							"fsl,sec-v4.0-job-ring");
+	}
+}
+#endif
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	unsigned int svr = gur_in32(&gur->svr);
+
+	/* delete crypto node if not on an E-processor */
+	if (!IS_E_PROCESSOR(svr))
+		fdt_fixup_crypto_node(blob, 0);
+#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
+	else {
+		ccsr_sec_t __iomem *sec;
+
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+		fdt_fixup_remove_jr(blob);
+		fdt_fixup_kaslr(blob);
+#endif
+
+		sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+		fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
+	}
+#endif
+
+#ifdef CONFIG_MP
+	ft_fixup_cpu(blob);
+#endif
+
+#ifdef CONFIG_SYS_NS16550
+	do_fixup_by_compat_u32(blob, "fsl,ns16550",
+			       "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+	do_fixup_by_path_u32(blob, "/sysclk", "clock-frequency",
+			     CONFIG_SYS_CLK_FREQ, 1);
+
+#ifdef CONFIG_PCI
+	ft_pci_setup(blob, bd);
+#endif
+
+#ifdef CONFIG_FSL_ESDHC
+	fdt_fixup_esdhc(blob, bd);
+#endif
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+	fdt_fixup_bportals(blob);
+	fdt_fixup_qportals(blob);
+	do_fixup_by_compat_u32(blob, "fsl,qman",
+			       "clock-frequency", get_qman_freq(), 1);
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+	fdt_fixup_fman_firmware(blob);
+#endif
+#ifndef CONFIG_ARCH_LS1012A
+	fsl_fdt_disable_usb(blob);
+#endif
+#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
+	fdt_fixup_gic(blob);
+#endif
+#ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI
+	fdt_fixup_msi(blob);
+#endif
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
new file mode 100644
index 0000000..cb64cc2
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+	int ret = 0;
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	if (!serdes1_prtcl_map[NONE])
+		fsl_serdes_init();
+
+	ret |= serdes1_prtcl_map[device];
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	if (!serdes2_prtcl_map[NONE])
+		fsl_serdes_init();
+
+	ret |= serdes2_prtcl_map[device];
+#endif
+
+	return !!ret;
+}
+
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 cfg = gur_in32(&gur->rcwsr[4]);
+	int i;
+
+	switch (sd) {
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	case FSL_SRDS_1:
+		cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+		cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+		break;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	case FSL_SRDS_2:
+		cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
+		cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
+		break;
+#endif
+	default:
+		printf("invalid SerDes%d\n", sd);
+		break;
+	}
+
+	/* Is serdes enabled at all? */
+	if (unlikely(cfg == 0))
+		return -ENODEV;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (serdes_get_prtcl(sd, cfg, i) == device)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+int get_serdes_protocol(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 cfg = gur_in32(&gur->rcwsr[4]) &
+			  FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+	cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+	return cfg;
+}
+
+const char *serdes_clock_to_string(u32 clock)
+{
+	switch (clock) {
+	case SRDS_PLLCR0_RFCK_SEL_100:
+		return "100";
+	case SRDS_PLLCR0_RFCK_SEL_125:
+		return "125";
+	case SRDS_PLLCR0_RFCK_SEL_156_25:
+		return "156.25";
+	default:
+		return "100";
+	}
+}
+
+void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
+		 u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 cfg;
+	int lane;
+
+	if (serdes_prtcl_map[NONE])
+		return;
+
+	memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
+
+	cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask;
+	cfg >>= sd_prctl_shift;
+	printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
+
+	if (!is_serdes_prtcl_valid(sd, cfg))
+		printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
+
+	for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+		enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
+
+		if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
+			debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
+		else
+			serdes_prtcl_map[lane_prtcl] = 1;
+	}
+
+	/* Set the first element to indicate serdes has been initialized */
+	serdes_prtcl_map[NONE] = 1;
+}
+
+__weak int get_serdes_volt(void)
+{
+	return -1;
+}
+
+__weak int set_serdes_volt(int svdd)
+{
+	return -1;
+}
+
+int setup_serdes_volt(u32 svdd)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	struct ccsr_serdes *serdes1_base;
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	struct ccsr_serdes *serdes2_base;
+#endif
+	u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]);
+	u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]);
+	u32 cfg_tmp, reg = 0;
+	int svdd_cur, svdd_tar;
+	int ret;
+	int i;
+
+	/* Only support switch SVDD to 900mV/1000mV */
+	if (svdd != 900 && svdd != 1000)
+		return -EINVAL;
+
+	svdd_tar = svdd;
+	svdd_cur = get_serdes_volt();
+	if (svdd_cur < 0)
+		return -EINVAL;
+
+	debug("%s: current SVDD: %dmV; target SVDD: %dmV\n",
+	      __func__, svdd_cur, svdd_tar);
+	if (svdd_cur == svdd_tar)
+		return 0;
+
+	serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR;
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	serdes2_base = (void *)serdes1_base + 0x10000;
+#endif
+
+	/* Put the all enabled lanes in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+		reg = in_be32(&serdes1_base->lane[i].gcr0);
+		reg &= 0xFF9FFFFF;
+		out_be32(&serdes1_base->lane[i].gcr0, reg);
+	}
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
+	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
+
+	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+		reg = in_be32(&serdes2_base->lane[i].gcr0);
+		reg &= 0xFF9FFFFF;
+		out_be32(&serdes2_base->lane[i].gcr0, reg);
+	}
+#endif
+
+	/* Put the all enabled PLL in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+		reg = in_be32(&serdes1_base->bank[i].rstctl);
+		reg &= 0xFFFFFFBF;
+		reg |= 0x10000000;
+		out_be32(&serdes1_base->bank[i].rstctl, reg);
+		udelay(1);
+
+		reg = in_be32(&serdes1_base->bank[i].rstctl);
+		reg &= 0xFFFFFF1F;
+		out_be32(&serdes1_base->bank[i].rstctl, reg);
+	}
+	udelay(1);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+		reg = in_be32(&serdes2_base->bank[i].rstctl);
+		reg &= 0xFFFFFFBF;
+		reg |= 0x10000000;
+		out_be32(&serdes2_base->bank[i].rstctl, reg);
+		udelay(1);
+
+		reg = in_be32(&serdes2_base->bank[i].rstctl);
+		reg &= 0xFFFFFF1F;
+		out_be32(&serdes2_base->bank[i].rstctl, reg);
+	}
+	udelay(1);
+#endif
+
+	/* Put the Rx/Tx calibration into reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	reg = in_be32(&serdes1_base->srdstcalcr);
+	reg &= 0xF7FFFFFF;
+	out_be32(&serdes1_base->srdstcalcr, reg);
+	reg = in_be32(&serdes1_base->srdsrcalcr);
+	reg &= 0xF7FFFFFF;
+	out_be32(&serdes1_base->srdsrcalcr, reg);
+
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	reg = in_be32(&serdes2_base->srdstcalcr);
+	reg &= 0xF7FFFFFF;
+	out_be32(&serdes2_base->srdstcalcr, reg);
+	reg = in_be32(&serdes2_base->srdsrcalcr);
+	reg &= 0xF7FFFFFF;
+	out_be32(&serdes2_base->srdsrcalcr, reg);
+#endif
+
+	/*
+	 * If SVDD set failed, will not return directly, so that the
+	 * serdes lanes can complete reseting.
+	 */
+	ret = set_serdes_volt(svdd_tar);
+	if (ret)
+		printf("%s: Failed to set SVDD\n", __func__);
+
+	/* Wait for SVDD to stabilize */
+	udelay(100);
+
+	/* For each PLL that’s not disabled via RCW */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+		reg = in_be32(&serdes1_base->bank[i].rstctl);
+		reg |= 0x00000020;
+		out_be32(&serdes1_base->bank[i].rstctl, reg);
+		udelay(1);
+
+		reg = in_be32(&serdes1_base->bank[i].rstctl);
+		reg |= 0x00000080;
+		out_be32(&serdes1_base->bank[i].rstctl, reg);
+
+		/* Take the Rx/Tx calibration out of reset */
+		if (!(cfg_tmp == 0x3 && i == 1)) {
+			udelay(1);
+			reg = in_be32(&serdes1_base->srdstcalcr);
+			reg |= 0x08000000;
+			out_be32(&serdes1_base->srdstcalcr, reg);
+			reg = in_be32(&serdes1_base->srdsrcalcr);
+			reg |= 0x08000000;
+			out_be32(&serdes1_base->srdsrcalcr, reg);
+		}
+	}
+	udelay(1);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+		reg = in_be32(&serdes2_base->bank[i].rstctl);
+		reg |= 0x00000020;
+		out_be32(&serdes2_base->bank[i].rstctl, reg);
+		udelay(1);
+
+		reg = in_be32(&serdes2_base->bank[i].rstctl);
+		reg |= 0x00000080;
+		out_be32(&serdes2_base->bank[i].rstctl, reg);
+
+		/* Take the Rx/Tx calibration out of reset */
+		if (!(cfg_tmp == 0x3 && i == 1)) {
+			udelay(1);
+			reg = in_be32(&serdes2_base->srdstcalcr);
+			reg |= 0x08000000;
+			out_be32(&serdes2_base->srdstcalcr, reg);
+			reg = in_be32(&serdes2_base->srdsrcalcr);
+			reg |= 0x08000000;
+			out_be32(&serdes2_base->srdsrcalcr, reg);
+		}
+	}
+	udelay(1);
+
+#endif
+
+	/* Wait for at lesat 625us to ensure the PLLs being reset are locked */
+	udelay(800);
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+		/* if the PLL is not locked, set RST_ERR */
+		reg = in_be32(&serdes1_base->bank[i].pllcr0);
+		if (!((reg >> 23) & 0x1)) {
+			reg = in_be32(&serdes1_base->bank[i].rstctl);
+			reg |= 0x20000000;
+			out_be32(&serdes1_base->bank[i].rstctl, reg);
+		} else {
+			udelay(1);
+			reg = in_be32(&serdes1_base->bank[i].rstctl);
+			reg &= 0xFFFFFFEF;
+			reg |= 0x00000040;
+			out_be32(&serdes1_base->bank[i].rstctl, reg);
+			udelay(1);
+		}
+	}
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
+		reg = in_be32(&serdes2_base->bank[i].pllcr0);
+		if (!((reg >> 23) & 0x1)) {
+			reg = in_be32(&serdes2_base->bank[i].rstctl);
+			reg |= 0x20000000;
+			out_be32(&serdes2_base->bank[i].rstctl, reg);
+		} else {
+			udelay(1);
+			reg = in_be32(&serdes2_base->bank[i].rstctl);
+			reg &= 0xFFFFFFEF;
+			reg |= 0x00000040;
+			out_be32(&serdes2_base->bank[i].rstctl, reg);
+			udelay(1);
+		}
+	}
+#endif
+
+	/* Take the all enabled lanes out of reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+		reg = in_be32(&serdes1_base->lane[i].gcr0);
+		reg |= 0x00600000;
+		out_be32(&serdes1_base->lane[i].gcr0, reg);
+	}
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
+	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
+
+	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+		reg = in_be32(&serdes2_base->lane[i].gcr0);
+		reg |= 0x00600000;
+		out_be32(&serdes2_base->lane[i].gcr0, reg);
+	}
+#endif
+	/* For each PLL being reset, and achieved PLL lock set RST_DONE */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
+	for (i = 0; i < 2; i++) {
+		reg = in_be32(&serdes1_base->bank[i].pllcr0);
+		if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
+			reg = in_be32(&serdes1_base->bank[i].rstctl);
+			reg |= 0x40000000;
+			out_be32(&serdes1_base->bank[i].rstctl, reg);
+		}
+	}
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
+	for (i = 0; i < 2; i++) {
+		reg = in_be32(&serdes2_base->bank[i].pllcr0);
+		if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
+			reg = in_be32(&serdes2_base->bank[i].rstctl);
+			reg |= 0x40000000;
+			out_be32(&serdes2_base->bank[i].rstctl, reg);
+		}
+	}
+#endif
+
+	return ret;
+}
+
+void fsl_serdes_init(void)
+{
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	serdes_init(FSL_SRDS_1,
+		    CONFIG_SYS_FSL_SERDES_ADDR,
+		    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK,
+		    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
+		    serdes1_prtcl_map);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	serdes_init(FSL_SRDS_2,
+		    CONFIG_SYS_FSL_SERDES_ADDR,
+		    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK,
+		    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT,
+		    serdes2_prtcl_map);
+#endif
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
new file mode 100644
index 0000000..723d7ea
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/soc.h>
+#include <fsl_ifc.h>
+#include "cpu.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
+#define CONFIG_SYS_FSL_NUM_CC_PLLS      2
+#endif
+
+void get_sys_info(struct sys_info *sys_info)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+#if (defined(CONFIG_FSL_ESDHC) &&\
+	defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)) ||\
+	defined(CONFIG_SYS_DPAA_FMAN)
+
+	u32 rcw_tmp;
+#endif
+	struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR);
+	unsigned int cpu;
+	const u8 core_cplx_pll[8] = {
+		[0] = 0,	/* CC1 PPL / 1 */
+		[1] = 0,	/* CC1 PPL / 2 */
+		[4] = 1,	/* CC2 PPL / 1 */
+		[5] = 1,	/* CC2 PPL / 2 */
+	};
+
+	const u8 core_cplx_pll_div[8] = {
+		[0] = 1,	/* CC1 PPL / 1 */
+		[1] = 2,	/* CC1 PPL / 2 */
+		[4] = 1,	/* CC2 PPL / 1 */
+		[5] = 2,	/* CC2 PPL / 2 */
+	};
+
+	uint i, cluster;
+	uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
+	uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
+	unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
+	unsigned long cluster_clk;
+
+	sys_info->freq_systembus = sysclk;
+#ifndef CONFIG_CLUSTER_CLK_FREQ
+#define CONFIG_CLUSTER_CLK_FREQ	CONFIG_SYS_CLK_FREQ
+#endif
+	cluster_clk = CONFIG_CLUSTER_CLK_FREQ;
+
+#ifdef CONFIG_DDR_CLK_FREQ
+	sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
+#else
+	sys_info->freq_ddrbus = sysclk;
+#endif
+
+	/* The freq_systembus is used to record frequency of platform PLL */
+	sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
+			FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
+			FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
+
+#ifdef CONFIG_ARCH_LS1012A
+	sys_info->freq_ddrbus = 2 * sys_info->freq_systembus;
+#else
+	sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
+			FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) &
+			FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK;
+#endif
+
+	for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
+		ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff;
+		if (ratio[i] > 4)
+			freq_c_pll[i] = cluster_clk * ratio[i];
+		else
+			freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
+	}
+
+	for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
+		cluster = fsl_qoriq_core_to_cluster(cpu);
+		u32 c_pll_sel = (in_be32(&clk->clkcsr[cluster].clkcncsr) >> 27)
+				& 0xf;
+		u32 cplx_pll = core_cplx_pll[c_pll_sel];
+
+		sys_info->freq_processor[cpu] =
+			freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
+	}
+
+#define HWA_CGA_M1_CLK_SEL	0xe0000000
+#define HWA_CGA_M1_CLK_SHIFT	29
+#ifdef CONFIG_SYS_DPAA_FMAN
+	rcw_tmp = in_be32(&gur->rcwsr[7]);
+	switch ((rcw_tmp & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) {
+	case 2:
+		sys_info->freq_fman[0] = freq_c_pll[0] / 2;
+		break;
+	case 3:
+		sys_info->freq_fman[0] = freq_c_pll[0] / 3;
+		break;
+	case 4:
+		sys_info->freq_fman[0] = freq_c_pll[0] / 4;
+		break;
+	case 5:
+		sys_info->freq_fman[0] = sys_info->freq_systembus;
+		break;
+	case 6:
+		sys_info->freq_fman[0] = freq_c_pll[1] / 2;
+		break;
+	case 7:
+		sys_info->freq_fman[0] = freq_c_pll[1] / 3;
+		break;
+	default:
+		printf("Error: Unknown FMan1 clock select!\n");
+		break;
+	}
+#endif
+
+#define HWA_CGA_M2_CLK_SEL	0x00000007
+#define HWA_CGA_M2_CLK_SHIFT	0
+#ifdef CONFIG_FSL_ESDHC
+#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
+	rcw_tmp = in_be32(&gur->rcwsr[15]);
+	switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) {
+	case 1:
+		sys_info->freq_sdhc = freq_c_pll[1];
+		break;
+	case 2:
+		sys_info->freq_sdhc = freq_c_pll[1] / 2;
+		break;
+	case 3:
+		sys_info->freq_sdhc = freq_c_pll[1] / 3;
+		break;
+	case 6:
+		sys_info->freq_sdhc = freq_c_pll[0] / 2;
+		break;
+	default:
+		printf("Error: Unknown ESDHC clock select!\n");
+		break;
+	}
+#else
+	sys_info->freq_sdhc = (sys_info->freq_systembus /
+				CONFIG_SYS_FSL_PCLK_DIV) /
+				CONFIG_SYS_FSL_SDHC_CLK_DIV;
+#endif
+#endif
+
+#if defined(CONFIG_FSL_IFC)
+	sys_info->freq_localbus = sys_info->freq_systembus /
+						CONFIG_SYS_FSL_IFC_CLK_DIV;
+#endif
+#ifdef CONFIG_SYS_DPAA_QBMAN
+	sys_info->freq_qman = (sys_info->freq_systembus /
+				CONFIG_SYS_FSL_PCLK_DIV) /
+				CONFIG_SYS_FSL_QMAN_CLK_DIV;
+#endif
+}
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+unsigned long get_qman_freq(void)
+{
+	struct sys_info sys_info;
+
+	get_sys_info(&sys_info);
+
+	return sys_info.freq_qman;
+}
+#endif
+
+int get_clocks(void)
+{
+	struct sys_info sys_info;
+
+	get_sys_info(&sys_info);
+	gd->cpu_clk = sys_info.freq_processor[0];
+	gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV;
+	gd->mem_clk = sys_info.freq_ddrbus;
+
+#ifdef CONFIG_FSL_ESDHC
+	gd->arch.sdhc_clk = sys_info.freq_sdhc;
+#endif
+
+	if (gd->cpu_clk != 0)
+		return 0;
+	else
+		return 1;
+}
+
+/********************************************
+ * get_bus_freq
+ * return platform clock in Hz
+ *********************************************/
+ulong get_bus_freq(ulong dummy)
+{
+	if (!gd->bus_clk)
+		get_clocks();
+
+	return gd->bus_clk;
+}
+
+ulong get_ddr_freq(ulong dummy)
+{
+	if (!gd->mem_clk)
+		get_clocks();
+
+	return gd->mem_clk;
+}
+
+#ifdef CONFIG_FSL_ESDHC
+int get_sdhc_freq(ulong dummy)
+{
+	if (!gd->arch.sdhc_clk)
+		get_clocks();
+
+	return gd->arch.sdhc_clk;
+}
+#endif
+
+int get_serial_clock(void)
+{
+	return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
+}
+
+int get_i2c_freq(ulong dummy)
+{
+	return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
+}
+
+int get_dspi_freq(ulong dummy)
+{
+	return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
+}
+
+#ifdef CONFIG_FSL_LPUART
+int get_uart_freq(ulong dummy)
+{
+	return get_bus_freq(0) / CONFIG_SYS_FSL_LPUART_CLK_DIV;
+}
+#endif
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_I2C_CLK:
+		return get_i2c_freq(0);
+#if defined(CONFIG_FSL_ESDHC)
+	case MXC_ESDHC_CLK:
+		return get_sdhc_freq(0);
+#endif
+	case MXC_DSPI_CLK:
+		return get_dspi_freq(0);
+#ifdef CONFIG_FSL_LPUART
+	case MXC_UART_CLK:
+		return get_uart_freq(0);
+#endif
+	default:
+		printf("Unsupported clock\n");
+	}
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
new file mode 100644
index 0000000..ab1be3f
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016-2018 NXP
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
+#include <fsl-mc/ldpaa_wriop.h>
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+static u8 serdes3_prtcl_map[SERDES_PRCTL_COUNT];
+#endif
+
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+#ifdef CONFIG_ARCH_LX2160A
+int xfi_dpmac[XFI14 + 1];
+int sgmii_dpmac[SGMII18 + 1];
+int a25gaui_dpmac[_25GE10 + 1];
+int xlaui_dpmac[_40GE2 + 1];
+int caui2_dpmac[_50GE2 + 1];
+int caui4_dpmac[_100GE2 + 1];
+#else
+int xfi_dpmac[XFI8 + 1];
+int sgmii_dpmac[SGMII16 + 1];
+#endif
+#endif
+
+__weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
+{
+	return;
+}
+
+/*
+ *The return value of this func is the serdes protocol used.
+ *Typically this function is called number of times depending
+ *upon the number of serdes blocks in the Silicon.
+ *Zero is used to denote that no serdes was enabled,
+ *this is the case when golden RCW was used where DPAA2 bring was
+ *intentionally removed to achieve boot to prompt
+*/
+
+__weak int serdes_get_number(int serdes, int cfg)
+{
+	return cfg;
+}
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+	int ret = 0;
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	if (!serdes1_prtcl_map[NONE])
+		fsl_serdes_init();
+
+	ret |= serdes1_prtcl_map[device];
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	if (!serdes2_prtcl_map[NONE])
+		fsl_serdes_init();
+
+	ret |= serdes2_prtcl_map[device];
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	if (!serdes3_prtcl_map[NONE])
+		fsl_serdes_init();
+
+	ret |= serdes3_prtcl_map[device];
+#endif
+
+	return !!ret;
+}
+
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 cfg = 0;
+	int i;
+
+	switch (sd) {
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	case FSL_SRDS_1:
+		cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
+		cfg &= FSL_CHASSIS3_SRDS1_PRTCL_MASK;
+		cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
+		break;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	case FSL_SRDS_2:
+		cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
+		cfg &= FSL_CHASSIS3_SRDS2_PRTCL_MASK;
+		cfg >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
+		break;
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	case NXP_SRDS_3:
+		cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]);
+		cfg &= FSL_CHASSIS3_SRDS3_PRTCL_MASK;
+		cfg >>= FSL_CHASSIS3_SRDS3_PRTCL_SHIFT;
+		break;
+#endif
+	default:
+		printf("invalid SerDes%d\n", sd);
+		break;
+	}
+
+	cfg = serdes_get_number(sd, cfg);
+
+	/* Is serdes enabled at all? */
+	if (cfg == 0)
+		return -ENODEV;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (serdes_get_prtcl(sd, cfg, i) == device)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask,
+		 u32 sd_prctl_shift, u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 cfg;
+	int lane;
+
+	if (serdes_prtcl_map[NONE])
+		return;
+
+	memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
+
+	cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask;
+	cfg >>= sd_prctl_shift;
+
+	cfg = serdes_get_number(sd, cfg);
+	printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
+
+	if (!is_serdes_prtcl_valid(sd, cfg))
+		printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
+
+	for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+		enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
+		if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
+			debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
+		else {
+			serdes_prtcl_map[lane_prtcl] = 1;
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+#ifdef CONFIG_ARCH_LX2160A
+			if (lane_prtcl >= XFI1 && lane_prtcl <= XFI14)
+				wriop_init_dpmac(sd, xfi_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= SGMII1 && lane_prtcl <= SGMII18)
+				wriop_init_dpmac(sd, sgmii_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _25GE1 && lane_prtcl <= _25GE10)
+				wriop_init_dpmac(sd, a25gaui_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _40GE1 && lane_prtcl <= _40GE2)
+				wriop_init_dpmac(sd, xlaui_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _50GE1 && lane_prtcl <= _50GE2)
+				wriop_init_dpmac(sd, caui2_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+			if (lane_prtcl >= _100GE1 && lane_prtcl <= _100GE2)
+				wriop_init_dpmac(sd, caui4_dpmac[lane_prtcl],
+						 (int)lane_prtcl);
+
+#else
+			switch (lane_prtcl) {
+			case QSGMII_A:
+			case QSGMII_B:
+			case QSGMII_C:
+			case QSGMII_D:
+				wriop_init_dpmac_qsgmii(sd, (int)lane_prtcl);
+				break;
+			default:
+				if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
+					wriop_init_dpmac(sd,
+							 xfi_dpmac[lane_prtcl],
+							 (int)lane_prtcl);
+
+				 if (lane_prtcl >= SGMII1 &&
+				     lane_prtcl <= SGMII16)
+					wriop_init_dpmac(sd, sgmii_dpmac[
+							 lane_prtcl],
+							 (int)lane_prtcl);
+				break;
+			}
+#endif
+#endif
+		}
+	}
+
+	/* Set the first element to indicate serdes has been initialized */
+	serdes_prtcl_map[NONE] = 1;
+}
+
+__weak int get_serdes_volt(void)
+{
+	return -1;
+}
+
+__weak int set_serdes_volt(int svdd)
+{
+	return -1;
+}
+
+#define LNAGCR0_RT_RSTB		0x00600000
+
+#define RSTCTL_RESET_MASK	0x000000E0
+
+#define RSTCTL_RSTREQ		0x80000000
+#define RSTCTL_RST_DONE		0x40000000
+#define RSTCTL_RSTERR		0x20000000
+
+#define RSTCTL_SDEN		0x00000020
+#define RSTCTL_SDRST_B		0x00000040
+#define RSTCTL_PLLRST_B		0x00000080
+
+#define TCALCR_CALRST_B		0x08000000
+
+struct serdes_prctl_info {
+	u32 id;
+	u32 mask;
+	u32 shift;
+};
+
+struct serdes_prctl_info srds_prctl_info[] = {
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	{.id = 1,
+	 .mask = FSL_CHASSIS3_SRDS1_PRTCL_MASK,
+	 .shift = FSL_CHASSIS3_SRDS1_PRTCL_SHIFT
+	},
+
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	{.id = 2,
+	 .mask = FSL_CHASSIS3_SRDS2_PRTCL_MASK,
+	 .shift = FSL_CHASSIS3_SRDS2_PRTCL_SHIFT
+	},
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	{.id = 3,
+	 .mask = FSL_CHASSIS3_SRDS3_PRTCL_MASK,
+	 .shift = FSL_CHASSIS3_SRDS3_PRTCL_SHIFT
+	},
+#endif
+	{} /* NULL ENTRY */
+};
+
+static int get_serdes_prctl_info_idx(u32 serdes_id)
+{
+	int pos = 0;
+	struct serdes_prctl_info *srds_info;
+
+	/* loop until NULL ENTRY defined by .id=0 */
+	for (srds_info = srds_prctl_info; srds_info->id != 0;
+	     srds_info++, pos++) {
+		if (srds_info->id == serdes_id)
+			return pos;
+	}
+
+	return -1;
+}
+
+static void do_enabled_lanes_reset(u32 serdes_id, u32 cfg,
+				   struct ccsr_serdes __iomem *serdes_base,
+				   bool cmplt)
+{
+	int i, pos;
+	u32 cfg_tmp;
+
+	pos = get_serdes_prctl_info_idx(serdes_id);
+	if (pos == -1) {
+		printf("invalid serdes_id %d\n", serdes_id);
+		return;
+	}
+
+	cfg_tmp = cfg & srds_prctl_info[pos].mask;
+	cfg_tmp >>= srds_prctl_info[pos].shift;
+
+	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+		if (cmplt)
+			setbits_le32(&serdes_base->lane[i].gcr0,
+				     LNAGCR0_RT_RSTB);
+		else
+			clrbits_le32(&serdes_base->lane[i].gcr0,
+				     LNAGCR0_RT_RSTB);
+	}
+}
+
+static void do_pll_reset(u32 cfg,
+			 struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+
+	for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
+		clrbits_le32(&serdes_base->bank[i].rstctl,
+			     RSTCTL_RESET_MASK);
+		udelay(1);
+
+		setbits_le32(&serdes_base->bank[i].rstctl,
+			     RSTCTL_RSTREQ);
+	}
+	udelay(1);
+}
+
+static void do_rx_tx_cal_reset(struct ccsr_serdes __iomem *serdes_base)
+{
+	clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+	clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+}
+
+static void do_rx_tx_cal_reset_comp(u32 cfg, int i,
+				    struct ccsr_serdes __iomem *serdes_base)
+{
+	if (!(cfg == 0x3 && i == 1)) {
+		udelay(1);
+		setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+		setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+	}
+	udelay(1);
+}
+
+static void do_pll_reset_done(u32 cfg,
+			      struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+	u32 reg = 0;
+
+	for (i = 0; i < 2; i++) {
+		reg = in_le32(&serdes_base->bank[i].pllcr0);
+		if (!(cfg & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
+			setbits_le32(&serdes_base->bank[i].rstctl,
+				     RSTCTL_RST_DONE);
+		}
+	}
+}
+
+static void do_serdes_enable(u32 cfg,
+			     struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+
+	for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
+		setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_SDEN);
+		udelay(1);
+
+		setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_PLLRST_B);
+		udelay(1);
+		/* Take the Rx/Tx calibration out of reset */
+		do_rx_tx_cal_reset_comp(cfg, i, serdes_base);
+	}
+}
+
+static void do_pll_lock(u32 cfg,
+			struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+	u32 reg = 0;
+
+	for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
+		/* if the PLL is not locked, set RST_ERR */
+		reg = in_le32(&serdes_base->bank[i].pllcr0);
+		if (!((reg >> 23) & 0x1)) {
+			setbits_le32(&serdes_base->bank[i].rstctl,
+				     RSTCTL_RSTERR);
+		} else {
+			udelay(1);
+			setbits_le32(&serdes_base->bank[i].rstctl,
+				     RSTCTL_SDRST_B);
+			udelay(1);
+		}
+	}
+}
+
+int setup_serdes_volt(u32 svdd)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	struct ccsr_serdes __iomem *serdes1_base =
+			(void *)CONFIG_SYS_FSL_LSCH3_SERDES_ADDR;
+	u32 cfg_rcwsrds1 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	struct ccsr_serdes __iomem *serdes2_base =
+			(void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x10000);
+	u32 cfg_rcwsrds2 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	struct ccsr_serdes __iomem *serdes3_base =
+			(void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x20000);
+	u32 cfg_rcwsrds3 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]);
+#endif
+	u32 cfg_tmp;
+	int svdd_cur, svdd_tar;
+	int ret = 1;
+
+	/* Only support switch SVDD to 900mV */
+	if (svdd != 900)
+		return -EINVAL;
+
+	/* Scale up to the LTC resolution is 1/4096V */
+	svdd = (svdd * 4096) / 1000;
+
+	svdd_tar = svdd;
+	svdd_cur = get_serdes_volt();
+	if (svdd_cur < 0)
+		return -EINVAL;
+
+	debug("%s: current SVDD: %x; target SVDD: %x\n",
+	      __func__, svdd_cur, svdd_tar);
+	if (svdd_cur == svdd_tar)
+		return 0;
+
+	/* Put the all enabled lanes in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, false);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, false);
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, false);
+#endif
+
+	/* Put the all enabled PLL in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_pll_reset(cfg_tmp, serdes1_base);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_pll_reset(cfg_tmp, serdes2_base);
+#endif
+
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	cfg_tmp = cfg_rcwsrds3 & 0x30;
+	cfg_tmp >>= 4;
+	do_pll_reset(cfg_tmp, serdes3_base);
+#endif
+
+	/* Put the Rx/Tx calibration into reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	do_rx_tx_cal_reset(serdes1_base);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	do_rx_tx_cal_reset(serdes2_base);
+#endif
+
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	do_rx_tx_cal_reset(serdes3_base);
+#endif
+
+	ret = set_serdes_volt(svdd);
+	if (ret < 0) {
+		printf("could not change SVDD\n");
+		ret = -1;
+	}
+
+	/* For each PLL that’s not disabled via RCW enable the SERDES */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_serdes_enable(cfg_tmp, serdes1_base);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_serdes_enable(cfg_tmp, serdes2_base);
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	cfg_tmp = cfg_rcwsrds3 & 0x30;
+	cfg_tmp >>= 4;
+	do_serdes_enable(cfg_tmp, serdes3_base);
+#endif
+
+	/* Wait for at at least 625us, ensure the PLLs being reset are locked */
+	udelay(800);
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_pll_lock(cfg_tmp, serdes1_base);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_pll_lock(cfg_tmp, serdes2_base);
+#endif
+
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	cfg_tmp = cfg_rcwsrds3 & 0x30;
+	cfg_tmp >>= 4;
+	do_pll_lock(cfg_tmp, serdes3_base);
+#endif
+
+	/* Take the all enabled lanes out of reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, true);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, true);
+#endif
+
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, true);
+#endif
+
+	/* For each PLL being reset, and achieved PLL lock set RST_DONE */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_pll_reset_done(cfg_tmp, serdes1_base);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_pll_reset_done(cfg_tmp, serdes2_base);
+#endif
+
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	cfg_tmp = cfg_rcwsrds3 & 0x30;
+	cfg_tmp >>= 4;
+	do_pll_reset_done(cfg_tmp, serdes3_base);
+#endif
+
+	return ret;
+}
+
+void fsl_serdes_init(void)
+{
+#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
+	int i , j;
+
+	for (i = XFI1, j = 1; i <= XFI8; i++, j++)
+		xfi_dpmac[i] = j;
+
+	for (i = SGMII1, j = 1; i <= SGMII16; i++, j++)
+		sgmii_dpmac[i] = j;
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	serdes_init(FSL_SRDS_1,
+		    CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
+		    FSL_CHASSIS3_SRDS1_REGSR,
+		    FSL_CHASSIS3_SRDS1_PRTCL_MASK,
+		    FSL_CHASSIS3_SRDS1_PRTCL_SHIFT,
+		    serdes1_prtcl_map);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	serdes_init(FSL_SRDS_2,
+		    CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
+		    FSL_CHASSIS3_SRDS2_REGSR,
+		    FSL_CHASSIS3_SRDS2_PRTCL_MASK,
+		    FSL_CHASSIS3_SRDS2_PRTCL_SHIFT,
+		    serdes2_prtcl_map);
+#endif
+#ifdef CONFIG_SYS_NXP_SRDS_3
+	serdes_init(NXP_SRDS_3,
+		    CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + NXP_SRDS_3 * 0x10000,
+		    FSL_CHASSIS3_SRDS3_REGSR,
+		    FSL_CHASSIS3_SRDS3_PRTCL_MASK,
+		    FSL_CHASSIS3_SRDS3_PRTCL_SHIFT,
+		    serdes3_prtcl_map);
+#endif
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c
new file mode 100644
index 0000000..bc268e2
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2015, Freescale Semiconductor, Inc.
+ *
+ * Derived from arch/power/cpu/mpc85xx/speed.c
+ */
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <fsl_ifc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/arch-fsl-layerscape/immap_lsch3.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/soc.h>
+#include "cpu.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
+#define CONFIG_SYS_FSL_NUM_CC_PLLS	6
+#endif
+
+
+void get_sys_info(struct sys_info *sys_info)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
+		(void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
+		(void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
+	};
+	struct ccsr_clk_ctrl __iomem *clk_ctrl =
+		(void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
+	unsigned int cpu;
+	const u8 core_cplx_pll[16] = {
+		[0] = 0,	/* CC1 PPL / 1 */
+		[1] = 0,	/* CC1 PPL / 2 */
+		[2] = 0,	/* CC1 PPL / 4 */
+		[4] = 1,	/* CC2 PPL / 1 */
+		[5] = 1,	/* CC2 PPL / 2 */
+		[6] = 1,	/* CC2 PPL / 4 */
+		[8] = 2,	/* CC3 PPL / 1 */
+		[9] = 2,	/* CC3 PPL / 2 */
+		[10] = 2,	/* CC3 PPL / 4 */
+		[12] = 3,	/* CC4 PPL / 1 */
+		[13] = 3,	/* CC4 PPL / 2 */
+		[14] = 3,	/* CC4 PPL / 4 */
+	};
+
+	const u8 core_cplx_pll_div[16] = {
+		[0] = 1,	/* CC1 PPL / 1 */
+		[1] = 2,	/* CC1 PPL / 2 */
+		[2] = 4,	/* CC1 PPL / 4 */
+		[4] = 1,	/* CC2 PPL / 1 */
+		[5] = 2,	/* CC2 PPL / 2 */
+		[6] = 4,	/* CC2 PPL / 4 */
+		[8] = 1,	/* CC3 PPL / 1 */
+		[9] = 2,	/* CC3 PPL / 2 */
+		[10] = 4,	/* CC3 PPL / 4 */
+		[12] = 1,	/* CC4 PPL / 1 */
+		[13] = 2,	/* CC4 PPL / 2 */
+		[14] = 4,	/* CC4 PPL / 4 */
+	};
+
+	uint i, cluster;
+	uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
+	uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
+	unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
+	int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
+	u32 c_pll_sel, cplx_pll;
+	void *offset;
+
+	sys_info->freq_systembus = sysclk;
+#ifdef CONFIG_DDR_CLK_FREQ
+	sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
+#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
+	sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ;
+#endif
+#else
+	sys_info->freq_ddrbus = sysclk;
+#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
+	sys_info->freq_ddrbus2 = sysclk;
+#endif
+#endif
+
+	/* The freq_systembus is used to record frequency of platform PLL */
+	sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
+			FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
+			FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
+	sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
+			FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
+			FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
+#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
+	if (soc_has_dp_ddr()) {
+		sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >>
+			FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) &
+			FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK;
+	} else {
+		sys_info->freq_ddrbus2 = 0;
+	}
+#endif
+
+	for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
+		/*
+		 * fixme: prefer to combine the following into one line, but
+		 * cannot pass compiling without warning about in_le32.
+		 */
+		offset = (void *)((size_t)clk_grp[i/3] +
+			 offsetof(struct ccsr_clk_cluster_group,
+				  pllngsr[i%3].gsr));
+		ratio[i] = (in_le32(offset) >> 1) & 0x3f;
+		freq_c_pll[i] = sysclk * ratio[i];
+	}
+
+	for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
+		cluster = fsl_qoriq_core_to_cluster(cpu);
+		c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
+			    & 0xf;
+		cplx_pll = core_cplx_pll[c_pll_sel];
+		cplx_pll += cc_group[cluster] - 1;
+		sys_info->freq_processor[cpu] =
+			freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
+	}
+
+#if defined(CONFIG_FSL_IFC)
+	sys_info->freq_localbus = sys_info->freq_systembus /
+						CONFIG_SYS_FSL_IFC_CLK_DIV;
+#endif
+}
+
+
+int get_clocks(void)
+{
+	struct sys_info sys_info;
+	get_sys_info(&sys_info);
+	gd->cpu_clk = sys_info.freq_processor[0];
+	gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV;
+	gd->mem_clk = sys_info.freq_ddrbus;
+#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
+	gd->arch.mem2_clk = sys_info.freq_ddrbus2;
+#endif
+#if defined(CONFIG_FSL_ESDHC)
+	gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV;
+#endif /* defined(CONFIG_FSL_ESDHC) */
+
+	if (gd->cpu_clk != 0)
+		return 0;
+	else
+		return 1;
+}
+
+/********************************************
+ * get_bus_freq
+ * return platform clock in Hz
+ *********************************************/
+ulong get_bus_freq(ulong dummy)
+{
+	if (!gd->bus_clk)
+		get_clocks();
+
+	return gd->bus_clk;
+}
+
+/********************************************
+ * get_ddr_freq
+ * return ddr bus freq in Hz
+ *********************************************/
+ulong get_ddr_freq(ulong ctrl_num)
+{
+	if (!gd->mem_clk)
+		get_clocks();
+
+	/*
+	 * DDR controller 0 & 1 are on memory complex 0
+	 * DDR controller 2 is on memory complext 1
+	 */
+#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
+	if (ctrl_num >= 2)
+		return gd->arch.mem2_clk;
+#endif
+
+	return gd->mem_clk;
+}
+
+int get_i2c_freq(ulong dummy)
+{
+	return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
+}
+
+int get_dspi_freq(ulong dummy)
+{
+	return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
+}
+
+#ifdef CONFIG_FSL_ESDHC
+int get_sdhc_freq(ulong dummy)
+{
+	if (!gd->arch.sdhc_clk)
+		get_clocks();
+
+	return gd->arch.sdhc_clk;
+}
+#endif
+
+int get_serial_clock(void)
+{
+	return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_I2C_CLK:
+		return get_i2c_freq(0);
+#if defined(CONFIG_FSL_ESDHC)
+	case MXC_ESDHC_CLK:
+		return get_sdhc_freq(0);
+#endif
+	case MXC_DSPI_CLK:
+		return get_dspi_freq(0);
+	default:
+		printf("Unsupported clock\n");
+	}
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/icid.c b/arch/arm/cpu/armv8/fsl-layerscape/icid.c
new file mode 100644
index 0000000..b1a950e
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/icid.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/arch-fsl-layerscape/fsl_icid.h>
+#include <fsl_fman.h>
+
+static void set_icid(struct icid_id_table *tbl, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		out_be32((u32 *)(tbl[i].reg_addr), tbl[i].reg);
+}
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+void set_fman_icids(struct fman_icid_id_table *tbl, int size)
+{
+	int i;
+	ccsr_fman_t *fm = (void *)CONFIG_SYS_FSL_FM1_ADDR;
+
+	for (i = 0; i < size; i++) {
+		out_be32(&fm->fm_bmi_common.fmbm_ppid[tbl[i].port_id - 1],
+			 tbl[i].icid);
+	}
+}
+#endif
+
+void set_icids(void)
+{
+	/* setup general icid offsets */
+	set_icid(icid_tbl, icid_tbl_sz);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+	set_fman_icids(fman_icid_tbl, fman_icid_tbl_sz);
+#endif
+}
+
+int fdt_set_iommu_prop(void *blob, int off, int smmu_ph, u32 *ids, int num_ids)
+{
+	int i, ret;
+	u32 prop[8];
+
+	/*
+	 * Note: The "iommus" property definition mentions Stream IDs while
+	 * this code handles ICIDs. The current implementation assumes that
+	 * ICIDs and Stream IDs are equal.
+	 */
+	for (i = 0; i < num_ids; i++) {
+		prop[i * 2] = cpu_to_fdt32(smmu_ph);
+		prop[i * 2 + 1] = cpu_to_fdt32(ids[i]);
+	}
+	ret = fdt_setprop(blob, off, "iommus",
+			  prop, sizeof(u32) * num_ids * 2);
+	if (ret) {
+		printf("WARNING unable to set iommus: %s\n", fdt_strerror(ret));
+		return ret;
+	}
+
+	return 0;
+}
+
+int fdt_fixup_icid_tbl(void *blob, int smmu_ph,
+		       struct icid_id_table *tbl, int size)
+{
+	int i, err, off;
+
+	for (i = 0; i < size; i++) {
+		if (!tbl[i].compat)
+			continue;
+
+		off = fdt_node_offset_by_compat_reg(blob,
+						    tbl[i].compat,
+						    tbl[i].compat_addr);
+		if (off > 0) {
+			err = fdt_set_iommu_prop(blob, off, smmu_ph,
+						 &tbl[i].id, 1);
+			if (err)
+				return err;
+		} else {
+			printf("WARNING could not find node %s: %s.\n",
+			       tbl[i].compat, fdt_strerror(off));
+		}
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+int get_fman_port_icid(int port_id, struct fman_icid_id_table *tbl,
+		       const int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (tbl[i].port_id == port_id)
+			return tbl[i].icid;
+	}
+
+	return -1;
+}
+
+void fdt_fixup_fman_port_icid_by_compat(void *blob, int smmu_ph,
+					const char *compat)
+{
+	int noff, len, icid;
+	const u32 *prop;
+
+	noff = fdt_node_offset_by_compatible(blob, -1, compat);
+	while (noff > 0) {
+		prop = fdt_getprop(blob, noff, "cell-index", &len);
+		if (!prop) {
+			printf("WARNING missing cell-index for fman port\n");
+			continue;
+		}
+		if (len != 4) {
+			printf("WARNING bad cell-index size for fman port\n");
+			continue;
+		}
+
+		icid = get_fman_port_icid(fdt32_to_cpu(*prop),
+					  fman_icid_tbl, fman_icid_tbl_sz);
+		if (icid < 0) {
+			printf("WARNING unknown ICID for fman port %d\n",
+			       *prop);
+			continue;
+		}
+
+		fdt_set_iommu_prop(blob, noff, smmu_ph, (u32 *)&icid, 1);
+
+		noff = fdt_node_offset_by_compatible(blob, noff, compat);
+	}
+}
+
+void fdt_fixup_fman_icids(void *blob, int smmu_ph)
+{
+	static const char * const compats[] = {
+		"fsl,fman-v3-port-oh",
+		"fsl,fman-v3-port-rx",
+		"fsl,fman-v3-port-tx",
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(compats); i++)
+		fdt_fixup_fman_port_icid_by_compat(blob, smmu_ph, compats[i]);
+}
+#endif
+
+int fdt_get_smmu_phandle(void *blob)
+{
+	int noff, smmu_ph;
+
+	noff = fdt_node_offset_by_compatible(blob, -1, "arm,mmu-500");
+	if (noff < 0) {
+		printf("WARNING failed to get smmu node: %s\n",
+		       fdt_strerror(noff));
+		return noff;
+	}
+
+	smmu_ph = fdt_get_phandle(blob, noff);
+	if (!smmu_ph) {
+		smmu_ph = fdt_create_phandle(blob, noff);
+		if (!smmu_ph) {
+			printf("WARNING failed to get smmu phandle\n");
+			return -1;
+		}
+	}
+
+	return smmu_ph;
+}
+
+void fdt_fixup_icid(void *blob)
+{
+	int smmu_ph;
+
+	smmu_ph = fdt_get_smmu_phandle(blob);
+	if (smmu_ph < 0)
+		return;
+
+	fdt_fixup_icid_tbl(blob, smmu_ph, icid_tbl, icid_tbl_sz);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+	fdt_fixup_fman_icids(blob, smmu_ph);
+#endif
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
new file mode 100644
index 0000000..6721a57
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -0,0 +1,583 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014-2015 Freescale Semiconductor
+ *
+ * Extracted from armv8/start.S
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/gic.h>
+#include <asm/macro.h>
+#include <asm/arch-fsl-layerscape/soc.h>
+#ifdef CONFIG_MP
+#include <asm/arch/mp.h>
+#endif
+#ifdef CONFIG_FSL_LSCH3
+#include <asm/arch-fsl-layerscape/immap_lsch3.h>
+#endif
+#include <asm/u-boot.h>
+
+/* Get GIC offset
+* For LS1043a rev1.0, GIC base address align with 4k.
+* For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT]
+* is set, GIC base address align with 4K, or else align
+* with 64k.
+* output:
+*	x0: the base address of GICD
+*	x1: the base address of GICC
+*/
+ENTRY(get_gic_offset)
+	ldr     x0, =GICD_BASE
+#ifdef CONFIG_GICV2
+	ldr     x1, =GICC_BASE
+#endif
+#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
+	ldr     x2, =DCFG_CCSR_SVR
+	ldr	w2, [x2]
+	rev	w2, w2
+	lsr	w3, w2, #16
+	ldr	w4, =SVR_DEV(SVR_LS1043A)
+	cmp	w3, w4
+	b.ne	1f
+	ands	w2, w2, #0xff
+	cmp	w2, #REV1_0
+	b.eq	1f
+	ldr	x2, =SCFG_GIC400_ALIGN
+	ldr	w2, [x2]
+	rev	w2, w2
+	tbnz	w2, #GIC_ADDR_BIT, 1f
+	ldr     x0, =GICD_BASE_64K
+#ifdef CONFIG_GICV2
+	ldr     x1, =GICC_BASE_64K
+#endif
+1:
+#endif
+	ret
+ENDPROC(get_gic_offset)
+
+ENTRY(smp_kick_all_cpus)
+	/* Kick secondary cpus up by SGI 0 interrupt */
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+	mov	x29, lr			/* Save LR */
+	bl	get_gic_offset
+	bl	gic_kick_secondary_cpus
+	mov	lr, x29			/* Restore LR */
+#endif
+	ret
+ENDPROC(smp_kick_all_cpus)
+
+
+ENTRY(lowlevel_init)
+	mov	x29, lr			/* Save LR */
+
+	/* unmask SError and abort */
+	msr daifclr, #4
+
+	/* Set HCR_EL2[AMO] so SError @EL2 is taken */
+	mrs	x0, hcr_el2
+	orr	x0, x0, #0x20			/* AMO */
+	msr	hcr_el2, x0
+	isb
+
+	switch_el x1, 1f, 100f, 100f	/* skip if not in EL3 */
+1:
+
+#if defined (CONFIG_SYS_FSL_HAS_CCN504)
+
+	/* Set Wuo bit for RN-I 20 */
+#ifdef CONFIG_ARCH_LS2080A
+	ldr	x0, =CCI_AUX_CONTROL_BASE(20)
+	ldr	x1, =0x00000010
+	bl	ccn504_set_aux
+
+	/*
+	 * Set forced-order mode in RNI-6, RNI-20
+	 * This is required for performance optimization on LS2088A
+	 * LS2080A family does not support setting forced-order mode,
+	 * so skip this operation for LS2080A family
+	 */
+	bl	get_svr
+	lsr	w0, w0, #16
+	ldr	w1, =SVR_DEV(SVR_LS2080A)
+	cmp	w0, w1
+	b.eq	1f
+
+	ldr	x0, =CCI_AUX_CONTROL_BASE(6)
+	ldr	x1, =0x00000020
+	bl	ccn504_set_aux
+	ldr	x0, =CCI_AUX_CONTROL_BASE(20)
+	ldr	x1, =0x00000020
+	bl	ccn504_set_aux
+1:
+#endif
+
+	/* Add fully-coherent masters to DVM domain */
+	ldr	x0, =CCI_MN_BASE
+	ldr	x1, =CCI_MN_RNF_NODEID_LIST
+	ldr	x2, =CCI_MN_DVM_DOMAIN_CTL_SET
+	bl	ccn504_add_masters_to_dvm
+
+	/* Set all RN-I ports to QoS of 15 */
+	ldr	x0, =CCI_S0_QOS_CONTROL_BASE(0)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S1_QOS_CONTROL_BASE(0)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S2_QOS_CONTROL_BASE(0)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+
+	ldr	x0, =CCI_S0_QOS_CONTROL_BASE(2)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S1_QOS_CONTROL_BASE(2)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S2_QOS_CONTROL_BASE(2)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+
+	ldr	x0, =CCI_S0_QOS_CONTROL_BASE(6)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S1_QOS_CONTROL_BASE(6)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S2_QOS_CONTROL_BASE(6)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+
+	ldr	x0, =CCI_S0_QOS_CONTROL_BASE(12)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S1_QOS_CONTROL_BASE(12)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S2_QOS_CONTROL_BASE(12)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+
+	ldr	x0, =CCI_S0_QOS_CONTROL_BASE(16)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S1_QOS_CONTROL_BASE(16)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S2_QOS_CONTROL_BASE(16)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+
+	ldr	x0, =CCI_S0_QOS_CONTROL_BASE(20)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S1_QOS_CONTROL_BASE(20)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+	ldr	x0, =CCI_S2_QOS_CONTROL_BASE(20)
+	ldr	x1, =0x00FF000C
+	bl	ccn504_set_qos
+#endif /* CONFIG_SYS_FSL_HAS_CCN504 */
+
+#ifdef SMMU_BASE
+	/* Set the SMMU page size in the sACR register */
+	ldr	x1, =SMMU_BASE
+	ldr	w0, [x1, #0x10]
+	orr	w0, w0, #1 << 16  /* set sACR.pagesize to indicate 64K page */
+	str	w0, [x1, #0x10]
+#endif
+
+	/* Initialize GIC Secure Bank Status */
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+	branch_if_slave x0, 1f
+	bl	get_gic_offset
+	bl	gic_init_secure
+1:
+#ifdef CONFIG_GICV3
+	ldr	x0, =GICR_BASE
+	bl	gic_init_secure_percpu
+#elif defined(CONFIG_GICV2)
+	bl	get_gic_offset
+	bl	gic_init_secure_percpu
+#endif
+#endif
+
+100:
+	branch_if_master x0, x1, 2f
+
+#if defined(CONFIG_MP) && defined(CONFIG_ARMV8_MULTIENTRY)
+	ldr	x0, =secondary_boot_func
+	blr	x0
+#endif
+
+2:
+	switch_el x1, 1f, 100f, 100f	/* skip if not in EL3 */
+1:
+#ifdef CONFIG_FSL_TZPC_BP147
+	/* Set Non Secure access for all devices protected via TZPC */
+	ldr	x1, =TZPCDECPROT_0_SET_BASE /* Decode Protection-0 Set Reg */
+	orr	w0, w0, #1 << 3 /* DCFG_RESET is accessible from NS world */
+	str	w0, [x1]
+
+	isb
+	dsb	sy
+#endif
+
+#ifdef CONFIG_FSL_TZASC_400
+	/*
+	 * LS2080 and its personalities does not support TZASC
+	 * So skip TZASC related operations
+	 */
+	bl	get_svr
+	lsr	w0, w0, #16
+	ldr	w1, =SVR_DEV(SVR_LS2080A)
+	cmp	w0, w1
+	b.eq	1f
+
+	/* Set TZASC so that:
+	 * a. We use only Region0 whose global secure write/read is EN
+	 * b. We use only Region0 whose NSAID write/read is EN
+	 *
+	 * NOTE: As per the CCSR map doc, TZASC 3 and TZASC 4 are just
+	 * 	 placeholders.
+	 */
+
+.macro tzasc_prog, xreg
+
+	mov     x12, TZASC1_BASE
+	mov     x16, #0x10000
+	mul     x14, \xreg, x16
+	add     x14, x14,x12
+	mov 	x1, #0x8
+	add     x1, x1, x14
+
+	ldr     w0, [x1]		/* Filter 0 Gate Keeper Register */
+	orr     w0, w0, #1 << 0		/* Set open_request for Filter 0 */
+	str     w0, [x1]
+
+	mov	x1, #0x110
+	add     x1, x1, x14
+
+	ldr     w0, [x1]		/* Region-0 Attributes Register */
+	orr     w0, w0, #1 << 31	/* Set Sec global write en, Bit[31] */
+	orr     w0, w0, #1 << 30	/* Set Sec global read en, Bit[30] */
+	str     w0, [x1]
+
+	mov	x1, #0x114
+	add     x1, x1, x14
+
+	ldr     w0, [x1]		/* Region-0 Access Register */
+	mov     w0, #0xFFFFFFFF		/* Set nsaid_wr_en and nsaid_rd_en */
+	str     w0, [x1]
+.endm
+
+#ifdef CONFIG_FSL_TZASC_1
+	mov     x13, #0
+	tzasc_prog	x13
+
+#endif
+#ifdef CONFIG_FSL_TZASC_2
+	mov     x13, #1
+	tzasc_prog	x13
+
+#endif
+	isb
+	dsb	sy
+#endif
+100:
+1:
+#ifdef CONFIG_ARCH_LS1046A
+	switch_el x1, 1f, 100f, 100f	/* skip if not in EL3 */
+1:
+	/* Initialize the L2 RAM latency */
+	mrs   x1, S3_1_c11_c0_2
+	mov   x0, #0x1C7
+	/* Clear L2 Tag RAM latency and L2 Data RAM latency */
+	bic   x1, x1, x0
+	/* Set L2 data ram latency bits [2:0] */
+	orr   x1, x1, #0x2
+	/* set L2 tag ram latency bits [8:6] */
+	orr   x1,  x1, #0x80
+	msr   S3_1_c11_c0_2, x1
+	isb
+100:
+#endif
+
+#if !defined(CONFIG_TFABOOT) && \
+	(defined(CONFIG_FSL_LSCH2) && !defined(CONFIG_SPL_BUILD))
+	bl	fsl_ocram_init
+#endif
+
+	mov	lr, x29			/* Restore LR */
+	ret
+ENDPROC(lowlevel_init)
+
+#if defined(CONFIG_FSL_LSCH2) && !defined(CONFIG_SPL_BUILD)
+ENTRY(fsl_ocram_init)
+	mov	x28, lr			/* Save LR */
+	bl	fsl_clear_ocram
+	bl	fsl_ocram_clear_ecc_err
+	mov	lr, x28			/* Restore LR */
+	ret
+ENDPROC(fsl_ocram_init)
+
+ENTRY(fsl_clear_ocram)
+/* Clear OCRAM */
+	ldr	x0, =CONFIG_SYS_FSL_OCRAM_BASE
+	ldr	x1, =(CONFIG_SYS_FSL_OCRAM_BASE + CONFIG_SYS_FSL_OCRAM_SIZE)
+	mov	x2, #0
+clear_loop:
+	str	x2, [x0]
+	add	x0, x0, #8
+	cmp	x0, x1
+	b.lo	clear_loop
+	ret
+ENDPROC(fsl_clear_ocram)
+
+ENTRY(fsl_ocram_clear_ecc_err)
+	/* OCRAM1/2 ECC status bit */
+	mov	w1, #0x60
+	ldr	x0, =DCSR_DCFG_SBEESR2
+	str	w1, [x0]
+	ldr	x0, =DCSR_DCFG_MBEESR2
+	str	w1, [x0]
+	ret
+ENDPROC(fsl_ocram_init)
+#endif
+
+#ifdef CONFIG_FSL_LSCH3
+	.globl get_svr
+get_svr:
+	ldr	x1, =FSL_LSCH3_SVR
+	ldr	w0, [x1]
+	ret
+#endif
+
+#if defined(CONFIG_SYS_FSL_HAS_CCN504) || defined(CONFIG_SYS_FSL_HAS_CCN508)
+hnf_pstate_poll:
+	/* x0 has the desired status, return 0 for success, 1 for timeout
+	 * clobber x1, x2, x3, x4, x6, x7
+	 */
+	mov	x1, x0
+	mov	x7, #0			/* flag for timeout */
+	mrs	x3, cntpct_el0		/* read timer */
+	add	x3, x3, #1200		/* timeout after 100 microseconds */
+	mov	x0, #0x18
+	movk	x0, #0x420, lsl #16	/* HNF0_PSTATE_STATUS */
+	mov	w6, #8			/* HN-F node count */
+1:
+	ldr	x2, [x0]
+	cmp	x2, x1			/* check status */
+	b.eq	2f
+	mrs	x4, cntpct_el0
+	cmp	x4, x3
+	b.ls	1b
+	mov	x7, #1			/* timeout */
+	b	3f
+2:
+	add	x0, x0, #0x10000	/* move to next node */
+	subs	w6, w6, #1
+	cbnz	w6, 1b
+3:
+	mov	x0, x7
+	ret
+
+hnf_set_pstate:
+	/* x0 has the desired state, clobber x1, x2, x6 */
+	mov	x1, x0
+	/* power state to SFONLY */
+	mov	w6, #8			/* HN-F node count */
+	mov	x0, #0x10
+	movk	x0, #0x420, lsl #16	/* HNF0_PSTATE_REQ */
+1:	/* set pstate to sfonly */
+	ldr	x2, [x0]
+	and	x2, x2, #0xfffffffffffffffc	/* & HNFPSTAT_MASK */
+	orr	x2, x2, x1
+	str	x2, [x0]
+	add	x0, x0, #0x10000	/* move to next node */
+	subs	w6, w6, #1
+	cbnz	w6, 1b
+
+	ret
+
+ENTRY(__asm_flush_l3_dcache)
+	/*
+	 * Return status in x0
+	 *    success 0
+	 *    timeout 1 for setting SFONLY, 2 for FAM, 3 for both
+	 */
+	mov	x29, lr
+	mov	x8, #0
+
+	dsb	sy
+	mov	x0, #0x1		/* HNFPSTAT_SFONLY */
+	bl	hnf_set_pstate
+
+	mov	x0, #0x4		/* SFONLY status */
+	bl	hnf_pstate_poll
+	cbz	x0, 1f
+	mov	x8, #1			/* timeout */
+1:
+	dsb	sy
+	mov	x0, #0x3		/* HNFPSTAT_FAM */
+	bl	hnf_set_pstate
+
+	mov	x0, #0xc		/* FAM status */
+	bl	hnf_pstate_poll
+	cbz	x0, 1f
+	add	x8, x8, #0x2
+1:
+	mov	x0, x8
+	mov	lr, x29
+	ret
+ENDPROC(__asm_flush_l3_dcache)
+#endif /* CONFIG_SYS_FSL_HAS_CCN504 */
+
+#ifdef CONFIG_MP
+	/* Keep literals not used by the secondary boot code outside it */
+	.ltorg
+
+	/* Using 64 bit alignment since the spin table is accessed as data */
+	.align 4
+	.global secondary_boot_code
+	/* Secondary Boot Code starts here */
+secondary_boot_code:
+	.global __spin_table
+__spin_table:
+	.space CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE
+
+	.align 2
+ENTRY(secondary_boot_func)
+	/*
+	 * MPIDR_EL1 Fields:
+	 * MPIDR[1:0] = AFF0_CPUID <- Core ID (0,1)
+	 * MPIDR[7:2] = AFF0_RES
+	 * MPIDR[15:8] = AFF1_CLUSTERID <- Cluster ID (0,1,2,3)
+	 * MPIDR[23:16] = AFF2_CLUSTERID
+	 * MPIDR[24] = MT
+	 * MPIDR[29:25] = RES0
+	 * MPIDR[30] = U
+	 * MPIDR[31] = ME
+	 * MPIDR[39:32] = AFF3
+	 *
+	 * Linear Processor ID (LPID) calculation from MPIDR_EL1:
+	 * (We only use AFF0_CPUID and AFF1_CLUSTERID for now
+	 * until AFF2_CLUSTERID and AFF3 have non-zero values)
+	 *
+	 * LPID = MPIDR[15:8] | MPIDR[1:0]
+	 */
+	mrs	x0, mpidr_el1
+	ubfm	x1, x0, #8, #15
+	ubfm	x2, x0, #0, #1
+	orr	x10, x2, x1, lsl #2	/* x10 has LPID */
+	ubfm    x9, x0, #0, #15         /* x9 contains MPIDR[15:0] */
+	/*
+	 * offset of the spin table element for this core from start of spin
+	 * table (each elem is padded to 64 bytes)
+	 */
+	lsl	x1, x10, #6
+	ldr	x0, =__spin_table
+	/* physical address of this cpus spin table element */
+	add	x11, x1, x0
+
+	ldr	x0, =__real_cntfrq
+	ldr	x0, [x0]
+	msr	cntfrq_el0, x0	/* set with real frequency */
+	str	x9, [x11, #16]	/* LPID */
+	mov	x4, #1
+	str	x4, [x11, #8]	/* STATUS */
+	dsb	sy
+#if defined(CONFIG_GICV3)
+	gic_wait_for_interrupt_m x0
+#elif defined(CONFIG_GICV2)
+	bl	get_gic_offset
+	mov	x0, x1
+        gic_wait_for_interrupt_m x0, w1
+#endif
+
+slave_cpu:
+	wfe
+	ldr	x0, [x11]
+	cbz	x0, slave_cpu
+#ifndef CONFIG_ARMV8_SWITCH_TO_EL1
+	mrs     x1, sctlr_el2
+#else
+	mrs     x1, sctlr_el1
+#endif
+	tbz     x1, #25, cpu_is_le
+	rev     x0, x0                  /* BE to LE conversion */
+cpu_is_le:
+	ldr	x5, [x11, #24]
+	cbz	x5, 1f
+
+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
+	adr	x4, secondary_switch_to_el1
+	ldr	x5, =ES_TO_AARCH64
+#else
+	ldr	x4, [x11]
+	ldr	x5, =ES_TO_AARCH32
+#endif
+	bl	secondary_switch_to_el2
+
+1:
+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
+	adr	x4, secondary_switch_to_el1
+#else
+	ldr	x4, [x11]
+#endif
+	ldr	x5, =ES_TO_AARCH64
+	bl	secondary_switch_to_el2
+
+ENDPROC(secondary_boot_func)
+
+ENTRY(secondary_switch_to_el2)
+	switch_el x6, 1f, 0f, 0f
+0:	ret
+1:	armv8_switch_to_el2_m x4, x5, x6
+ENDPROC(secondary_switch_to_el2)
+
+ENTRY(secondary_switch_to_el1)
+	mrs	x0, mpidr_el1
+	ubfm	x1, x0, #8, #15
+	ubfm	x2, x0, #0, #1
+	orr	x10, x2, x1, lsl #2	/* x10 has LPID */
+
+	lsl	x1, x10, #6
+	ldr	x0, =__spin_table
+	/* physical address of this cpus spin table element */
+	add	x11, x1, x0
+
+	ldr	x4, [x11]
+
+	ldr	x5, [x11, #24]
+	cbz	x5, 2f
+
+	ldr	x5, =ES_TO_AARCH32
+	bl	switch_to_el1
+
+2:	ldr	x5, =ES_TO_AARCH64
+
+switch_to_el1:
+	switch_el x6, 0f, 1f, 0f
+0:	ret
+1:	armv8_switch_to_el1_m x4, x5, x6
+ENDPROC(secondary_switch_to_el1)
+
+	/* Ensure that the literals used by the secondary boot code are
+	 * assembled within it (this is required so that we can protect
+	 * this area with a single memreserve region
+	 */
+	.ltorg
+
+	/* 64 bit alignment for elements accessed as data */
+	.align 4
+	.global __real_cntfrq
+__real_cntfrq:
+	.quad COUNTER_FREQUENCY
+	.globl __secondary_boot_code_size
+	.type __secondary_boot_code_size, %object
+	/* Secondary Boot Code ends here */
+__secondary_boot_code_size:
+	.quad .-secondary_boot_code
+#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c
new file mode 100644
index 0000000..8d7beca
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_lsch2.h>
+
+struct serdes_config {
+	u32 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	{0x2208, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, SATA1} },
+	{0x0008, {NONE, NONE, NONE, SATA1} },
+	{0x3508, {SGMII_FM1_DTSEC1, PCIE1, NONE, SATA1} },
+	{0x3305, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} },
+	{0x2205, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, PCIE1} },
+	{0x2305, {SGMII_2500_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} },
+	{0x9508, {TX_CLK, PCIE1, NONE, SATA1} },
+	{0x3905, {SGMII_FM1_DTSEC1, TX_CLK, NONE, PCIE1} },
+	{0x9305, {TX_CLK, SGMII_FM1_DTSEC2, NONE, PCIE1} },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1043_ids.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1043_ids.c
new file mode 100644
index 0000000..0e86494
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1043_ids.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <asm/arch-fsl-layerscape/immap_lsch2.h>
+#include <asm/arch-fsl-layerscape/fsl_icid.h>
+#include <asm/arch-fsl-layerscape/fsl_portals.h>
+#include <fsl_sec.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+};
+#endif
+
+struct icid_id_table icid_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+	SET_QMAN_ICID(FSL_DPAA1_STREAM_ID_START),
+	SET_BMAN_ICID(FSL_DPAA1_STREAM_ID_START + 1),
+#endif
+
+	SET_SDHC_ICID(FSL_SDHC_STREAM_ID),
+
+	SET_USB_ICID(1, "snps,dwc3", FSL_USB1_STREAM_ID),
+	SET_USB_ICID(2, "snps,dwc3", FSL_USB2_STREAM_ID),
+	SET_USB_ICID(3, "snps,dwc3", FSL_USB3_STREAM_ID),
+
+	SET_SATA_ICID("fsl,ls1043a-ahci", FSL_SATA_STREAM_ID),
+	SET_QDMA_ICID("fsl,ls1043a-qdma", FSL_QDMA_STREAM_ID),
+	SET_EDMA_ICID(FSL_EDMA_STREAM_ID),
+	SET_ETR_ICID(FSL_ETR_STREAM_ID),
+	SET_DEBUG_ICID(FSL_DEBUG_STREAM_ID),
+	SET_QE_ICID(FSL_QE_STREAM_ID),
+#ifdef CONFIG_FSL_CAAM
+	SET_SEC_QI_ICID(FSL_DPAA1_STREAM_ID_START + 2),
+	SET_SEC_JR_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 3),
+	SET_SEC_JR_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 4),
+	SET_SEC_JR_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 5),
+	SET_SEC_JR_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 6),
+	SET_SEC_RTIC_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 7),
+	SET_SEC_RTIC_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 8),
+	SET_SEC_RTIC_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 9),
+	SET_SEC_RTIC_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 10),
+	SET_SEC_DECO_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 11),
+	SET_SEC_DECO_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 12),
+#endif
+};
+
+int icid_tbl_sz = ARRAY_SIZE(icid_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct fman_icid_id_table fman_icid_tbl[] = {
+	/* port id, icid */
+	SET_FMAN_ICID_ENTRY(0x02, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x03, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x04, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x05, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x06, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x07, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x08, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x09, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0a, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0b, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0c, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0d, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x28, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x29, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2a, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2b, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2c, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2d, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x10, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x11, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x30, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x31, FSL_DPAA1_STREAM_ID_END),
+};
+
+int fman_icid_tbl_sz = ARRAY_SIZE(fman_icid_tbl);
+#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_psci.S b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_psci.S
new file mode 100644
index 0000000..b4c7d6f
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_psci.S
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Author: Hongbo Zhang <hongbo.zhang@nxp.com>
+ * This file implements LS102X platform PSCI SYSTEM-SUSPEND function
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/psci.h>
+
+	.pushsection ._secure.text, "ax"
+
+.globl	psci_version
+psci_version:
+	ldr	w0, =0x00010000		/* PSCI v1.0 */
+	ret
+
+	.popsection
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c
new file mode 100644
index 0000000..6c5e52e
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_lsch2.h>
+
+struct serdes_config {
+	u32 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x1555, {XFI_FM1_MAC9, PCIE1, PCIE2, PCIE3} },
+	{0x2555, {SGMII_2500_FM1_DTSEC9, PCIE1, PCIE2, PCIE3} },
+	{0x4555, {QSGMII_FM1_A, PCIE1, PCIE2, PCIE3} },
+	{0x4558, {QSGMII_FM1_A, PCIE1, PCIE2, SATA1} },
+	{0x1355, {XFI_FM1_MAC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} },
+	{0x2355, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} },
+	{0x3335, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5,
+		  PCIE3} },
+	{0x3355, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} },
+	{0x3358, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, SATA1} },
+	{0x3555, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, PCIE3} },
+	{0x3558, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, SATA1} },
+	{0x7000, {PCIE1, PCIE1, PCIE1, PCIE1} },
+	{0x9998, {PCIE1, PCIE2, PCIE3, SATA1} },
+	{0x6058, {PCIE1, PCIE1, PCIE2, SATA1} },
+	{0x1455, {XFI_FM1_MAC9, QSGMII_FM1_A, PCIE2, PCIE3} },
+	{0x2455, {SGMII_2500_FM1_DTSEC9, QSGMII_FM1_A, PCIE2, PCIE3} },
+	{0x2255, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC2, PCIE2, PCIE3} },
+	{0x3333, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1046_ids.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1046_ids.c
new file mode 100644
index 0000000..2da9ada
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1046_ids.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <asm/arch-fsl-layerscape/immap_lsch2.h>
+#include <asm/arch-fsl-layerscape/fsl_icid.h>
+#include <asm/arch-fsl-layerscape/fsl_portals.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+	SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0),
+};
+#endif
+
+struct icid_id_table icid_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+	SET_QMAN_ICID(FSL_DPAA1_STREAM_ID_START),
+	SET_BMAN_ICID(FSL_DPAA1_STREAM_ID_START + 1),
+#endif
+
+	SET_SDHC_ICID(FSL_SDHC_STREAM_ID),
+
+	SET_USB_ICID(1, "snps,dwc3", FSL_USB1_STREAM_ID),
+	SET_USB_ICID(2, "snps,dwc3", FSL_USB2_STREAM_ID),
+	SET_USB_ICID(3, "snps,dwc3", FSL_USB3_STREAM_ID),
+
+	SET_SATA_ICID("fsl,ls1046a-ahci", FSL_SATA_STREAM_ID),
+	SET_QDMA_ICID("fsl,ls1046a-qdma", FSL_QDMA_STREAM_ID),
+	SET_EDMA_ICID(FSL_EDMA_STREAM_ID),
+	SET_ETR_ICID(FSL_ETR_STREAM_ID),
+	SET_DEBUG_ICID(FSL_DEBUG_STREAM_ID),
+#ifdef CONFIG_FSL_CAAM
+	SET_SEC_QI_ICID(FSL_DPAA1_STREAM_ID_START + 2),
+	SET_SEC_JR_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 3),
+	SET_SEC_JR_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 4),
+	SET_SEC_JR_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 5),
+	SET_SEC_JR_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 6),
+	SET_SEC_RTIC_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 7),
+	SET_SEC_RTIC_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 8),
+	SET_SEC_RTIC_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 9),
+	SET_SEC_RTIC_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 10),
+	SET_SEC_DECO_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 11),
+	SET_SEC_DECO_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 12),
+	SET_SEC_DECO_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 13),
+#endif
+};
+
+int icid_tbl_sz = ARRAY_SIZE(icid_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct fman_icid_id_table fman_icid_tbl[] = {
+	/* port id, icid */
+	SET_FMAN_ICID_ENTRY(0x02, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x03, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x04, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x05, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x06, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x07, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x08, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x09, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0a, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0b, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0c, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x0d, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x28, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x29, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2a, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2b, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2c, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x2d, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x10, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x11, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x30, FSL_DPAA1_STREAM_ID_END),
+	SET_FMAN_ICID_ENTRY(0x31, FSL_DPAA1_STREAM_ID_END),
+};
+
+int fman_icid_tbl_sz = ARRAY_SIZE(fman_icid_tbl);
+#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c
new file mode 100644
index 0000000..f8310f2
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_lsch2.h>
+
+struct serdes_config {
+	u32 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x3333, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x1133, {XFI_FM1_MAC9, XFI_FM1_MAC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x1333, {XFI_FM1_MAC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x2333, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5,
+		  SGMII_FM1_DTSEC6} },
+	{0x2233, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10,
+		  SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6} },
+	{0x1040, {XFI_FM1_MAC9, NONE, QSGMII_FM1_A, NONE} },
+	{0x2040, {SGMII_2500_FM1_DTSEC9, NONE, QSGMII_FM1_A, NONE} },
+	{0x1163, {XFI_FM1_MAC9, XFI_FM1_MAC10, PCIE1, SGMII_FM1_DTSEC6} },
+	{0x2263, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10, PCIE1,
+		  SGMII_FM1_DTSEC6} },
+	{0x3363, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6, PCIE1,
+		  SGMII_FM1_DTSEC6} },
+	{0x2223, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10,
+		  SGMII_2500_FM1_DTSEC5, SGMII_FM1_DTSEC6} },
+	{}
+};
+
+static struct serdes_config serdes2_cfg_tbl[] = {
+	/* SerDes 2 */
+	{0x8888, {PCIE1, PCIE1, PCIE1, PCIE1} },
+	{0x5559, {PCIE1, PCIE2, PCIE3, SATA1} },
+	{0x5577, {PCIE1, PCIE2, PCIE3, PCIE3} },
+	{0x5506, {PCIE1, PCIE2, NONE, PCIE3} },
+	{0x0506, {NONE, PCIE2, NONE, PCIE3} },
+	{0x0559, {NONE, PCIE2, PCIE3, SATA1} },
+	{0x5A59, {PCIE1, SGMII_FM1_DTSEC2, PCIE3, SATA1} },
+	{0x5A06, {PCIE1, SGMII_FM1_DTSEC2, NONE, PCIE3} },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+	serdes2_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c
new file mode 100644
index 0000000..8e8b45a
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2017 NXP
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+
+struct serdes_config {
+	u8 ip_protocol;
+	u8 lanes[SRDS_MAX_LANES];
+	u8 rcw_lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x12, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 3 }  },
+	{0x15, {SGMII3, SGMII7, XFI1, XFI2 }, {3, 3, 1, 1 } },
+	{0x16, {SGMII3, SGMII7, SGMII1, XFI2 }, {3, 3, 3, 1 } },
+	{0x17, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 2 } },
+	{0x18, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 2, 2 } },
+	{0x19, {SGMII3, QSGMII_B, XFI1, XFI2}, {3, 4, 1, 1 } },
+	{0x1A, {SGMII3, QSGMII_B, SGMII1, XFI2 }, {3, 4, 3, 1 } },
+	{0x1B, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 2 } },
+	{0x1C, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 2, 2 } },
+	{0x1D, {QSGMII_A, QSGMII_B, XFI1, XFI2 }, {4, 4, 1, 1 } },
+	{0x1E, {QSGMII_A, QSGMII_B, SGMII1, XFI2  }, {4, 4, 3, 1 } },
+	{0x1F, {QSGMII_A, QSGMII_B, SGMII1, SGMII2  }, {4, 4, 3, 2 } },
+	{0x20, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 2, 2 } },
+	{0x35, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 3 } },
+	{0x36, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 3, 3 } },
+	{0x3A, {SGMII3, PCIE1, SGMII1, SGMII2 }, {3, 5, 3, 3 } },
+		{}
+};
+static struct serdes_config serdes2_cfg_tbl[] = {
+	/* SerDes 2 */
+	{0x0C, {PCIE1, PCIE1, PCIE1, PCIE1 }, {8, 8, 8, 8 } },
+	{0x0D, {PCIE1, PCIE2, PCIE3, SATA1 }, {5, 5, 5, 9 }  },
+	{0x0E, {PCIE1, PCIE1, PCIE2, SATA1 }, {7, 7, 6, 9 }  },
+	{0x13, {PCIE1, PCIE1, PCIE3, PCIE3 }, {7, 7, 7, 7 }  },
+	{0x14, {PCIE1, PCIE2, PCIE3, PCIE3 }, {5, 5, 7, 7 }  },
+	{0x3C, {NONE, PCIE2, NONE, PCIE3 }, {0, 5, 0, 6 }  },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+	serdes2_cfg_tbl,
+};
+
+int serdes_get_number(int serdes, int cfg)
+{
+	struct serdes_config *ptr;
+	int i, j, index, lnk;
+	int is_found, max_lane = SRDS_MAX_LANES;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+
+	while (ptr->ip_protocol) {
+		is_found = 1;
+		for (i = 0, j = max_lane - 1; i < max_lane; i++, j--) {
+			lnk = cfg & (0xf << 4 * i);
+			lnk = lnk >> (4 * i);
+
+			index = (serdes == FSL_SRDS_1) ? j : i;
+
+			if (ptr->rcw_lanes[index] == lnk && is_found)
+				is_found = 1;
+			else
+				is_found = 0;
+		}
+
+		if (is_found)
+			return ptr->ip_protocol;
+		ptr++;
+	}
+
+	return 0;
+}
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->ip_protocol) {
+		if (ptr->ip_protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->ip_protocol) {
+		if (ptr->ip_protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->ip_protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c
new file mode 100644
index 0000000..7997422
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+
+struct serdes_config {
+	u8 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x03, {PCIE2, PCIE2, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } },
+	{0x05, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII4, SGMII3, SGMII2, SGMII1 } },
+	{0x07, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+		SGMII1 } },
+	{0x09, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+		SGMII1 } },
+	{0x0A, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+		SGMII1 } },
+	{0x0C, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+		SGMII1 } },
+	{0x0E, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2,
+		SGMII1 } },
+	{0x26, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, XFI2, XFI1 } },
+	{0x28, {SGMII8, SGMII7, SGMII6, SGMII5, XFI4, XFI3, XFI2, XFI1 } },
+	{0x2A, {XFI8, XFI7, XFI6, XFI5, XFI4, XFI3, XFI2, XFI1 } },
+	{0x2B, {SGMII8, SGMII7, SGMII6, SGMII5, XAUI1, XAUI1, XAUI1, XAUI1  } },
+	{0x32, {XAUI2, XAUI2, XAUI2, XAUI2, XAUI1, XAUI1, XAUI1, XAUI1  } },
+	{0x33, {PCIE2, PCIE2, PCIE2, PCIE2, QSGMII_D, QSGMII_C, QSGMII_B,
+		QSGMII_A} },
+	{0x35, {QSGMII_D, QSGMII_C, QSGMII_B, PCIE2, XFI4, XFI3, XFI2, XFI1 } },
+	{0x39, {SGMII8, SGMII7, SGMII6, PCIE2, SGMII4, SGMII3, SGMII2,
+		PCIE1 } },
+	{0x3B, {XFI8, XFI7, XFI6, PCIE2, XFI4, XFI3, XFI2, PCIE1 } },
+	{0x4B, {PCIE2, PCIE2, PCIE2, PCIE2, XFI4, XFI3, XFI2, XFI1 } },
+	{0x4C, {XFI8, XFI7, XFI6, XFI5, PCIE1, PCIE1, PCIE1, PCIE1 } },
+	{0x4D, {SGMII8, SGMII7, PCIE2, PCIE2, SGMII4, SGMII3, PCIE1, PCIE1 } },
+		{}
+};
+static struct serdes_config serdes2_cfg_tbl[] = {
+	/* SerDes 2 */
+	{0x07, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+		SGMII16 } },
+	{0x09, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+		SGMII16 } },
+	{0x0A, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+		SGMII16 } },
+	{0x0C, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+		SGMII16 } },
+	{0x0E, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15,
+		SGMII16 } },
+	{0x3D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
+	{0x3E, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
+	{0x3F, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
+	{0x40, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
+	{0x41, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
+	{0x42, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
+	{0x43, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } },
+	{0x44, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } },
+	{0x45, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, PCIE4,
+		PCIE4 } },
+	{0x47, {PCIE3, SGMII10, SGMII11, SGMII12, PCIE4, SGMII14, SGMII15,
+		SGMII16 } },
+	{0x49, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1,
+		SATA2 } },
+	{0x4A, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1,
+		SATA2 } },
+	{0x51, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
+	{0x57, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SGMII15, SGMII16 } },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+	serdes2_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c
new file mode 100644
index 0000000..a04a370
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+
+struct serdes_config {
+	u8 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	/* SerDes 1 */
+	{0x01, {PCIE2, PCIE2, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } },
+	{0x02, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII6, SGMII5, SGMII4, SGMII3 } },
+	{0x03, {PCIE2, PCIE2, PCIE2, PCIE2, XFI6, XFI5, XFI4,
+		XFI3 } },
+	{0x04, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, SGMII4,
+		SGMII3 } },
+	{0x05, {XFI10, XFI9, XFI8, XFI7, PCIE1, PCIE1, PCIE1,
+		PCIE1 } },
+	{0x06, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, XFI4,
+		XFI3 } },
+	{0x07, {SGMII10, SGMII9, SGMII8, SGMII7, XFI6, XFI5, XFI4,
+		XFI3 } },
+	{0x08, {XFI10, XFI9, XFI8, XFI7, XFI6, XFI5, XFI4, XFI3 } },
+	{0x09, {SGMII10, SGMII9, SGMII8, PCIE2, SGMII6, SGMII5, SGMII4,
+		PCIE1 } },
+	{0x0A, {XFI10, XFI9, XFI8, PCIE2, XFI6, XFI5, XFI4, PCIE1 } },
+	{0x0B, {SGMII10, SGMII9, PCIE2, PCIE2, SGMII6, SGMII5, PCIE1, PCIE1 } },
+	{0x0C, {SGMII10, SGMII9, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } },
+	{0x0D, {_100GE2, _100GE2, _100GE2, _100GE2, _100GE1, _100GE1, _100GE1,
+		_100GE1 } },
+	{0x0E, {PCIE2, PCIE2, PCIE2, PCIE2, _100GE1, _100GE1, _100GE1,
+		_100GE1 } },
+	{0x0F, {PCIE2, PCIE2, PCIE2, PCIE2, _50GE2, _50GE2, _50GE1, _50GE1 } },
+	{0x10, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _50GE1, _50GE1 } },
+	{0x11, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4, _25GE3 } },
+	{0x12, {XFI10, XFI9, XFI8, XFI7, _25GE6, _25GE5, XFI4,
+		XFI3 } },
+	{0x13, {_40GE2, _40GE2, _40GE2, _40GE2, _25GE6, _25GE5, XFI4, XFI3 } },
+	{0x14, {_40GE2, _40GE2, _40GE2, _40GE2, _40GE1, _40GE1, _40GE1,
+		_40GE1 } },
+	{0x15, {_25GE10, _25GE9, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4,
+		_25GE3 } },
+	{0x16, {XFI10, XFI9, PCIE2, PCIE2, XFI6, XFI5, XFI4, XFI3 } },
+	{}
+};
+
+static struct serdes_config serdes2_cfg_tbl[] = {
+	/* SerDes 2 */
+	{0x01, {PCIE3, PCIE3, SATA1, SATA2, PCIE4, PCIE4, PCIE4, PCIE4 } },
+	{0x02, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } },
+	{0x03, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } },
+	{0x04, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } },
+	{0x05, {PCIE3, PCIE3, PCIE3, PCIE3, SATA3, SATA4, SATA1, SATA2 } },
+	{0x06, {PCIE3, PCIE3, PCIE3, PCIE3, SGMII15, SGMII16, XFI13,
+		XFI14 } },
+	{0x07, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, XFI13,
+		XFI14 } },
+	{0x08, {NONE, NONE, SATA1, SATA2, SATA3, SATA4, XFI13, XFI14 } },
+	{0x09, {SGMII11, SGMII12, SGMII17, SGMII18, SGMII15, SGMII16, SGMII13,
+		SGMII14} },
+	{0x0A, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, PCIE4,
+		PCIE4 } },
+	{0x0B, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, SGMII13,
+		SGMII14 } },
+	{0x0C, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, SATA1,
+		SATA2 } },
+	{0x0D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SGMII13, SGMII14 } },
+	{0x0E, {PCIE3, PCIE3, SGMII17, SGMII18, PCIE4, PCIE4, SGMII13,
+		SGMII14 } },
+	{}
+};
+
+static struct serdes_config serdes3_cfg_tbl[] = {
+	/* SerDes 3 */
+	{0x02, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5 } },
+	{0x03, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE6, PCIE6, PCIE6, PCIE6 } },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+	serdes2_cfg_tbl,
+	serdes3_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/mp.c b/arch/arm/cpu/armv8/fsl-layerscape/mp.c
new file mode 100644
index 0000000..7627fd1
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/mp.c
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/mp.h>
+#include <asm/arch/soc.h>
+#include "cpu.h"
+#include <asm/arch-fsl-layerscape/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void *get_spin_tbl_addr(void)
+{
+	return &__spin_table;
+}
+
+phys_addr_t determine_mp_bootpg(void)
+{
+	return (phys_addr_t)&secondary_boot_code;
+}
+
+void update_os_arch_secondary_cores(uint8_t os_arch)
+{
+	u64 *table = get_spin_tbl_addr();
+	int i;
+
+	for (i = 1; i < CONFIG_MAX_CPUS; i++) {
+		if (os_arch == IH_ARCH_DEFAULT)
+			table[i * WORDS_PER_SPIN_TABLE_ENTRY +
+				SPIN_TABLE_ELEM_ARCH_COMP_IDX] = OS_ARCH_SAME;
+		else
+			table[i * WORDS_PER_SPIN_TABLE_ENTRY +
+				SPIN_TABLE_ELEM_ARCH_COMP_IDX] = OS_ARCH_DIFF;
+	}
+}
+
+#ifdef CONFIG_FSL_LSCH3
+void wake_secondary_core_n(int cluster, int core, int cluster_cores)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	struct ccsr_reset __iomem *rst = (void *)(CONFIG_SYS_FSL_RST_ADDR);
+	u32 mpidr = 0;
+
+	mpidr = ((cluster << 8) | core);
+	/*
+	 * mpidr_el1 register value of core which needs to be released
+	 * is written to scratchrw[6] register
+	 */
+	gur_out32(&gur->scratchrw[6], mpidr);
+	asm volatile("dsb st" : : : "memory");
+	rst->brrl |= 1 << ((cluster * cluster_cores) + core);
+	asm volatile("dsb st" : : : "memory");
+	/*
+	 * scratchrw[6] register value is polled
+	 * when the value becomes zero, this means that this core is up
+	 * and running, next core can be released now
+	 */
+	while (gur_in32(&gur->scratchrw[6]) != 0)
+		;
+}
+#endif
+
+int fsl_layerscape_wake_seconday_cores(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+#ifdef CONFIG_FSL_LSCH3
+	struct ccsr_reset __iomem *rst = (void *)(CONFIG_SYS_FSL_RST_ADDR);
+	u32 svr, ver, cluster, type;
+	int j = 0, cluster_cores = 0;
+#elif defined(CONFIG_FSL_LSCH2)
+	struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR);
+#endif
+	u32 cores, cpu_up_mask = 1;
+	int i, timeout = 10;
+	u64 *table = get_spin_tbl_addr();
+
+#ifdef COUNTER_FREQUENCY_REAL
+	/* update for secondary cores */
+	__real_cntfrq = COUNTER_FREQUENCY_REAL;
+	flush_dcache_range((unsigned long)&__real_cntfrq,
+			   (unsigned long)&__real_cntfrq + 8);
+#endif
+
+	cores = cpu_mask();
+	/* Clear spin table so that secondary processors
+	 * observe the correct value after waking up from wfe.
+	 */
+	memset(table, 0, CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE);
+	flush_dcache_range((unsigned long)table,
+			   (unsigned long)table +
+			   (CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE));
+
+	printf("Waking secondary cores to start from %lx\n", gd->relocaddr);
+
+#ifdef CONFIG_FSL_LSCH3
+	gur_out32(&gur->bootlocptrh, (u32)(gd->relocaddr >> 32));
+	gur_out32(&gur->bootlocptrl, (u32)gd->relocaddr);
+
+	svr = gur_in32(&gur->svr);
+	ver = SVR_SOC_VER(svr);
+	if (ver == SVR_LS2080A || ver == SVR_LS2085A) {
+		gur_out32(&gur->scratchrw[6], 1);
+		asm volatile("dsb st" : : : "memory");
+		rst->brrl = cores;
+		asm volatile("dsb st" : : : "memory");
+	} else {
+		/*
+		 * Release the cores out of reset one-at-a-time to avoid
+		 * power spikes
+		 */
+		i = 0;
+		cluster = in_le32(&gur->tp_cluster[i].lower);
+		for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+			type = initiator_type(cluster, j);
+			if (type &&
+			    TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)
+				cluster_cores++;
+		}
+
+		do {
+			cluster = in_le32(&gur->tp_cluster[i].lower);
+			for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+				type = initiator_type(cluster, j);
+				if (type &&
+				    TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)
+					wake_secondary_core_n(i, j,
+							      cluster_cores);
+			}
+		i++;
+		} while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC);
+	}
+#elif defined(CONFIG_FSL_LSCH2)
+	scfg_out32(&scfg->scratchrw[0], (u32)(gd->relocaddr >> 32));
+	scfg_out32(&scfg->scratchrw[1], (u32)gd->relocaddr);
+	asm volatile("dsb st" : : : "memory");
+	gur_out32(&gur->brrl, cores);
+	asm volatile("dsb st" : : : "memory");
+
+	/* Bootup online cores */
+	scfg_out32(&scfg->corebcr, cores);
+#endif
+	/* This is needed as a precautionary measure.
+	 * If some code before this has accidentally  released the secondary
+	 * cores then the pre-bootloader code will trap them in a "wfe" unless
+	 * the scratchrw[6] is set. In this case we need a sev here to get these
+	 * cores moving again.
+	 */
+	asm volatile("sev");
+
+	while (timeout--) {
+		flush_dcache_range((unsigned long)table, (unsigned long)table +
+				   CONFIG_MAX_CPUS * 64);
+		for (i = 1; i < CONFIG_MAX_CPUS; i++) {
+			if (table[i * WORDS_PER_SPIN_TABLE_ENTRY +
+					SPIN_TABLE_ELEM_STATUS_IDX])
+				cpu_up_mask |= 1 << i;
+		}
+		if (hweight32(cpu_up_mask) == hweight32(cores))
+			break;
+		udelay(10);
+	}
+	if (timeout <= 0) {
+		printf("Not all cores (0x%x) are up (0x%x)\n",
+		       cores, cpu_up_mask);
+		return 1;
+	}
+	printf("All (%d) cores are up.\n", hweight32(cores));
+
+	return 0;
+}
+
+int is_core_valid(unsigned int core)
+{
+	return !!((1 << core) & cpu_mask());
+}
+
+static int is_pos_valid(unsigned int pos)
+{
+	return !!((1 << pos) & cpu_pos_mask());
+}
+
+int is_core_online(u64 cpu_id)
+{
+	u64 *table;
+	int pos = id_to_core(cpu_id);
+	table = (u64 *)get_spin_tbl_addr() + pos * WORDS_PER_SPIN_TABLE_ENTRY;
+	return table[SPIN_TABLE_ELEM_STATUS_IDX] == 1;
+}
+
+int cpu_reset(u32 nr)
+{
+	puts("Feature is not implemented.\n");
+
+	return 0;
+}
+
+int cpu_disable(u32 nr)
+{
+	puts("Feature is not implemented.\n");
+
+	return 0;
+}
+
+static int core_to_pos(int nr)
+{
+	u32 cores = cpu_pos_mask();
+	int i, count = 0;
+
+	if (nr == 0) {
+		return 0;
+	} else if (nr >= hweight32(cores)) {
+		puts("Not a valid core number.\n");
+		return -1;
+	}
+
+	for (i = 1; i < 32; i++) {
+		if (is_pos_valid(i)) {
+			count++;
+			if (count == nr)
+				break;
+		}
+	}
+
+	if (count != nr)
+		return -1;
+
+	return i;
+}
+
+int cpu_status(u32 nr)
+{
+	u64 *table;
+	int pos;
+
+	if (nr == 0) {
+		table = (u64 *)get_spin_tbl_addr();
+		printf("table base @ 0x%p\n", table);
+	} else {
+		pos = core_to_pos(nr);
+		if (pos < 0)
+			return -1;
+		table = (u64 *)get_spin_tbl_addr() + pos *
+			WORDS_PER_SPIN_TABLE_ENTRY;
+		printf("table @ 0x%p\n", table);
+		printf("   addr - 0x%016llx\n",
+		       table[SPIN_TABLE_ELEM_ENTRY_ADDR_IDX]);
+		printf("   status   - 0x%016llx\n",
+		       table[SPIN_TABLE_ELEM_STATUS_IDX]);
+		printf("   lpid  - 0x%016llx\n",
+		       table[SPIN_TABLE_ELEM_LPID_IDX]);
+	}
+
+	return 0;
+}
+
+int cpu_release(u32 nr, int argc, char * const argv[])
+{
+	u64 boot_addr;
+	u64 *table = (u64 *)get_spin_tbl_addr();
+	int pos;
+
+	pos = core_to_pos(nr);
+	if (pos <= 0)
+		return -1;
+
+	table += pos * WORDS_PER_SPIN_TABLE_ENTRY;
+	boot_addr = simple_strtoull(argv[0], NULL, 16);
+	table[SPIN_TABLE_ELEM_ENTRY_ADDR_IDX] = boot_addr;
+	flush_dcache_range((unsigned long)table,
+			   (unsigned long)table + SPIN_TABLE_ELEM_SIZE);
+	asm volatile("dsb st");
+	smp_kick_all_cpus();	/* only those with entry addr set will run */
+	/*
+	 * When the first release command runs, all cores are set to go. Those
+	 * without a valid entry address will be trapped by "wfe". "sev" kicks
+	 * them off to check the address again. When set, they continue to run.
+	 */
+	asm volatile("sev");
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
new file mode 100644
index 0000000..d391f93
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ */
+#include <common.h>
+#include <malloc.h>
+#include <config.h>
+#include <errno.h>
+#include <asm/system.h>
+#include <asm/types.h>
+#include <asm/arch/soc.h>
+#ifdef CONFIG_FSL_LSCH3
+#include <asm/arch/immap_lsch3.h>
+#elif defined(CONFIG_FSL_LSCH2)
+#include <asm/arch/immap_lsch2.h>
+#endif
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
+#include <asm/armv8/sec_firmware.h>
+#endif
+#ifdef CONFIG_CHAIN_OF_TRUST
+#include <fsl_validate.h>
+#endif
+
+#ifdef CONFIG_SYS_LS_PPA_FW_IN_NAND
+#include <nand.h>
+#elif defined(CONFIG_SYS_LS_PPA_FW_IN_MMC)
+#include <mmc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int ppa_init(void)
+{
+	unsigned int el = current_el();
+	void *ppa_fit_addr;
+	u32 *boot_loc_ptr_l, *boot_loc_ptr_h;
+	u32 *loadable_l, *loadable_h;
+	int ret;
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+	uintptr_t ppa_esbc_hdr = 0;
+	uintptr_t ppa_img_addr = 0;
+#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \
+	defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
+	void *ppa_hdr_ddr;
+#endif
+#endif
+
+	/* Skip if running at lower exception level */
+	if (el < 3) {
+		debug("Skipping PPA init, running at EL%d\n", el);
+		return 0;
+	}
+
+#ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP
+	ppa_fit_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR;
+	debug("%s: PPA image load from XIP\n", __func__);
+#ifdef CONFIG_CHAIN_OF_TRUST
+	ppa_esbc_hdr = CONFIG_SYS_LS_PPA_ESBC_ADDR;
+#endif
+#else /* !CONFIG_SYS_LS_PPA_FW_IN_XIP */
+	size_t fw_length, fdt_header_len = sizeof(struct fdt_header);
+
+	/* Copy PPA image from MMC/SD/NAND to allocated memory */
+#ifdef CONFIG_SYS_LS_PPA_FW_IN_MMC
+	struct mmc *mmc;
+	int dev = CONFIG_SYS_MMC_ENV_DEV;
+	struct fdt_header *fitp;
+	u32 cnt;
+	u32 blk;
+
+	debug("%s: PPA image load from eMMC/SD\n", __func__);
+
+	ret = mmc_initialize(gd->bd);
+	if (ret) {
+		printf("%s: mmc_initialize() failed\n", __func__);
+		return ret;
+	}
+	mmc = find_mmc_device(dev);
+	if (!mmc) {
+		printf("PPA: MMC cannot find device for PPA firmware\n");
+		return -ENODEV;
+	}
+
+	ret = mmc_init(mmc);
+	if (ret) {
+		printf("%s: mmc_init() failed\n", __func__);
+		return ret;
+	}
+
+	fitp = malloc(roundup(fdt_header_len, 512));
+	if (!fitp) {
+		printf("PPA: malloc failed for FIT header(size 0x%zx)\n",
+		       roundup(fdt_header_len, 512));
+		return -ENOMEM;
+	}
+
+	blk = CONFIG_SYS_LS_PPA_FW_ADDR / 512;
+	cnt = DIV_ROUND_UP(fdt_header_len, 512);
+	debug("%s: MMC read PPA FIT header: dev # %u, block # %u, count %u\n",
+	      __func__, dev, blk, cnt);
+	ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, fitp);
+	if (ret != cnt) {
+		free(fitp);
+		printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n",
+		       CONFIG_SYS_LS_PPA_FW_ADDR);
+		return -EIO;
+	}
+
+	ret = fdt_check_header(fitp);
+	if (ret) {
+		free(fitp);
+		printf("%s: fdt_check_header() failed\n", __func__);
+		return ret;
+	}
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+	ppa_hdr_ddr = malloc(CONFIG_LS_PPA_ESBC_HDR_SIZE);
+	if (!ppa_hdr_ddr) {
+		printf("PPA: malloc failed for PPA header\n");
+		return -ENOMEM;
+	}
+
+	blk = CONFIG_SYS_LS_PPA_ESBC_ADDR >> 9;
+	cnt = DIV_ROUND_UP(CONFIG_LS_PPA_ESBC_HDR_SIZE, 512);
+	ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, ppa_hdr_ddr);
+	if (ret != cnt) {
+		free(ppa_hdr_ddr);
+		printf("MMC/SD read of PPA header failed\n");
+		return -EIO;
+	}
+	debug("Read PPA header to 0x%p\n", ppa_hdr_ddr);
+
+	ppa_esbc_hdr = (uintptr_t)ppa_hdr_ddr;
+#endif
+
+	fw_length = fdt_totalsize(fitp);
+	free(fitp);
+
+	fw_length = roundup(fw_length, 512);
+	ppa_fit_addr = malloc(fw_length);
+	if (!ppa_fit_addr) {
+		printf("PPA: malloc failed for PPA image(size 0x%zx)\n",
+		       fw_length);
+		return -ENOMEM;
+	}
+
+	blk = CONFIG_SYS_LS_PPA_FW_ADDR / 512;
+	cnt = DIV_ROUND_UP(fw_length, 512);
+	debug("%s: MMC read PPA FIT image: dev # %u, block # %u, count %u\n",
+	      __func__, dev, blk, cnt);
+	ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, ppa_fit_addr);
+	if (ret != cnt) {
+		free(ppa_fit_addr);
+		printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n",
+		       CONFIG_SYS_LS_PPA_FW_ADDR);
+		return -EIO;
+	}
+
+#elif defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
+	struct fdt_header fit;
+
+	debug("%s: PPA image load from NAND\n", __func__);
+
+	nand_init();
+	ret = nand_read(get_nand_dev_by_index(0),
+			(loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
+			&fdt_header_len, (u_char *)&fit);
+	if (ret == -EUCLEAN) {
+		printf("NAND read of PPA FIT header at offset 0x%x failed\n",
+		       CONFIG_SYS_LS_PPA_FW_ADDR);
+		return -EIO;
+	}
+
+	ret = fdt_check_header(&fit);
+	if (ret) {
+		printf("%s: fdt_check_header() failed\n", __func__);
+		return ret;
+	}
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+	ppa_hdr_ddr = malloc(CONFIG_LS_PPA_ESBC_HDR_SIZE);
+	if (!ppa_hdr_ddr) {
+		printf("PPA: malloc failed for PPA header\n");
+		return -ENOMEM;
+	}
+
+	fw_length = CONFIG_LS_PPA_ESBC_HDR_SIZE;
+
+	ret = nand_read(get_nand_dev_by_index(0),
+			(loff_t)CONFIG_SYS_LS_PPA_ESBC_ADDR,
+			&fw_length, (u_char *)ppa_hdr_ddr);
+	if (ret == -EUCLEAN) {
+		free(ppa_hdr_ddr);
+		printf("NAND read of PPA firmware at offset 0x%x failed\n",
+		       CONFIG_SYS_LS_PPA_FW_ADDR);
+		return -EIO;
+	}
+	debug("Read PPA header to 0x%p\n", ppa_hdr_ddr);
+
+	ppa_esbc_hdr = (uintptr_t)ppa_hdr_ddr;
+#endif
+
+	fw_length = fdt_totalsize(&fit);
+
+	ppa_fit_addr = malloc(fw_length);
+	if (!ppa_fit_addr) {
+		printf("PPA: malloc failed for PPA image(size 0x%zx)\n",
+		       fw_length);
+		return -ENOMEM;
+	}
+
+	ret = nand_read(get_nand_dev_by_index(0),
+			(loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
+			&fw_length, (u_char *)ppa_fit_addr);
+	if (ret == -EUCLEAN) {
+		free(ppa_fit_addr);
+		printf("NAND read of PPA firmware at offset 0x%x failed\n",
+		       CONFIG_SYS_LS_PPA_FW_ADDR);
+		return -EIO;
+	}
+#else
+#error "No CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
+#endif
+
+#endif
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+	ppa_img_addr = (uintptr_t)ppa_fit_addr;
+	if (fsl_check_boot_mode_secure() != 0) {
+		/*
+		 * In case of failure in validation, fsl_secboot_validate
+		 * would not return back in case of Production environment
+		 * with ITS=1. In Development environment (ITS=0 and
+		 * SB_EN=1), the function may return back in case of
+		 * non-fatal failures.
+		 */
+		ret = fsl_secboot_validate(ppa_esbc_hdr,
+					   PPA_KEY_HASH,
+					   &ppa_img_addr);
+		if (ret != 0)
+			printf("SEC firmware(s) validation failed\n");
+		else
+			printf("SEC firmware(s) validation Successful\n");
+	}
+#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \
+	defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
+	free(ppa_hdr_ddr);
+#endif
+#endif
+
+#ifdef CONFIG_FSL_LSCH3
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	boot_loc_ptr_l = &gur->bootlocptrl;
+	boot_loc_ptr_h = &gur->bootlocptrh;
+
+	/* Assign addresses to loadable ptrs */
+	loadable_l = &gur->scratchrw[4];
+	loadable_h = &gur->scratchrw[5];
+#elif defined(CONFIG_FSL_LSCH2)
+	struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR);
+	boot_loc_ptr_l = &scfg->scratchrw[1];
+	boot_loc_ptr_h = &scfg->scratchrw[0];
+
+	/* Assign addresses to loadable ptrs */
+	loadable_l = &scfg->scratchrw[2];
+	loadable_h = &scfg->scratchrw[3];
+#endif
+
+	debug("fsl-ppa: boot_loc_ptr_l = 0x%p, boot_loc_ptr_h =0x%p\n",
+	      boot_loc_ptr_l, boot_loc_ptr_h);
+	ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h,
+				loadable_l, loadable_h);
+
+#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \
+	defined(CONFIG_SYS_LS_PPA_FW_IN_NAND)
+	free(ppa_fit_addr);
+#endif
+
+	return ret;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
new file mode 100644
index 0000000..0092a22
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -0,0 +1,822 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2015 Freescale Semiconductor
+ */
+
+#include <common.h>
+#include <fsl_immap.h>
+#include <fsl_ifc.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
+#include <asm/io.h>
+#include <asm/global_data.h>
+#include <asm/arch-fsl-layerscape/config.h>
+#include <asm/arch-fsl-layerscape/ns_access.h>
+#include <asm/arch-fsl-layerscape/fsl_icid.h>
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+#include <fsl_csu.h>
+#endif
+#ifdef CONFIG_SYS_FSL_DDR
+#include <fsl_ddr_sdram.h>
+#include <fsl_ddr.h>
+#endif
+#ifdef CONFIG_CHAIN_OF_TRUST
+#include <fsl_validate.h>
+#endif
+#include <fsl_immap.h>
+#ifdef CONFIG_TFABOOT
+#include <environment.h>
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+bool soc_has_dp_ddr(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 svr = gur_in32(&gur->svr);
+
+	/* LS2085A, LS2088A, LS2048A has DP_DDR */
+	if ((SVR_SOC_VER(svr) == SVR_LS2085A) ||
+	    (SVR_SOC_VER(svr) == SVR_LS2088A) ||
+	    (SVR_SOC_VER(svr) == SVR_LS2048A))
+		return true;
+
+	return false;
+}
+
+bool soc_has_aiop(void)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 svr = gur_in32(&gur->svr);
+
+	/* LS2085A has AIOP */
+	if (SVR_SOC_VER(svr) == SVR_LS2085A)
+		return true;
+
+	return false;
+}
+
+static inline void set_usb_txvreftune(u32 __iomem *scfg, u32 offset)
+{
+	scfg_clrsetbits32(scfg + offset / 4,
+			0xF << 6,
+			SCFG_USB_TXVREFTUNE << 6);
+}
+
+static void erratum_a009008(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009008
+	u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
+
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \
+	defined(CONFIG_ARCH_LS1012A)
+	set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB1);
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
+	set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB2);
+	set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB3);
+#endif
+#elif defined(CONFIG_ARCH_LS2080A)
+	set_usb_txvreftune(scfg, SCFG_USB3PRM1CR);
+#endif
+#endif /* CONFIG_SYS_FSL_ERRATUM_A009008 */
+}
+
+static inline void set_usb_sqrxtune(u32 __iomem *scfg, u32 offset)
+{
+	scfg_clrbits32(scfg + offset / 4,
+			SCFG_USB_SQRXTUNE_MASK << 23);
+}
+
+static void erratum_a009798(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009798
+	u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
+
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \
+	defined(CONFIG_ARCH_LS1012A)
+	set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB1);
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
+	set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB2);
+	set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB3);
+#endif
+#elif defined(CONFIG_ARCH_LS2080A)
+	set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR);
+#endif
+#endif /* CONFIG_SYS_FSL_ERRATUM_A009798 */
+}
+
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \
+	defined(CONFIG_ARCH_LS1012A)
+static inline void set_usb_pcstxswingfull(u32 __iomem *scfg, u32 offset)
+{
+	scfg_clrsetbits32(scfg + offset / 4,
+			0x7F << 9,
+			SCFG_USB_PCSTXSWINGFULL << 9);
+}
+#endif
+
+static void erratum_a008997(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008997
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \
+	defined(CONFIG_ARCH_LS1012A)
+	u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
+
+	set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB1);
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
+	set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB2);
+	set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB3);
+#endif
+#endif
+#endif /* CONFIG_SYS_FSL_ERRATUM_A008997 */
+}
+
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \
+	defined(CONFIG_ARCH_LS1012A)
+
+#define PROGRAM_USB_PHY_RX_OVRD_IN_HI(phy)	\
+	out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1);	\
+	out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_2);	\
+	out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_3);	\
+	out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_4)
+
+#elif defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A)
+
+#define PROGRAM_USB_PHY_RX_OVRD_IN_HI(phy)	\
+	out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1); \
+	out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_2); \
+	out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_3); \
+	out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_4)
+
+#endif
+
+static void erratum_a009007(void)
+{
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \
+	defined(CONFIG_ARCH_LS1012A)
+	void __iomem *usb_phy = (void __iomem *)SCFG_USB_PHY1;
+
+	PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy);
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
+	usb_phy = (void __iomem *)SCFG_USB_PHY2;
+	PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy);
+
+	usb_phy = (void __iomem *)SCFG_USB_PHY3;
+	PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy);
+#endif
+#elif defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A)
+	void __iomem *dcsr = (void __iomem *)DCSR_BASE;
+
+	PROGRAM_USB_PHY_RX_OVRD_IN_HI(dcsr + DCSR_USB_PHY1);
+	PROGRAM_USB_PHY_RX_OVRD_IN_HI(dcsr + DCSR_USB_PHY2);
+#endif /* CONFIG_SYS_FSL_ERRATUM_A009007 */
+}
+
+#if defined(CONFIG_FSL_LSCH3)
+/*
+ * This erratum requires setting a value to eddrtqcr1 to
+ * optimal the DDR performance.
+ */
+static void erratum_a008336(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008336
+	u32 *eddrtqcr1;
+
+#ifdef CONFIG_SYS_FSL_DCSR_DDR_ADDR
+	eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR_ADDR + 0x800;
+	if (fsl_ddr_get_version(0) == 0x50200)
+		out_le32(eddrtqcr1, 0x63b30002);
+#endif
+#ifdef CONFIG_SYS_FSL_DCSR_DDR2_ADDR
+	eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR2_ADDR + 0x800;
+	if (fsl_ddr_get_version(0) == 0x50200)
+		out_le32(eddrtqcr1, 0x63b30002);
+#endif
+#endif
+}
+
+/*
+ * This erratum requires a register write before being Memory
+ * controller 3 being enabled.
+ */
+static void erratum_a008514(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008514
+	u32 *eddrtqcr1;
+
+#ifdef CONFIG_SYS_FSL_DCSR_DDR3_ADDR
+	eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR3_ADDR + 0x800;
+	out_le32(eddrtqcr1, 0x63b20002);
+#endif
+#endif
+}
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009635
+#define PLATFORM_CYCLE_ENV_VAR	"a009635_interval_val"
+
+static unsigned long get_internval_val_mhz(void)
+{
+	char *interval = env_get(PLATFORM_CYCLE_ENV_VAR);
+	/*
+	 *  interval is the number of platform cycles(MHz) between
+	 *  wake up events generated by EPU.
+	 */
+	ulong interval_mhz = get_bus_freq(0) / (1000 * 1000);
+
+	if (interval)
+		interval_mhz = simple_strtoul(interval, NULL, 10);
+
+	return interval_mhz;
+}
+
+void erratum_a009635(void)
+{
+	u32 val;
+	unsigned long interval_mhz = get_internval_val_mhz();
+
+	if (!interval_mhz)
+		return;
+
+	val = in_le32(DCSR_CGACRE5);
+	writel(val | 0x00000200, DCSR_CGACRE5);
+
+	val = in_le32(EPU_EPCMPR5);
+	writel(interval_mhz, EPU_EPCMPR5);
+	val = in_le32(EPU_EPCCR5);
+	writel(val | 0x82820000, EPU_EPCCR5);
+	val = in_le32(EPU_EPSMCR5);
+	writel(val | 0x002f0000, EPU_EPSMCR5);
+	val = in_le32(EPU_EPECR5);
+	writel(val | 0x20000000, EPU_EPECR5);
+	val = in_le32(EPU_EPGCR);
+	writel(val | 0x80000000, EPU_EPGCR);
+}
+#endif	/* CONFIG_SYS_FSL_ERRATUM_A009635 */
+
+static void erratum_rcw_src(void)
+{
+#if defined(CONFIG_SPL) && defined(CONFIG_NAND_BOOT)
+	u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE;
+	u32 __iomem *dcfg_dcsr = (u32 __iomem *)DCFG_DCSR_BASE;
+	u32 val;
+
+	val = in_le32(dcfg_ccsr + DCFG_PORSR1 / 4);
+	val &= ~DCFG_PORSR1_RCW_SRC;
+	val |= DCFG_PORSR1_RCW_SRC_NOR;
+	out_le32(dcfg_dcsr + DCFG_DCSR_PORCR1 / 4, val);
+#endif
+}
+
+#define I2C_DEBUG_REG 0x6
+#define I2C_GLITCH_EN 0x8
+/*
+ * This erratum requires setting glitch_en bit to enable
+ * digital glitch filter to improve clock stability.
+ */
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009203
+static void erratum_a009203(void)
+{
+#ifdef CONFIG_SYS_I2C
+	u8 __iomem *ptr;
+#ifdef I2C1_BASE_ADDR
+	ptr = (u8 __iomem *)(I2C1_BASE_ADDR + I2C_DEBUG_REG);
+
+	writeb(I2C_GLITCH_EN, ptr);
+#endif
+#ifdef I2C2_BASE_ADDR
+	ptr = (u8 __iomem *)(I2C2_BASE_ADDR + I2C_DEBUG_REG);
+
+	writeb(I2C_GLITCH_EN, ptr);
+#endif
+#ifdef I2C3_BASE_ADDR
+	ptr = (u8 __iomem *)(I2C3_BASE_ADDR + I2C_DEBUG_REG);
+
+	writeb(I2C_GLITCH_EN, ptr);
+#endif
+#ifdef I2C4_BASE_ADDR
+	ptr = (u8 __iomem *)(I2C4_BASE_ADDR + I2C_DEBUG_REG);
+
+	writeb(I2C_GLITCH_EN, ptr);
+#endif
+#endif
+}
+#endif
+
+void bypass_smmu(void)
+{
+	u32 val;
+	val = (in_le32(SMMU_SCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK);
+	out_le32(SMMU_SCR0, val);
+	val = (in_le32(SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK);
+	out_le32(SMMU_NSCR0, val);
+}
+void fsl_lsch3_early_init_f(void)
+{
+	erratum_rcw_src();
+#ifdef CONFIG_FSL_IFC
+	init_early_memctl_regs();	/* tighten IFC timing */
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009203
+	erratum_a009203();
+#endif
+	erratum_a008514();
+	erratum_a008336();
+	erratum_a009008();
+	erratum_a009798();
+	erratum_a008997();
+	erratum_a009007();
+#ifdef CONFIG_CHAIN_OF_TRUST
+	/* In case of Secure Boot, the IBR configures the SMMU
+	* to allow only Secure transactions.
+	* SMMU must be reset in bypass mode.
+	* Set the ClientPD bit and Clear the USFCFG Bit
+	*/
+	if (fsl_check_boot_mode_secure() == 1)
+		bypass_smmu();
+#endif
+}
+
+/* Get VDD in the unit mV from voltage ID */
+int get_core_volt_from_fuse(void)
+{
+	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int vdd;
+	u32 fusesr;
+	u8 vid;
+
+	/* get the voltage ID from fuse status register */
+	fusesr = in_le32(&gur->dcfg_fusesr);
+	debug("%s: fusesr = 0x%x\n", __func__, fusesr);
+	vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
+		FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK;
+	if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) {
+		vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) &
+			FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
+	}
+	debug("%s: VID = 0x%x\n", __func__, vid);
+	switch (vid) {
+	case 0x00: /* VID isn't supported */
+		vdd = -EINVAL;
+		debug("%s: The VID feature is not supported\n", __func__);
+		break;
+	case 0x08: /* 0.9V silicon */
+		vdd = 900;
+		break;
+	case 0x10: /* 1.0V silicon */
+		vdd = 1000;
+		break;
+	default:  /* Other core voltage */
+		vdd = -EINVAL;
+		debug("%s: The VID(%x) isn't supported\n", __func__, vid);
+		break;
+	}
+	debug("%s: The required minimum volt of CORE is %dmV\n", __func__, vdd);
+
+	return vdd;
+}
+
+#elif defined(CONFIG_FSL_LSCH2)
+
+static void erratum_a009929(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009929
+	struct ccsr_gur *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+	u32 __iomem *dcsr_cop_ccp = (void *)CONFIG_SYS_DCSR_COP_CCP_ADDR;
+	u32 rstrqmr1 = gur_in32(&gur->rstrqmr1);
+
+	rstrqmr1 |= 0x00000400;
+	gur_out32(&gur->rstrqmr1, rstrqmr1);
+	writel(0x01000000, dcsr_cop_ccp);
+#endif
+}
+
+/*
+ * This erratum requires setting a value to eddrtqcr1 to optimal
+ * the DDR performance. The eddrtqcr1 register is in SCFG space
+ * of LS1043A and the offset is 0x157_020c.
+ */
+#if defined(CONFIG_SYS_FSL_ERRATUM_A009660) \
+	&& defined(CONFIG_SYS_FSL_ERRATUM_A008514)
+#error A009660 and A008514 can not be both enabled.
+#endif
+
+static void erratum_a009660(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009660
+	u32 *eddrtqcr1 = (void *)CONFIG_SYS_FSL_SCFG_ADDR + 0x20c;
+	out_be32(eddrtqcr1, 0x63b20042);
+#endif
+}
+
+static void erratum_a008850_early(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008850
+	/* part 1 of 2 */
+	struct ccsr_cci400 __iomem *cci = (void *)(CONFIG_SYS_IMMR +
+						CONFIG_SYS_CCI400_OFFSET);
+	struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+
+	/* Skip if running at lower exception level */
+	if (current_el() < 3)
+		return;
+
+	/* disables propagation of barrier transactions to DDRC from CCI400 */
+	out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
+
+	/* disable the re-ordering in DDRC */
+	ddr_out32(&ddr->eor, DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS);
+#endif
+}
+
+void erratum_a008850_post(void)
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008850
+	/* part 2 of 2 */
+	struct ccsr_cci400 __iomem *cci = (void *)(CONFIG_SYS_IMMR +
+						CONFIG_SYS_CCI400_OFFSET);
+	struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+	u32 tmp;
+
+	/* Skip if running at lower exception level */
+	if (current_el() < 3)
+		return;
+
+	/* enable propagation of barrier transactions to DDRC from CCI400 */
+	out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
+
+	/* enable the re-ordering in DDRC */
+	tmp = ddr_in32(&ddr->eor);
+	tmp &= ~(DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS);
+	ddr_out32(&ddr->eor, tmp);
+#endif
+}
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A010315
+void erratum_a010315(void)
+{
+	int i;
+
+	for (i = PCIE1; i <= PCIE4; i++)
+		if (!is_serdes_configured(i)) {
+			debug("PCIe%d: disabled all R/W permission!\n", i);
+			set_pcie_ns_access(i, 0);
+		}
+}
+#endif
+
+static void erratum_a010539(void)
+{
+#if defined(CONFIG_SYS_FSL_ERRATUM_A010539) && defined(CONFIG_QSPI_BOOT)
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	u32 porsr1;
+
+	porsr1 = in_be32(&gur->porsr1);
+	porsr1 &= ~FSL_CHASSIS2_CCSR_PORSR1_RCW_MASK;
+	out_be32((void *)(CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_PORCR1),
+		 porsr1);
+	out_be32((void *)(CONFIG_SYS_FSL_SCFG_ADDR + 0x1a8), 0xffffffff);
+#endif
+}
+
+/* Get VDD in the unit mV from voltage ID */
+int get_core_volt_from_fuse(void)
+{
+	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int vdd;
+	u32 fusesr;
+	u8 vid;
+
+	fusesr = in_be32(&gur->dcfg_fusesr);
+	debug("%s: fusesr = 0x%x\n", __func__, fusesr);
+	vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
+		FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
+	if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
+		vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
+			FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
+	}
+	debug("%s: VID = 0x%x\n", __func__, vid);
+	switch (vid) {
+	case 0x00: /* VID isn't supported */
+		vdd = -EINVAL;
+		debug("%s: The VID feature is not supported\n", __func__);
+		break;
+	case 0x08: /* 0.9V silicon */
+		vdd = 900;
+		break;
+	case 0x10: /* 1.0V silicon */
+		vdd = 1000;
+		break;
+	default:  /* Other core voltage */
+		vdd = -EINVAL;
+		printf("%s: The VID(%x) isn't supported\n", __func__, vid);
+		break;
+	}
+	debug("%s: The required minimum volt of CORE is %dmV\n", __func__, vdd);
+
+	return vdd;
+}
+
+__weak int board_switch_core_volt(u32 vdd)
+{
+	return 0;
+}
+
+static int setup_core_volt(u32 vdd)
+{
+	return board_setup_core_volt(vdd);
+}
+
+#ifdef CONFIG_SYS_FSL_DDR
+static void ddr_enable_0v9_volt(bool en)
+{
+	struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+	u32 tmp;
+
+	tmp = ddr_in32(&ddr->ddr_cdr1);
+
+	if (en)
+		tmp |= DDR_CDR1_V0PT9_EN;
+	else
+		tmp &= ~DDR_CDR1_V0PT9_EN;
+
+	ddr_out32(&ddr->ddr_cdr1, tmp);
+}
+#endif
+
+int setup_chip_volt(void)
+{
+	int vdd;
+
+	vdd = get_core_volt_from_fuse();
+	/* Nothing to do for silicons doesn't support VID */
+	if (vdd < 0)
+		return vdd;
+
+	if (setup_core_volt(vdd))
+		printf("%s: Switch core VDD to %dmV failed\n", __func__, vdd);
+#ifdef CONFIG_SYS_HAS_SERDES
+	if (setup_serdes_volt(vdd))
+		printf("%s: Switch SVDD to %dmV failed\n", __func__, vdd);
+#endif
+
+#ifdef CONFIG_SYS_FSL_DDR
+	if (vdd == 900)
+		ddr_enable_0v9_volt(true);
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_FSL_PFE
+void init_pfe_scfg_dcfg_regs(void)
+{
+	struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
+	u32 ecccr2;
+
+	out_be32(&scfg->pfeasbcr,
+		 in_be32(&scfg->pfeasbcr) | SCFG_PFEASBCR_AWCACHE0);
+	out_be32(&scfg->pfebsbcr,
+		 in_be32(&scfg->pfebsbcr) | SCFG_PFEASBCR_AWCACHE0);
+
+	/* CCI-400 QoS settings for PFE */
+	out_be32(&scfg->wr_qos1, (unsigned int)(SCFG_WR_QOS1_PFE1_QOS
+		 | SCFG_WR_QOS1_PFE2_QOS));
+	out_be32(&scfg->rd_qos1, (unsigned int)(SCFG_RD_QOS1_PFE1_QOS
+		 | SCFG_RD_QOS1_PFE2_QOS));
+
+	ecccr2 = in_be32(CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2);
+	out_be32((void *)CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2,
+		 ecccr2 | (unsigned int)DISABLE_PFE_ECC);
+}
+#endif
+
+void fsl_lsch2_early_init_f(void)
+{
+	struct ccsr_cci400 *cci = (struct ccsr_cci400 *)(CONFIG_SYS_IMMR +
+					CONFIG_SYS_CCI400_OFFSET);
+	struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
+
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+
+#ifdef CONFIG_FSL_IFC
+	init_early_memctl_regs();	/* tighten IFC timing */
+#endif
+
+#if defined(CONFIG_FSL_QSPI) && !defined(CONFIG_QSPI_BOOT)
+	out_be32(&scfg->qspi_cfg, SCFG_QSPI_CLKSEL);
+#endif
+	/* Make SEC reads and writes snoopable */
+	setbits_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SECRDSNP |
+		     SCFG_SNPCNFGCR_SECWRSNP |
+		     SCFG_SNPCNFGCR_SATARDSNP |
+		     SCFG_SNPCNFGCR_SATAWRSNP);
+
+	/*
+	 * Enable snoop requests and DVM message requests for
+	 * Slave insterface S4 (A53 core cluster)
+	 */
+	if (current_el() == 3) {
+		out_le32(&cci->slave[4].snoop_ctrl,
+			 CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+	}
+
+	/*
+	 * Program Central Security Unit (CSU) to grant access
+	 * permission for USB 2.0 controller
+	 */
+#if defined(CONFIG_ARCH_LS1012A) && defined(CONFIG_USB_EHCI_FSL)
+	if (current_el() == 3)
+		set_devices_ns_access(CSU_CSLX_USB_2, CSU_ALL_RW);
+#endif
+	/* Erratum */
+	erratum_a008850_early(); /* part 1 of 2 */
+	erratum_a009929();
+	erratum_a009660();
+	erratum_a010539();
+	erratum_a009008();
+	erratum_a009798();
+	erratum_a008997();
+	erratum_a009007();
+
+#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A)
+	set_icids();
+#endif
+}
+#endif
+
+#ifdef CONFIG_QSPI_AHB_INIT
+/* Enable 4bytes address support and fast read */
+int qspi_ahb_init(void)
+{
+	u32 *qspi_lut, lut_key, *qspi_key;
+
+	qspi_key = (void *)SYS_FSL_QSPI_ADDR + 0x300;
+	qspi_lut = (void *)SYS_FSL_QSPI_ADDR + 0x310;
+
+	lut_key = in_be32(qspi_key);
+
+	if (lut_key == 0x5af05af0) {
+		/* That means the register is BE */
+		out_be32(qspi_key, 0x5af05af0);
+		/* Unlock the lut table */
+		out_be32(qspi_key + 1, 0x00000002);
+		out_be32(qspi_lut, 0x0820040c);
+		out_be32(qspi_lut + 1, 0x1c080c08);
+		out_be32(qspi_lut + 2, 0x00002400);
+		/* Lock the lut table */
+		out_be32(qspi_key, 0x5af05af0);
+		out_be32(qspi_key + 1, 0x00000001);
+	} else {
+		/* That means the register is LE */
+		out_le32(qspi_key, 0x5af05af0);
+		/* Unlock the lut table */
+		out_le32(qspi_key + 1, 0x00000002);
+		out_le32(qspi_lut, 0x0820040c);
+		out_le32(qspi_lut + 1, 0x1c080c08);
+		out_le32(qspi_lut + 2, 0x00002400);
+		/* Lock the lut table */
+		out_le32(qspi_key, 0x5af05af0);
+		out_le32(qspi_key + 1, 0x00000001);
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_TFABOOT
+#define MAX_BOOTCMD_SIZE	256
+
+int fsl_setenv_bootcmd(void)
+{
+	int ret;
+	enum boot_src src = get_boot_src();
+	char bootcmd_str[MAX_BOOTCMD_SIZE];
+
+	switch (src) {
+#ifdef IFC_NOR_BOOTCOMMAND
+	case BOOT_SOURCE_IFC_NOR:
+		sprintf(bootcmd_str, IFC_NOR_BOOTCOMMAND);
+		break;
+#endif
+#ifdef QSPI_NOR_BOOTCOMMAND
+	case BOOT_SOURCE_QSPI_NOR:
+		sprintf(bootcmd_str, QSPI_NOR_BOOTCOMMAND);
+		break;
+#endif
+#ifdef XSPI_NOR_BOOTCOMMAND
+	case BOOT_SOURCE_XSPI_NOR:
+		sprintf(bootcmd_str, XSPI_NOR_BOOTCOMMAND);
+		break;
+#endif
+#ifdef IFC_NAND_BOOTCOMMAND
+	case BOOT_SOURCE_IFC_NAND:
+		sprintf(bootcmd_str, IFC_NAND_BOOTCOMMAND);
+		break;
+#endif
+#ifdef QSPI_NAND_BOOTCOMMAND
+	case BOOT_SOURCE_QSPI_NAND:
+		sprintf(bootcmd_str, QSPI_NAND_BOOTCOMMAND);
+		break;
+#endif
+#ifdef XSPI_NAND_BOOTCOMMAND
+	case BOOT_SOURCE_XSPI_NAND:
+		sprintf(bootcmd_str, XSPI_NAND_BOOTCOMMAND);
+		break;
+#endif
+#ifdef SD_BOOTCOMMAND
+	case BOOT_SOURCE_SD_MMC:
+		sprintf(bootcmd_str, SD_BOOTCOMMAND);
+		break;
+#endif
+#ifdef SD2_BOOTCOMMAND
+	case BOOT_SOURCE_SD_MMC2:
+		sprintf(bootcmd_str, SD2_BOOTCOMMAND);
+		break;
+#endif
+	default:
+#ifdef QSPI_NOR_BOOTCOMMAND
+		sprintf(bootcmd_str, QSPI_NOR_BOOTCOMMAND);
+#endif
+		break;
+	}
+
+	ret = env_set("bootcmd", bootcmd_str);
+	if (ret) {
+		printf("Failed to set bootcmd: ret = %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+int fsl_setenv_mcinitcmd(void)
+{
+	int ret = 0;
+	enum boot_src src = get_boot_src();
+
+	switch (src) {
+#ifdef IFC_MC_INIT_CMD
+	case BOOT_SOURCE_IFC_NAND:
+	case BOOT_SOURCE_IFC_NOR:
+	ret = env_set("mcinitcmd", IFC_MC_INIT_CMD);
+		break;
+#endif
+#ifdef QSPI_MC_INIT_CMD
+	case BOOT_SOURCE_QSPI_NAND:
+	case BOOT_SOURCE_QSPI_NOR:
+	ret = env_set("mcinitcmd", QSPI_MC_INIT_CMD);
+		break;
+#endif
+#ifdef XSPI_MC_INIT_CMD
+	case BOOT_SOURCE_XSPI_NAND:
+	case BOOT_SOURCE_XSPI_NOR:
+	ret = env_set("mcinitcmd", XSPI_MC_INIT_CMD);
+		break;
+#endif
+#ifdef SD_MC_INIT_CMD
+	case BOOT_SOURCE_SD_MMC:
+	ret = env_set("mcinitcmd", SD_MC_INIT_CMD);
+		break;
+#endif
+#ifdef SD2_MC_INIT_CMD
+	case BOOT_SOURCE_SD_MMC2:
+	ret = env_set("mcinitcmd", SD2_MC_INIT_CMD);
+		break;
+#endif
+	default:
+#ifdef QSPI_MC_INIT_CMD
+	ret = env_set("mcinitcmd", QSPI_MC_INIT_CMD);
+#endif
+		break;
+	}
+
+	if (ret) {
+		printf("Failed to set mcinitcmd: ret = %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+#ifdef CONFIG_CHAIN_OF_TRUST
+	fsl_setenv_chain_of_trust();
+#endif
+#ifdef CONFIG_TFABOOT
+	/*
+	 * check if gd->env_addr is default_environment; then setenv bootcmd
+	 * and mcinitcmd.
+	 */
+	if (gd->env_addr + gd->reloc_off == (ulong)&default_environment[0]) {
+		fsl_setenv_bootcmd();
+		fsl_setenv_mcinitcmd();
+	}
+#endif
+#ifdef CONFIG_QSPI_AHB_INIT
+	qspi_ahb_init();
+#endif
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
new file mode 100644
index 0000000..3e53084
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <fsl_ifc.h>
+#include <i2c.h>
+#include <fsl_csu.h>
+#include <asm/arch/fdt.h>
+#include <asm/arch/ppa.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+#ifdef CONFIG_SPL_MMC_SUPPORT
+	return BOOT_DEVICE_MMC1;
+#endif
+#ifdef CONFIG_SPL_NAND_SUPPORT
+	return BOOT_DEVICE_NAND;
+#endif
+#ifdef CONFIG_QSPI_BOOT
+	return BOOT_DEVICE_NOR;
+#endif
+	return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+
+void spl_board_init(void)
+{
+#if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_FSL_LSCH2)
+	/*
+	 * In case of Secure Boot, the IBR configures the SMMU
+	 * to allow only Secure transactions.
+	 * SMMU must be reset in bypass mode.
+	 * Set the ClientPD bit and Clear the USFCFG Bit
+	*/
+	u32 val;
+	val = (in_le32(SMMU_SCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK);
+	out_le32(SMMU_SCR0, val);
+	val = (in_le32(SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK);
+	out_le32(SMMU_NSCR0, val);
+#endif
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+#ifdef CONFIG_SPL_FSL_LS_PPA
+	ppa_init();
+#endif
+}
+
+void board_init_f(ulong dummy)
+{
+	icache_enable();
+	/* Clear global data */
+	memset((void *)gd, 0, sizeof(gd_t));
+	board_early_init_f();
+	timer_init();
+#ifdef CONFIG_ARCH_LS2080A
+	env_init();
+#endif
+	get_clocks();
+
+	preloader_console_init();
+	spl_set_bd();
+
+#ifdef CONFIG_SPL_I2C_SUPPORT
+	i2c_init_all();
+#endif
+#ifdef CONFIG_VID
+	init_func_vid();
+#endif
+	dram_init();
+#ifdef CONFIG_SPL_FSL_LS_PPA
+#ifndef CONFIG_SYS_MEM_RESERVE_SECURE
+#error Need secure RAM for PPA
+#endif
+	/*
+	 * Secure memory location is determined in dram_init_banksize().
+	 * gd->ram_size is deducted by the size of secure ram.
+	 */
+	dram_init_banksize();
+
+	/*
+	 * After dram_init_bank_size(), we know U-Boot only uses the first
+	 * memory bank regardless how big the memory is.
+	 */
+	gd->ram_top = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
+
+	/*
+	 * If PPA is loaded, U-Boot will resume running at EL2.
+	 * Cache and MMU will be enabled. Need a place for TLB.
+	 * U-Boot will be relocated to the end of available memory
+	 * in first bank. At this point, we cannot know how much
+	 * memory U-Boot uses. Put TLB table lower by SPL_TLB_SETBACK
+	 * to avoid overlapping. As soon as the RAM version U-Boot sets
+	 * up new MMU, this space is no longer needed.
+	 */
+	gd->ram_top -= SPL_TLB_SETBACK;
+	gd->arch.tlb_size = PGTABLE_SIZE;
+	gd->arch.tlb_addr = (gd->ram_top - gd->arch.tlb_size) & ~(0x10000 - 1);
+	gd->arch.tlb_allocated = gd->arch.tlb_addr;
+#endif	/* CONFIG_SPL_FSL_LS_PPA */
+#if defined(CONFIG_QSPI_AHB_INIT) && defined(CONFIG_QSPI_BOOT)
+	qspi_ahb_init();
+#endif
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+/*
+ * Return
+ * 0 if booting into OS is selected
+ * 1 if booting into U-Boot is selected
+ */
+int spl_start_uboot(void)
+{
+	env_init();
+	if (env_get_yesno("boot_os") != 0)
+		return 0;
+
+	return 1;
+}
+#endif	/* CONFIG_SPL_OS_BOOT */
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif
+#endif /* CONFIG_SPL_BUILD */
diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c
new file mode 100644
index 0000000..9957c29
--- /dev/null
+++ b/arch/arm/cpu/armv8/fwcall.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/**
+ * (C) Copyright 2014, Cavium Inc.
+ * (C) Copyright 2017, Xilinx Inc.
+ *
+**/
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <version.h>
+#include <asm/macro.h>
+#include <asm/psci.h>
+#include <asm/system.h>
+
+/*
+ * Issue the hypervisor call
+ *
+ * x0~x7: input arguments
+ * x0~x3: output arguments
+ */
+static void hvc_call(struct pt_regs *args)
+{
+	asm volatile(
+		"ldr x0, %0\n"
+		"ldr x1, %1\n"
+		"ldr x2, %2\n"
+		"ldr x3, %3\n"
+		"ldr x4, %4\n"
+		"ldr x5, %5\n"
+		"ldr x6, %6\n"
+		"ldr x7, %7\n"
+		"hvc	#0\n"
+		"str x0, %0\n"
+		"str x1, %1\n"
+		"str x2, %2\n"
+		"str x3, %3\n"
+		: "+m" (args->regs[0]), "+m" (args->regs[1]),
+		  "+m" (args->regs[2]), "+m" (args->regs[3])
+		: "m" (args->regs[4]), "m" (args->regs[5]),
+		  "m" (args->regs[6]), "m" (args->regs[7])
+		: "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
+		  "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
+		  "x16", "x17");
+}
+
+/*
+ * void smc_call(arg0, arg1...arg7)
+ *
+ * issue the secure monitor call
+ *
+ * x0~x7: input arguments
+ * x0~x3: output arguments
+ */
+
+void smc_call(struct pt_regs *args)
+{
+	asm volatile(
+		"ldr x0, %0\n"
+		"ldr x1, %1\n"
+		"ldr x2, %2\n"
+		"ldr x3, %3\n"
+		"ldr x4, %4\n"
+		"ldr x5, %5\n"
+		"ldr x6, %6\n"
+		"smc	#0\n"
+		"str x0, %0\n"
+		"str x1, %1\n"
+		"str x2, %2\n"
+		"str x3, %3\n"
+		: "+m" (args->regs[0]), "+m" (args->regs[1]),
+		  "+m" (args->regs[2]), "+m" (args->regs[3])
+		: "m" (args->regs[4]), "m" (args->regs[5]),
+		  "m" (args->regs[6])
+		: "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
+		  "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
+		  "x16", "x17");
+}
+
+/*
+ * For now, all systems we support run at least in EL2 and thus
+ * trigger PSCI calls to EL3 using SMC. If anyone ever wants to
+ * use PSCI on U-Boot running below a hypervisor, please detect
+ * this and set the flag accordingly.
+ */
+static const bool use_smc_for_psci = true;
+
+void __noreturn psci_system_reset(void)
+{
+	struct pt_regs regs;
+
+	regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET;
+
+	if (use_smc_for_psci)
+		smc_call(&regs);
+	else
+		hvc_call(&regs);
+
+	while (1)
+		;
+}
+
+void __noreturn psci_system_off(void)
+{
+	struct pt_regs regs;
+
+	regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_OFF;
+
+	if (use_smc_for_psci)
+		smc_call(&regs);
+	else
+		hvc_call(&regs);
+
+	while (1)
+		;
+}
diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c
new file mode 100644
index 0000000..c1706dc
--- /dev/null
+++ b/arch/arm/cpu/armv8/generic_timer.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Generic timer implementation of get_tbclk()
+ */
+unsigned long get_tbclk(void)
+{
+	unsigned long cntfrq;
+	asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq));
+	return cntfrq;
+}
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008585
+/*
+ * FSL erratum A-008585 says that the ARM generic timer counter "has the
+ * potential to contain an erroneous value for a small number of core
+ * clock cycles every time the timer value changes".
+ * This sometimes leads to a consecutive counter read returning a lower
+ * value than the previous one, thus reporting the time to go backwards.
+ * The workaround is to read the counter twice and only return when the value
+ * was the same in both reads.
+ * Assumes that the CPU runs in much higher frequency than the timer.
+ */
+unsigned long timer_read_counter(void)
+{
+	unsigned long cntpct;
+	unsigned long temp;
+
+	isb();
+	asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
+	asm volatile("mrs %0, cntpct_el0" : "=r" (temp));
+	while (temp != cntpct) {
+		asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
+		asm volatile("mrs %0, cntpct_el0" : "=r" (temp));
+	}
+
+	return cntpct;
+}
+#elif CONFIG_SUNXI_A64_TIMER_ERRATUM
+/*
+ * This erratum sometimes flips the lower 11 bits of the counter value
+ * to all 0's or all 1's, leading to jumps forwards or backwards.
+ * Backwards jumps might be interpreted all roll-overs and be treated as
+ * huge jumps forward.
+ * The workaround is to check whether the lower 11 bits of the counter are
+ * all 0 or all 1, then discard this value and read again.
+ * This occasionally discards valid values, but will catch all erroneous
+ * reads and fixes the problem reliably. Also this mostly requires only a
+ * single read, so does not have any significant overhead.
+ * The algorithm was conceived by Samuel Holland.
+ */
+unsigned long timer_read_counter(void)
+{
+	unsigned long cntpct;
+
+	isb();
+	do {
+		asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
+	} while (((cntpct + 1) & GENMASK(10, 0)) <= 1);
+
+	return cntpct;
+}
+#else
+/*
+ * timer_read_counter() using the Arm Generic Timer (aka arch timer).
+ */
+unsigned long timer_read_counter(void)
+{
+	unsigned long cntpct;
+
+	isb();
+	asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
+
+	return cntpct;
+}
+#endif
+
+uint64_t get_ticks(void)
+{
+	unsigned long ticks = timer_read_counter();
+
+	gd->arch.tbl = ticks;
+
+	return ticks;
+}
+
+unsigned long usec2ticks(unsigned long usec)
+{
+	ulong ticks;
+	if (usec < 1000)
+		ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
+	else
+		ticks = ((usec / 10) * (get_tbclk() / 100000));
+
+	return ticks;
+}
+
+ulong timer_get_boot_us(void)
+{
+	u64 val = get_ticks() * 1000000;
+
+	return val / get_tbclk();
+}
diff --git a/arch/arm/cpu/armv8/hisilicon/Makefile b/arch/arm/cpu/armv8/hisilicon/Makefile
new file mode 100644
index 0000000..cf2fe05
--- /dev/null
+++ b/arch/arm/cpu/armv8/hisilicon/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2015 Linaro
+# Peter Griffin <peter.griffin@linaro.org>
+
+obj-y	+= pinmux.o
diff --git a/arch/arm/cpu/armv8/hisilicon/pinmux.c b/arch/arm/cpu/armv8/hisilicon/pinmux.c
new file mode 100644
index 0000000..c549ddb
--- /dev/null
+++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Linaro.
+ * Peter Griffin <peter.griffin@linaro.org>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/pinmux.h>
+
+struct hi6220_pinmux0_regs *pmx0 =
+	(struct hi6220_pinmux0_regs *)HI6220_PINMUX0_BASE;
+
+struct hi6220_pinmux1_regs *pmx1 =
+	(struct hi6220_pinmux1_regs *)HI6220_PINMUX1_BASE;
+
+static void hi6220_uart_config(int peripheral)
+{
+	switch (peripheral) {
+	case PERIPH_ID_UART0:
+		writel(MUX_M0, &pmx0->iomg[48]); /* UART0_RXD */
+		writel(MUX_M0, &pmx0->iomg[49]); /* UART0_TXD */
+
+		writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[49]); /* UART0_RXD */
+		writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[50]); /* UART0_TXD */
+		break;
+
+	case PERIPH_ID_UART1:
+		writel(MUX_M0, &pmx0->iomg[50]); /* UART1_CTS_N */
+		writel(MUX_M0, &pmx0->iomg[51]); /* UART1_RTS_N */
+		writel(MUX_M0, &pmx0->iomg[52]); /* UART1_RXD */
+		writel(MUX_M0, &pmx0->iomg[53]); /* UART1_TXD */
+
+		writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[51]); /*UART1_CTS_N*/
+		writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[53]); /* UART1_RXD */
+		writel(DRIVE1_02MA, &pmx1->iocfg[52]); /* UART1_RTS_N */
+		writel(DRIVE1_02MA, &pmx1->iocfg[54]); /* UART1_TXD */
+		break;
+
+	case PERIPH_ID_UART2:
+		writel(MUX_M0, &pmx0->iomg[54]); /* UART2_CTS_N */
+		writel(MUX_M0, &pmx0->iomg[55]); /* UART2_RTS_N */
+		writel(MUX_M0, &pmx0->iomg[56]); /* UART2_RXD */
+		writel(MUX_M0, &pmx0->iomg[57]); /* UART2_TXD */
+
+		writel(DRIVE1_02MA, &pmx1->iocfg[55]); /* UART2_CTS_N */
+		writel(DRIVE1_02MA, &pmx1->iocfg[56]); /* UART2_RTS_N */
+		writel(DRIVE1_02MA, &pmx1->iocfg[57]); /* UART2_RXD */
+		writel(DRIVE1_02MA, &pmx1->iocfg[58]); /* UART2_TXD */
+		break;
+
+	case PERIPH_ID_UART3:
+		writel(MUX_M1, &pmx0->iomg[96]); /* UART3_CTS_N */
+		writel(MUX_M1, &pmx0->iomg[97]); /* UART3_RTS_N */
+		writel(MUX_M1, &pmx0->iomg[98]); /* UART3_RXD */
+		writel(MUX_M1, &pmx0->iomg[99]); /* UART3_TXD */
+
+		/* UART3_TXD */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[100]);
+		/* UART3_RTS_N */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[101]);
+		/* UART3_RXD */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[102]);
+		/* UART3_TXD */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[103]);
+		break;
+
+	case PERIPH_ID_UART4:
+		writel(MUX_M1, &pmx0->iomg[116]); /* UART4_CTS_N */
+		writel(MUX_M1, &pmx0->iomg[117]); /* UART4_RTS_N */
+		writel(MUX_M1, &pmx0->iomg[118]); /* UART4_RXD */
+		writel(MUX_M1, &pmx0->iomg[119]); /* UART4_TXD */
+
+		/* UART4_CTS_N */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[120]);
+		/* UART4_RTS_N */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[121]);
+		/* UART4_RXD */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[122]);
+		/* UART4_TXD */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[123]);
+		break;
+	case PERIPH_ID_UART5:
+		writel(MUX_M1, &pmx0->iomg[114]); /* UART5_RXD */
+		writel(MUX_M1, &pmx0->iomg[115]); /* UART5_TXD */
+
+		/* UART5_RXD */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[118]);
+		/* UART5_TXD */
+		writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[119]);
+
+		break;
+
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return;
+	}
+}
+
+static int hi6220_mmc_config(int peripheral)
+{
+	u32 tmp;
+
+	switch (peripheral) {
+	case PERIPH_ID_SDMMC0:
+
+		/* eMMC pinmux config */
+		writel(MUX_M0, &pmx0->iomg[64]); /* EMMC_CLK */
+		writel(MUX_M0, &pmx0->iomg[65]); /* EMMC_CMD */
+		writel(MUX_M0, &pmx0->iomg[66]); /* EMMC_DATA0 */
+		writel(MUX_M0, &pmx0->iomg[67]); /* EMMC_DATA1 */
+		writel(MUX_M0, &pmx0->iomg[68]); /* EMMC_DATA2 */
+		writel(MUX_M0, &pmx0->iomg[69]); /* EMMC_DATA3 */
+		writel(MUX_M0, &pmx0->iomg[70]); /* EMMC_DATA4 */
+		writel(MUX_M0, &pmx0->iomg[71]); /* EMMC_DATA5 */
+		writel(MUX_M0, &pmx0->iomg[72]); /* EMMC_DATA6 */
+		writel(MUX_M0, &pmx0->iomg[73]); /* EMMC_DATA7 */
+
+		/*eMMC configure up/down/drive */
+		writel(DRIVE1_08MA, &pmx1->iocfg[65]); /* EMMC_CLK */
+
+		tmp = DRIVE1_04MA | PULL_UP;
+		writel(tmp, &pmx1->iocfg[65]); /* EMMC_CMD */
+		writel(tmp, &pmx1->iocfg[66]); /* EMMC_DATA0 */
+		writel(tmp, &pmx1->iocfg[67]); /* EMMC_DATA1 */
+		writel(tmp, &pmx1->iocfg[68]); /* EMMC_DATA2 */
+		writel(tmp, &pmx1->iocfg[69]); /* EMMC_DATA3 */
+		writel(tmp, &pmx1->iocfg[70]); /* EMMC_DATA4 */
+		writel(tmp, &pmx1->iocfg[71]); /* EMMC_DATA5 */
+		writel(tmp, &pmx1->iocfg[72]); /* EMMC_DATA6 */
+		writel(tmp, &pmx1->iocfg[73]); /* EMMC_DATA7 */
+
+		writel(DRIVE1_04MA, &pmx1->iocfg[73]); /* EMMC_RST_N */
+		break;
+
+	case PERIPH_ID_SDMMC1:
+
+		writel(MUX_M0, &pmx0->iomg[3]); /* SD_CLK */
+		writel(MUX_M0, &pmx0->iomg[4]); /* SD_CMD */
+		writel(MUX_M0, &pmx0->iomg[5]); /* SD_DATA0 */
+		writel(MUX_M0, &pmx0->iomg[6]); /* SD_DATA1 */
+		writel(MUX_M0, &pmx0->iomg[7]); /* SD_DATA2 */
+		writel(MUX_M0, &pmx0->iomg[8]); /* SD_DATA3 */
+
+		writel(DRIVE1_10MA | BIT(2), &pmx1->iocfg[3]); /*SD_CLK*/
+		writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[4]); /*SD_CMD*/
+		writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[5]); /*SD_DATA0*/
+		writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[6]); /*SD_DATA1*/
+		writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[7]); /*SD_DATA2*/
+		writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[8]); /*SD_DATA3*/
+		break;
+
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return -1;
+	}
+
+	return 0;
+}
+
+int hi6220_pinmux_config(int peripheral)
+{
+	switch (peripheral) {
+	case PERIPH_ID_UART0:
+	case PERIPH_ID_UART1:
+	case PERIPH_ID_UART2:
+	case PERIPH_ID_UART3:
+		hi6220_uart_config(peripheral);
+		break;
+	case PERIPH_ID_SDMMC0:
+	case PERIPH_ID_SDMMC1:
+		return hi6220_mmc_config(peripheral);
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return -1;
+	}
+
+	return 0;
+}
+
+
diff --git a/arch/arm/cpu/armv8/linux-kernel-image-header-vars.h b/arch/arm/cpu/armv8/linux-kernel-image-header-vars.h
new file mode 100644
index 0000000..fa6e86d
--- /dev/null
+++ b/arch/arm/cpu/armv8/linux-kernel-image-header-vars.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2017 NVIDIA Corporation <www.nvidia.com>
+ *
+ * Derived from Linux kernel v4.14 files:
+ *
+ * arch/arm64/include/asm/assembler.h:
+ * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * arch/arm64/kernel/head.S:
+ * Based on arch/arm/kernel/head.S
+ * Copyright (C) 1994-2002 Russell King
+ * Copyright (C) 2003-2012 ARM Ltd.
+ * Authors:	Catalin Marinas <catalin.marinas@arm.com>
+ *		Will Deacon <will.deacon@arm.com>
+ *
+ * arch/arm64/kernel/image.h:
+ * Copyright (C) 2014 ARM Ltd.
+ */
+
+/*
+ * There aren't any ELF relocations we can use to endian-swap values known only
+ * at link time (e.g. the subtraction of two symbol addresses), so we must get
+ * the linker to endian-swap certain values before emitting them.
+ *
+ * Note that, in order for this to work when building the ELF64 PIE executable
+ * (for KASLR), these values should not be referenced via R_AARCH64_ABS64
+ * relocations, since these are fixed up at runtime rather than at build time
+ * when PIE is in effect. So we need to split them up in 32-bit high and low
+ * words.
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define DATA_LE32(data)				\
+	((((data) & 0x000000ff) << 24) |	\
+	 (((data) & 0x0000ff00) << 8)  |	\
+	 (((data) & 0x00ff0000) >> 8)  |	\
+	 (((data) & 0xff000000) >> 24))
+#else
+#define DATA_LE32(data) ((data) & 0xffffffff)
+#endif
+
+#define DEFINE_IMAGE_LE64(sym, data)				\
+	sym##_lo32 = DATA_LE32((data) & 0xffffffff);		\
+	sym##_hi32 = DATA_LE32((data) >> 32)
+
+#define __MAX(a, b)		(((a) > (b)) ? (a) : (b))
+#define __CODE_DATA_SIZE	(__bss_start - _start)
+#define __BSS_SIZE		(__bss_end - __bss_start)
+#ifdef CONFIG_SYS_INIT_SP_BSS_OFFSET
+#define __MAX_EXTRA_RAM_USAGE	__MAX(__BSS_SIZE, CONFIG_SYS_INIT_SP_BSS_OFFSET)
+#else
+#define __MAX_EXTRA_RAM_USAGE	__BSS_SIZE
+#endif
+#define __MEM_USAGE		(__CODE_DATA_SIZE + __MAX_EXTRA_RAM_USAGE)
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define __HEAD_FLAG_BE		1
+#else
+#define __HEAD_FLAG_BE		0
+#endif
+
+#define __HEAD_FLAG_PAGE_SIZE	1 /* 4K hard-coded */
+
+#define __HEAD_FLAG_PHYS_BASE	1
+
+#define __HEAD_FLAGS		((__HEAD_FLAG_BE << 0) |	\
+				 (__HEAD_FLAG_PAGE_SIZE << 1) |	\
+				 (__HEAD_FLAG_PHYS_BASE << 3))
+
+#define TEXT_OFFSET (CONFIG_SYS_TEXT_BASE - \
+			CONFIG_LNX_KRNL_IMG_TEXT_OFFSET_BASE)
+
+/*
+ * These will output as part of the Image header, which should be little-endian
+ * regardless of the endianness of the kernel. While constant values could be
+ * endian swapped in head.S, all are done here for consistency.
+ */
+#define HEAD_SYMBOLS						\
+	DEFINE_IMAGE_LE64(_kernel_size_le, __MEM_USAGE);	\
+	DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET);	\
+	DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS);
+
+	HEAD_SYMBOLS
diff --git a/arch/arm/cpu/armv8/lowlevel_init.S b/arch/arm/cpu/armv8/lowlevel_init.S
new file mode 100644
index 0000000..f4f0cdc
--- /dev/null
+++ b/arch/arm/cpu/armv8/lowlevel_init.S
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * A lowlevel_init function that sets up the stack to call a C function to
+ * perform further init.
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+ENTRY(lowlevel_init)
+	/*
+	 * Setup a temporary stack. Global data is not available yet.
+	 */
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
+	ldr	w0, =CONFIG_SPL_STACK
+#else
+	ldr	w0, =CONFIG_SYS_INIT_SP_ADDR
+#endif
+	bic	sp, x0, #0xf	/* 16-byte alignment for ABI compliance */
+
+	/*
+	 * Save the old LR(passed in x29) and the current LR to stack
+	 */
+	stp	x29, x30, [sp, #-16]!
+
+	/*
+	 * Call the very early init function. This should do only the
+	 * absolute bare minimum to get started. It should not:
+	 *
+	 * - set up DRAM
+	 * - use global_data
+	 * - clear BSS
+	 * - try to start a console
+	 *
+	 * For boards with SPL this should be empty since SPL can do all of
+	 * this init in the SPL board_init_f() function which is called
+	 * immediately after this.
+	 */
+	bl	s_init
+	ldp	x29, x30, [sp]
+	ret
+ENDPROC(lowlevel_init)
diff --git a/arch/arm/cpu/armv8/psci.S b/arch/arm/cpu/armv8/psci.S
new file mode 100644
index 0000000..358df8f
--- /dev/null
+++ b/arch/arm/cpu/armv8/psci.S
@@ -0,0 +1,311 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Author: Hongbo Zhang <hongbo.zhang@nxp.com>
+ * This file implements LS102X platform PSCI SYSTEM-SUSPEND function
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/psci.h>
+
+/* Default PSCI function, return -1, Not Implemented */
+#define PSCI_DEFAULT(__fn) \
+	ENTRY(__fn); \
+	mov	w0, #ARM_PSCI_RET_NI; \
+	ret; \
+	ENDPROC(__fn); \
+	.weak __fn
+
+/* PSCI function and ID table definition*/
+#define PSCI_TABLE(__id, __fn) \
+	.word __id; \
+	.word __fn
+
+.pushsection ._secure.text, "ax"
+
+/* 32 bits PSCI default functions */
+PSCI_DEFAULT(psci_version)
+PSCI_DEFAULT(psci_cpu_suspend)
+PSCI_DEFAULT(psci_cpu_off)
+PSCI_DEFAULT(psci_cpu_on)
+PSCI_DEFAULT(psci_affinity_info)
+PSCI_DEFAULT(psci_migrate)
+PSCI_DEFAULT(psci_migrate_info_type)
+PSCI_DEFAULT(psci_migrate_info_up_cpu)
+PSCI_DEFAULT(psci_system_off)
+PSCI_DEFAULT(psci_system_reset)
+PSCI_DEFAULT(psci_features)
+PSCI_DEFAULT(psci_cpu_freeze)
+PSCI_DEFAULT(psci_cpu_default_suspend)
+PSCI_DEFAULT(psci_node_hw_state)
+PSCI_DEFAULT(psci_system_suspend)
+PSCI_DEFAULT(psci_set_suspend_mode)
+PSCI_DEFAULT(psi_stat_residency)
+PSCI_DEFAULT(psci_stat_count)
+
+.align 3
+_psci_32_table:
+PSCI_TABLE(ARM_PSCI_FN_CPU_SUSPEND, psci_cpu_suspend)
+PSCI_TABLE(ARM_PSCI_FN_CPU_OFF, psci_cpu_off)
+PSCI_TABLE(ARM_PSCI_FN_CPU_ON, psci_cpu_on)
+PSCI_TABLE(ARM_PSCI_FN_MIGRATE, psci_migrate)
+PSCI_TABLE(ARM_PSCI_0_2_FN_PSCI_VERSION, psci_version)
+PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_SUSPEND, psci_cpu_suspend)
+PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_OFF, psci_cpu_off)
+PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_ON, psci_cpu_on)
+PSCI_TABLE(ARM_PSCI_0_2_FN_AFFINITY_INFO, psci_affinity_info)
+PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE, psci_migrate)
+PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE, psci_migrate_info_type)
+PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU, psci_migrate_info_up_cpu)
+PSCI_TABLE(ARM_PSCI_0_2_FN_SYSTEM_OFF, psci_system_off)
+PSCI_TABLE(ARM_PSCI_0_2_FN_SYSTEM_RESET, psci_system_reset)
+PSCI_TABLE(ARM_PSCI_1_0_FN_PSCI_FEATURES, psci_features)
+PSCI_TABLE(ARM_PSCI_1_0_FN_CPU_FREEZE, psci_cpu_freeze)
+PSCI_TABLE(ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND, psci_cpu_default_suspend)
+PSCI_TABLE(ARM_PSCI_1_0_FN_NODE_HW_STATE, psci_node_hw_state)
+PSCI_TABLE(ARM_PSCI_1_0_FN_SYSTEM_SUSPEND, psci_system_suspend)
+PSCI_TABLE(ARM_PSCI_1_0_FN_SET_SUSPEND_MODE, psci_set_suspend_mode)
+PSCI_TABLE(ARM_PSCI_1_0_FN_STAT_RESIDENCY, psi_stat_residency)
+PSCI_TABLE(ARM_PSCI_1_0_FN_STAT_COUNT, psci_stat_count)
+PSCI_TABLE(0, 0)
+
+/* 64 bits PSCI default functions */
+PSCI_DEFAULT(psci_cpu_suspend_64)
+PSCI_DEFAULT(psci_cpu_on_64)
+PSCI_DEFAULT(psci_affinity_info_64)
+PSCI_DEFAULT(psci_migrate_64)
+PSCI_DEFAULT(psci_migrate_info_up_cpu_64)
+PSCI_DEFAULT(psci_cpu_default_suspend_64)
+PSCI_DEFAULT(psci_node_hw_state_64)
+PSCI_DEFAULT(psci_system_suspend_64)
+PSCI_DEFAULT(psci_stat_residency_64)
+PSCI_DEFAULT(psci_stat_count_64)
+
+.align 3
+_psci_64_table:
+PSCI_TABLE(ARM_PSCI_0_2_FN64_CPU_SUSPEND, psci_cpu_suspend_64)
+PSCI_TABLE(ARM_PSCI_0_2_FN64_CPU_ON, psci_cpu_on_64)
+PSCI_TABLE(ARM_PSCI_0_2_FN64_AFFINITY_INFO, psci_affinity_info_64)
+PSCI_TABLE(ARM_PSCI_0_2_FN64_MIGRATE, psci_migrate_64)
+PSCI_TABLE(ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU, psci_migrate_info_up_cpu_64)
+PSCI_TABLE(ARM_PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND, psci_cpu_default_suspend_64)
+PSCI_TABLE(ARM_PSCI_1_0_FN64_NODE_HW_STATE, psci_node_hw_state_64)
+PSCI_TABLE(ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND, psci_system_suspend_64)
+PSCI_TABLE(ARM_PSCI_1_0_FN64_STAT_RESIDENCY, psci_stat_residency_64)
+PSCI_TABLE(ARM_PSCI_1_0_FN64_STAT_COUNT, psci_stat_count_64)
+PSCI_TABLE(0, 0)
+
+.macro	psci_enter
+	/* PSCI call is Fast Call(atomic), so mask DAIF */
+	mrs	x15, DAIF
+	stp	x15, xzr, [sp, #-16]!
+	ldr	x15, =0x3C0
+	msr	DAIF, x15
+	/* SMC convention, x18 ~ x30 should be saved by callee */
+	stp	x29, x30, [sp, #-16]!
+	stp	x27, x28, [sp, #-16]!
+	stp	x25, x26, [sp, #-16]!
+	stp	x23, x24, [sp, #-16]!
+	stp	x21, x22, [sp, #-16]!
+	stp	x19, x20, [sp, #-16]!
+	mrs	x15, elr_el3
+	stp	x18, x15, [sp, #-16]!
+.endm
+
+.macro	psci_return
+	/* restore registers */
+	ldp	x18, x15, [sp], #16
+	msr	elr_el3, x15
+	ldp	x19, x20, [sp], #16
+	ldp	x21, x22, [sp], #16
+	ldp	x23, x24, [sp], #16
+	ldp	x25, x26, [sp], #16
+	ldp	x27, x28, [sp], #16
+	ldp	x29, x30, [sp], #16
+	/* restore DAIF */
+	ldp	x15, xzr, [sp], #16
+	msr	DAIF, x15
+	eret
+.endm
+
+/* Caller must put PSCI function-ID table base in x9 */
+handle_psci:
+	psci_enter
+1:	ldr x10, [x9]			/* Load PSCI function table */
+	ubfx x11, x10, #32, #32
+	ubfx x10, x10, #0, #32
+	cbz	x10, 3f			/* If reach the end, bail out */
+	cmp	x10, x0
+	b.eq	2f			/* PSCI function found */
+	add x9, x9, #8			/* If not match, try next entry */
+	b	1b
+
+2:	blr	x11			/* Call PSCI function */
+	psci_return
+
+3:	mov	x0, #ARM_PSCI_RET_NI
+	psci_return
+
+unknown_smc_id:
+	ldr	x0, =0xFFFFFFFF
+	eret
+
+handle_smc32:
+	/* SMC function ID  0x84000000-0x8400001F: 32 bits PSCI */
+	ldr	w9, =0x8400001F
+	cmp	w0, w9
+	b.gt	unknown_smc_id
+	ldr	w9, =0x84000000
+	cmp	w0, w9
+	b.lt	unknown_smc_id
+
+	adr	x9, _psci_32_table
+	b	handle_psci
+
+handle_smc64:
+	/* check SMC32 or SMC64 calls */
+	ubfx	x9, x0, #30, #1
+	cbz	x9, handle_smc32
+
+	/* SMC function ID 0xC4000000-0xC400001F: 64 bits PSCI */
+	ldr	x9, =0xC400001F
+	cmp	x0, x9
+	b.gt	unknown_smc_id
+	ldr	x9, =0xC4000000
+	cmp	x0, x9
+	b.lt	unknown_smc_id
+
+	adr	x9, _psci_64_table
+	b	handle_psci
+
+/*
+ * Get CPU ID from MPIDR, suppose every cluster has same number of CPU cores,
+ * Platform with asymmetric clusters should implement their own interface.
+ * In case this function being called by other platform's C code, the ARM
+ * Architecture Procedure Call Standard is considered, e.g. register X0 is
+ * used for the return value, while in this PSCI environment, X0 usually holds
+ * the SMC function identifier, so X0 should be saved by caller function.
+ */
+ENTRY(psci_get_cpu_id)
+#ifdef CONFIG_ARMV8_PSCI_CPUS_PER_CLUSTER
+	mrs	x9, MPIDR_EL1
+	ubfx	x9, x9, #8, #8
+	ldr	x10, =CONFIG_ARMV8_PSCI_CPUS_PER_CLUSTER
+	mul	x9, x10, x9
+#else
+	mov	x9, xzr
+#endif
+	mrs	x10, MPIDR_EL1
+	ubfx	x10, x10, #0, #8
+	add	x0, x10, x9
+	ret
+ENDPROC(psci_get_cpu_id)
+.weak psci_get_cpu_id
+
+/* CPU ID input in x0, stack top output in x0*/
+LENTRY(psci_get_cpu_stack_top)
+	adr	x9, __secure_stack_end
+	lsl	x0, x0, #ARM_PSCI_STACK_SHIFT
+	sub	x0, x9, x0
+	ret
+ENDPROC(psci_get_cpu_stack_top)
+
+unhandled_exception:
+	b	unhandled_exception	/* simply dead loop */
+
+handle_sync:
+	mov	x15, x30
+	mov	x14, x0
+
+	bl	psci_get_cpu_id
+	bl	psci_get_cpu_stack_top
+	mov	x9, #1
+	msr	spsel, x9
+	mov	sp, x0
+
+	mov	x0, x14
+	mov	x30, x15
+
+	mrs	x9, esr_el3
+	ubfx	x9, x9, #26, #6
+	cmp	x9, #0x13
+	b.eq	handle_smc32
+	cmp	x9, #0x17
+	b.eq	handle_smc64
+
+	b	unhandled_exception
+
+#ifdef CONFIG_ARMV8_EA_EL3_FIRST
+/*
+ * Override this function if custom error handling is
+ * needed for asynchronous aborts
+ */
+ENTRY(plat_error_handler)
+	ret
+ENDPROC(plat_error_handler)
+.weak plat_error_handler
+
+handle_error:
+	bl	psci_get_cpu_id
+	bl	psci_get_cpu_stack_top
+	mov	x9, #1
+	msr	spsel, x9
+	mov	sp, x0
+
+	bl	plat_error_handler	/* Platform specific error handling */
+deadloop:
+	b	deadloop		/* Never return */
+#endif
+
+	.align	11
+	.globl	el3_exception_vectors
+el3_exception_vectors:
+	b	unhandled_exception	/* Sync, Current EL using SP0 */
+	.align	7
+	b	unhandled_exception	/* IRQ, Current EL using SP0 */
+	.align	7
+	b	unhandled_exception	/* FIQ, Current EL using SP0 */
+	.align	7
+	b	unhandled_exception	/* SError, Current EL using SP0 */
+	.align	7
+	b	unhandled_exception	/* Sync, Current EL using SPx */
+	.align	7
+	b	unhandled_exception	/* IRQ, Current EL using SPx */
+	.align	7
+	b	unhandled_exception	/* FIQ, Current EL using SPx */
+	.align	7
+	b	unhandled_exception	/* SError, Current EL using SPx */
+	.align	7
+	b	handle_sync		/* Sync, Lower EL using AArch64 */
+	.align	7
+	b	unhandled_exception	/* IRQ, Lower EL using AArch64 */
+	.align	7
+	b	unhandled_exception	/* FIQ, Lower EL using AArch64 */
+	.align	7
+#ifdef CONFIG_ARMV8_EA_EL3_FIRST
+	b	handle_error		/* SError, Lower EL using AArch64 */
+#else
+	b	unhandled_exception	/* SError, Lower EL using AArch64 */
+#endif
+	.align	7
+	b	unhandled_exception	/* Sync, Lower EL using AArch32 */
+	.align	7
+	b	unhandled_exception	/* IRQ, Lower EL using AArch32 */
+	.align	7
+	b	unhandled_exception	/* FIQ, Lower EL using AArch32 */
+	.align	7
+	b	unhandled_exception	/* SError, Lower EL using AArch32 */
+
+ENTRY(psci_setup_vectors)
+	adr	x0, el3_exception_vectors
+	msr	vbar_el3, x0
+	ret
+ENDPROC(psci_setup_vectors)
+
+ENTRY(psci_arch_init)
+	ret
+ENDPROC(psci_arch_init)
+.weak psci_arch_init
+
+.popsection
diff --git a/arch/arm/cpu/armv8/s32v234/Makefile b/arch/arm/cpu/armv8/s32v234/Makefile
new file mode 100644
index 0000000..3bdb98d
--- /dev/null
+++ b/arch/arm/cpu/armv8/s32v234/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2013-2016, Freescale Semiconductor, Inc.
+
+obj-y += generic.o
+obj-y += cpu.o
diff --git a/arch/arm/cpu/armv8/s32v234/cpu.c b/arch/arm/cpu/armv8/s32v234/cpu.c
new file mode 100644
index 0000000..1fa6841
--- /dev/null
+++ b/arch/arm/cpu/armv8/s32v234/cpu.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014-2016, Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/armv8/mmu.h>
+#include <asm/io.h>
+#include <asm/arch/mc_me_regs.h>
+#include "cpu.h"
+
+u32 cpu_mask(void)
+{
+	return readl(MC_ME_CS);
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+
+#define S32V234_IRAM_BASE        0x3e800000UL
+#define S32V234_IRAM_SIZE        0x800000UL
+#define S32V234_DRAM_BASE1       0x80000000UL
+#define S32V234_DRAM_SIZE1       0x40000000UL
+#define S32V234_DRAM_BASE2       0xC0000000UL
+#define S32V234_DRAM_SIZE2       0x20000000UL
+#define S32V234_PERIPH_BASE      0x40000000UL
+#define S32V234_PERIPH_SIZE      0x40000000UL
+
+static struct mm_region s32v234_mem_map[] = {
+	{
+		.virt = S32V234_IRAM_BASE,
+		.phys = S32V234_IRAM_BASE,
+		.size = S32V234_IRAM_SIZE,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE
+	}, {
+		.virt = S32V234_DRAM_BASE1,
+		.phys = S32V234_DRAM_BASE1,
+		.size = S32V234_DRAM_SIZE1,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE
+	}, {
+		.virt = S32V234_PERIPH_BASE,
+		.phys = S32V234_PERIPH_BASE,
+		.size = S32V234_PERIPH_SIZE,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE
+			 /* TODO: Do we need these? */
+			 /* | PTE_BLOCK_PXN | PTE_BLOCK_UXN */
+	}, {
+		.virt = S32V234_DRAM_BASE2,
+		.phys = S32V234_DRAM_BASE2,
+		.size = S32V234_DRAM_SIZE2,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
+			 PTE_BLOCK_OUTER_SHARE
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = s32v234_mem_map;
+
+#endif
+
+/*
+ * Return the number of cores on this SOC.
+ */
+int cpu_numcores(void)
+{
+	int numcores;
+	u32 mask;
+
+	mask = cpu_mask();
+	numcores = hweight32(cpu_mask());
+
+	/* Verify if M4 is deactivated */
+	if (mask & 0x1)
+		numcores--;
+
+	return numcores;
+}
+
+#if defined(CONFIG_ARCH_EARLY_INIT_R)
+int arch_early_init_r(void)
+{
+	int rv;
+	asm volatile ("dsb sy");
+	rv = fsl_s32v234_wake_seconday_cores();
+
+	if (rv)
+		printf("Did not wake secondary cores\n");
+
+	asm volatile ("sev");
+	return 0;
+}
+#endif /* CONFIG_ARCH_EARLY_INIT_R */
diff --git a/arch/arm/cpu/armv8/s32v234/cpu.h b/arch/arm/cpu/armv8/s32v234/cpu.h
new file mode 100644
index 0000000..11c3a6b
--- /dev/null
+++ b/arch/arm/cpu/armv8/s32v234/cpu.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014-2016, Freescale Semiconductor, Inc.
+ */
+
+u32 cpu_mask(void);
+int cpu_numcores(void);
diff --git a/arch/arm/cpu/armv8/s32v234/generic.c b/arch/arm/cpu/armv8/s32v234/generic.c
new file mode 100644
index 0000000..273b88e
--- /dev/null
+++ b/arch/arm/cpu/armv8/s32v234/generic.c
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013-2016, Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/mc_cgm_regs.h>
+#include <asm/arch/mc_me_regs.h>
+#include <asm/arch/mc_rgm_regs.h>
+#include <netdev.h>
+#include <div64.h>
+#include <errno.h>
+
+u32 get_cpu_rev(void)
+{
+	struct mscm_ir *mscmir = (struct mscm_ir *)MSCM_BASE_ADDR;
+	u32 cpu = readl(&mscmir->cpxtype);
+
+	return cpu;
+}
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static uintptr_t get_pllfreq(u32 pll, u32 refclk_freq, u32 plldv,
+			     u32 pllfd, u32 selected_output)
+{
+	u32 vco = 0, plldv_prediv = 0, plldv_mfd = 0, pllfd_mfn = 0;
+	u32 plldv_rfdphi_div = 0, fout = 0;
+	u32 dfs_portn = 0, dfs_mfn = 0, dfs_mfi = 0;
+
+	if (selected_output > DFS_MAXNUMBER) {
+		return -1;
+	}
+
+	plldv_prediv =
+	    (plldv & PLLDIG_PLLDV_PREDIV_MASK) >> PLLDIG_PLLDV_PREDIV_OFFSET;
+	plldv_mfd = (plldv & PLLDIG_PLLDV_MFD_MASK);
+
+	pllfd_mfn = (pllfd & PLLDIG_PLLFD_MFN_MASK);
+
+	plldv_prediv = plldv_prediv == 0 ? 1 : plldv_prediv;
+
+	/* The formula for VCO is from TR manual, rev. D */
+	vco = refclk_freq / plldv_prediv * (plldv_mfd + pllfd_mfn / 20481);
+
+	if (selected_output != 0) {
+		/* Determine the RFDPHI for PHI1 */
+		plldv_rfdphi_div =
+		    (plldv & PLLDIG_PLLDV_RFDPHI1_MASK) >>
+		    PLLDIG_PLLDV_RFDPHI1_OFFSET;
+		plldv_rfdphi_div = plldv_rfdphi_div == 0 ? 1 : plldv_rfdphi_div;
+		if (pll == ARM_PLL || pll == ENET_PLL || pll == DDR_PLL) {
+			dfs_portn =
+			    readl(DFS_DVPORTn(pll, selected_output - 1));
+			dfs_mfi =
+			    (dfs_portn & DFS_DVPORTn_MFI_MASK) >>
+			    DFS_DVPORTn_MFI_OFFSET;
+			dfs_mfn =
+			    (dfs_portn & DFS_DVPORTn_MFI_MASK) >>
+			    DFS_DVPORTn_MFI_OFFSET;
+			fout = vco / (dfs_mfi + (dfs_mfn / 256));
+		} else {
+			fout = vco / plldv_rfdphi_div;
+		}
+
+	} else {
+		/* Determine the RFDPHI for PHI0 */
+		plldv_rfdphi_div =
+		    (plldv & PLLDIG_PLLDV_RFDPHI_MASK) >>
+		    PLLDIG_PLLDV_RFDPHI_OFFSET;
+		fout = vco / plldv_rfdphi_div;
+	}
+
+	return fout;
+
+}
+
+/* Implemented for ARMPLL, PERIPH_PLL, ENET_PLL, DDR_PLL, VIDEO_LL */
+static uintptr_t decode_pll(enum pll_type pll, u32 refclk_freq,
+			    u32 selected_output)
+{
+	u32 plldv, pllfd;
+
+	plldv = readl(PLLDIG_PLLDV(pll));
+	pllfd = readl(PLLDIG_PLLFD(pll));
+
+	return get_pllfreq(pll, refclk_freq, plldv, pllfd, selected_output);
+}
+
+static u32 get_mcu_main_clk(void)
+{
+	u32 coreclk_div;
+	u32 sysclk_sel;
+	u32 freq = 0;
+
+	sysclk_sel = readl(CGM_SC_SS(MC_CGM1_BASE_ADDR)) & MC_CGM_SC_SEL_MASK;
+	sysclk_sel >>= MC_CGM_SC_SEL_OFFSET;
+
+	coreclk_div =
+	    readl(CGM_SC_DCn(MC_CGM1_BASE_ADDR, 0)) & MC_CGM_SC_DCn_PREDIV_MASK;
+	coreclk_div >>= MC_CGM_SC_DCn_PREDIV_OFFSET;
+	coreclk_div += 1;
+
+	switch (sysclk_sel) {
+	case MC_CGM_SC_SEL_FIRC:
+		freq = FIRC_CLK_FREQ;
+		break;
+	case MC_CGM_SC_SEL_XOSC:
+		freq = XOSC_CLK_FREQ;
+		break;
+	case MC_CGM_SC_SEL_ARMPLL:
+		/* ARMPLL has as source XOSC and CORE_CLK has as input PHI0 */
+		freq = decode_pll(ARM_PLL, XOSC_CLK_FREQ, 0);
+		break;
+	case MC_CGM_SC_SEL_CLKDISABLE:
+		printf("Sysclk is disabled\n");
+		break;
+	default:
+		printf("unsupported system clock select\n");
+	}
+
+	return freq / coreclk_div;
+}
+
+static u32 get_sys_clk(u32 number)
+{
+	u32 sysclk_div, sysclk_div_number;
+	u32 sysclk_sel;
+	u32 freq = 0;
+
+	switch (number) {
+	case 3:
+		sysclk_div_number = 0;
+		break;
+	case 6:
+		sysclk_div_number = 1;
+		break;
+	default:
+		printf("unsupported system clock \n");
+		return -1;
+	}
+	sysclk_sel = readl(CGM_SC_SS(MC_CGM0_BASE_ADDR)) & MC_CGM_SC_SEL_MASK;
+	sysclk_sel >>= MC_CGM_SC_SEL_OFFSET;
+
+	sysclk_div =
+	    readl(CGM_SC_DCn(MC_CGM1_BASE_ADDR, sysclk_div_number)) &
+	    MC_CGM_SC_DCn_PREDIV_MASK;
+	sysclk_div >>= MC_CGM_SC_DCn_PREDIV_OFFSET;
+	sysclk_div += 1;
+
+	switch (sysclk_sel) {
+	case MC_CGM_SC_SEL_FIRC:
+		freq = FIRC_CLK_FREQ;
+		break;
+	case MC_CGM_SC_SEL_XOSC:
+		freq = XOSC_CLK_FREQ;
+		break;
+	case MC_CGM_SC_SEL_ARMPLL:
+		/* ARMPLL has as source XOSC and SYSn_CLK has as input DFS1 */
+		freq = decode_pll(ARM_PLL, XOSC_CLK_FREQ, 1);
+		break;
+	case MC_CGM_SC_SEL_CLKDISABLE:
+		printf("Sysclk is disabled\n");
+		break;
+	default:
+		printf("unsupported system clock select\n");
+	}
+
+	return freq / sysclk_div;
+}
+
+static u32 get_peripherals_clk(void)
+{
+	u32 aux5clk_div;
+	u32 freq = 0;
+
+	aux5clk_div =
+	    readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 5, 0)) &
+	    MC_CGM_ACn_DCm_PREDIV_MASK;
+	aux5clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
+	aux5clk_div += 1;
+
+	freq = decode_pll(PERIPH_PLL, XOSC_CLK_FREQ, 0);
+
+	return freq / aux5clk_div;
+
+}
+
+static u32 get_uart_clk(void)
+{
+	u32 auxclk3_div, auxclk3_sel, freq = 0;
+
+	auxclk3_sel =
+	    readl(CGM_ACn_SS(MC_CGM0_BASE_ADDR, 3)) & MC_CGM_ACn_SEL_MASK;
+	auxclk3_sel >>= MC_CGM_ACn_SEL_OFFSET;
+
+	auxclk3_div =
+	    readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 3, 0)) &
+	    MC_CGM_ACn_DCm_PREDIV_MASK;
+	auxclk3_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
+	auxclk3_div += 1;
+
+	switch (auxclk3_sel) {
+	case MC_CGM_ACn_SEL_FIRC:
+		freq = FIRC_CLK_FREQ;
+		break;
+	case MC_CGM_ACn_SEL_XOSC:
+		freq = XOSC_CLK_FREQ;
+		break;
+	case MC_CGM_ACn_SEL_PERPLLDIVX:
+		freq = get_peripherals_clk() / 3;
+		break;
+	case MC_CGM_ACn_SEL_SYSCLK:
+		freq = get_sys_clk(6);
+		break;
+	default:
+		printf("unsupported system clock select\n");
+	}
+
+	return freq / auxclk3_div;
+}
+
+static u32 get_fec_clk(void)
+{
+	u32 aux2clk_div;
+	u32 freq = 0;
+
+	aux2clk_div =
+	    readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 2, 0)) &
+	    MC_CGM_ACn_DCm_PREDIV_MASK;
+	aux2clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
+	aux2clk_div += 1;
+
+	freq = decode_pll(ENET_PLL, XOSC_CLK_FREQ, 0);
+
+	return freq / aux2clk_div;
+}
+
+static u32 get_usdhc_clk(void)
+{
+	u32 aux15clk_div;
+	u32 freq = 0;
+
+	aux15clk_div =
+	    readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 15, 0)) &
+	    MC_CGM_ACn_DCm_PREDIV_MASK;
+	aux15clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET;
+	aux15clk_div += 1;
+
+	freq = decode_pll(ENET_PLL, XOSC_CLK_FREQ, 4);
+
+	return freq / aux15clk_div;
+}
+
+static u32 get_i2c_clk(void)
+{
+	return get_peripherals_clk();
+}
+
+/* return clocks in Hz */
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return get_mcu_main_clk();
+	case MXC_PERIPHERALS_CLK:
+		return get_peripherals_clk();
+	case MXC_UART_CLK:
+		return get_uart_clk();
+	case MXC_FEC_CLK:
+		return get_fec_clk();
+	case MXC_I2C_CLK:
+		return get_i2c_clk();
+	case MXC_USDHC_CLK:
+		return get_usdhc_clk();
+	default:
+		break;
+	}
+	printf("Error: Unsupported function to read the frequency! \
+			Please define it correctly!");
+	return -1;
+}
+
+/* Not yet implemented - int soc_clk_dump(); */
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+static char *get_reset_cause(void)
+{
+	u32 cause = readl(MC_RGM_BASE_ADDR + 0x300);
+
+	switch (cause) {
+	case F_SWT4:
+		return "WDOG";
+	case F_JTAG:
+		return "JTAG";
+	case F_FCCU_SOFT:
+		return "FCCU soft reaction";
+	case F_FCCU_HARD:
+		return "FCCU hard reaction";
+	case F_SOFT_FUNC:
+		return "Software Functional reset";
+	case F_ST_DONE:
+		return "Self Test done reset";
+	case F_EXT_RST:
+		return "External reset";
+	default:
+		return "unknown reset";
+	}
+
+}
+
+#define SRC_SCR_SW_RST					(1<<12)
+
+void reset_cpu(ulong addr)
+{
+	printf("Feature not supported.\n");
+};
+
+int print_cpuinfo(void)
+{
+	printf("CPU:   Freescale Treerunner S32V234 at %d MHz\n",
+	       mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("Reset cause: %s\n", get_reset_cause());
+
+	return 0;
+}
+#endif
+
+int cpu_eth_init(bd_t * bis)
+{
+	int rc = -ENODEV;
+
+#if defined(CONFIG_FEC_MXC)
+	rc = fecmxc_initialize(bis);
+#endif
+
+	return rc;
+}
+
+int get_clocks(void)
+{
+#ifdef CONFIG_FSL_ESDHC
+	gd->arch.sdhc_clk = mxc_get_clock(MXC_USDHC_CLK);
+#endif
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c
new file mode 100644
index 0000000..8dc0ac9
--- /dev/null
+++ b/arch/arm/cpu/armv8/sec_firmware.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/types.h>
+#include <asm/macro.h>
+#include <asm/armv8/sec_firmware.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+extern void c_runtime_cpu_setup(void);
+
+#define SEC_FIRMWARE_LOADED	0x1
+#define SEC_FIRMWARE_RUNNING	0x2
+#define SEC_FIRMWARE_ADDR_MASK	(~0x3)
+/*
+ * Secure firmware load addr
+ * Flags used: 0x1 secure firmware has been loaded to secure memory
+ *             0x2 secure firmware is running
+ */
+phys_addr_t sec_firmware_addr;
+
+#ifndef SEC_FIRMWARE_FIT_IMAGE
+#define SEC_FIRMWARE_FIT_IMAGE		"firmware"
+#endif
+#ifndef SEC_FIRMEWARE_FIT_CNF_NAME
+#define SEC_FIRMEWARE_FIT_CNF_NAME	"config-1"
+#endif
+#ifndef SEC_FIRMWARE_TARGET_EL
+#define SEC_FIRMWARE_TARGET_EL		2
+#endif
+
+static int sec_firmware_get_data(const void *sec_firmware_img,
+				const void **data, size_t *size)
+{
+	int conf_node_off, fw_node_off;
+	char *conf_node_name = NULL;
+	char *desc;
+	int ret;
+
+	conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME;
+
+	conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name);
+	if (conf_node_off < 0) {
+		printf("SEC Firmware: %s: no such config\n", conf_node_name);
+		return -ENOENT;
+	}
+
+	fw_node_off = fit_conf_get_prop_node(sec_firmware_img, conf_node_off,
+			SEC_FIRMWARE_FIT_IMAGE);
+	if (fw_node_off < 0) {
+		printf("SEC Firmware: No '%s' in config\n",
+		       SEC_FIRMWARE_FIT_IMAGE);
+		return -ENOLINK;
+	}
+
+	/* Verify secure firmware image */
+	if (!(fit_image_verify(sec_firmware_img, fw_node_off))) {
+		printf("SEC Firmware: Bad firmware image (bad CRC)\n");
+		return -EINVAL;
+	}
+
+	if (fit_image_get_data(sec_firmware_img, fw_node_off, data, size)) {
+		printf("SEC Firmware: Can't get %s subimage data/size",
+		       SEC_FIRMWARE_FIT_IMAGE);
+		return -ENOENT;
+	}
+
+	ret = fit_get_desc(sec_firmware_img, fw_node_off, &desc);
+	if (ret)
+		printf("SEC Firmware: Can't get description\n");
+	else
+		printf("%s\n", desc);
+
+	return ret;
+}
+
+/*
+ * SEC Firmware FIT image parser checks if the image is in FIT
+ * format, verifies integrity of the image and calculates raw
+ * image address and size values.
+ *
+ * Returns 0 on success and a negative errno on error task fail.
+ */
+static int sec_firmware_parse_image(const void *sec_firmware_img,
+					const void **raw_image_addr,
+					size_t *raw_image_size)
+{
+	int ret;
+
+	ret = sec_firmware_get_data(sec_firmware_img, raw_image_addr,
+					raw_image_size);
+	if (ret)
+		return ret;
+
+	debug("SEC Firmware: raw_image_addr = 0x%p, raw_image_size = 0x%lx\n",
+	      *raw_image_addr, *raw_image_size);
+
+	return 0;
+}
+
+/*
+ * SEC Firmware FIT image parser to check if any loadable is
+ * present. If present, verify integrity of the loadable and
+ * copy loadable to address provided in (loadable_h, loadable_l).
+ *
+ * Returns 0 on success and a negative errno on error task fail.
+ */
+static int sec_firmware_check_copy_loadable(const void *sec_firmware_img,
+					    u32 *loadable_l, u32 *loadable_h)
+{
+	phys_addr_t sec_firmware_loadable_addr = 0;
+	int conf_node_off, ld_node_off, images;
+	char *conf_node_name = NULL;
+	const void *data;
+	size_t size;
+	ulong load;
+	const char *name, *str, *type;
+	int len;
+
+	conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME;
+
+	conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name);
+	if (conf_node_off < 0) {
+		printf("SEC Firmware: %s: no such config\n", conf_node_name);
+		return -ENOENT;
+	}
+
+	/* find the node holding the images information */
+	images = fdt_path_offset(sec_firmware_img, FIT_IMAGES_PATH);
+	if (images < 0) {
+		printf("%s: Cannot find /images node: %d\n", __func__, images);
+		return -1;
+	}
+
+	type = FIT_LOADABLE_PROP;
+
+	name = fdt_getprop(sec_firmware_img, conf_node_off, type, &len);
+	if (!name) {
+		/* Loadables not present */
+		return 0;
+	}
+
+	printf("SEC Firmware: '%s' present in config\n", type);
+
+	for (str = name; str && ((str - name) < len);
+	     str = strchr(str, '\0') + 1) {
+		printf("%s: '%s'\n", type, str);
+		ld_node_off = fdt_subnode_offset(sec_firmware_img, images, str);
+		if (ld_node_off < 0) {
+			printf("cannot find image node '%s': %d\n", str,
+			       ld_node_off);
+			return -EINVAL;
+		}
+
+		/* Verify secure firmware image */
+		if (!(fit_image_verify(sec_firmware_img, ld_node_off))) {
+			printf("SEC Loadable: Bad loadable image (bad CRC)\n");
+			return -EINVAL;
+		}
+
+		if (fit_image_get_data(sec_firmware_img, ld_node_off,
+				       &data, &size)) {
+			printf("SEC Loadable: Can't get subimage data/size");
+			return -ENOENT;
+		}
+
+		/* Get load address, treated as load offset to secure memory */
+		if (fit_image_get_load(sec_firmware_img, ld_node_off, &load)) {
+			printf("SEC Loadable: Can't get subimage load");
+			return -ENOENT;
+		}
+
+		/* Compute load address for loadable in secure memory */
+		sec_firmware_loadable_addr = (sec_firmware_addr -
+						gd->arch.tlb_size) + load;
+
+		/* Copy loadable to secure memory and flush dcache */
+		debug("%s copied to address 0x%p\n",
+		      FIT_LOADABLE_PROP, (void *)sec_firmware_loadable_addr);
+		memcpy((void *)sec_firmware_loadable_addr, data, size);
+		flush_dcache_range(sec_firmware_loadable_addr,
+				   sec_firmware_loadable_addr + size);
+
+		/* Populate loadable address only for Trusted OS */
+		if (!strcmp(str, "trustedOS@1")) {
+			/*
+			 * Populate address ptrs for loadable image with
+			 * loadbale addr
+			 */
+			out_le32(loadable_l, (sec_firmware_loadable_addr &
+					      WORD_MASK));
+			out_le32(loadable_h, (sec_firmware_loadable_addr >>
+					      WORD_SHIFT));
+		}
+	}
+
+	return 0;
+}
+
+static int sec_firmware_copy_image(const char *title,
+			 u64 image_addr, u32 image_size, u64 sec_firmware)
+{
+	debug("%s copied to address 0x%p\n", title, (void *)sec_firmware);
+	memcpy((void *)sec_firmware, (void *)image_addr, image_size);
+	flush_dcache_range(sec_firmware, sec_firmware + image_size);
+
+	return 0;
+}
+
+/*
+ * This function will parse the SEC Firmware image, and then load it
+ * to secure memory. Also load any loadable if present along with SEC
+ * Firmware image.
+ */
+static int sec_firmware_load_image(const void *sec_firmware_img,
+				   u32 *loadable_l, u32 *loadable_h)
+{
+	const void *raw_image_addr;
+	size_t raw_image_size = 0;
+	int ret;
+
+	/*
+	 * The Excetpion Level must be EL3 to load and initialize
+	 * the SEC Firmware.
+	 */
+	if (current_el() != 3) {
+		ret = -EACCES;
+		goto out;
+	}
+
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	/*
+	 * The SEC Firmware must be stored in secure memory.
+	 * Append SEC Firmware to secure mmu table.
+	 */
+	if (!(gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED)) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	sec_firmware_addr = (gd->arch.secure_ram & MEM_RESERVE_SECURE_ADDR_MASK) +
+			gd->arch.tlb_size;
+#else
+#error "The CONFIG_SYS_MEM_RESERVE_SECURE must be defined when enabled SEC Firmware support"
+#endif
+
+	/* Align SEC Firmware base address to 4K */
+	sec_firmware_addr = (sec_firmware_addr + 0xfff) & ~0xfff;
+	debug("SEC Firmware: Load address: 0x%llx\n",
+	      sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK);
+
+	ret = sec_firmware_parse_image(sec_firmware_img, &raw_image_addr,
+			&raw_image_size);
+	if (ret)
+		goto out;
+
+	/* TODO:
+	 * Check if the end addr of SEC Firmware has been extend the secure
+	 * memory.
+	 */
+
+	/* Copy the secure firmware to secure memory */
+	ret = sec_firmware_copy_image("SEC Firmware", (u64)raw_image_addr,
+			raw_image_size, sec_firmware_addr &
+			SEC_FIRMWARE_ADDR_MASK);
+	if (ret)
+		goto out;
+
+	/*
+	 * Check if any loadable are present along with firmware image, if
+	 * present load them.
+	 */
+	ret = sec_firmware_check_copy_loadable(sec_firmware_img, loadable_l,
+					       loadable_h);
+	if (ret)
+		goto out;
+
+	sec_firmware_addr |= SEC_FIRMWARE_LOADED;
+	debug("SEC Firmware: Entry point: 0x%llx\n",
+	      sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK);
+
+	return 0;
+
+out:
+	printf("SEC Firmware: error (%d)\n", ret);
+	sec_firmware_addr = 0;
+
+	return ret;
+}
+
+static int sec_firmware_entry(u32 *eret_hold_l, u32 *eret_hold_h)
+{
+	const void *entry = (void *)(sec_firmware_addr &
+				SEC_FIRMWARE_ADDR_MASK);
+
+	return _sec_firmware_entry(entry, eret_hold_l, eret_hold_h);
+}
+
+/* Check the secure firmware FIT image */
+__weak bool sec_firmware_is_valid(const void *sec_firmware_img)
+{
+	if (fdt_check_header(sec_firmware_img)) {
+		printf("SEC Firmware: Bad firmware image (not a FIT image)\n");
+		return false;
+	}
+
+	if (!fit_check_format(sec_firmware_img)) {
+		printf("SEC Firmware: Bad firmware image (bad FIT header)\n");
+		return false;
+	}
+
+	return true;
+}
+
+#ifdef CONFIG_SEC_FIRMWARE_ARMV8_PSCI
+/*
+ * The PSCI_VERSION function is added from PSCI v0.2. When the PSCI
+ * v0.1 received this function, the NOT_SUPPORTED (0xffff_ffff) error
+ * number will be returned according to SMC Calling Conventions. But
+ * when getting the NOT_SUPPORTED error number, we cannot ensure if
+ * the PSCI version is v0.1 or other error occurred. So, PSCI v0.1
+ * won't be supported by this framework.
+ * And if the secure firmware isn't running, return NOT_SUPPORTED.
+ *
+ * The return value on success is PSCI version in format
+ * major[31:16]:minor[15:0].
+ */
+unsigned int sec_firmware_support_psci_version(void)
+{
+	if (current_el() == SEC_FIRMWARE_TARGET_EL)
+		return _sec_firmware_support_psci_version();
+
+	return PSCI_INVALID_VER;
+}
+#endif
+
+/*
+ * Check with sec_firmware if it supports random number generation
+ * via HW RNG
+ *
+ * The return value will be true if it is supported
+ */
+bool sec_firmware_support_hwrng(void)
+{
+#ifdef CONFIG_TFABOOT
+	/* return true as TFA has one job ring reserved */
+	return true;
+#endif
+	if (sec_firmware_addr & SEC_FIRMWARE_RUNNING) {
+			return true;
+	}
+
+	return false;
+}
+
+/*
+ * sec_firmware_get_random - Get a random number from SEC Firmware
+ * @rand:		random number buffer to be filled
+ * @bytes:		Number of bytes of random number to be supported
+ * @eret:		-1 in case of error, 0 for success
+ */
+int sec_firmware_get_random(uint8_t *rand, int bytes)
+{
+	unsigned long long num;
+	struct pt_regs regs;
+	int param1;
+
+	if (!bytes || bytes > 8) {
+		printf("Max Random bytes genration supported is 8\n");
+		return -1;
+	}
+#define SIP_RNG_64 0xC200FF11
+	regs.regs[0] = SIP_RNG_64;
+
+	if (bytes <= 4)
+		param1 = 0;
+	else
+		param1 = 1;
+	regs.regs[1] = param1;
+
+	smc_call(&regs);
+
+	if (regs.regs[0])
+		return -1;
+
+	num = regs.regs[1];
+	memcpy(rand, &num, bytes);
+
+	return 0;
+}
+
+/*
+ * sec_firmware_init - Initialize the SEC Firmware
+ * @sec_firmware_img:	the SEC Firmware image address
+ * @eret_hold_l:	the address to hold exception return address low
+ * @eret_hold_h:	the address to hold exception return address high
+ * @loadable_l:		the address to hold loadable address low
+ * @loadable_h:		the address to hold loadable address high
+ */
+int sec_firmware_init(const void *sec_firmware_img,
+			u32 *eret_hold_l,
+			u32 *eret_hold_h,
+			u32 *loadable_l,
+			u32 *loadable_h)
+{
+	int ret;
+
+	if (!sec_firmware_is_valid(sec_firmware_img))
+		return -EINVAL;
+
+	ret = sec_firmware_load_image(sec_firmware_img, loadable_l,
+				      loadable_h);
+	if (ret) {
+		printf("SEC Firmware: Failed to load image\n");
+		return ret;
+	} else if (sec_firmware_addr & SEC_FIRMWARE_LOADED) {
+		ret = sec_firmware_entry(eret_hold_l, eret_hold_h);
+		if (ret) {
+			printf("SEC Firmware: Failed to initialize\n");
+			return ret;
+		}
+	}
+
+	debug("SEC Firmware: Return from SEC Firmware: current_el = %d\n",
+	      current_el());
+
+	/*
+	 * The PE will be turned into target EL when returned from
+	 * SEC Firmware.
+	 */
+	if (current_el() != SEC_FIRMWARE_TARGET_EL)
+		return -EACCES;
+
+	sec_firmware_addr |= SEC_FIRMWARE_RUNNING;
+
+	/* Set exception table and enable caches if it isn't EL3 */
+	if (current_el() != 3) {
+		c_runtime_cpu_setup();
+		enable_caches();
+	}
+
+	return 0;
+}
+
+/*
+ * fdt_fix_kaslr - Add kalsr-seed node in Device tree
+ * @fdt:		Device tree
+ * @eret:		0 in case of error, 1 for success
+ */
+int fdt_fixup_kaslr(void *fdt)
+{
+	int nodeoffset;
+	int err, ret = 0;
+	u8 rand[8];
+
+#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT)
+	/* Check if random seed generation is  supported */
+	if (sec_firmware_support_hwrng() == false) {
+		printf("WARNING: SEC firmware not running, no kaslr-seed\n");
+		return 0;
+	}
+
+	ret = sec_firmware_get_random(rand, 8);
+	if (ret < 0) {
+		printf("WARNING: No random number to set kaslr-seed\n");
+		return 0;
+	}
+
+	err = fdt_check_header(fdt);
+	if (err < 0) {
+		printf("fdt_chosen: %s\n", fdt_strerror(err));
+		return 0;
+	}
+
+	/* find or create "/chosen" node. */
+	nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
+	if (nodeoffset < 0)
+		return 0;
+
+	err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", rand,
+				  sizeof(rand));
+	if (err < 0) {
+		printf("WARNING: can't set kaslr-seed %s.\n",
+		       fdt_strerror(err));
+		return 0;
+	}
+	ret = 1;
+#endif
+
+	return ret;
+}
diff --git a/arch/arm/cpu/armv8/sec_firmware_asm.S b/arch/arm/cpu/armv8/sec_firmware_asm.S
new file mode 100644
index 0000000..af1b2da
--- /dev/null
+++ b/arch/arm/cpu/armv8/sec_firmware_asm.S
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/system.h>
+#include <asm/macro.h>
+
+WEAK(_sec_firmware_entry)
+	/*
+	 * x0: Secure Firmware entry point
+	 * x1: Exception return address Low
+	 * x2: Exception return address High
+	 */
+
+	/* Save stack pointer for EL2 */
+	mov	x3, sp
+	msr	sp_el2, x3
+
+	/* Set exception return address hold pointer */
+        adr	x4, 1f
+        mov	x3, x4
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT
+        rev	w3, w3
+#endif
+        str	w3, [x1]
+        lsr	x3, x4, #32
+#ifdef CONFIG_ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT
+        rev	w3, w3
+#endif
+        str	w3, [x2]
+
+	/* Call SEC monitor */
+        br	x0
+
+1:
+        mov	x0, #0
+        ret
+ENDPROC(_sec_firmware_entry)
+
+#ifdef CONFIG_SEC_FIRMWARE_ARMV8_PSCI
+ENTRY(_sec_firmware_support_psci_version)
+	mov	x0, 0x84000000
+	mov	x1, 0x0
+	mov	x2, 0x0
+	mov	x3, 0x0
+	smc	#0
+	ret
+ENDPROC(_sec_firmware_support_psci_version)
+
+/*
+ * Switch from AArch64 EL2 to AArch32 EL2
+ * @param inputs:
+ * x0: argument, zero
+ * x1: machine nr
+ * x2: fdt address
+ * x3: input argument
+ * x4: kernel entry point
+ * @param outputs for secure firmware:
+ * x0: function id
+ * x1: kernel entry point
+ * x2: machine nr
+ * x3: fdt address
+*/
+ENTRY(armv8_el2_to_aarch32)
+	mov	x3, x2
+	mov	x2, x1
+	mov	x1, x4
+	ldr	x0, =0xc200ff17
+	smc	#0
+	ret
+ENDPROC(armv8_el2_to_aarch32)
+#endif
diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
new file mode 100644
index 0000000..86de4b4
--- /dev/null
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2015, Linaro Limited
+ */
+#include <linux/linkage.h>
+#include <linux/arm-smccc.h>
+#include <generated/asm-offsets.h>
+
+	.section	.text.efi_runtime
+
+	.macro SMCCC instr
+	.cfi_startproc
+	\instr	#0
+	ldr	x4, [sp]
+	stp	x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
+	stp	x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
+	ldr	x4, [sp, #8]
+	cbz	x4, 1f /* no quirk structure */
+	ldr	x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
+	cmp	x9, #ARM_SMCCC_QUIRK_QCOM_A6
+	b.ne	1f
+	str	x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
+1:	ret
+	.cfi_endproc
+	.endm
+
+/*
+ * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+ *		  unsigned long a3, unsigned long a4, unsigned long a5,
+ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ *		  struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_smc)
+	SMCCC	smc
+ENDPROC(__arm_smccc_smc)
+
+/*
+ * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
+ *		  unsigned long a3, unsigned long a4, unsigned long a5,
+ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ *		  struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_hvc)
+	SMCCC	hvc
+ENDPROC(__arm_smccc_hvc)
diff --git a/arch/arm/cpu/armv8/spin_table.c b/arch/arm/cpu/armv8/spin_table.c
new file mode 100644
index 0000000..42a0962
--- /dev/null
+++ b/arch/arm/cpu/armv8/spin_table.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ */
+
+#include <common.h>
+#include <linux/libfdt.h>
+#include <asm/spin_table.h>
+
+int spin_table_update_dt(void *fdt)
+{
+	int cpus_offset, offset;
+	const char *prop;
+	int ret;
+	unsigned long rsv_addr = (unsigned long)&spin_table_reserve_begin;
+	unsigned long rsv_size = &spin_table_reserve_end -
+						&spin_table_reserve_begin;
+
+	cpus_offset = fdt_path_offset(fdt, "/cpus");
+	if (cpus_offset < 0)
+		return -ENODEV;
+
+	for (offset = fdt_first_subnode(fdt, cpus_offset);
+	     offset >= 0;
+	     offset = fdt_next_subnode(fdt, offset)) {
+		prop = fdt_getprop(fdt, offset, "device_type", NULL);
+		if (!prop || strcmp(prop, "cpu"))
+			continue;
+
+		/*
+		 * In the first loop, we check if every CPU node specifies
+		 * spin-table.  Otherwise, just return successfully to not
+		 * disturb other methods, like psci.
+		 */
+		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
+		if (!prop || strcmp(prop, "spin-table"))
+			return 0;
+	}
+
+	for (offset = fdt_first_subnode(fdt, cpus_offset);
+	     offset >= 0;
+	     offset = fdt_next_subnode(fdt, offset)) {
+		prop = fdt_getprop(fdt, offset, "device_type", NULL);
+		if (!prop || strcmp(prop, "cpu"))
+			continue;
+
+		ret = fdt_setprop_u64(fdt, offset, "cpu-release-addr",
+				(unsigned long)&spin_table_cpu_release_addr);
+		if (ret)
+			return -ENOSPC;
+	}
+
+	ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size);
+	if (ret)
+		return -ENOSPC;
+
+	printf("   Reserved memory region for spin-table: addr=%lx size=%lx\n",
+	       rsv_addr, rsv_size);
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/spin_table_v8.S b/arch/arm/cpu/armv8/spin_table_v8.S
new file mode 100644
index 0000000..6d26843
--- /dev/null
+++ b/arch/arm/cpu/armv8/spin_table_v8.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(spin_table_secondary_jump)
+.globl spin_table_reserve_begin
+spin_table_reserve_begin:
+0:	wfe
+	ldr	x0, spin_table_cpu_release_addr
+	cbz	x0, 0b
+	br	x0
+.globl spin_table_cpu_release_addr
+	.align	3
+spin_table_cpu_release_addr:
+	.quad	0
+.globl spin_table_reserve_end
+spin_table_reserve_end:
+ENDPROC(spin_table_secondary_jump)
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
new file mode 100644
index 0000000..12a78ee
--- /dev/null
+++ b/arch/arm/cpu/armv8/start.S
@@ -0,0 +1,374 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/macro.h>
+#include <asm/armv8/mmu.h>
+
+/*************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ *************************************************************************/
+
+.globl	_start
+_start:
+#if defined(LINUX_KERNEL_IMAGE_HEADER)
+#include <asm/boot0-linux-kernel-header.h>
+#elif defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
+/*
+ * Various SoCs need something special and SoC-specific up front in
+ * order to boot, allow them to set that in their boot0.h file and then
+ * use it here.
+ */
+#include <asm/arch/boot0.h>
+#else
+	b	reset
+#endif
+
+	.align 3
+
+.globl	_TEXT_BASE
+_TEXT_BASE:
+	.quad	CONFIG_SYS_TEXT_BASE
+
+/*
+ * These are defined in the linker script.
+ */
+.globl	_end_ofs
+_end_ofs:
+	.quad	_end - _start
+
+.globl	_bss_start_ofs
+_bss_start_ofs:
+	.quad	__bss_start - _start
+
+.globl	_bss_end_ofs
+_bss_end_ofs:
+	.quad	__bss_end - _start
+
+reset:
+	/* Allow the board to save important registers */
+	b	save_boot_params
+.globl	save_boot_params_ret
+save_boot_params_ret:
+
+#if CONFIG_POSITION_INDEPENDENT
+	/*
+	 * Fix .rela.dyn relocations. This allows U-Boot to be loaded to and
+	 * executed at a different address than it was linked at.
+	 */
+pie_fixup:
+	adr	x0, _start		/* x0 <- Runtime value of _start */
+	ldr	x1, _TEXT_BASE		/* x1 <- Linked value of _start */
+	sub	x9, x0, x1		/* x9 <- Run-vs-link offset */
+	adr	x2, __rel_dyn_start	/* x2 <- Runtime &__rel_dyn_start */
+	adr	x3, __rel_dyn_end	/* x3 <- Runtime &__rel_dyn_end */
+pie_fix_loop:
+	ldp	x0, x1, [x2], #16	/* (x0, x1) <- (Link location, fixup) */
+	ldr	x4, [x2], #8		/* x4 <- addend */
+	cmp	w1, #1027		/* relative fixup? */
+	bne	pie_skip_reloc
+	/* relative fix: store addend plus offset at dest location */
+	add	x0, x0, x9
+	add	x4, x4, x9
+	str	x4, [x0]
+pie_skip_reloc:
+	cmp	x2, x3
+	b.lo	pie_fix_loop
+pie_fixup_done:
+#endif
+
+#ifdef CONFIG_SYS_RESET_SCTRL
+	bl reset_sctrl
+#endif
+
+#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
+.macro	set_vbar, regname, reg
+	msr	\regname, \reg
+.endm
+	adr	x0, vectors
+#else
+.macro	set_vbar, regname, reg
+.endm
+#endif
+	/*
+	 * Could be EL3/EL2/EL1, Initial State:
+	 * Little Endian, MMU Disabled, i/dCache Disabled
+	 */
+	switch_el x1, 3f, 2f, 1f
+3:	set_vbar vbar_el3, x0
+	mrs	x0, scr_el3
+	orr	x0, x0, #0xf			/* SCR_EL3.NS|IRQ|FIQ|EA */
+	msr	scr_el3, x0
+	msr	cptr_el3, xzr			/* Enable FP/SIMD */
+#ifdef COUNTER_FREQUENCY
+	ldr	x0, =COUNTER_FREQUENCY
+	msr	cntfrq_el0, x0			/* Initialize CNTFRQ */
+#endif
+	b	0f
+2:	set_vbar	vbar_el2, x0
+	mov	x0, #0x33ff
+	msr	cptr_el2, x0			/* Enable FP/SIMD */
+	b	0f
+1:	set_vbar	vbar_el1, x0
+	mov	x0, #3 << 20
+	msr	cpacr_el1, x0			/* Enable FP/SIMD */
+0:
+
+	/*
+	 * Enable SMPEN bit for coherency.
+	 * This register is not architectural but at the moment
+	 * this bit should be set for A53/A57/A72.
+	 */
+#ifdef CONFIG_ARMV8_SET_SMPEN
+	switch_el x1, 3f, 1f, 1f
+3:
+	mrs     x0, S3_1_c15_c2_1               /* cpuectlr_el1 */
+	orr     x0, x0, #0x40
+	msr     S3_1_c15_c2_1, x0
+1:
+#endif
+
+	/* Apply ARM core specific erratas */
+	bl	apply_core_errata
+
+	/*
+	 * Cache/BPB/TLB Invalidate
+	 * i-cache is invalidated before enabled in icache_enable()
+	 * tlb is invalidated before mmu is enabled in dcache_enable()
+	 * d-cache is invalidated before enabled in dcache_enable()
+	 */
+
+	/* Processor specific initialization */
+	bl	lowlevel_init
+
+#if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD)
+	branch_if_master x0, x1, master_cpu
+	b	spin_table_secondary_jump
+	/* never return */
+#elif defined(CONFIG_ARMV8_MULTIENTRY)
+	branch_if_master x0, x1, master_cpu
+
+	/*
+	 * Slave CPUs
+	 */
+slave_cpu:
+	wfe
+	ldr	x1, =CPU_RELEASE_ADDR
+	ldr	x0, [x1]
+	cbz	x0, slave_cpu
+	br	x0			/* branch to the given address */
+#endif /* CONFIG_ARMV8_MULTIENTRY */
+master_cpu:
+	bl	_main
+
+#ifdef CONFIG_SYS_RESET_SCTRL
+reset_sctrl:
+	switch_el x1, 3f, 2f, 1f
+3:
+	mrs	x0, sctlr_el3
+	b	0f
+2:
+	mrs	x0, sctlr_el2
+	b	0f
+1:
+	mrs	x0, sctlr_el1
+
+0:
+	ldr	x1, =0xfdfffffa
+	and	x0, x0, x1
+
+	switch_el x1, 6f, 5f, 4f
+6:
+	msr	sctlr_el3, x0
+	b	7f
+5:
+	msr	sctlr_el2, x0
+	b	7f
+4:
+	msr	sctlr_el1, x0
+
+7:
+	dsb	sy
+	isb
+	b	__asm_invalidate_tlb_all
+	ret
+#endif
+
+/*-----------------------------------------------------------------------*/
+
+WEAK(apply_core_errata)
+
+	mov	x29, lr			/* Save LR */
+	/* For now, we support Cortex-A53, Cortex-A57 specific errata */
+
+	/* Check if we are running on a Cortex-A53 core */
+	branch_if_a53_core x0, apply_a53_core_errata
+
+	/* Check if we are running on a Cortex-A57 core */
+	branch_if_a57_core x0, apply_a57_core_errata
+0:
+	mov	lr, x29			/* Restore LR */
+	ret
+
+apply_a53_core_errata:
+
+#ifdef CONFIG_ARM_ERRATA_855873
+	mrs	x0, midr_el1
+	tst	x0, #(0xf << 20)
+	b.ne	0b
+
+	mrs	x0, midr_el1
+	and	x0, x0, #0xf
+	cmp	x0, #3
+	b.lt	0b
+
+	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
+	/* Enable data cache clean as data cache clean/invalidate */
+	orr	x0, x0, #1 << 44
+	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
+#endif
+	b 0b
+
+apply_a57_core_errata:
+
+#ifdef CONFIG_ARM_ERRATA_828024
+	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
+	/* Disable non-allocate hint of w-b-n-a memory type */
+	orr	x0, x0, #1 << 49
+	/* Disable write streaming no L1-allocate threshold */
+	orr	x0, x0, #3 << 25
+	/* Disable write streaming no-allocate threshold */
+	orr	x0, x0, #3 << 27
+	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_826974
+	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
+	/* Disable speculative load execution ahead of a DMB */
+	orr	x0, x0, #1 << 59
+	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_833471
+	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
+	/* FPSCR write flush.
+	 * Note that in some cases where a flush is unnecessary this
+	    could impact performance. */
+	orr	x0, x0, #1 << 38
+	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_829520
+	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
+	/* Disable Indirect Predictor bit will prevent this erratum
+	    from occurring
+	 * Note that in some cases where a flush is unnecessary this
+	    could impact performance. */
+	orr	x0, x0, #1 << 4
+	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_833069
+	mrs	x0, S3_1_c15_c2_0	/* cpuactlr_el1 */
+	/* Disable Enable Invalidates of BTB bit */
+	and	x0, x0, #0xE
+	msr	S3_1_c15_c2_0, x0	/* cpuactlr_el1 */
+#endif
+	b 0b
+ENDPROC(apply_core_errata)
+
+/*-----------------------------------------------------------------------*/
+
+WEAK(lowlevel_init)
+	mov	x29, lr			/* Save LR */
+
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+	branch_if_slave x0, 1f
+	ldr	x0, =GICD_BASE
+	bl	gic_init_secure
+1:
+#if defined(CONFIG_GICV3)
+	ldr	x0, =GICR_BASE
+	bl	gic_init_secure_percpu
+#elif defined(CONFIG_GICV2)
+	ldr	x0, =GICD_BASE
+	ldr	x1, =GICC_BASE
+	bl	gic_init_secure_percpu
+#endif
+#endif
+
+#ifdef CONFIG_ARMV8_MULTIENTRY
+	branch_if_master x0, x1, 2f
+
+	/*
+	 * Slave should wait for master clearing spin table.
+	 * This sync prevent salves observing incorrect
+	 * value of spin table and jumping to wrong place.
+	 */
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+#ifdef CONFIG_GICV2
+	ldr	x0, =GICC_BASE
+#endif
+	bl	gic_wait_for_interrupt
+#endif
+
+	/*
+	 * All slaves will enter EL2 and optionally EL1.
+	 */
+	adr	x4, lowlevel_in_el2
+	ldr	x5, =ES_TO_AARCH64
+	bl	armv8_switch_to_el2
+
+lowlevel_in_el2:
+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
+	adr	x4, lowlevel_in_el1
+	ldr	x5, =ES_TO_AARCH64
+	bl	armv8_switch_to_el1
+
+lowlevel_in_el1:
+#endif
+
+#endif /* CONFIG_ARMV8_MULTIENTRY */
+
+2:
+	mov	lr, x29			/* Restore LR */
+	ret
+ENDPROC(lowlevel_init)
+
+WEAK(smp_kick_all_cpus)
+	/* Kick secondary cpus up by SGI 0 interrupt */
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+	ldr	x0, =GICD_BASE
+	b	gic_kick_secondary_cpus
+#endif
+	ret
+ENDPROC(smp_kick_all_cpus)
+
+/*-----------------------------------------------------------------------*/
+
+ENTRY(c_runtime_cpu_setup)
+#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
+	/* Relocate vBAR */
+	adr	x0, vectors
+	switch_el x1, 3f, 2f, 1f
+3:	msr	vbar_el3, x0
+	b	0f
+2:	msr	vbar_el2, x0
+	b	0f
+1:	msr	vbar_el1, x0
+0:
+#endif
+
+	ret
+ENDPROC(c_runtime_cpu_setup)
+
+WEAK(save_boot_params)
+	b	save_boot_params_ret	/* back to my caller */
+ENDPROC(save_boot_params)
diff --git a/arch/arm/cpu/armv8/tlb.S b/arch/arm/cpu/armv8/tlb.S
new file mode 100644
index 0000000..46a0d7d
--- /dev/null
+++ b/arch/arm/cpu/armv8/tlb.S
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/macro.h>
+
+/*
+ * void __asm_invalidate_tlb_all(void)
+ *
+ * invalidate all tlb entries.
+*/
+.pushsection .text.__asm_invalidate_tlb_all, "ax"
+ENTRY(__asm_invalidate_tlb_all)
+	switch_el x9, 3f, 2f, 1f
+3:	tlbi	alle3
+	dsb	sy
+	isb
+	b	0f
+2:	tlbi	alle2
+	dsb	sy
+	isb
+	b	0f
+1:	tlbi	vmalle1
+	dsb	sy
+	isb
+0:
+	ret
+ENDPROC(__asm_invalidate_tlb_all)
+.popsection
diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S
new file mode 100644
index 0000000..a31af4f
--- /dev/null
+++ b/arch/arm/cpu/armv8/transition.S
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/macro.h>
+
+.pushsection .text.armv8_switch_to_el2, "ax"
+ENTRY(armv8_switch_to_el2)
+	switch_el x6, 1f, 0f, 0f
+0:
+	cmp x5, #ES_TO_AARCH64
+	b.eq 2f
+	/*
+	 * When loading 32-bit kernel, it will jump
+	 * to secure firmware again, and never return.
+	 */
+	bl armv8_el2_to_aarch32
+2:
+	/*
+	 * x4 is kernel entry point or switch_to_el1
+	 * if CONFIG_ARMV8_SWITCH_TO_EL1 is defined.
+         * When running in EL2 now, jump to the
+	 * address saved in x4.
+	 */
+	br x4
+1:	armv8_switch_to_el2_m x4, x5, x6
+ENDPROC(armv8_switch_to_el2)
+.popsection
+
+.pushsection .text.armv8_switch_to_el1, "ax"
+ENTRY(armv8_switch_to_el1)
+	switch_el x6, 0f, 1f, 0f
+0:
+	/* x4 is kernel entry point. When running in EL1
+	 * now, jump to the address saved in x4.
+	 */
+	br x4
+1:	armv8_switch_to_el1_m x4, x5, x6
+ENDPROC(armv8_switch_to_el1)
+.popsection
+
+.pushsection .text.armv8_el2_to_aarch32, "ax"
+WEAK(armv8_el2_to_aarch32)
+	ret
+ENDPROC(armv8_el2_to_aarch32)
+.popsection
diff --git a/arch/arm/cpu/armv8/u-boot-spl.lds b/arch/arm/cpu/armv8/u-boot-spl.lds
new file mode 100644
index 0000000..4e48da5
--- /dev/null
+++ b/arch/arm/cpu/armv8/u-boot-spl.lds
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *	Aneesh V <aneesh@ti.com>
+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,
+		LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+	.text : {
+		. = ALIGN(8);
+		*(.__image_copy_start)
+		CPUDIR/start.o (.text*)
+		*(.text*)
+	} >.sram
+
+	.rodata : {
+		. = ALIGN(8);
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+	} >.sram
+
+	.data : {
+		. = ALIGN(8);
+		*(.data*)
+	} >.sram
+
+	.u_boot_list : {
+		. = ALIGN(8);
+		KEEP(*(SORT(.u_boot_list*)));
+	} >.sram
+
+	.image_copy_end : {
+		. = ALIGN(8);
+		*(.__image_copy_end)
+	} >.sram
+
+	.end : {
+		. = ALIGN(8);
+		*(.__end)
+	} >.sram
+
+	_image_binary_end = .;
+
+	.bss_start (NOLOAD) : {
+		. = ALIGN(8);
+		KEEP(*(.__bss_start));
+	} >.sdram
+
+	.bss (NOLOAD) : {
+		*(.bss*)
+		 . = ALIGN(8);
+	} >.sdram
+
+	.bss_end (NOLOAD) : {
+		KEEP(*(.__bss_end));
+	} >.sdram
+
+	/DISCARD/ : { *(.dynsym) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+}
diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds
new file mode 100644
index 0000000..53de80f
--- /dev/null
+++ b/arch/arm/cpu/armv8/u-boot.lds
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013
+ * David Feng <fenghua@phytium.com.cn>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+#include <config.h>
+#include <asm/psci.h>
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+#ifdef CONFIG_ARMV8_SECURE_BASE
+	/DISCARD/ : { *(.rela._secure*) }
+#endif
+	. = 0x00000000;
+
+	. = ALIGN(8);
+	.text :
+	{
+		*(.__image_copy_start)
+		CPUDIR/start.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.efi_runtime : {
+                __efi_runtime_start = .;
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+                __efi_runtime_stop = .;
+	}
+
+	.text_rest :
+	{
+		*(.text*)
+	}
+
+#ifdef CONFIG_ARMV8_PSCI
+	.__secure_start :
+#ifndef CONFIG_ARMV8_SECURE_BASE
+		ALIGN(CONSTANT(COMMONPAGESIZE))
+#endif
+	{
+		KEEP(*(.__secure_start))
+	}
+
+#ifndef CONFIG_ARMV8_SECURE_BASE
+#define CONFIG_ARMV8_SECURE_BASE
+#define __ARMV8_PSCI_STACK_IN_RAM
+#endif
+	.secure_text CONFIG_ARMV8_SECURE_BASE :
+		AT(ADDR(.__secure_start) + SIZEOF(.__secure_start))
+	{
+		*(._secure.text)
+	}
+
+	.secure_data : AT(LOADADDR(.secure_text) + SIZEOF(.secure_text))
+	{
+		*(._secure.data)
+	}
+
+	.secure_stack ALIGN(ADDR(.secure_data) + SIZEOF(.secure_data),
+			    CONSTANT(COMMONPAGESIZE)) (NOLOAD) :
+#ifdef __ARMV8_PSCI_STACK_IN_RAM
+		AT(ADDR(.secure_stack))
+#else
+		AT(LOADADDR(.secure_data) + SIZEOF(.secure_data))
+#endif
+	{
+		KEEP(*(.__secure_stack_start))
+
+		. = . + CONFIG_ARMV8_PSCI_NR_CPUS * ARM_PSCI_STACK_SIZE;
+
+		. = ALIGN(CONSTANT(COMMONPAGESIZE));
+
+		KEEP(*(.__secure_stack_end))
+	}
+
+#ifndef __ARMV8_PSCI_STACK_IN_RAM
+	. = LOADADDR(.secure_stack);
+#endif
+
+	.__secure_end : AT(ADDR(.__secure_end)) {
+		KEEP(*(.__secure_end))
+		LONG(0x1d1071c);	/* Must output something to reset LMA */
+	}
+#endif
+
+	. = ALIGN(8);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(8);
+	.data : {
+		*(.data*)
+	}
+
+	. = ALIGN(8);
+
+	. = .;
+
+	. = ALIGN(8);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+
+	. = ALIGN(8);
+
+	.efi_runtime_rel : {
+                __efi_runtime_rel_start = .;
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
+                __efi_runtime_rel_stop = .;
+	}
+
+	. = ALIGN(8);
+
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
+	}
+
+	. = ALIGN(8);
+
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rela.dyn : {
+		*(.rela*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
+	}
+
+	_end = .;
+
+	. = ALIGN(8);
+
+	.bss_start : {
+		KEEP(*(.__bss_start));
+	}
+
+	.bss : {
+		*(.bss*)
+		 . = ALIGN(8);
+	}
+
+	.bss_end : {
+		KEEP(*(.__bss_end));
+	}
+
+	/DISCARD/ : { *(.dynsym) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+
+#ifdef CONFIG_LINUX_KERNEL_IMAGE_HEADER
+#include "linux-kernel-image-header-vars.h"
+#endif
+}
diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig
new file mode 100644
index 0000000..91b017a
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/Kconfig
@@ -0,0 +1,157 @@
+if ARCH_ZYNQMP
+
+config SPL_FAT_SUPPORT
+	default y
+
+config SPL_LIBCOMMON_SUPPORT
+	default y
+
+config SPL_LIBDISK_SUPPORT
+	default y
+
+config SPL_LIBGENERIC_SUPPORT
+	default y
+
+config SPL_MMC_SUPPORT
+	default y if MMC_SDHCI_ZYNQ
+
+config SPL_SERIAL_SUPPORT
+	default y
+
+config SPL_SPI_FLASH_SUPPORT
+	default y if ZYNQ_QSPI
+
+config SPL_SPI_SUPPORT
+	default y if ZYNQ_QSPI
+
+config SYS_BOARD
+	default "zynqmp"
+
+config SYS_VENDOR
+	string "Vendor name"
+	default "xilinx"
+
+config SYS_SOC
+	default "zynqmp"
+
+config SYS_CONFIG_NAME
+	string "Board configuration name"
+	default "xilinx_zynqmp"
+	help
+	  This option contains information about board configuration name.
+	  Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
+	  will be used for board configuration.
+
+config SYS_MEM_RSVD_FOR_MMU
+	bool "Reserve memory for MMU Table"
+	help
+	  If defined this option is used to setup different space for
+	  MMU table than the one which will be allocated during
+	  relocation.
+
+config BOOT_INIT_FILE
+	string "boot.bin init register filename"
+	depends on SPL
+	default ""
+	help
+	  Add register writes to boot.bin format (max 256 pairs).
+	  Expect a table of register-value pairs, e.g. "0x12345678 0x4321"
+
+config PMUFW_INIT_FILE
+	string "PMU firmware"
+	depends on SPL
+	default ""
+	help
+	  Include external PMUFW (Platform Management Unit FirmWare) to
+	  a Xilinx bootable image (boot.bin).
+
+config ZYNQMP_USB
+	bool "Configure ZynqMP USB"
+
+config ZYNQMP_NO_DDR
+	bool "Disable DDR MMU mapping"
+	help
+	  This option configures MMU with no DDR to avoid speculative
+	  access to DDR memory where DDR is not present.
+
+config SYS_MALLOC_F_LEN
+	default 0x600
+
+config DEFINE_TCM_OCM_MMAP
+	bool "Define TCM and OCM memory in MMU Table"
+	default y if MP
+	help
+	  This option if enabled defines the TCM and OCM memory and its
+	  memory attributes in MMU table entry.
+
+config ZYNQMP_PSU_INIT_ENABLED
+	bool "Include psu_init"
+	help
+	  Include psu_init to full u-boot. SPL include psu_init by default.
+
+config SPL_ZYNQMP_ALT_BOOTMODE_ENABLED
+	bool "Overwrite SPL bootmode"
+	depends on SPL
+	help
+	  Overwrite bootmode selected via boot mode pins to tell SPL what should
+	  be the next boot device.
+
+config ZYNQ_SDHCI_MAX_FREQ
+	default 200000000
+
+config SPL_ZYNQMP_ALT_BOOTMODE
+	hex
+	default 0x0 if JTAG_MODE
+	default 0x1 if QSPI_MODE_24BIT
+	default 0x2 if QSPI_MODE_32BIT
+	default 0x3 if SD_MODE
+	default 0x4 if NAND_MODE
+	default 0x5 if SD_MODE1
+	default 0x6 if EMMC_MODE
+	default 0x7 if USB_MODE
+	default 0xa if SW_USBHOST_MODE
+	default 0xb if SW_SATA_MODE
+	default 0xe if SD1_LSHFT_MODE
+
+choice
+	prompt "Boot mode"
+	depends on SPL_ZYNQMP_ALT_BOOTMODE_ENABLED
+	default JTAG_MODE
+
+config JTAG_MODE
+	bool "JTAG_MODE"
+
+config QSPI_MODE_24BIT
+	bool "QSPI_MODE_24BIT"
+
+config QSPI_MODE_32BIT
+	bool "QSPI_MODE_32BIT"
+
+config SD_MODE
+	bool "SD_MODE"
+
+config SD_MODE1
+	bool "SD_MODE1"
+
+config NAND_MODE
+	bool "NAND_MODE"
+
+config EMMC_MODE
+	bool "EMMC_MODE"
+
+config USB_MODE
+	bool "USB"
+
+config SW_USBHOST_MODE
+	bool "SW USBHOST_MODE"
+
+config SW_SATA_MODE
+	bool "SW SATA_MODE"
+
+config SD1_LSHFT_MODE
+	bool "SD1_LSHFT_MODE"
+
+endchoice
+
+endif
+
diff --git a/arch/arm/cpu/armv8/zynqmp/Makefile b/arch/arm/cpu/armv8/zynqmp/Makefile
new file mode 100644
index 0000000..8a3b074
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2014 - 2015 Xilinx, Inc.
+# Michal Simek <michal.simek@xilinx.com>
+
+obj-y	+= clk.o
+obj-y	+= cpu.o
+obj-$(CONFIG_MP)	+= mp.o
+obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o
+obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED)	+= psu_spl_init.o
diff --git a/arch/arm/cpu/armv8/zynqmp/clk.c b/arch/arm/cpu/armv8/zynqmp/clk.c
new file mode 100644
index 0000000..0593b63
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/clk.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <common.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned long zynqmp_get_system_timer_freq(void)
+{
+	u32 ver = zynqmp_get_silicon_version();
+
+	switch (ver) {
+	case ZYNQMP_CSU_VERSION_QEMU:
+		return 50000000;
+	}
+
+	return 100000000;
+}
+
+#ifdef CONFIG_CLOCKS
+/**
+ * set_cpu_clk_info() - Initialize clock framework
+ * Always returns zero.
+ *
+ * This function is called from common code after relocation and sets up the
+ * clock framework. The framework must not be used before this function had been
+ * called.
+ */
+int set_cpu_clk_info(void)
+{
+	gd->cpu_clk = get_tbclk();
+
+	gd->bd->bi_arm_freq = gd->cpu_clk / 1000000;
+
+	gd->bd->bi_dsp_freq = 0;
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c
new file mode 100644
index 0000000..4ee8e3f
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/armv8/mmu.h>
+#include <asm/io.h>
+
+#define ZYNQ_SILICON_VER_MASK	0xF000
+#define ZYNQ_SILICON_VER_SHIFT	12
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Number of filled static entries and also the first empty
+ * slot in zynqmp_mem_map.
+ */
+#define ZYNQMP_MEM_MAP_USED	4
+
+#if !defined(CONFIG_ZYNQMP_NO_DDR)
+#define DRAM_BANKS CONFIG_NR_DRAM_BANKS
+#else
+#define DRAM_BANKS 0
+#endif
+
+#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
+#define TCM_MAP 1
+#else
+#define TCM_MAP 0
+#endif
+
+/* +1 is end of list which needs to be empty */
+#define ZYNQMP_MEM_MAP_MAX (ZYNQMP_MEM_MAP_USED + DRAM_BANKS + TCM_MAP + 1)
+
+static struct mm_region zynqmp_mem_map[ZYNQMP_MEM_MAP_MAX] = {
+	{
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
+		.size = 0x70000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.virt = 0xf8000000UL,
+		.phys = 0xf8000000UL,
+		.size = 0x07e00000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.virt = 0x400000000UL,
+		.phys = 0x400000000UL,
+		.size = 0x400000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.virt = 0x1000000000UL,
+		.phys = 0x1000000000UL,
+		.size = 0xf000000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}
+};
+
+void mem_map_fill(void)
+{
+	int banks = ZYNQMP_MEM_MAP_USED;
+
+#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
+	zynqmp_mem_map[banks].virt = 0xffe00000UL;
+	zynqmp_mem_map[banks].phys = 0xffe00000UL;
+	zynqmp_mem_map[banks].size = 0x00200000UL;
+	zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+				      PTE_BLOCK_INNER_SHARE;
+	banks = banks + 1;
+#endif
+
+#if !defined(CONFIG_ZYNQMP_NO_DDR)
+	for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		/* Zero size means no more DDR that's this is end */
+		if (!gd->bd->bi_dram[i].size)
+			break;
+
+		zynqmp_mem_map[banks].virt = gd->bd->bi_dram[i].start;
+		zynqmp_mem_map[banks].phys = gd->bd->bi_dram[i].start;
+		zynqmp_mem_map[banks].size = gd->bd->bi_dram[i].size;
+		zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+					      PTE_BLOCK_INNER_SHARE;
+		banks = banks + 1;
+	}
+#endif
+}
+
+struct mm_region *mem_map = zynqmp_mem_map;
+
+u64 get_page_table_size(void)
+{
+	return 0x14000;
+}
+
+#if defined(CONFIG_SYS_MEM_RSVD_FOR_MMU) || defined(CONFIG_DEFINE_TCM_OCM_MMAP)
+void tcm_init(u8 mode)
+{
+	puts("WARNING: Initializing TCM overwrites TCM content\n");
+	initialize_tcm(mode);
+	memset((void *)ZYNQMP_TCM_BASE_ADDR, 0, ZYNQMP_TCM_SIZE);
+}
+#endif
+
+#ifdef CONFIG_SYS_MEM_RSVD_FOR_MMU
+int reserve_mmu(void)
+{
+	tcm_init(TCM_LOCK);
+	gd->arch.tlb_size = PGTABLE_SIZE;
+	gd->arch.tlb_addr = ZYNQMP_TCM_BASE_ADDR;
+
+	return 0;
+}
+#endif
+
+static unsigned int zynqmp_get_silicon_version_secure(void)
+{
+	u32 ver;
+
+	ver = readl(&csu_base->version);
+	ver &= ZYNQMP_SILICON_VER_MASK;
+	ver >>= ZYNQMP_SILICON_VER_SHIFT;
+
+	return ver;
+}
+
+unsigned int zynqmp_get_silicon_version(void)
+{
+	if (current_el() == 3)
+		return zynqmp_get_silicon_version_secure();
+
+	gd->cpu_clk = get_tbclk();
+
+	switch (gd->cpu_clk) {
+	case 50000000:
+		return ZYNQMP_CSU_VERSION_QEMU;
+	}
+
+	return ZYNQMP_CSU_VERSION_SILICON;
+}
+
+#define ZYNQMP_MMIO_READ	0xC2000014
+#define ZYNQMP_MMIO_WRITE	0xC2000013
+
+int __maybe_unused invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2,
+			      u32 arg3, u32 *ret_payload)
+{
+	/*
+	 * Added SIP service call Function Identifier
+	 * Make sure to stay in x0 register
+	 */
+	struct pt_regs regs;
+
+	regs.regs[0] = pm_api_id;
+	regs.regs[1] = ((u64)arg1 << 32) | arg0;
+	regs.regs[2] = ((u64)arg3 << 32) | arg2;
+
+	smc_call(&regs);
+
+	if (ret_payload != NULL) {
+		ret_payload[0] = (u32)regs.regs[0];
+		ret_payload[1] = upper_32_bits(regs.regs[0]);
+		ret_payload[2] = (u32)regs.regs[1];
+		ret_payload[3] = upper_32_bits(regs.regs[1]);
+		ret_payload[4] = (u32)regs.regs[2];
+	}
+
+	return regs.regs[0];
+}
+
+#if defined(CONFIG_CLK_ZYNQMP)
+unsigned int zynqmp_pmufw_version(void)
+{
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	static u32 pm_api_version = ZYNQMP_PM_VERSION_INVALID;
+
+	/*
+	 * Get PMU version only once and later
+	 * just return stored values instead of
+	 * asking PMUFW again.
+	 */
+	if (pm_api_version == ZYNQMP_PM_VERSION_INVALID) {
+		ret = invoke_smc(ZYNQMP_SIP_SVC_GET_API_VERSION, 0, 0, 0, 0,
+				 ret_payload);
+		pm_api_version = ret_payload[1];
+
+		if (ret)
+			panic("PMUFW is not found - Please load it!\n");
+	}
+
+	return pm_api_version;
+}
+#endif
+
+static int zynqmp_mmio_rawwrite(const u32 address,
+		      const u32 mask,
+		      const u32 value)
+{
+	u32 data;
+	u32 value_local = value;
+	int ret;
+
+	ret = zynqmp_mmio_read(address, &data);
+	if (ret)
+		return ret;
+
+	data &= ~mask;
+	value_local &= mask;
+	value_local |= data;
+	writel(value_local, (ulong)address);
+	return 0;
+}
+
+static int zynqmp_mmio_rawread(const u32 address, u32 *value)
+{
+	*value = readl((ulong)address);
+	return 0;
+}
+
+int zynqmp_mmio_write(const u32 address,
+		      const u32 mask,
+		      const u32 value)
+{
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3)
+		return zynqmp_mmio_rawwrite(address, mask, value);
+	else
+		return invoke_smc(ZYNQMP_MMIO_WRITE, address, mask,
+				  value, 0, NULL);
+
+	return -EINVAL;
+}
+
+int zynqmp_mmio_read(const u32 address, u32 *value)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	u32 ret;
+
+	if (!value)
+		return -EINVAL;
+
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		ret = zynqmp_mmio_rawread(address, value);
+	} else {
+		ret = invoke_smc(ZYNQMP_MMIO_READ, address, 0, 0,
+				 0, ret_payload);
+		*value = ret_payload[1];
+	}
+
+	return ret;
+}
diff --git a/arch/arm/cpu/armv8/zynqmp/handoff.c b/arch/arm/cpu/armv8/zynqmp/handoff.c
new file mode 100644
index 0000000..f71ff7b
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/handoff.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 - 2017 Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+
+/*
+ * atfhandoffparams
+ * Parameter	bitfield	encoding
+ * -----------------------------------------------------------------------------
+ * Exec State	0	0 -> Aarch64, 1-> Aarch32
+ * endianness	1	0 -> LE, 1 -> BE
+ * secure (TZ)	2	0 -> Non secure, 1 -> secure
+ * EL		3:4	00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3
+ * CPU#		5:6	00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3
+ */
+
+#define FSBL_FLAGS_ESTATE_SHIFT		0
+#define FSBL_FLAGS_ESTATE_MASK		(1 << FSBL_FLAGS_ESTATE_SHIFT)
+#define FSBL_FLAGS_ESTATE_A64		0
+#define FSBL_FLAGS_ESTATE_A32		1
+
+#define FSBL_FLAGS_ENDIAN_SHIFT		1
+#define FSBL_FLAGS_ENDIAN_MASK		(1 << FSBL_FLAGS_ENDIAN_SHIFT)
+#define FSBL_FLAGS_ENDIAN_LE		0
+#define FSBL_FLAGS_ENDIAN_BE		1
+
+#define FSBL_FLAGS_TZ_SHIFT		2
+#define FSBL_FLAGS_TZ_MASK		(1 << FSBL_FLAGS_TZ_SHIFT)
+#define FSBL_FLAGS_NON_SECURE		0
+#define FSBL_FLAGS_SECURE		1
+
+#define FSBL_FLAGS_EL_SHIFT		3
+#define FSBL_FLAGS_EL_MASK		(3 << FSBL_FLAGS_EL_SHIFT)
+#define FSBL_FLAGS_EL0			0
+#define FSBL_FLAGS_EL1			1
+#define FSBL_FLAGS_EL2			2
+#define FSBL_FLAGS_EL3			3
+
+#define FSBL_FLAGS_CPU_SHIFT		5
+#define FSBL_FLAGS_CPU_MASK		(3 << FSBL_FLAGS_CPU_SHIFT)
+#define FSBL_FLAGS_A53_0		0
+#define FSBL_FLAGS_A53_1		1
+#define FSBL_FLAGS_A53_2		2
+#define FSBL_FLAGS_A53_3		3
+
+#define FSBL_MAX_PARTITIONS		8
+
+/* Structure corresponding to each partition entry */
+struct xfsbl_partition {
+	uint64_t entry_point;
+	uint64_t flags;
+};
+
+/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */
+struct xfsbl_atf_handoff_params {
+	uint8_t magic[4];
+	uint32_t num_entries;
+	struct xfsbl_partition partition[FSBL_MAX_PARTITIONS];
+};
+
+#ifdef CONFIG_SPL_OS_BOOT
+void handoff_setup(void)
+{
+	struct xfsbl_atf_handoff_params *atfhandoffparams;
+
+	atfhandoffparams = (void *)CONFIG_SPL_TEXT_BASE;
+	atfhandoffparams->magic[0] = 'X';
+	atfhandoffparams->magic[1] = 'L';
+	atfhandoffparams->magic[2] = 'N';
+	atfhandoffparams->magic[3] = 'X';
+
+	atfhandoffparams->num_entries = 1;
+	atfhandoffparams->partition[0].entry_point = CONFIG_SYS_TEXT_BASE;
+	atfhandoffparams->partition[0].flags = FSBL_FLAGS_EL2 <<
+					       FSBL_FLAGS_EL_SHIFT;
+
+	writel(CONFIG_SPL_TEXT_BASE, &pmu_base->gen_storage6);
+}
+#endif
diff --git a/arch/arm/cpu/armv8/zynqmp/mp.c b/arch/arm/cpu/armv8/zynqmp/mp.c
new file mode 100644
index 0000000..2a71870
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/mp.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+
+#define LOCK		0
+#define SPLIT		1
+
+#define HALT		0
+#define RELEASE		1
+
+#define ZYNQMP_BOOTADDR_HIGH_MASK		0xFFFFFFFF
+#define ZYNQMP_R5_HIVEC_ADDR			0xFFFF0000
+#define ZYNQMP_R5_LOVEC_ADDR			0x0
+#define ZYNQMP_RPU_CFG_CPU_HALT_MASK		0x01
+#define ZYNQMP_RPU_CFG_HIVEC_MASK		0x04
+#define ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK	0x08
+#define ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK	0x40
+#define ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK	0x10
+
+#define ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK	0x04
+#define ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK	0x01
+#define ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK	0x02
+#define ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK	0x1000000
+
+#define ZYNQMP_TCM_START_ADDRESS		0xFFE00000
+#define ZYNQMP_TCM_BOTH_SIZE			0x40000
+
+#define ZYNQMP_CORE_APU0	0
+#define ZYNQMP_CORE_APU3	3
+
+#define ZYNQMP_MAX_CORES	6
+
+int is_core_valid(unsigned int core)
+{
+	if (core < ZYNQMP_MAX_CORES)
+		return 1;
+
+	return 0;
+}
+
+int cpu_reset(u32 nr)
+{
+	puts("Feature is not implemented.\n");
+	return 0;
+}
+
+static void set_r5_halt_mode(u8 halt, u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&rpu_base->rpu0_cfg);
+	if (halt == HALT)
+		tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+	else
+		tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+	writel(tmp, &rpu_base->rpu0_cfg);
+
+	if (mode == LOCK) {
+		tmp = readl(&rpu_base->rpu1_cfg);
+		if (halt == HALT)
+			tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+		else
+			tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+		writel(tmp, &rpu_base->rpu1_cfg);
+	}
+}
+
+static void set_r5_tcm_mode(u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&rpu_base->rpu_glbl_ctrl);
+	if (mode == LOCK) {
+		tmp &= ~ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK;
+		tmp |= ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK |
+		       ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK;
+	} else {
+		tmp |= ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK;
+		tmp &= ~(ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK |
+		       ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK);
+	}
+
+	writel(tmp, &rpu_base->rpu_glbl_ctrl);
+}
+
+static void set_r5_reset(u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&crlapb_base->rst_lpd_top);
+	tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+	       ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+
+	if (mode == LOCK)
+		tmp |= ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+
+	writel(tmp, &crlapb_base->rst_lpd_top);
+}
+
+static void release_r5_reset(u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&crlapb_base->rst_lpd_top);
+	tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+	       ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+
+	if (mode == LOCK)
+		tmp &= ~ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+
+	writel(tmp, &crlapb_base->rst_lpd_top);
+}
+
+static void enable_clock_r5(void)
+{
+	u32 tmp;
+
+	tmp = readl(&crlapb_base->cpu_r5_ctrl);
+	tmp |= ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK;
+	writel(tmp, &crlapb_base->cpu_r5_ctrl);
+
+	/* Give some delay for clock
+	 * to propagate */
+	udelay(0x500);
+}
+
+int cpu_disable(u32 nr)
+{
+	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+		u32 val = readl(&crfapb_base->rst_fpd_apu);
+		val |= 1 << nr;
+		writel(val, &crfapb_base->rst_fpd_apu);
+	} else {
+		set_r5_reset(LOCK);
+	}
+
+	return 0;
+}
+
+int cpu_status(u32 nr)
+{
+	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+		u32 addr_low = readl(((u8 *)&apu_base->rvbar_addr0_l) + nr * 8);
+		u32 addr_high = readl(((u8 *)&apu_base->rvbar_addr0_h) +
+				      nr * 8);
+		u32 val = readl(&crfapb_base->rst_fpd_apu);
+		val &= 1 << nr;
+		printf("APU CPU%d %s - starting address HI: %x, LOW: %x\n",
+		       nr, val ? "OFF" : "ON" , addr_high, addr_low);
+	} else {
+		u32 val = readl(&crlapb_base->rst_lpd_top);
+		val &= 1 << (nr - 4);
+		printf("RPU CPU%d %s\n", nr - 4, val ? "OFF" : "ON");
+	}
+
+	return 0;
+}
+
+static void set_r5_start(u8 high)
+{
+	u32 tmp;
+
+	tmp = readl(&rpu_base->rpu0_cfg);
+	if (high)
+		tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK;
+	else
+		tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK;
+	writel(tmp, &rpu_base->rpu0_cfg);
+
+	tmp = readl(&rpu_base->rpu1_cfg);
+	if (high)
+		tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK;
+	else
+		tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK;
+	writel(tmp, &rpu_base->rpu1_cfg);
+}
+
+static void write_tcm_boot_trampoline(u32 boot_addr)
+{
+	if (boot_addr) {
+		/*
+		 * Boot trampoline is simple ASM code below.
+		 *
+		 *		b over;
+		 *	label:
+		 *	.word	0
+		 *	over:	ldr	r0, =label
+		 *		ldr	r1, [r0]
+		 *		bx	r1
+		 */
+		debug("Write boot trampoline for %x\n", boot_addr);
+		writel(0xea000000, ZYNQMP_TCM_START_ADDRESS);
+		writel(boot_addr, ZYNQMP_TCM_START_ADDRESS + 0x4);
+		writel(0xe59f0004, ZYNQMP_TCM_START_ADDRESS + 0x8);
+		writel(0xe5901000, ZYNQMP_TCM_START_ADDRESS + 0xc);
+		writel(0xe12fff11, ZYNQMP_TCM_START_ADDRESS + 0x10);
+		writel(0x00000004, ZYNQMP_TCM_START_ADDRESS + 0x14); // address for
+	}
+}
+
+void initialize_tcm(bool mode)
+{
+	if (!mode) {
+		set_r5_tcm_mode(LOCK);
+		set_r5_halt_mode(HALT, LOCK);
+		enable_clock_r5();
+		release_r5_reset(LOCK);
+	} else {
+		set_r5_tcm_mode(SPLIT);
+		set_r5_halt_mode(HALT, SPLIT);
+		enable_clock_r5();
+		release_r5_reset(SPLIT);
+	}
+}
+
+int cpu_release(u32 nr, int argc, char * const argv[])
+{
+	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+		u64 boot_addr = simple_strtoull(argv[0], NULL, 16);
+		/* HIGH */
+		writel((u32)(boot_addr >> 32),
+		       ((u8 *)&apu_base->rvbar_addr0_h) + nr * 8);
+		/* LOW */
+		writel((u32)(boot_addr & ZYNQMP_BOOTADDR_HIGH_MASK),
+		       ((u8 *)&apu_base->rvbar_addr0_l) + nr * 8);
+
+		u32 val = readl(&crfapb_base->rst_fpd_apu);
+		val &= ~(1 << nr);
+		writel(val, &crfapb_base->rst_fpd_apu);
+	} else {
+		if (argc != 2) {
+			printf("Invalid number of arguments to release.\n");
+			printf("<addr> <mode>-Start addr lockstep or split\n");
+			return 1;
+		}
+
+		u32 boot_addr = simple_strtoul(argv[0], NULL, 16);
+		u32 boot_addr_uniq = 0;
+		if (!(boot_addr == ZYNQMP_R5_LOVEC_ADDR ||
+		      boot_addr == ZYNQMP_R5_HIVEC_ADDR)) {
+			printf("Using TCM jump trampoline for address 0x%x\n",
+			       boot_addr);
+			/* Save boot address for later usage */
+			boot_addr_uniq = boot_addr;
+			/*
+			 * R5 needs to start from LOVEC at TCM
+			 * OCM will be probably occupied by ATF
+			 */
+			boot_addr = ZYNQMP_R5_LOVEC_ADDR;
+		}
+
+		/*
+		 * Since we don't know where the user may have loaded the image
+		 * for an R5 we have to flush all the data cache to ensure
+		 * the R5 sees it.
+		 */
+		flush_dcache_all();
+
+		if (!strncmp(argv[1], "lockstep", 8)) {
+			printf("R5 lockstep mode\n");
+			set_r5_reset(LOCK);
+			set_r5_tcm_mode(LOCK);
+			set_r5_halt_mode(HALT, LOCK);
+			set_r5_start(boot_addr);
+			enable_clock_r5();
+			release_r5_reset(LOCK);
+			dcache_disable();
+			write_tcm_boot_trampoline(boot_addr_uniq);
+			dcache_enable();
+			set_r5_halt_mode(RELEASE, LOCK);
+		} else if (!strncmp(argv[1], "split", 5)) {
+			printf("R5 split mode\n");
+			set_r5_reset(SPLIT);
+			set_r5_tcm_mode(SPLIT);
+			set_r5_halt_mode(HALT, SPLIT);
+			set_r5_start(boot_addr);
+			enable_clock_r5();
+			release_r5_reset(SPLIT);
+			dcache_disable();
+			write_tcm_boot_trampoline(boot_addr_uniq);
+			dcache_enable();
+			set_r5_halt_mode(RELEASE, SPLIT);
+		} else {
+			printf("Unsupported mode\n");
+			return 1;
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/zynqmp/psu_spl_init.c b/arch/arm/cpu/armv8/zynqmp/psu_spl_init.c
new file mode 100644
index 0000000..b357de3
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/psu_spl_init.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/psu_init_gpl.h>
+
+#define PSU_MASK_POLL_TIME 1100000
+
+int __maybe_unused mask_pollonvalue(unsigned long add, u32 mask, u32 value)
+{
+	int i = 0;
+
+	while ((__raw_readl(add) & mask) != value) {
+		if (i == PSU_MASK_POLL_TIME)
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
+__weak int mask_poll(u32 add, u32 mask)
+{
+	int i = 0;
+	unsigned long addr = add;
+
+	while (!(__raw_readl(addr) & mask)) {
+		if (i == PSU_MASK_POLL_TIME)
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
+__weak u32 mask_read(u32 add, u32 mask)
+{
+	unsigned long addr = add;
+
+	return __raw_readl(addr) & mask;
+}
+
+__weak void mask_delay(u32 delay)
+{
+	udelay(delay);
+}
+
+__weak void psu_mask_write(unsigned long offset, unsigned long mask,
+			   unsigned long val)
+{
+	unsigned long regval = 0;
+
+	regval = readl(offset);
+	regval &= ~(mask);
+	regval |= (val & mask);
+	writel(regval, offset);
+}
+
+__weak void prog_reg(unsigned long addr, unsigned long mask,
+		     unsigned long shift, unsigned long value)
+{
+	int rdata = 0;
+
+	rdata = readl(addr);
+	rdata = rdata & (~mask);
+	rdata = rdata | (value << shift);
+	writel(rdata, addr);
+}
+
+__weak int psu_init(void)
+{
+	/*
+	 * This function is overridden by the one in
+	 * board/xilinx/zynqmp/(platform)/psu_init_gpl.c, if it exists.
+	 */
+	return -1;
+}
diff --git a/arch/arm/cpu/armv8/zynqmp/spl.c b/arch/arm/cpu/armv8/zynqmp/spl.c
new file mode 100644
index 0000000..01f31d0
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/spl.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015 - 2016 Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <spl.h>
+
+#include <asm/io.h>
+#include <asm/spl.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+
+void board_init_f(ulong dummy)
+{
+	board_early_init_f();
+	board_early_init_r();
+
+#ifdef CONFIG_DEBUG_UART
+	/* Uart debug for sure */
+	debug_uart_init();
+	puts("Debug uart enabled\n"); /* or printch() */
+#endif
+	/* Delay is required for clocks to be propagated */
+	udelay(1000000);
+
+	/* Clear the BSS */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* No need to call timer init - it is empty for ZynqMP */
+	board_init_r(NULL, 0);
+}
+
+static void ps_mode_reset(ulong mode)
+{
+	writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT,
+	       &crlapb_base->boot_pin_ctrl);
+	udelay(5);
+	writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT |
+	       mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT,
+	       &crlapb_base->boot_pin_ctrl);
+}
+
+/*
+ * Set default PS_MODE1 which is used for USB ULPI phy reset
+ * Also other resets can be connected to this certain pin
+ */
+#ifndef MODE_RESET
+# define MODE_RESET	PS_MODE1
+#endif
+
+#ifdef CONFIG_SPL_BOARD_INIT
+void spl_board_init(void)
+{
+	preloader_console_init();
+	ps_mode_reset(MODE_RESET);
+	board_init();
+}
+#endif
+
+u32 spl_boot_device(void)
+{
+	u32 reg = 0;
+	u8 bootmode;
+
+#if defined(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE_ENABLED)
+	/* Change default boot mode at run-time */
+	writel(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE << BOOT_MODE_ALT_SHIFT,
+	       &crlapb_base->boot_mode);
+#endif
+
+	reg = readl(&crlapb_base->boot_mode);
+	if (reg >> BOOT_MODE_ALT_SHIFT)
+		reg >>= BOOT_MODE_ALT_SHIFT;
+
+	bootmode = reg & BOOT_MODES_MASK;
+
+	switch (bootmode) {
+	case JTAG_MODE:
+		return BOOT_DEVICE_RAM;
+#ifdef CONFIG_SPL_MMC_SUPPORT
+	case SD_MODE1:
+	case SD1_LSHFT_MODE: /* not working on silicon v1 */
+/* if both controllers enabled, then these two are the second controller */
+#if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1)
+		return BOOT_DEVICE_MMC2;
+/* else, fall through, the one SDHCI controller that is enabled is number 1 */
+#endif
+	case SD_MODE:
+	case EMMC_MODE:
+		return BOOT_DEVICE_MMC1;
+#endif
+#ifdef CONFIG_SPL_DFU_SUPPORT
+	case USB_MODE:
+		return BOOT_DEVICE_DFU;
+#endif
+#ifdef CONFIG_SPL_SATA_SUPPORT
+	case SW_SATA_MODE:
+		return BOOT_DEVICE_SATA;
+#endif
+#ifdef CONFIG_SPL_SPI_SUPPORT
+	case QSPI_MODE_24BIT:
+	case QSPI_MODE_32BIT:
+		return BOOT_DEVICE_SPI;
+#endif
+	default:
+		printf("Invalid Boot Mode:0x%x\n", bootmode);
+		break;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+int spl_start_uboot(void)
+{
+	handoff_setup();
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/cpu/pxa/Makefile b/arch/arm/cpu/pxa/Makefile
new file mode 100644
index 0000000..263d9dd
--- /dev/null
+++ b/arch/arm/cpu/pxa/Makefile
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	= start.o
+
+obj-$(CONFIG_CPU_PXA25X)	+= pxa2xx.o
+obj-$(CONFIG_CPU_PXA27X)	+= pxa2xx.o
+
+obj-y	+= cpuinfo.o
+obj-y	+= timer.o
+obj-y	+= usb.o
+obj-y	+= relocate.o
+obj-y	+= cache.o
diff --git a/arch/arm/cpu/pxa/cache.c b/arch/arm/cpu/pxa/cache.c
new file mode 100644
index 0000000..8b932b1
--- /dev/null
+++ b/arch/arm/cpu/pxa/cache.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Vasily Khoruzhick <anarsoul@gmail.com>
+ */
+
+#include <linux/types.h>
+#include <common.h>
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void invalidate_dcache_all(void)
+{
+	/* Flush/Invalidate I cache */
+	asm volatile("mcr p15, 0, %0, c7, c5, 0\n" : : "r"(0));
+	/* Flush/Invalidate D cache */
+	asm volatile("mcr p15, 0, %0, c7, c6, 0\n" : : "r"(0));
+}
+
+void flush_dcache_all(void)
+{
+	return invalidate_dcache_all();
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+	start &= ~(CONFIG_SYS_CACHELINE_SIZE - 1);
+	stop &= ~(CONFIG_SYS_CACHELINE_SIZE - 1);
+
+	while (start <= stop) {
+		asm volatile("mcr p15, 0, %0, c7, c6, 1\n" : : "r"(start));
+		start += CONFIG_SYS_CACHELINE_SIZE;
+	}
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+	return invalidate_dcache_range(start, stop);
+}
+#else /* #ifndef CONFIG_SYS_DCACHE_OFF */
+void invalidate_dcache_all(void)
+{
+}
+
+void flush_dcache_all(void)
+{
+}
+#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
+
+/*
+ * Stub implementations for l2 cache operations
+ */
+
+__weak void l2_cache_disable(void) {}
+
+#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
+__weak void invalidate_l2_cache(void) {}
+#endif
diff --git a/arch/arm/cpu/pxa/config.mk b/arch/arm/cpu/pxa/config.mk
new file mode 100644
index 0000000..e7b1836
--- /dev/null
+++ b/arch/arm/cpu/pxa/config.mk
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2002
+# Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+# Marius Groeger <mgroeger@sysgo.de>
+
+#
+# !WARNING!
+# The PXA's OneNAND SPL uses .text.0 and .text.1 segments to allow booting from
+# really small OneNAND memories where the mmap'd window is only 1KiB big. The
+# .text.0 contains only the bare minimum needed to load the real SPL into SRAM.
+# Add .text.0 and .text.1 into OBJFLAGS, so when the SPL is being objcopy'd,
+# they are not discarded.
+#
+
+#ifdef CONFIG_SPL_BUILD
+OBJCOPYFLAGS += -j .text.0 -j .text.1
+#endif
diff --git a/arch/arm/cpu/pxa/cpuinfo.c b/arch/arm/cpu/pxa/cpuinfo.c
new file mode 100644
index 0000000..5379e13
--- /dev/null
+++ b/arch/arm/cpu/pxa/cpuinfo.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PXA CPU information display
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <linux/compiler.h>
+
+#ifdef CONFIG_CPU_PXA25X
+#if ((CONFIG_SYS_INIT_SP_ADDR) != 0xfffff800)
+#error "Init SP address must be set to 0xfffff800 for PXA250"
+#endif
+#endif
+
+#define	CPU_MASK_PXA_PRODID	0x000003f0
+#define	CPU_MASK_PXA_REVID	0x0000000f
+
+#define	CPU_MASK_PRODREV	(CPU_MASK_PXA_PRODID | CPU_MASK_PXA_REVID)
+
+#define	CPU_VALUE_PXA25X	0x100
+#define	CPU_VALUE_PXA27X	0x110
+
+static uint32_t pxa_get_cpuid(void)
+{
+	uint32_t cpuid;
+	asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(cpuid));
+	return cpuid;
+}
+
+int cpu_is_pxa25x(void)
+{
+	uint32_t id = pxa_get_cpuid();
+	id &= CPU_MASK_PXA_PRODID;
+	return id == CPU_VALUE_PXA25X;
+}
+
+int cpu_is_pxa27x(void)
+{
+	uint32_t id = pxa_get_cpuid();
+	id &= CPU_MASK_PXA_PRODID;
+	return id == CPU_VALUE_PXA27X;
+}
+
+int cpu_is_pxa27xm(void)
+{
+	uint32_t id = pxa_get_cpuid();
+	return ((id & CPU_MASK_PXA_PRODID) == CPU_VALUE_PXA27X) &&
+			((id & CPU_MASK_PXA_REVID) == 8);
+}
+
+uint32_t pxa_get_cpu_revision(void)
+{
+	return pxa_get_cpuid() & CPU_MASK_PRODREV;
+}
+
+#ifdef	CONFIG_DISPLAY_CPUINFO
+static const char *pxa25x_get_revision(void)
+{
+	static __maybe_unused const char * const revs_25x[] = { "A0" };
+	static __maybe_unused const char * const revs_26x[] = {
+								"A0", "B0", "B1"
+								};
+	static const char *unknown = "Unknown";
+	uint32_t id;
+
+	if (!cpu_is_pxa25x())
+		return unknown;
+
+	id = pxa_get_cpuid() & CPU_MASK_PXA_REVID;
+
+/* PXA26x is a sick special case as it can't be told apart from PXA25x :-( */
+#ifdef	CONFIG_CPU_PXA26X
+	switch (id) {
+	case 3: return revs_26x[0];
+	case 5: return revs_26x[1];
+	case 6: return revs_26x[2];
+	}
+#else
+	if (id == 6)
+		return revs_25x[0];
+#endif
+	return unknown;
+}
+
+static const char *pxa27x_get_revision(void)
+{
+	static const char *const rev[] = { "A0", "A1", "B0", "B1", "C0", "C5" };
+	static const char *unknown = "Unknown";
+	uint32_t id;
+
+	if (!cpu_is_pxa27x())
+		return unknown;
+
+	id = pxa_get_cpuid() & CPU_MASK_PXA_REVID;
+
+	if ((id == 5) || (id == 6) || (id > 8))
+		return unknown;
+
+	/* Cap the special PXA270 C5 case. */
+	if (id == 7)
+		id = 5;
+
+	/* Cap the special PXA270M A1 case. */
+	if (id == 8)
+		id = 1;
+
+	return rev[id];
+}
+
+static int print_cpuinfo_pxa2xx(void)
+{
+	if (cpu_is_pxa25x()) {
+		puts("Marvell PXA25x rev. ");
+		puts(pxa25x_get_revision());
+	} else if (cpu_is_pxa27x()) {
+		puts("Marvell PXA27x");
+		if (cpu_is_pxa27xm()) puts("M");
+		puts(" rev. ");
+		puts(pxa27x_get_revision());
+	} else
+		return -EINVAL;
+
+	puts("\n");
+
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	int ret;
+
+	puts("CPU: ");
+
+	ret = print_cpuinfo_pxa2xx();
+	if (!ret)
+		return ret;
+
+	return ret;
+}
+#endif
diff --git a/arch/arm/cpu/pxa/pxa2xx.c b/arch/arm/cpu/pxa/pxa2xx.c
new file mode 100644
index 0000000..b9fd41e
--- /dev/null
+++ b/arch/arm/cpu/pxa/pxa2xx.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ */
+
+#include <common.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <command.h>
+
+/* Flush I/D-cache */
+static void cache_flush(void)
+{
+	unsigned long i = 0;
+
+	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i));
+}
+
+int cleanup_before_linux(void)
+{
+	/*
+	 * This function is called just before we call Linux. It prepares
+	 * the processor for Linux by just disabling everything that can
+	 * disturb booting Linux.
+	 */
+
+	disable_interrupts();
+	icache_disable();
+	dcache_disable();
+	cache_flush();
+
+	return 0;
+}
+
+void pxa_wait_ticks(int ticks)
+{
+	writel(0, OSCR);
+	while (readl(OSCR) < ticks)
+		asm volatile("" : : : "memory");
+}
+
+inline void writelrb(uint32_t val, uint32_t addr)
+{
+	writel(val, addr);
+	asm volatile("" : : : "memory");
+	readl(addr);
+	asm volatile("" : : : "memory");
+}
+
+void pxa2xx_dram_init(void)
+{
+	uint32_t tmp;
+	int i;
+	/*
+	 * 1) Initialize Asynchronous static memory controller
+	 */
+
+	writelrb(CONFIG_SYS_MSC0_VAL, MSC0);
+	writelrb(CONFIG_SYS_MSC1_VAL, MSC1);
+	writelrb(CONFIG_SYS_MSC2_VAL, MSC2);
+	/*
+	 * 2) Initialize Card Interface
+	 */
+
+	/* MECR: Memory Expansion Card Register */
+	writelrb(CONFIG_SYS_MECR_VAL, MECR);
+	/* MCMEM0: Card Interface slot 0 timing */
+	writelrb(CONFIG_SYS_MCMEM0_VAL, MCMEM0);
+	/* MCMEM1: Card Interface slot 1 timing */
+	writelrb(CONFIG_SYS_MCMEM1_VAL, MCMEM1);
+	/* MCATT0: Card Interface Attribute Space Timing, slot 0 */
+	writelrb(CONFIG_SYS_MCATT0_VAL, MCATT0);
+	/* MCATT1: Card Interface Attribute Space Timing, slot 1 */
+	writelrb(CONFIG_SYS_MCATT1_VAL, MCATT1);
+	/* MCIO0: Card Interface I/O Space Timing, slot 0 */
+	writelrb(CONFIG_SYS_MCIO0_VAL, MCIO0);
+	/* MCIO1: Card Interface I/O Space Timing, slot 1 */
+	writelrb(CONFIG_SYS_MCIO1_VAL, MCIO1);
+
+	/*
+	 * 3) Configure Fly-By DMA register
+	 */
+
+	writelrb(CONFIG_SYS_FLYCNFG_VAL, FLYCNFG);
+
+	/*
+	 * 4) Initialize Timing for Sync Memory (SDCLK0)
+	 */
+
+	/*
+	 * Before accessing MDREFR we need a valid DRI field, so we set
+	 * this to power on defaults + DRI field.
+	 */
+
+	/* Read current MDREFR config and zero out DRI */
+	tmp = readl(MDREFR) & ~0xfff;
+	/* Add user-specified DRI */
+	tmp |= CONFIG_SYS_MDREFR_VAL & 0xfff;
+	/* Configure important bits */
+	tmp |= MDREFR_K0RUN | MDREFR_SLFRSH;
+	tmp &= ~(MDREFR_APD | MDREFR_E1PIN);
+
+	/* Write MDREFR back */
+	writelrb(tmp, MDREFR);
+
+	/*
+	 * 5) Initialize Synchronous Static Memory (Flash/Peripherals)
+	 */
+
+	/* Initialize SXCNFG register. Assert the enable bits.
+	 *
+	 * Write SXMRS to cause an MRS command to all enabled banks of
+	 * synchronous static memory. Note that SXLCR need not be written
+	 * at this time.
+	 */
+	writelrb(CONFIG_SYS_SXCNFG_VAL, SXCNFG);
+
+	/*
+	 * 6) Initialize SDRAM
+	 */
+
+	writelrb(CONFIG_SYS_MDREFR_VAL & ~MDREFR_SLFRSH, MDREFR);
+	writelrb(CONFIG_SYS_MDREFR_VAL | MDREFR_E1PIN, MDREFR);
+
+	/*
+	 * 7) Write MDCNFG with MDCNFG:DEx deasserted (set to 0), to configure
+	 *    but not enable each SDRAM partition pair.
+	 */
+
+	writelrb(CONFIG_SYS_MDCNFG_VAL &
+		~(MDCNFG_DE0 | MDCNFG_DE1 | MDCNFG_DE2 | MDCNFG_DE3), MDCNFG);
+	/* Wait for the clock to the SDRAMs to stabilize, 100..200 usec. */
+	pxa_wait_ticks(0x300);
+
+	/*
+	 * 8) Trigger a number (usually 8) refresh cycles by attempting
+	 *    non-burst read or write accesses to disabled SDRAM, as commonly
+	 *    specified in the power up sequence documented in SDRAM data
+	 *    sheets. The address(es) used for this purpose must not be
+	 *    cacheable.
+	 */
+	for (i = 9; i >= 0; i--) {
+		writel(i, 0xa0000000);
+		asm volatile("" : : : "memory");
+	}
+	/*
+	 * 9) Write MDCNFG with enable bits asserted (MDCNFG:DEx set to 1).
+	 */
+
+	tmp = CONFIG_SYS_MDCNFG_VAL &
+		(MDCNFG_DE0 | MDCNFG_DE1 | MDCNFG_DE2 | MDCNFG_DE3);
+	tmp |= readl(MDCNFG);
+	writelrb(tmp, MDCNFG);
+
+	/*
+	 * 10) Write MDMRS.
+	 */
+
+	writelrb(CONFIG_SYS_MDMRS_VAL, MDMRS);
+
+	/*
+	 * 11) Enable APD
+	 */
+
+	if (CONFIG_SYS_MDREFR_VAL & MDREFR_APD) {
+		tmp = readl(MDREFR);
+		tmp |= MDREFR_APD;
+		writelrb(tmp, MDREFR);
+	}
+}
+
+void pxa_gpio_setup(void)
+{
+	writel(CONFIG_SYS_GPSR0_VAL, GPSR0);
+	writel(CONFIG_SYS_GPSR1_VAL, GPSR1);
+	writel(CONFIG_SYS_GPSR2_VAL, GPSR2);
+#if defined(CONFIG_CPU_PXA27X)
+	writel(CONFIG_SYS_GPSR3_VAL, GPSR3);
+#endif
+
+	writel(CONFIG_SYS_GPCR0_VAL, GPCR0);
+	writel(CONFIG_SYS_GPCR1_VAL, GPCR1);
+	writel(CONFIG_SYS_GPCR2_VAL, GPCR2);
+#if defined(CONFIG_CPU_PXA27X)
+	writel(CONFIG_SYS_GPCR3_VAL, GPCR3);
+#endif
+
+	writel(CONFIG_SYS_GPDR0_VAL, GPDR0);
+	writel(CONFIG_SYS_GPDR1_VAL, GPDR1);
+	writel(CONFIG_SYS_GPDR2_VAL, GPDR2);
+#if defined(CONFIG_CPU_PXA27X)
+	writel(CONFIG_SYS_GPDR3_VAL, GPDR3);
+#endif
+
+	writel(CONFIG_SYS_GAFR0_L_VAL, GAFR0_L);
+	writel(CONFIG_SYS_GAFR0_U_VAL, GAFR0_U);
+	writel(CONFIG_SYS_GAFR1_L_VAL, GAFR1_L);
+	writel(CONFIG_SYS_GAFR1_U_VAL, GAFR1_U);
+	writel(CONFIG_SYS_GAFR2_L_VAL, GAFR2_L);
+	writel(CONFIG_SYS_GAFR2_U_VAL, GAFR2_U);
+#if defined(CONFIG_CPU_PXA27X)
+	writel(CONFIG_SYS_GAFR3_L_VAL, GAFR3_L);
+	writel(CONFIG_SYS_GAFR3_U_VAL, GAFR3_U);
+#endif
+
+	writel(CONFIG_SYS_PSSR_VAL, PSSR);
+}
+
+void pxa_interrupt_setup(void)
+{
+	writel(0, ICLR);
+	writel(0, ICMR);
+#if defined(CONFIG_CPU_PXA27X)
+	writel(0, ICLR2);
+	writel(0, ICMR2);
+#endif
+}
+
+void pxa_clock_setup(void)
+{
+	writel(CONFIG_SYS_CKEN, CKEN);
+	writel(CONFIG_SYS_CCCR, CCCR);
+	asm volatile("mcr	p14, 0, %0, c6, c0, 0" : : "r"(0x0b));
+
+	/* enable the 32Khz oscillator for RTC and PowerManager */
+	writel(OSCC_OON, OSCC);
+	while (!(readl(OSCC) & OSCC_OOK))
+		asm volatile("" : : : "memory");
+}
+
+void pxa_wakeup(void)
+{
+	uint32_t rcsr;
+
+	rcsr = readl(RCSR);
+	writel(rcsr & (RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR), RCSR);
+
+	/* Wakeup */
+	if (rcsr & RCSR_SMR) {
+		writel(PSSR_PH, PSSR);
+		pxa2xx_dram_init();
+		icache_disable();
+		dcache_disable();
+		asm volatile("mov	pc, %0" : : "r"(readl(PSPR)));
+	}
+}
+
+int arch_cpu_init(void)
+{
+	pxa_gpio_setup();
+	pxa_wakeup();
+	pxa_interrupt_setup();
+	pxa_clock_setup();
+	return 0;
+}
+
+void i2c_clk_enable(void)
+{
+	/* Set the global I2C clock on */
+	writel(readl(CKEN) | CKEN14_I2C, CKEN);
+}
+
+void __attribute__((weak)) reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+	uint32_t tmp;
+
+	setbits_le32(OWER, OWER_WME);
+
+	tmp = readl(OSCR);
+	tmp += 0x1000;
+	writel(tmp, OSMR3);
+	writel(MDREFR_SLFRSH, MDREFR);
+
+	for (;;)
+		;
+}
+
+void enable_caches(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+	icache_enable();
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+	dcache_enable();
+#endif
+}
diff --git a/arch/arm/cpu/pxa/relocate.S b/arch/arm/cpu/pxa/relocate.S
new file mode 100644
index 0000000..778cd45
--- /dev/null
+++ b/arch/arm/cpu/pxa/relocate.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  relocate - PXA270 vector relocation
+ *
+ *  Copyright (c) 2013  Albert ARIBAUD <albert.u.boot@aribaud.net>
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * The PXA SoC is very specific with respect to exceptions: it
+ * does not provide RAM at the high vectors address (0xFFFF0000),
+ * thus only the low address (0x00000000) is useable; but that is
+ * in ROM, so let's avoid relocating the vectors.
+ */
+	.section	.text.relocate_vectors,"ax",%progbits
+
+ENTRY(relocate_vectors)
+
+	bx	lr
+
+ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/pxa/start.S b/arch/arm/cpu/pxa/start.S
new file mode 100644
index 0000000..575abac
--- /dev/null
+++ b/arch/arm/cpu/pxa/start.S
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for XScale CPU-core
+ *
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000	Wolfgang Denk <wd@denx.de>
+ *  Copyright (C) 2001	Alex Zuepke <azu@sysgo.de>
+ *  Copyright (C) 2001	Marius Groger <mag@sysgo.de>
+ *  Copyright (C) 2002	Alex Zupke <azu@sysgo.de>
+ *  Copyright (C) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (C) 2002	Kyle Harris <kharris@nexus-tech.net>
+ *  Copyright (C) 2003	Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
+ *  Copyright (C) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (C) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (C) 2003	Robert Schwebel <r.schwebel@pengutronix.de>
+ *  Copyright (C) 2004	Texas Instruments <r-woodruff2@ti.com>
+ *  Copyright (C) 2010	Marek Vasut <marek.vasut@gmail.com>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl  cpu_init_crit
+#endif
+
+#ifdef	CONFIG_CPU_PXA25X
+	bl	lock_cache_for_stack
+#endif
+#ifdef	CONFIG_CPU_PXA27X
+	/*
+	 * enable clock for SRAM
+	 */
+	ldr	r0,=CKEN
+	ldr	r1,[r0]
+	orr	r1,r1,#(1 << 20)
+	str	r1,[r0]
+#endif
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+#ifdef CONFIG_CPU_PXA25X
+	/*
+	 * Unlock (actually, disable) the cache now that board_init_f
+	 * is done. We could do this earlier but we would need to add
+	 * a new C runtime hook, whereas c_runtime_cpu_setup already
+	 * exists.
+	 * As this routine is just a call to cpu_init_crit, let us
+	 * tail-optimize and do a simple branch here.
+	 */
+	b	cpu_init_crit
+#else
+	bx	lr
+#endif
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X)
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
+	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00003300	@ clear bits 13:12, 9:8 (--VI --RS)
+	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
+	orr	r0, r0, #0x00000002	@ set bit 1 (A) Align
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mov	pc, lr		/* back to my caller */
+#endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */
+
+/*
+ * Enable MMU to use DCache as DRAM.
+ *
+ * This is useful on PXA25x and PXA26x in early bootstages, where there is no
+ * other possible memory available to hold stack.
+ */
+#ifdef CONFIG_CPU_PXA25X
+.macro CPWAIT reg
+	mrc	p15, 0, \reg, c2, c0, 0
+	mov	\reg, \reg
+	sub	pc, pc, #4
+.endm
+lock_cache_for_stack:
+	/* Domain access -- enable for all CPs */
+	ldr	r0, =0x0000ffff
+	mcr	p15, 0, r0, c3, c0, 0
+
+	/* Point TTBR to MMU table */
+	ldr	r0, =mmutable
+	mcr	p15, 0, r0, c2, c0, 0
+
+	/* Kick in MMU, ICache, DCache, BTB */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, #0x1b00
+	bic	r0, #0x0087
+	orr	r0, #0x1800
+	orr	r0, #0x0005
+	mcr	p15, 0, r0, c1, c0, 0
+	CPWAIT	r0
+
+	/* Unlock Icache, Dcache */
+	mcr	p15, 0, r0, c9, c1, 1
+	mcr	p15, 0, r0, c9, c2, 1
+
+	/* Flush Icache, Dcache, BTB */
+	mcr	p15, 0, r0, c7, c7, 0
+
+	/* Unlock I-TLB, D-TLB */
+	mcr	p15, 0, r0, c10, c4, 1
+	mcr	p15, 0, r0, c10, c8, 1
+
+	/* Flush TLB */
+	mcr	p15, 0, r0, c8, c7, 0
+
+	/* Allocate 4096 bytes of Dcache as RAM */
+
+	/* Drain pending loads and stores */
+	mcr	p15, 0, r0, c7, c10, 4
+
+	mov	r4, #0x00
+	mov	r5, #0x00
+	mov	r2, #0x01
+	mcr	p15, 0, r0, c9, c2, 0
+	CPWAIT	r0
+
+	/* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
+	mov	r0, #128
+	ldr	r1, =0xfffff000
+
+alloc:
+	mcr	p15, 0, r1, c7, c2, 5
+	/* Drain pending loads and stores */
+	mcr	p15, 0, r0, c7, c10, 4
+	strd	r4, [r1], #8
+	strd	r4, [r1], #8
+	strd	r4, [r1], #8
+	strd	r4, [r1], #8
+	subs	r0, #0x01
+	bne	alloc
+	/* Drain pending loads and stores */
+	mcr	p15, 0, r0, c7, c10, 4
+	mov	r2, #0x00
+	mcr	p15, 0, r2, c9, c2, 0
+	CPWAIT	r0
+
+	mov	pc, lr
+
+.section .mmutable, "a"
+mmutable:
+	.align	14
+	/* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */
+	.set	__base, 0
+	.rept	0xfff
+	.word	(__base << 20) | 0xc12
+	.set	__base, __base + 1
+	.endr
+
+	/* 0xfff00000 : 1:1, cached mapping */
+	.word	(0xfff << 20) | 0x1c1e
+#endif	/* CONFIG_CPU_PXA25X */
diff --git a/arch/arm/cpu/pxa/timer.c b/arch/arm/cpu/pxa/timer.c
new file mode 100644
index 0000000..169fed8
--- /dev/null
+++ b/arch/arm/cpu/pxa/timer.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Marvell PXA2xx/3xx timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+int timer_init(void)
+{
+	writel(0, CONFIG_SYS_TIMER_COUNTER);
+	return 0;
+}
diff --git a/arch/arm/cpu/pxa/usb.c b/arch/arm/cpu/pxa/usb.c
new file mode 100644
index 0000000..80a5977
--- /dev/null
+++ b/arch/arm/cpu/pxa/usb.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2006
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
+# if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_CPU_PXA27X)
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/io.h>
+#include <usb.h>
+
+int usb_cpu_init(void)
+{
+#if defined(CONFIG_CPU_MONAHANS)
+	/* Enable USB host clock. */
+	writel(readl(CKENA) | CKENA_2_USBHOST | CKENA_20_UDC, CKENA);
+	udelay(100);
+#endif
+#if defined(CONFIG_CPU_PXA27X)
+	/* Enable USB host clock. */
+	writel(readl(CKEN) | CKEN10_USBHOST, CKEN);
+#endif
+
+#if defined(CONFIG_CPU_MONAHANS)
+	/* Configure Port 2 for Host (USB Client Registers) */
+	writel(0x3000c, UP2OCR);
+#endif
+
+	writel(readl(UHCHR) | UHCHR_FHR, UHCHR);
+	mdelay(11);
+	writel(readl(UHCHR) & ~UHCHR_FHR, UHCHR);
+
+	writel(readl(UHCHR) | UHCHR_FSBIR, UHCHR);
+	while (readl(UHCHR) & UHCHR_FSBIR)
+		udelay(1);
+
+#if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X)
+	writel(readl(UHCHR) & ~UHCHR_SSEP0, UHCHR);
+#endif
+#if defined(CONFIG_CPU_PXA27X)
+	writel(readl(UHCHR) & ~UHCHR_SSEP2, UHCHR);
+#endif
+	writel(readl(UHCHR) & ~(UHCHR_SSEP1 | UHCHR_SSE), UHCHR);
+
+	return 0;
+}
+
+int usb_cpu_stop(void)
+{
+	writel(readl(UHCHR) | UHCHR_FHR, UHCHR);
+	udelay(11);
+	writel(readl(UHCHR) & ~UHCHR_FHR, UHCHR);
+
+	writel(readl(UHCCOMS) | UHCCOMS_HCR, UHCCOMS);
+	udelay(10);
+
+#if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X)
+	writel(readl(UHCHR) | UHCHR_SSEP0, UHCHR);
+#endif
+#if defined(CONFIG_CPU_PXA27X)
+	writel(readl(UHCHR) | UHCHR_SSEP2, UHCHR);
+#endif
+	writel(readl(UHCHR) | UHCHR_SSEP1 | UHCHR_SSE, UHCHR);
+
+#if defined(CONFIG_CPU_MONAHANS)
+	/* Disable USB host clock. */
+	writel(readl(CKENA) & ~(CKENA_2_USBHOST | CKENA_20_UDC), CKENA);
+	udelay(100);
+#endif
+#if defined(CONFIG_CPU_PXA27X)
+	/* Disable USB host clock. */
+	writel(readl(CKEN) & ~CKEN10_USBHOST, CKEN);
+#endif
+
+	return 0;
+}
+
+int usb_cpu_init_fail(void)
+{
+	return usb_cpu_stop();
+}
+
+# endif /* defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_CPU_PXA27X) */
+#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/arch/arm/cpu/sa1100/Makefile b/arch/arm/cpu/sa1100/Makefile
new file mode 100644
index 0000000..3819309
--- /dev/null
+++ b/arch/arm/cpu/sa1100/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+extra-y	= start.o
+
+obj-y	+= cpu.o
+obj-y	+= timer.o
diff --git a/arch/arm/cpu/sa1100/cpu.c b/arch/arm/cpu/sa1100/cpu.c
new file mode 100644
index 0000000..f81ebc9
--- /dev/null
+++ b/arch/arm/cpu/sa1100/cpu.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+static void cache_flush(void);
+
+int cleanup_before_linux (void)
+{
+	/*
+	 * this function is called just before we call linux
+	 * it prepares the processor for linux
+	 *
+	 * just disable everything that can disturb booting linux
+	 */
+
+	disable_interrupts ();
+
+	/* turn off I-cache */
+	icache_disable();
+	dcache_disable();
+
+	/* flush I-cache */
+	cache_flush();
+
+	return (0);
+}
+
+/* flush I/D-cache */
+static void cache_flush (void)
+{
+	unsigned long i = 0;
+
+	asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i));
+}
+
+#define RST_BASE 0x90030000
+#define RSRR	0x00
+#define RCSR	0x04
+
+__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused)))
+{
+	/* repeat endlessly */
+	while (1) {
+		writel(0, RST_BASE + RCSR);
+		writel(1, RST_BASE + RSRR);
+	}
+}
diff --git a/arch/arm/cpu/sa1100/start.S b/arch/arm/cpu/sa1100/start.S
new file mode 100644
index 0000000..8eb0053
--- /dev/null
+++ b/arch/arm/cpu/sa1100/start.S
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  armboot - Startup Code for SA1100 CPU
+ *
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000	Wolfgang Denk <wd@denx.de>
+ *  Copyright (c) 2001	Alex Züpke <azu@sysgo.de>
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * relocate armboot to ram
+ * setup stack
+ * jump to second stage
+ *
+ *************************************************************************
+ */
+
+	.globl	reset
+
+reset:
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	_main
+
+/*------------------------------------------------------------------------------*/
+
+	.globl	c_runtime_cpu_setup
+c_runtime_cpu_setup:
+
+	mov	pc, lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+
+
+/* Interrupt-Controller base address */
+IC_BASE:	.word	0x90050000
+#define ICMR	0x04
+
+
+/* Reset-Controller */
+RST_BASE:		.word   0x90030000
+#define RSRR	0x00
+#define RCSR	0x04
+
+
+/* PWR */
+PWR_BASE:		.word   0x90020000
+#define PSPR    0x08
+#define PPCR    0x14
+cpuspeed:		.word   CONFIG_SYS_CPUSPEED
+
+
+cpu_init_crit:
+	/*
+	 * mask all IRQs
+	 */
+	ldr	r0, IC_BASE
+	mov	r1, #0x00
+	str	r1, [r0, #ICMR]
+
+	/* set clock speed */
+	ldr	r0, PWR_BASE
+	ldr	r1, cpuspeed
+	str	r1, [r0, #PPCR]
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+	/*
+	 * before relocating, we have to setup RAM timing
+	 * because memory timing is board-dependend, you will
+	 * find a lowlevel_init.S in your board directory.
+	 */
+	mov	ip,	lr
+	bl	lowlevel_init
+	mov	lr,	ip
+#endif
+
+	/*
+	 * disable MMU stuff and enable I-cache
+	 */
+	mrc	p15,0,r0,c1,c0
+	bic	r0, r0, #0x00002000	@ clear bit 13 (X)
+	bic	r0, r0, #0x0000000f	@ clear bits 3-0 (WCAM)
+	orr	r0, r0, #0x00001000	@ set bit 12 (I) Icache
+	orr	r0, r0, #0x00000002	@ set bit 1 (A) Align
+	mcr	p15,0,r0,c1,c0
+
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	mov	pc, lr
diff --git a/arch/arm/cpu/sa1100/timer.c b/arch/arm/cpu/sa1100/timer.c
new file mode 100644
index 0000000..0fac5c1
--- /dev/null
+++ b/arch/arm/cpu/sa1100/timer.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ */
+
+#include <common.h>
+#include <SA-1100.h>
+
+static ulong get_timer_masked (void)
+{
+	return OSCR;
+}
+
+ulong get_timer (ulong base)
+{
+	return get_timer_masked ();
+}
+
+void __udelay (unsigned long usec)
+{
+	ulong tmo;
+	ulong endtime;
+	signed long diff;
+
+	if (usec >= 1000) {
+		tmo = usec / 1000;
+		tmo *= CONFIG_SYS_HZ;
+		tmo /= 1000;
+	} else {
+		tmo = usec * CONFIG_SYS_HZ;
+		tmo /= (1000*1000);
+	}
+
+	endtime = get_timer_masked () + tmo;
+
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk (void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/cpu/u-boot-spl.lds b/arch/arm/cpu/u-boot-spl.lds
new file mode 100644
index 0000000..9d13331
--- /dev/null
+++ b/arch/arm/cpu/u-boot-spl.lds
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text :
+	{
+		__image_copy_start = .;
+		*(.vectors)
+		CPUDIR/start.o (.text*)
+		*(.text*)
+		*(.glue*)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data*)
+	}
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+
+	. = ALIGN(4);
+	.binman_sym_table : {
+		__binman_sym_start = .;
+		KEEP(*(SORT(.binman_sym*)));
+		__binman_sym_end = .;
+	}
+
+	. = ALIGN(4);
+
+	__image_copy_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.end :
+	{
+		*(.__end)
+	}
+
+	_image_binary_end = .;
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss*)
+		 . = ALIGN(4);
+		__bss_end = .;
+	}
+	__bss_size = __bss_end - __bss_start;
+	.dynsym _image_binary_end : { *(.dynsym) }
+	.dynbss : { *(.dynbss) }
+	.dynstr : { *(.dynstr*) }
+	.dynamic : { *(.dynamic*) }
+	.hash : { *(.hash*) }
+	.plt : { *(.plt*) }
+	.interp : { *(.interp*) }
+	.gnu : { *(.gnu*) }
+	.ARM.exidx : { *(.ARM.exidx*) }
+}
+
+#if defined(CONFIG_SPL_MAX_SIZE)
+ASSERT(__image_copy_end - __image_copy_start < (CONFIG_SPL_MAX_SIZE), \
+	"SPL image too big");
+#endif
+
+#if defined(CONFIG_SPL_BSS_MAX_SIZE)
+ASSERT(__bss_end - __bss_start < (CONFIG_SPL_BSS_MAX_SIZE), \
+	"SPL image BSS too big");
+#endif
+
+#if defined(CONFIG_SPL_MAX_FOOTPRINT)
+ASSERT(__bss_end - _start < (CONFIG_SPL_MAX_FOOTPRINT), \
+	"SPL image plus BSS too big");
+#endif
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
new file mode 100644
index 0000000..0eb164d
--- /dev/null
+++ b/arch/arm/cpu/u-boot.lds
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ */
+
+#include <config.h>
+#include <asm/psci.h>
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+#ifndef CONFIG_CMDLINE
+	/DISCARD/ : { *(.u_boot_list_2_cmd_*) }
+#endif
+#if defined(CONFIG_ARMV7_SECURE_BASE) && defined(CONFIG_ARMV7_NONSEC)
+	/*
+	 * If CONFIG_ARMV7_SECURE_BASE is true, secure code will not
+	 * bundle with u-boot, and code offsets are fixed. Secure zone
+	 * only needs to be copied from the loading address to
+	 * CONFIG_ARMV7_SECURE_BASE, which is the linking and running
+	 * address for secure code.
+	 *
+	 * If CONFIG_ARMV7_SECURE_BASE is undefined, the secure zone will
+	 * be included in u-boot address space, and some absolute address
+	 * were used in secure code. The absolute addresses of the secure
+	 * code also needs to be relocated along with the accompanying u-boot
+	 * code.
+	 *
+	 * So DISCARD is only for CONFIG_ARMV7_SECURE_BASE.
+	 */
+	/DISCARD/ : { *(.rel._secure*) }
+#endif
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text :
+	{
+		*(.__image_copy_start)
+		*(.vectors)
+		CPUDIR/start.o (.text*)
+	}
+
+	/* This needs to come before *(.text*) */
+	.__efi_runtime_start : {
+		*(.__efi_runtime_start)
+	}
+
+	.efi_runtime : {
+		*(.text.efi_runtime*)
+		*(.rodata.efi_runtime*)
+		*(.data.efi_runtime*)
+	}
+
+	.__efi_runtime_stop : {
+		*(.__efi_runtime_stop)
+	}
+
+	.text_rest :
+	{
+		*(.text*)
+	}
+
+#ifdef CONFIG_ARMV7_NONSEC
+
+	/* Align the secure section only if we're going to use it in situ */
+	.__secure_start
+#ifndef CONFIG_ARMV7_SECURE_BASE
+		ALIGN(CONSTANT(COMMONPAGESIZE))
+#endif
+	: {
+		KEEP(*(.__secure_start))
+	}
+
+#ifndef CONFIG_ARMV7_SECURE_BASE
+#define CONFIG_ARMV7_SECURE_BASE
+#define __ARMV7_PSCI_STACK_IN_RAM
+#endif
+
+	.secure_text CONFIG_ARMV7_SECURE_BASE :
+		AT(ADDR(.__secure_start) + SIZEOF(.__secure_start))
+	{
+		*(._secure.text)
+	}
+
+	.secure_data : AT(LOADADDR(.secure_text) + SIZEOF(.secure_text))
+	{
+		*(._secure.data)
+	}
+
+#ifdef CONFIG_ARMV7_PSCI
+	.secure_stack ALIGN(ADDR(.secure_data) + SIZEOF(.secure_data),
+			    CONSTANT(COMMONPAGESIZE)) (NOLOAD) :
+#ifdef __ARMV7_PSCI_STACK_IN_RAM
+		AT(ADDR(.secure_stack))
+#else
+		AT(LOADADDR(.secure_data) + SIZEOF(.secure_data))
+#endif
+	{
+		KEEP(*(.__secure_stack_start))
+
+		/* Skip addreses for stack */
+		. = . + CONFIG_ARMV7_PSCI_NR_CPUS * ARM_PSCI_STACK_SIZE;
+
+		/* Align end of stack section to page boundary */
+		. = ALIGN(CONSTANT(COMMONPAGESIZE));
+
+		KEEP(*(.__secure_stack_end))
+
+#ifdef CONFIG_ARMV7_SECURE_MAX_SIZE
+		/*
+		 * We are not checking (__secure_end - __secure_start) here,
+		 * as these are the load addresses, and do not include the
+		 * stack section. Instead, use the end of the stack section
+		 * and the start of the text section.
+		 */
+		ASSERT((. - ADDR(.secure_text)) <= CONFIG_ARMV7_SECURE_MAX_SIZE,
+		       "Error: secure section exceeds secure memory size");
+#endif
+	}
+
+#ifndef __ARMV7_PSCI_STACK_IN_RAM
+	/* Reset VMA but don't allocate space if we have secure SRAM */
+	. = LOADADDR(.secure_stack);
+#endif
+
+#endif
+
+	.__secure_end : AT(ADDR(.__secure_end)) {
+		*(.__secure_end)
+		LONG(0x1d1071c);	/* Must output something to reset LMA */
+	}
+#endif
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data*)
+	}
+
+	. = ALIGN(4);
+
+	. = .;
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+
+	. = ALIGN(4);
+
+	.efi_runtime_rel_start :
+	{
+		*(.__efi_runtime_rel_start)
+	}
+
+	.efi_runtime_rel : {
+		*(.rel*.efi_runtime)
+		*(.rel*.efi_runtime.*)
+	}
+
+	.efi_runtime_rel_stop :
+	{
+		*(.__efi_runtime_rel_stop)
+	}
+
+	. = ALIGN(4);
+
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
+	}
+
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
+	}
+
+	.end :
+	{
+		*(.__end)
+	}
+
+	_image_binary_end = .;
+
+	/*
+	 * Deprecated: this MMU section is used by pxa at present but
+	 * should not be used by new boards/CPUs.
+	 */
+	. = ALIGN(4096);
+	.mmutable : {
+		*(.mmutable)
+	}
+
+/*
+ * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
+ * __bss_base and __bss_limit are for linker only (overlay ordering)
+ */
+
+	.bss_start __rel_dyn_start (OVERLAY) : {
+		KEEP(*(.__bss_start));
+		__bss_base = .;
+	}
+
+	.bss __bss_base (OVERLAY) : {
+		*(.bss*)
+		 . = ALIGN(4);
+		 __bss_limit = .;
+	}
+
+	.bss_end __bss_limit (OVERLAY) : {
+		KEEP(*(.__bss_end));
+	}
+
+	.dynsym _image_binary_end : { *(.dynsym) }
+	.dynbss : { *(.dynbss) }
+	.dynstr : { *(.dynstr*) }
+	.dynamic : { *(.dynamic*) }
+	.plt : { *(.plt*) }
+	.interp : { *(.interp*) }
+	.gnu.hash : { *(.gnu.hash) }
+	.gnu : { *(.gnu*) }
+	.ARM.exidx : { *(.ARM.exidx*) }
+	.gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
new file mode 100644
index 0000000..dda4e59
--- /dev/null
+++ b/arch/arm/dts/Makefile
@@ -0,0 +1,586 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+dtb-$(CONFIG_TARGET_SMARTWEB) += at91sam9260-smartweb.dtb
+dtb-$(CONFIG_TARGET_TAURUS) += at91sam9g20-taurus.dtb
+dtb-$(CONFIG_TARGET_CORVUS) += at91sam9g45-corvus.dtb
+dtb-$(CONFIG_TARGET_GURNARD) += at91sam9g45-gurnard.dtb
+
+dtb-$(CONFIG_S5PC100) += s5pc1xx-smdkc100.dtb
+dtb-$(CONFIG_S5PC110) += s5pc1xx-goni.dtb
+dtb-$(CONFIG_EXYNOS4) += exynos4210-origen.dtb \
+	exynos4210-smdkv310.dtb \
+	exynos4210-universal_c210.dtb \
+	exynos4210-trats.dtb \
+	exynos4412-trats2.dtb \
+	exynos4412-odroid.dtb
+
+dtb-$(CONFIG_TARGET_HIKEY) += hi6220-hikey.dtb
+
+dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \
+	exynos5250-snow.dtb \
+	exynos5250-spring.dtb \
+	exynos5250-smdk5250.dtb \
+	exynos5420-smdk5420.dtb \
+	exynos5420-peach-pit.dtb \
+	exynos5800-peach-pi.dtb \
+	exynos5422-odroidxu3.dtb
+dtb-$(CONFIG_EXYNOS7420) += exynos7420-espresso7420.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += \
+	rk3036-sdk.dtb \
+	rk3128-evb.dtb \
+	rk3188-radxarock.dtb \
+	rk3288-evb.dtb \
+	rk3288-fennec.dtb \
+	rk3288-firefly.dtb \
+	rk3288-miqi.dtb \
+	rk3288-phycore-rdk.dtb \
+	rk3288-popmetal.dtb \
+	rk3288-rock2-square.dtb \
+	rk3288-tinker.dtb \
+	rk3288-veyron-jerry.dtb \
+	rk3288-veyron-mickey.dtb \
+	rk3288-veyron-minnie.dtb \
+	rk3288-vyasa.dtb \
+	rk3328-evb.dtb \
+	rk3399-ficus.dtb \
+	rk3368-lion.dtb \
+	rk3368-sheep.dtb \
+	rk3368-geekbox.dtb \
+	rk3368-px5-evb.dtb \
+	rk3399-evb.dtb \
+	rk3399-firefly.dtb \
+	rk3399-puma-ddr1333.dtb \
+	rk3399-puma-ddr1600.dtb \
+	rk3399-puma-ddr1866.dtb \
+	rk3399-rock960.dtb \
+	rv1108-elgin-r1.dtb \
+	rv1108-evb.dtb
+dtb-$(CONFIG_ARCH_MESON) += \
+	meson-gxbb-nanopi-k2.dtb \
+	meson-gxbb-odroidc2.dtb \
+	meson-gxbb-nanopi-k2.dtb \
+	meson-gxl-s905x-p212.dtb \
+	meson-gxl-s905x-libretech-cc.dtb \
+	meson-gxl-s905x-khadas-vim.dtb \
+	meson-gxm-khadas-vim2.dtb \
+	meson-axg-s400.dtb
+dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
+	tegra20-medcom-wide.dtb \
+	tegra20-paz00.dtb \
+	tegra20-plutux.dtb \
+	tegra20-seaboard.dtb \
+	tegra20-tec.dtb \
+	tegra20-trimslice.dtb \
+	tegra20-ventana.dtb \
+	tegra20-colibri.dtb \
+	tegra30-apalis.dtb \
+	tegra30-beaver.dtb \
+	tegra30-cardhu.dtb \
+	tegra30-colibri.dtb \
+	tegra30-tec-ng.dtb \
+	tegra114-dalmore.dtb \
+	tegra124-apalis.dtb \
+	tegra124-jetson-tk1.dtb \
+	tegra124-nyan-big.dtb \
+	tegra124-cei-tk1-som.dtb \
+	tegra124-venice2.dtb \
+	tegra186-p2771-0000-000.dtb \
+	tegra186-p2771-0000-500.dtb \
+	tegra210-e2220-1170.dtb \
+	tegra210-p2371-0000.dtb \
+	tegra210-p2371-2180.dtb \
+	tegra210-p2571.dtb
+
+dtb-$(CONFIG_ARCH_MVEBU) +=			\
+	armada-3720-db.dtb			\
+	armada-3720-espressobin.dtb		\
+	armada-3720-turris-mox.dtb		\
+	armada-375-db.dtb			\
+	armada-388-clearfog.dtb			\
+	armada-388-gp.dtb			\
+	armada-388-helios4.dtb			\
+	armada-385-amc.dtb			\
+	armada-7040-db.dtb			\
+	armada-7040-db-nand.dtb			\
+	armada-8040-db.dtb			\
+	armada-8040-mcbin.dtb			\
+	armada-8040-clearfog-gt-8k.dtb		\
+	armada-xp-gp.dtb			\
+	armada-xp-maxbcm.dtb			\
+	armada-xp-synology-ds414.dtb		\
+	armada-xp-theadorable.dtb		\
+	armada-38x-controlcenterdc.dtb
+
+dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \
+	uniphier-ld11-global.dtb \
+	uniphier-ld11-ref.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_LD20) += \
+	uniphier-ld20-global.dtb \
+	uniphier-ld20-ref.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_LD4) += \
+	uniphier-ld4-ref.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_LD6B) += \
+	uniphier-ld6b-ref.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_PRO4) += \
+	uniphier-pro4-ace.dtb \
+	uniphier-pro4-ref.dtb \
+	uniphier-pro4-sanji.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_PRO5) += \
+	uniphier-pro5-4kbox.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_PXS2) += \
+	uniphier-pxs2-gentil.dtb \
+	uniphier-pxs2-vodka.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_PXS3) += \
+	uniphier-pxs3-ref.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER_SLD8) += \
+	uniphier-sld8-ref.dtb
+
+dtb-$(CONFIG_ARCH_ZYNQ) += \
+	zynq-cc108.dtb \
+	zynq-cse-nand.dtb \
+	zynq-cse-nor.dtb \
+	zynq-cse-qspi-single.dtb \
+	zynq-dlc20-rev1.0.dtb \
+	zynq-microzed.dtb \
+	zynq-minized.dtb \
+	zynq-picozed.dtb \
+	zynq-syzygy-hub.dtb \
+	zynq-topic-miami.dtb \
+	zynq-topic-miamilite.dtb \
+	zynq-topic-miamiplus.dtb \
+	zynq-zc702.dtb \
+	zynq-zc706.dtb \
+	zynq-zc770-xm010.dtb \
+	zynq-zc770-xm011.dtb \
+	zynq-zc770-xm012.dtb \
+	zynq-zc770-xm013.dtb \
+	zynq-zed.dtb \
+	zynq-zturn.dtb \
+	zynq-zybo.dtb \
+	zynq-zybo-z7.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += \
+	avnet-ultra96-rev1.dtb			\
+	zynqmp-mini.dtb				\
+	zynqmp-mini-emmc0.dtb			\
+	zynqmp-mini-emmc1.dtb			\
+	zynqmp-mini-nand.dtb			\
+	zynqmp-mini-qspi.dtb			\
+	zynqmp-zcu100-revC.dtb			\
+	zynqmp-zcu102-revA.dtb			\
+	zynqmp-zcu102-revB.dtb			\
+	zynqmp-zcu102-rev1.0.dtb		\
+	zynqmp-zcu104-revA.dtb			\
+	zynqmp-zcu104-revC.dtb			\
+	zynqmp-zcu106-revA.dtb			\
+	zynqmp-zcu111-revA.dtb			\
+	zynqmp-zc1232-revA.dtb			\
+	zynqmp-zc1254-revA.dtb			\
+	zynqmp-zc1275-revA.dtb			\
+	zynqmp-zc1275-revB.dtb			\
+	zynqmp-zc1751-xm015-dc1.dtb		\
+	zynqmp-zc1751-xm016-dc2.dtb		\
+	zynqmp-zc1751-xm017-dc3.dtb		\
+	zynqmp-zc1751-xm018-dc4.dtb		\
+	zynqmp-zc1751-xm019-dc5.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP_R5) += \
+	zynqmp-r5.dtb
+dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb \
+	am335x-draco.dtb \
+	am335x-evm.dtb \
+	am335x-evmsk.dtb \
+	am335x-bonegreen.dtb \
+	am335x-icev2.dtb \
+	am335x-pxm50.dtb \
+	am335x-rut.dtb \
+	am335x-pdu001.dtb \
+	am335x-chiliboard.dtb
+dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb	\
+	am43x-epos-evm.dtb \
+	am437x-idk-evm.dtb \
+	am4372-generic.dtb
+dtb-$(CONFIG_TI816X) += dm8168-evm.dtb
+dtb-$(CONFIG_THUNDERX) += thunderx-88xx.dtb
+
+dtb-$(CONFIG_ARCH_SOCFPGA) +=				\
+	socfpga_arria5_socdk.dtb			\
+	socfpga_arria10_socdk_sdmmc.dtb			\
+	socfpga_cyclone5_is1.dtb			\
+	socfpga_cyclone5_socdk.dtb			\
+	socfpga_cyclone5_dbm_soc1.dtb			\
+	socfpga_cyclone5_de0_nano_soc.dtb		\
+	socfpga_cyclone5_de1_soc.dtb			\
+	socfpga_cyclone5_de10_nano.dtb			\
+	socfpga_cyclone5_sockit.dtb			\
+	socfpga_cyclone5_socrates.dtb			\
+	socfpga_cyclone5_sr1500.dtb			\
+	socfpga_cyclone5_vining_fpga.dtb		\
+	socfpga_stratix10_socdk.dtb
+
+dtb-$(CONFIG_TARGET_DRA7XX_EVM) += dra72-evm.dtb dra7-evm.dtb	\
+	dra72-evm-revc.dtb dra71-evm.dtb dra76-evm.dtb
+dtb-$(CONFIG_TARGET_AM57XX_EVM) += am57xx-beagle-x15.dtb \
+	am57xx-beagle-x15-revb1.dtb \
+	am57xx-beagle-x15-revc.dtb \
+	am574x-idk.dtb \
+	am572x-idk.dtb	\
+	am571x-idk.dtb
+dtb-$(CONFIG_TARGET_STV0991) += stv0991.dtb
+
+dtb-$(CONFIG_ARCH_LS1021A) += ls1021a-qds-duart.dtb \
+	ls1021a-qds-lpuart.dtb \
+	ls1021a-twr-duart.dtb ls1021a-twr-lpuart.dtb \
+	ls1021a-iot-duart.dtb
+dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \
+	fsl-ls2080a-rdb.dtb \
+	fsl-ls2081a-rdb.dtb \
+	fsl-ls2088a-rdb-qspi.dtb \
+	fsl-ls1088a-rdb.dtb \
+	fsl-ls1088a-qds.dtb
+dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds-duart.dtb \
+	fsl-ls1043a-qds-lpuart.dtb \
+	fsl-ls1043a-rdb.dtb \
+	fsl-ls1046a-qds-duart.dtb \
+	fsl-ls1046a-qds-lpuart.dtb \
+	fsl-ls1046a-rdb.dtb \
+	fsl-ls1012a-qds.dtb \
+	fsl-ls1012a-rdb.dtb \
+	fsl-ls1012a-2g5rdb.dtb \
+	fsl-ls1012a-frdm.dtb \
+	fsl-ls1012a-frwy.dtb
+
+dtb-$(CONFIG_TARGET_DRAGONBOARD410C) += dragonboard410c.dtb
+dtb-$(CONFIG_TARGET_DRAGONBOARD820C) += dragonboard820c.dtb
+
+dtb-$(CONFIG_STM32F4) += stm32f429-disco.dtb \
+	stm32429i-eval.dtb \
+	stm32f469-disco.dtb
+
+dtb-$(CONFIG_STM32F7) += stm32f746-disco.dtb \
+	stm32f769-disco.dtb \
+	stm32746g-eval.dtb
+dtb-$(CONFIG_STM32H7) += stm32h743i-disco.dtb \
+	stm32h743i-eval.dtb
+
+dtb-$(CONFIG_MACH_SUN4I) += \
+	sun4i-a10-a1000.dtb \
+	sun4i-a10-ba10-tvbox.dtb \
+	sun4i-a10-chuwi-v7-cw0825.dtb \
+	sun4i-a10-cubieboard.dtb \
+	sun4i-a10-dserve-dsrv9703c.dtb \
+	sun4i-a10-gemei-g9.dtb \
+	sun4i-a10-hackberry.dtb \
+	sun4i-a10-hyundai-a7hd.dtb \
+	sun4i-a10-inet1.dtb \
+	sun4i-a10-inet-3f.dtb \
+	sun4i-a10-inet-3w.dtb \
+	sun4i-a10-inet97fv2.dtb \
+	sun4i-a10-inet9f-rev03.dtb \
+	sun4i-a10-itead-iteaduino-plus.dtb \
+	sun4i-a10-jesurun-q5.dtb \
+	sun4i-a10-marsboard.dtb \
+	sun4i-a10-mini-xplus.dtb \
+	sun4i-a10-mk802.dtb \
+	sun4i-a10-mk802ii.dtb \
+	sun4i-a10-olinuxino-lime.dtb \
+	sun4i-a10-pcduino.dtb \
+	sun4i-a10-pcduino2.dtb \
+	sun4i-a10-pov-protab2-ips9.dtb
+dtb-$(CONFIG_MACH_SUN5I) += \
+	sun5i-a10s-auxtek-t003.dtb \
+	sun5i-a10s-auxtek-t004.dtb \
+	sun5i-a10s-mk802.dtb \
+	sun5i-a10s-olinuxino-micro.dtb \
+	sun5i-a10s-r7-tv-dongle.dtb \
+	sun5i-a10s-wobo-i5.dtb \
+	sun5i-a13-ampe-a76.dtb \
+	sun5i-a13-difrnce-dit4350.dtb \
+	sun5i-a13-empire-electronix-d709.dtb \
+	sun5i-a13-empire-electronix-m712.dtb \
+	sun5i-a13-hsg-h702.dtb \
+	sun5i-a13-inet-86vs.dtb \
+	sun5i-a13-inet-98v-rev2.dtb \
+	sun5i-a13-olinuxino.dtb \
+	sun5i-a13-olinuxino-micro.dtb \
+	sun5i-a13-q8-tablet.dtb \
+	sun5i-a13-utoo-p66.dtb \
+	sun5i-gr8-chip-pro.dtb \
+	sun5i-r8-chip.dtb
+dtb-$(CONFIG_MACH_SUN6I) += \
+	sun6i-a31-app4-evb1.dtb \
+	sun6i-a31-colombus.dtb \
+	sun6i-a31-hummingbird.dtb \
+	sun6i-a31-i7.dtb \
+	sun6i-a31-m9.dtb \
+	sun6i-a31-mele-a1000g-quad.dtb \
+	sun6i-a31-mixtile-loftq.dtb \
+	sun6i-a31s-colorfly-e708-q1.dtb \
+	sun6i-a31s-cs908.dtb \
+	sun6i-a31s-inet-q972.dtb \
+	sun6i-a31s-primo81.dtb \
+	sun6i-a31s-sina31s.dtb \
+	sun6i-a31s-sinovoip-bpi-m2.dtb \
+	sun6i-a31s-yones-toptech-bs1078-v2.dtb
+dtb-$(CONFIG_MACH_SUN7I) += \
+	sun7i-a20-ainol-aw1.dtb \
+	sun7i-a20-bananapi.dtb \
+	sun7i-a20-bananapi-m1-plus.dtb \
+	sun7i-a20-bananapro.dtb \
+	sun7i-a20-cubieboard2.dtb \
+	sun7i-a20-cubietruck.dtb \
+	sun7i-a20-hummingbird.dtb \
+	sun7i-a20-i12-tvbox.dtb \
+	sun7i-a20-icnova-swac.dtb \
+	sun7i-a20-itead-ibox.dtb \
+	sun7i-a20-lamobo-r1.dtb \
+	sun7i-a20-m3.dtb \
+	sun7i-a20-m5.dtb \
+	sun7i-a20-mk808c.dtb \
+	sun7i-a20-olimex-som-evb.dtb \
+	sun7i-a20-olimex-som204-evb.dtb \
+	sun7i-a20-olimex-som204-evb-emmc.dtb \
+	sun7i-a20-olinuxino-lime.dtb \
+	sun7i-a20-olinuxino-lime2.dtb \
+	sun7i-a20-olinuxino-lime2-emmc.dtb \
+	sun7i-a20-olinuxino-micro.dtb \
+	sun7i-a20-orangepi.dtb \
+	sun7i-a20-orangepi-mini.dtb \
+	sun7i-a20-pcduino3.dtb \
+	sun7i-a20-pcduino3-nano.dtb \
+	sun7i-a20-primo73.dtb \
+	sun7i-a20-wexler-tab7200.dtb \
+	sun7i-a20-wits-pro-a20-dkt.dtb \
+	sun7i-a20-yones-toptech-bd1078.dtb
+dtb-$(CONFIG_MACH_SUN8I_A23) += \
+	sun8i-a23-evb.dtb \
+	sun8i-a23-gt90h-v4.dtb \
+	sun8i-a23-inet86dz.dtb \
+	sun8i-a23-polaroid-mid2407pxe03.dtb \
+	sun8i-a23-polaroid-mid2809pxe04.dtb \
+	sun8i-a23-q8-tablet.dtb
+dtb-$(CONFIG_MACH_SUN8I_A33) += \
+	sun8i-a33-ga10h-v1.1.dtb \
+	sun8i-a33-inet-d978-rev2.dtb \
+	sun8i-a33-olinuxino.dtb \
+	sun8i-a33-q8-tablet.dtb \
+	sun8i-a33-sinlinx-sina33.dtb \
+	sun8i-r16-bananapi-m2m.dtb \
+	sun8i-r16-nintendo-nes-classic-edition.dtb \
+	sun8i-r16-parrot.dtb
+dtb-$(CONFIG_MACH_SUN8I_A83T) += \
+	sun8i-a83t-allwinner-h8homlet-v2.dtb \
+	sun8i-a83t-bananapi-m3.dtb \
+	sun8i-a83t-cubietruck-plus.dtb \
+	sun8i-a83t-tbs-a711.dts
+dtb-$(CONFIG_MACH_SUN8I_H3) += \
+	sun8i-h2-plus-bananapi-m2-zero.dtb \
+	sun8i-h2-plus-libretech-all-h3-cc.dtb \
+	sun8i-h2-plus-orangepi-r1.dtb \
+	sun8i-h2-plus-orangepi-zero.dtb \
+	sun8i-h3-bananapi-m2-plus.dtb \
+	sun8i-h3-libretech-all-h3-cc.dtb \
+	sun8i-h3-nanopi-m1.dtb \
+	sun8i-h3-nanopi-m1-plus.dtb \
+	sun8i-h3-nanopi-neo.dtb \
+	sun8i-h3-nanopi-neo-air.dtb \
+	sun8i-h3-orangepi-2.dtb \
+	sun8i-h3-orangepi-lite.dtb \
+	sun8i-h3-orangepi-one.dtb \
+	sun8i-h3-orangepi-pc.dtb \
+	sun8i-h3-orangepi-pc-plus.dtb \
+	sun8i-h3-orangepi-plus.dtb \
+	sun8i-h3-orangepi-plus2e.dtb
+dtb-$(CONFIG_MACH_SUN8I_R40) += \
+	sun8i-r40-bananapi-m2-ultra.dtb \
+	sun8i-v40-bananapi-m2-berry.dtb
+dtb-$(CONFIG_MACH_SUN8I_V3S) += \
+	sun8i-v3s-licheepi-zero.dtb
+dtb-$(CONFIG_MACH_SUN50I_H5) += \
+	sun50i-h5-libretech-all-h3-cc.dtb \
+	sun50i-h5-nanopi-neo2.dtb \
+	sun50i-h5-nanopi-neo-plus2.dtb \
+	sun50i-h5-orangepi-zero-plus.dtb \
+	sun50i-h5-orangepi-pc2.dtb \
+	sun50i-h5-orangepi-prime.dtb \
+	sun50i-h5-orangepi-zero-plus2.dtb
+dtb-$(CONFIG_MACH_SUN50I_H6) += \
+	sun50i-h6-orangepi-lite2.dtb \
+	sun50i-h6-orangepi-one-plus.dtb \
+	sun50i-h6-pine-h64.dtb
+dtb-$(CONFIG_MACH_SUN50I) += \
+	sun50i-a64-amarula-relic.dtb \
+	sun50i-a64-bananapi-m64.dtb \
+	sun50i-a64-nanopi-a64.dtb \
+	sun50i-a64-olinuxino.dtb \
+	sun50i-a64-orangepi-win.dtb \
+	sun50i-a64-pine64-plus.dtb \
+	sun50i-a64-pine64.dtb \
+	sun50i-a64-pinebook.dtb \
+	sun50i-a64-sopine-baseboard.dtb
+dtb-$(CONFIG_MACH_SUN9I) += \
+	sun9i-a80-optimus.dtb \
+	sun9i-a80-cubieboard4.dtb \
+	sun9i-a80-cx-a99.dtb
+
+dtb-$(CONFIG_VF610) += vf500-colibri.dtb \
+	vf610-colibri.dtb \
+	vf610-twr.dtb \
+	pcm052.dtb \
+	bk4r1.dtb
+
+dtb-$(CONFIG_MX53) += imx53-cx9020.dtb
+
+dtb-$(CONFIG_MX6QDL) += \
+	imx6dl-icore.dtb \
+	imx6dl-icore-mipi.dtb \
+	imx6dl-icore-rqs.dtb \
+	imx6dl-mamoj.dtb \
+	imx6q-cm-fx6.dtb \
+	imx6q-icore.dtb \
+	imx6q-icore-mipi.dtb \
+	imx6q-icore-rqs.dtb \
+	imx6q-logicpd.dtb
+
+dtb-$(CONFIG_MX6SL) += imx6sl-evk.dtb
+
+dtb-$(CONFIG_MX6SL) += imx6sll-evk.dtb
+
+dtb-$(CONFIG_MX6SX) += \
+	imx6sx-sabreauto.dtb \
+	imx6sx-sdb.dtb
+
+dtb-$(CONFIG_MX6UL) += \
+	imx6ul-geam.dtb \
+	imx6ul-isiot-emmc.dtb \
+	imx6ul-isiot-nand.dtb \
+	imx6ul-opos6uldev.dtb \
+	imx6ul-14x14-evk.dtb \
+	imx6ul-9x9-evk.dtb
+
+dtb-$(CONFIG_MX6ULL) += imx6ull-14x14-evk.dtb
+
+dtb-$(CONFIG_MX7) += imx7-colibri.dtb \
+	imx7d-sdb.dtb \
+	imx7d-sdb-qspi.dtb
+
+dtb-$(CONFIG_ARCH_MX7ULP) += imx7ulp-evk.dtb
+
+dtb-$(CONFIG_ARCH_IMX8) += fsl-imx8qxp-mek.dtb
+
+dtb-$(CONFIG_ARCH_IMX8M) += fsl-imx8mq-evk.dtb
+
+dtb-$(CONFIG_RCAR_GEN3) += \
+	r8a7795-h3ulcb-u-boot.dtb \
+	r8a7795-salvator-x-u-boot.dtb \
+	r8a7796-m3ulcb-u-boot.dtb \
+	r8a7796-salvator-x-u-boot.dtb \
+	r8a77965-salvator-x-u-boot.dtb \
+	r8a77970-eagle-u-boot.dtb \
+	r8a77990-ebisu-u-boot.dtb \
+	r8a77995-draak-u-boot.dtb
+
+dtb-$(CONFIG_SOC_KEYSTONE) += keystone-k2hk-evm.dtb \
+	keystone-k2l-evm.dtb \
+	keystone-k2e-evm.dtb \
+	keystone-k2g-evm.dtb \
+	keystone-k2g-generic.dtb \
+	keystone-k2g-ice.dtb
+
+dtb-$(CONFIG_TARGET_AT91SAM9261EK) += at91sam9261ek.dtb
+
+dtb-$(CONFIG_TARGET_PM9263) += at91sam9263ek.dtb
+
+dtb-$(CONFIG_TARGET_AT91SAM9263EK) += at91sam9263ek.dtb
+
+dtb-$(CONFIG_TARGET_AT91SAM9RLEK) += at91sam9rlek.dtb
+
+dtb-$(CONFIG_TARGET_AT91SAM9260EK) += \
+	at91sam9260ek.dtb	\
+	at91sam9g20ek.dtb	\
+	at91sam9g20ek_2mmc.dtb
+
+dtb-$(CONFIG_TARGET_AT91SAM9M10G45EK) += at91sam9m10g45ek.dtb
+
+dtb-$(CONFIG_TARGET_AT91SAM9X5EK) += \
+	at91sam9g15ek.dtb	\
+	at91sam9g25ek.dtb	\
+	at91sam9g35ek.dtb	\
+	at91sam9x25ek.dtb	\
+	at91sam9x35ek.dtb
+
+dtb-$(CONFIG_TARGET_AT91SAM9N12EK) += at91sam9n12ek.dtb
+
+dtb-$(CONFIG_TARGET_OMAP3_LOGIC) += \
+	logicpd-torpedo-37xx-devkit.dtb \
+	logicpd-som-lv-37xx-devkit.dtb
+
+dtb-$(CONFIG_TARGET_OMAP3_EVM) += \
+	omap3-evm-37xx.dtb \
+	omap3-evm.dtb
+
+dtb-$(CONFIG_TARGET_OMAP3_BEAGLE) += \
+	omap3-beagle-xm-ab.dtb \
+	omap3-beagle-xm.dtb \
+	omap3-beagle.dtb
+
+dtb-$(CONFIG_TARGET_SAMA5D2_PTC_EK) += \
+	at91-sama5d2_ptc_ek.dtb
+
+dtb-$(CONFIG_TARGET_SAMA5D2_XPLAINED) += \
+	at91-sama5d2_xplained.dtb
+
+dtb-$(CONFIG_TARGET_SAMA5D27_SOM1_EK) += \
+	at91-sama5d27_som1_ek.dtb
+
+dtb-$(CONFIG_TARGET_SAMA5D3XEK) += \
+	sama5d31ek.dtb \
+	sama5d33ek.dtb \
+	sama5d34ek.dtb \
+	sama5d35ek.dtb \
+	sama5d36ek.dtb \
+	sama5d36ek_cmp.dtb
+
+dtb-$(CONFIG_TARGET_SAMA5D3_XPLAINED) += \
+	at91-sama5d3_xplained.dtb
+
+dtb-$(CONFIG_TARGET_SAMA5D4EK) += \
+	at91-sama5d4ek.dtb
+
+dtb-$(CONFIG_TARGET_SAMA5D4_XPLAINED) += \
+	at91-sama5d4_xplained.dtb
+
+dtb-$(CONFIG_TARGET_VINCO) += \
+	at91-vinco.dtb
+
+dtb-$(CONFIG_ARCH_BCM283X) += \
+	bcm2835-rpi-a-plus.dtb \
+	bcm2835-rpi-a.dtb \
+	bcm2835-rpi-b-plus.dtb \
+	bcm2835-rpi-b-rev2.dtb \
+	bcm2835-rpi-b.dtb \
+	bcm2836-rpi-2-b.dtb \
+	bcm2837-rpi-3-b.dtb
+
+dtb-$(CONFIG_ARCH_ASPEED) += ast2500-evb.dtb
+
+dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb
+
+dtb-$(CONFIG_TARGET_STM32MP1) += \
+	stm32mp157c-ed1.dtb \
+	stm32mp157c-ev1.dtb
+
+dtb-$(CONFIG_SOC_K3_AM6) += k3-am654-base-board.dtb k3-am654-r5-base-board.dtb
+
+dtb-$(CONFIG_ARCH_MEDIATEK) += \
+	mt7623n-bananapi-bpi-r2.dtb \
+	mt7629-rfb.dtb
+
+targets += $(dtb-y)
+
+# Add any required device tree compiler flags here
+DTC_FLAGS +=
+
+PHONY += dtbs
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+	@:
+
+clean-files := *.dtb
diff --git a/arch/arm/dts/am335x-baltos.dts b/arch/arm/dts/am335x-baltos.dts
new file mode 100644
index 0000000..f939cf6
--- /dev/null
+++ b/arch/arm/dts/am335x-baltos.dts
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * VScom OnRISC
+ * http://www.vscom.de
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	model = "OnRISC Baltos";
+	compatible = "vscom,onrisc", "ti,am33xx";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+};
+
+&am33xx_pinmux {
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0xf0 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat3.mmc0_dat3 */
+			0xf4 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat2.mmc0_dat2 */
+			0xf8 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat1.mmc0_dat1 */
+			0xfc (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat0.mmc0_dat0 */
+			0x100 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_clk.mmc0_clk */
+			0x104 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_cmd.mmc0_cmd */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x158 0x2a      /* spi0_d1.i2c1_sda_mux3, INPUT | MODE2 */
+			0x15c 0x2a      /* spi0_cs0.i2c1_scl_mux3, INPUT | MODE2 */
+		>;
+	};
+
+	tps65910_pins: pinmux_tps65910_pins {
+		pinctrl-single,pins = <
+			0x078 (PIN_INPUT_PULLUP | MUX_MODE7)      /* gpmc_ben1.gpio1[28] */
+		>;
+
+	};
+	tca6416_pins: pinmux_tca6416_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)		/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1)       /* mii1_crs.rmii1_crs_dv */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_tx_en.rmii1_txen */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd1.rmii1_txd1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd0.rmii1_txd0 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd1.rmii1_rxd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd0.rmii1_rxd0 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0)      /* rmii1_ref_clk.rmii1_refclk */
+
+
+			/* Slave 2 */
+			0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
+			0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value*/
+			0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	nandflash_pins_s0: nandflash_pins_s0 {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins_s0>;
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+	status = "okay";
+
+	nand@0,0 {
+		reg = <0 0 0>; /* CS0, offset 0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		ti,nand-xfer-type = "polled";
+
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+
+		boot@0 {
+		       label = "SPL";
+		       reg = <0x0 0x20000>;
+		};
+		boot@20000{
+		       label = "SPL.backup1";
+		       reg = <0x20000 0x20000>;
+		};
+		boot@40000 {
+		       label = "SPL.backup2";
+		       reg = <0x40000 0x20000>;
+		};
+		boot@60000 {
+		       label = "SPL.backup3";
+		       reg = <0x60000 0x20000>;
+		};
+		boot@80000 {
+		       label = "u-boot";
+		       reg = <0x80000 0x1e0000>;
+		};
+		boot@260000 {
+		       label = "UBI";
+		       reg = <0x260000 0xfda0000>;
+		};
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+	clock-frequency = <1000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tps65910_pins>;
+	};
+
+	at24@50 {
+		compatible = "at24,24c02";
+		pagesize = <8>;
+		reg = <0x50>;
+	};
+
+	tca6416: gpio@20 {
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <20 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tca6416_pins>;
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+/include/ "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	ti,en-ck32k-xtal = <1>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	dual_emac = <1>;
+
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <7>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <2>;
+};
+
+&phy_sel {
+	rmii-clock-ext = <1>;
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&vmmc_reg>;
+	status = "okay";
+};
+
+&gpio0 {
+	ti,no-reset-on-init;
+};
diff --git a/arch/arm/dts/am335x-bone-common.dtsi b/arch/arm/dts/am335x-bone-common.dtsi
new file mode 100644
index 0000000..40a3c35
--- /dev/null
+++ b/arch/arm/dts/am335x-bone-common.dtsi
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&dcdc2_reg>;
+		};
+	};
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds_s0>;
+
+		compatible = "gpio-leds";
+
+		led@2 {
+			label = "beaglebone:green:heartbeat";
+			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "beaglebone:green:mmc0";
+			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led@4 {
+			label = "beaglebone:green:usr2";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led@5 {
+			label = "beaglebone:green:usr3";
+			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&clkout2_pin>;
+
+	user_leds_s0: user_leds_s0 {
+		pinctrl-single,pins = <
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+			0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			0x178 (PIN_INPUT_PULLUP | MUX_MODE3)	/* uart1_ctsn.i2c2_sda */
+			0x17c (PIN_INPUT_PULLUP | MUX_MODE3)	/* uart1_rtsn.i2c2_scl */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x110 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxerr.mii1_rxerr */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txen.mii1_txen */
+			0x118 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxdv.mii1_rxdv */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd3.mii1_txd3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd2.mii1_txd2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd1.mii1_txd1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd0.mii1_txd0 */
+			0x12c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_txclk.mii1_txclk */
+			0x130 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxclk.mii1_rxclk */
+			0x134 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd3.mii1_rxd3 */
+			0x138 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd2.mii1_rxd2 */
+			0x13c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd1.mii1_rxd1 */
+			0x140 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd0.mii1_rxd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
+		>;
+	};
+
+	emmc_pins: pinmux_emmc_pins {
+		pinctrl-single,pins = <
+			0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+			0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+			0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+			0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+			0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+			0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "peripheral";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
+	baseboard_eeprom: baseboard_eeprom@50 {
+		compatible = "at,24c256";
+		reg = <0x50>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		baseboard_data: baseboard_data@0 {
+			reg = <0 0x100>;
+		};
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+
+	status = "okay";
+	clock-frequency = <100000>;
+
+	cape_eeprom0: cape_eeprom0@54 {
+		compatible = "at,24c256";
+		reg = <0x54>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		cape0_data: cape_data@0 {
+			reg = <0 0x100>;
+		};
+	};
+
+	cape_eeprom1: cape_eeprom1@55 {
+		compatible = "at,24c256";
+		reg = <0x55>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		cape1_data: cape_data@0 {
+			reg = <0 0x100>;
+		};
+	};
+
+	cape_eeprom2: cape_eeprom2@56 {
+		compatible = "at,24c256";
+		reg = <0x56>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		cape2_data: cape_data@0 {
+			reg = <0 0x100>;
+		};
+	};
+
+	cape_eeprom3: cape_eeprom3@57 {
+		compatible = "at,24c256";
+		reg = <0x57>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		cape3_data: cape_data@0 {
+			reg = <0 0x100>;
+		};
+	};
+};
+
+
+/include/ "tps65217.dtsi"
+
+&tps {
+	/*
+	 * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
+	 * mode") at poweroff.  Most BeagleBone versions do not support RTC-only
+	 * mode and risk hardware damage if this mode is entered.
+	 *
+	 * For details, see linux-omap mailing list May 2015 thread
+	 *	[PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
+	 * In particular, messages:
+	 *	http://www.spinics.net/lists/linux-omap/msg118585.html
+	 *	http://www.spinics.net/lists/linux-omap/msg118615.html
+	 *
+	 * You can override this later with
+	 *	&tps {  /delete-property/ ti,pmic-shutdown-controller;  }
+	 * if you want to use RTC-only mode and made sure you are not affected
+	 * by the hardware problems. (Tip: double-check by performing a current
+	 * measurement after shutdown: it should be less than 1 mA.)
+	 */
+	ti,pmic-shutdown-controller;
+
+	regulators {
+		dcdc1_reg: regulator@0 {
+			regulator-name = "vdds_dpr";
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			regulator-name = "vio,vrtc,vdds";
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			regulator-name = "vdd_3v3aux";
+			regulator-always-on;
+		};
+
+		ldo3_reg: regulator@5 {
+			regulator-name = "vdd_1v8";
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			regulator-name = "vdd_3v3a";
+			regulator-always-on;
+		};
+	};
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "mii";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "mii";
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&mmc1 {
+	status = "okay";
+	bus-width = <0x4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&aes {
+	status = "okay";
+};
+
+&sham {
+	status = "okay";
+};
diff --git a/arch/arm/dts/am335x-bone.dts b/arch/arm/dts/am335x-bone.dts
new file mode 100644
index 0000000..6b84937
--- /dev/null
+++ b/arch/arm/dts/am335x-bone.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+/ {
+	model = "TI AM335x BeagleBone";
+	compatible = "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-always-on;
+};
+
+&mmc1 {
+	vmmc-supply = <&ldo3_reg>;
+};
diff --git a/arch/arm/dts/am335x-boneblack.dts b/arch/arm/dts/am335x-boneblack.dts
new file mode 100644
index 0000000..27ebe4a
--- /dev/null
+++ b/arch/arm/dts/am335x-boneblack.dts
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+/ {
+	model = "TI AM335x BeagleBone Black";
+	compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+};
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins>;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&am33xx_pinmux {
+	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+		pinctrl-single,pins = <
+			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+			0xa0 0x08       /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xa4 0x08       /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xa8 0x08       /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xac 0x08       /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xb0 0x08       /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xb4 0x08       /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xb8 0x08       /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xbc 0x08       /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xc0 0x08       /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xc4 0x08       /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xc8 0x08       /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xcc 0x08       /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xd0 0x08       /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xd4 0x08       /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xd8 0x08       /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xdc 0x08       /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xe0 0x00       /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+			0xe4 0x00       /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+			0xe8 0x00       /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+			0xec 0x00       /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+		>;
+	};
+	nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+		pinctrl-single,pins = <
+			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+		>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+/ {
+	hdmi {
+		compatible = "ti,tilcdc,slave";
+		i2c = <&i2c0>;
+		pinctrl-names = "default", "off";
+		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+		status = "okay";
+	};
+};
+
+&rtc {
+	system-power-controller;
+};
diff --git a/arch/arm/dts/am335x-bonegreen.dts b/arch/arm/dts/am335x-bonegreen.dts
new file mode 100644
index 0000000..9c59da9
--- /dev/null
+++ b/arch/arm/dts/am335x-bonegreen.dts
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+/ {
+	model = "TI AM335x BeagleBone Green";
+	compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+};
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins>;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&am33xx_pinmux {
+	uart2_pins: uart2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)	/* spi0_sclk.uart2_rxd */
+			AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)	/* spi0_d0.uart2_txd */
+		>;
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+	status = "okay";
+};
+
+&rtc {
+	system-power-controller;
+};
diff --git a/arch/arm/dts/am335x-brppt1-mmc.dts b/arch/arm/dts/am335x-brppt1-mmc.dts
new file mode 100644
index 0000000..9be34d9
--- /dev/null
+++ b/arch/arm/dts/am335x-brppt1-mmc.dts
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 B&R Industrial Automation GmbH
+ * http://www.br-automation.com
+ *
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	model = "BRPPT1 (MMC) Panel";
+	compatible = "ti,am33xx";
+
+	fset: factory-settings {
+		bl-version	= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890";
+		version		= <0x0100>;
+		order-no	= "6PPT30 (MMC)";
+		hw-revision	= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890";
+		serial-no	= "0";
+		device-id	= <0x0>;
+		parent-id	= <0x0>;
+		hw-variant	= <0x1>;
+	};
+
+	aliases {
+		ds1bkl0 = &pwmbacklight;
+		ds1bkl1 = &tps_bl;
+		ds1timing = &timing0;
+		ds1ctrl = &lcdc;
+		gpmc = &gpmc;
+		mmc = &mmc2;
+		fset = &fset;
+	};
+
+	chosen {
+		bootargs = "console=ttyO0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	panel {
+		status = "disabled";
+
+		compatible = "ti,tilcdc,panel";
+		enable-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+
+		backlight = <&pwmbacklight>;
+		bkl-pwm = <&pwmbacklight>;
+		bkl-tps = <&tps_bl>;
+
+		panel-info {
+			ac-bias		= <255>;
+			ac-bias-intrpt	= <0>;
+			dma-burst-sz	= <16>;
+			bpp		= <32>;
+			fdd		= <0x80>;
+			sync-edge	= <0>;
+			sync-ctrl	= <1>;
+			raster-order	= <0>;
+			fifo-th		= <0>;
+		};
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: lcd {
+				clock-frequency	= <32000000>;
+				hactive		= <800>;
+				vactive		= <480>;
+				hfront-porch	= <2>;
+				hback-porch	= <192>;
+				hsync-len	= <1>;
+				vfront-porch	= <20>;
+				vback-porch	= <2>;
+				vsync-len	= <1>;
+				hsync-active	= <1>;
+				vsync-active	= <1>;
+				pupdelay	= <10>;
+				pondelay	= <10>;
+			};
+		};
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	pwm0: omap-pwm@timer5 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer5>;
+		#pwm-cells = <3>;
+	};
+
+	pwm1: omap-pwm@timer6 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer6>;
+		#pwm-cells = <3>;
+	};
+
+	beeper: pwm-beep {
+		compatible = "pwm-beeper";
+		pwms = <&pwm0 0 0 0>;
+	};
+
+	pwmbacklight: pwm-bkl {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000 0>;
+
+		default-brightness-level = <255>;
+		brightness-levels = <0 16 32 64 128 170 202 234 255>;
+
+		power-supply = <&vmmcsd_fixed>;
+		enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&uart0 {		/* console uart */
+	u-boot,dm-spl;
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&i2c0 {
+	u-boot,dm-spl;
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@24 {		/* PMIC controller */
+		u-boot,dm-spl;
+		reg = <0x24>;
+		compatible = "ti,tps65217";
+
+		tps_bl: backlight {
+			compatible = "ti,tps65217-bl";
+			isel = <1>;	/* 1 - ISET1, 2 ISET2 */
+			fdim = <1000>;	/* TPS65217_BL_FDIM_1kHZ */
+			default-brightness = <50>;
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&edma {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&davinci_mdio {
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <1>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <2>;
+	};
+};
+
+&mac {
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy-handle = <&phy0>;
+	dual_emac_res_vlan = <1>;
+	phy-mode = "mii";
+};
+
+&cpsw_emac1 {
+	phy-handle = <&phy1>;
+	dual_emac_res_vlan = <2>;
+	phy-mode = "mii";
+};
+
+&mmc1 {
+	u-boot,dm-spl;
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <0x4>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	ti,vcc-aux-disable-is-sleep;
+	status = "okay";
+};
+
+&mmc2 {
+	u-boot,dm-spl;
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <0x8>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	ti,vcc-aux-disable-is-sleep;
+	status = "okay";
+};
+
+&lcdc {
+	status = "disabled";
+};
+
+&elm {
+	status = "okay";
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&gpio0 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio1 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio2 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio3 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&wdt2 {
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,zx-cutoff-ratio = <40>;
+		ti,min_deviation = <60>;
+		ti,max_deviation = <600>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+
+		bnr-buttons {
+			Home-Button {};
+		};
+	};
+
+	adc {
+		ti,adc-channels = <5 6 7>;
+	};
+};
+
+&timer6 {		/* used for cpsw end device */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer7 {		/* used for cpsw end device */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&wdt2 {
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&tscadc {
+	status = "okay";
+};
+
+&dcan0 {
+	status = "okay";
+};
+
+&dcan1 {
+	status = "okay";
+};
+
+&sham {
+	status = "disabled";
+};
+
+&aes {
+	status = "disabled";
+};
+
+&rng {
+	status = "disabled";
+};
diff --git a/arch/arm/dts/am335x-brppt1-nand.dts b/arch/arm/dts/am335x-brppt1-nand.dts
new file mode 100644
index 0000000..11bd5c5
--- /dev/null
+++ b/arch/arm/dts/am335x-brppt1-nand.dts
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 B&R Industrial Automation GmbH
+ * http://www.br-automation.com
+ *
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	model = "BRPPT1 (NAND) Panel";
+	compatible = "ti,am33xx";
+
+	fset: factory-settings {
+		bl-version	= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890";
+		version		= <0x0100>;
+		order-no	= "6PPT30 (NAND)";
+		hw-revision	= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890";
+		serial-no	= "0";
+		device-id	= <0x0>;
+		parent-id	= <0x0>;
+		hw-variant	= <0x1>;
+	};
+
+	aliases {
+		ds1bkl0 = &pwmbacklight;
+		ds1bkl1 = &tps_bl;
+		ds1timing = &timing0;
+		ds1ctrl = &lcdc;
+		gpmc = &gpmc;
+		mmc = &mmc2;
+		fset = &fset;
+	};
+
+	chosen {
+		bootargs = "console=ttyO0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	panel {
+		status = "disabled";
+
+		compatible = "ti,tilcdc,panel";
+		enable-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+
+		backlight = <&pwmbacklight>;
+		bkl-pwm = <&pwmbacklight>;
+		bkl-tps = <&tps_bl>;
+
+		panel-info {
+			ac-bias		= <255>;
+			ac-bias-intrpt	= <0>;
+			dma-burst-sz	= <16>;
+			bpp		= <32>;
+			fdd		= <0x80>;
+			sync-edge	= <0>;
+			sync-ctrl	= <1>;
+			raster-order	= <0>;
+			fifo-th		= <0>;
+		};
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: lcd {
+				clock-frequency	= <32000000>;
+				hactive		= <800>;
+				vactive		= <480>;
+				hfront-porch	= <2>;
+				hback-porch	= <192>;
+				hsync-len	= <1>;
+				vfront-porch	= <20>;
+				vback-porch	= <2>;
+				vsync-len	= <1>;
+				hsync-active	= <1>;
+				vsync-active	= <1>;
+				pupdelay	= <10>;
+				pondelay	= <10>;
+			};
+		};
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	pwm0: omap-pwm@timer5 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer5>;
+		#pwm-cells = <3>;
+	};
+
+	pwm1: omap-pwm@timer6 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer6>;
+		#pwm-cells = <3>;
+	};
+
+	beeper: pwm-beep {
+		compatible = "pwm-beeper";
+		pwms = <&pwm0 0 0 0>;
+	};
+
+	pwmbacklight: pwm-bkl {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000 0>;
+
+		default-brightness-level = <255>;
+		brightness-levels = <0 16 32 64 128 170 202 234 255>;
+
+		power-supply = <&vmmcsd_fixed>;
+		enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&uart0 {		/* console uart */
+	u-boot,dm-spl;
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&i2c0 {
+	u-boot,dm-spl;
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@24 {		/* PMIC controller */
+		u-boot,dm-spl;
+		reg = <0x24>;
+		compatible = "ti,tps65217";
+
+		tps_bl: backlight {
+			compatible = "ti,tps65217-bl";
+			isel = <1>;	/* 1 - ISET1, 2 ISET2 */
+			fdim = <1000>;	/* TPS65217_BL_FDIM_1kHZ */
+			default-brightness = <50>;
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&edma {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&davinci_mdio {
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <1>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <2>;
+	};
+};
+
+&mac {
+	dual_emac;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy-handle = <&phy0>;
+	dual_emac_res_vlan = <1>;
+	phy-mode = "mii";
+};
+
+&cpsw_emac1 {
+	phy-handle = <&phy1>;
+	dual_emac_res_vlan = <2>;
+	phy-mode = "mii";
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <0x4>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	ti,vcc-aux-disable-is-sleep;
+	status = "disabled";
+};
+
+&lcdc {
+	status = "disabled";
+};
+
+&elm {
+	status = "okay";
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&gpio0 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio1 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio2 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio3 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&wdt2 {
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,zx-cutoff-ratio = <40>;
+		ti,min_deviation = <60>;
+		ti,max_deviation = <600>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+
+		bnr-buttons {
+			Home-Button {};
+		};
+	};
+
+	adc {
+		ti,adc-channels = <5 6 7>;
+	};
+};
+
+&gpmc {
+	u-boot,dm-spl;
+	status = "okay";
+	pinctrl-names = "default";
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		interrupt-parent = <&gpmc>;
+		rb-gpios = <&gpmc 1 GPIO_ACTIVE_HIGH>; /* gpmc_wait1 */
+		ti,nand-ecc-opt = "bch8";
+		ti,elm-id = <&elm>;
+		nand-bus-width = <8>;
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+		gpmc,wait-pin = <1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "NAND.MLO";
+			reg = <0x00000000 0x000020000>;
+		};
+		partition@1 {
+			label = "NAND.cfgscr";
+			reg = <0x00020000 0x00020000>;
+		};
+		partition@2 {
+			label = "NAND.dtb";
+			reg = <0x00040000 0x00020000>;
+		};
+		partition@3 {
+			label = "NAND.u-boot-env";
+			reg = <0x00060000 0x00020000>;
+		};
+		partition@4 {
+			label = "NAND.u-boot";
+			reg = <0x00080000 0x00080000>;
+		};
+		partition@5 {
+			label = "NAND.kernel";
+			reg = <0x00100000 0x00400000>;
+		};
+		partition@6 {
+			label = "NAND.rootfs";
+			reg = <0x00500000 0x08000000>;
+		};
+		partition@7 {
+			label = "NAND.user";
+			reg = <0x08500000 0x17b00000>;
+		};
+	};
+};
diff --git a/arch/arm/dts/am335x-brppt1-spi.dts b/arch/arm/dts/am335x-brppt1-spi.dts
new file mode 100644
index 0000000..522ed50
--- /dev/null
+++ b/arch/arm/dts/am335x-brppt1-spi.dts
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 B&R Industrial Automation GmbH
+ * http://www.br-automation.com
+ *
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	model = "BRPPT1 (MMC) Panel";
+	compatible = "ti,am33xx";
+
+	fset: factory-settings {
+		bl-version	= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890";
+		version		= <0x0100>;
+		order-no	= "6PPT30 (SPI)";
+		hw-revision	= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890";
+		serial-no	= "0";
+		device-id	= <0x0>;
+		parent-id	= <0x0>;
+		hw-variant	= <0x1>;
+	};
+
+	aliases {
+		ds1bkl0 = &pwmbacklight;
+		ds1bkl1 = &tps_bl;
+		ds1timing = &timing0;
+		ds1ctrl = &lcdc;
+		gpmc = &gpmc;
+		mmc = &mmc2;
+		spi0 = &spi0;
+		fset = &fset;
+	};
+
+	chosen {
+		bootargs = "console=ttyO0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	panel {
+		status = "disabled";
+
+		compatible = "ti,tilcdc,panel";
+		enable-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+
+		backlight = <&pwmbacklight>;
+		bkl-pwm = <&pwmbacklight>;
+		bkl-tps = <&tps_bl>;
+
+		panel-info {
+			ac-bias		= <255>;
+			ac-bias-intrpt	= <0>;
+			dma-burst-sz	= <16>;
+			bpp		= <32>;
+			fdd		= <0x80>;
+			sync-edge	= <0>;
+			sync-ctrl	= <1>;
+			raster-order	= <0>;
+			fifo-th		= <0>;
+		};
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: lcd {
+				clock-frequency	= <32000000>;
+				hactive		= <800>;
+				vactive		= <480>;
+				hfront-porch	= <2>;
+				hback-porch	= <192>;
+				hsync-len	= <1>;
+				vfront-porch	= <20>;
+				vback-porch	= <2>;
+				vsync-len	= <1>;
+				hsync-active	= <1>;
+				vsync-active	= <1>;
+				pupdelay	= <10>;
+				pondelay	= <10>;
+			};
+		};
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	pwm0: omap-pwm@timer5 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer5>;
+		#pwm-cells = <3>;
+	};
+
+	pwm1: omap-pwm@timer6 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer6>;
+		#pwm-cells = <3>;
+	};
+
+	beeper: pwm-beep {
+		compatible = "pwm-beeper";
+		pwms = <&pwm0 0 0 0>;
+	};
+
+	pwmbacklight: pwm-bkl {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000 0>;
+
+		default-brightness-level = <255>;
+		brightness-levels = <0 16 32 64 128 170 202 234 255>;
+
+		power-supply = <&vmmcsd_fixed>;
+		enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&uart0 {		/* console uart */
+	u-boot,dm-spl;
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&i2c0 {
+	u-boot,dm-spl;
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@24 {		/* PMIC controller */
+		u-boot,dm-spl;
+		reg = <0x24>;
+		compatible = "ti,tps65217";
+
+		tps_bl: backlight {
+			compatible = "ti,tps65217-bl";
+			isel = <1>;	/* 1 - ISET1, 2 ISET2 */
+			fdim = <1000>;	/* TPS65217_BL_FDIM_1kHZ */
+			default-brightness = <50>;
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&spi0 {
+	u-boot,dm-spl;
+	status = "okay";
+
+	cs-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>,
+		   <&gpio0 6 GPIO_ACTIVE_HIGH>,
+		   <0>,
+		   <0>;
+
+	spi-max-frequency = <24000000>;
+
+	spi_flash: spiflash@0 {
+		u-boot,dm-spl;
+		u-boot,dm-pre-reloc;
+		compatible = "spidev", "spi-flash";
+		spi-max-frequency = <24000000>;
+		reg = <0>;
+	};
+};
+
+&edma {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&davinci_mdio {
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <1>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <2>;
+	};
+};
+
+&mac {
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy-handle = <&phy0>;
+	dual_emac_res_vlan = <1>;
+	phy-mode = "mii";
+};
+
+&cpsw_emac1 {
+	phy-handle = <&phy1>;
+	dual_emac_res_vlan = <2>;
+	phy-mode = "mii";
+};
+
+&mmc1 {
+	u-boot,dm-spl;
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <0x4>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	ti,vcc-aux-disable-is-sleep;
+	status = "okay";
+};
+
+&mmc2 {
+	u-boot,dm-spl;
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <0x8>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	ti,vcc-aux-disable-is-sleep;
+	status = "okay";
+};
+
+&lcdc {
+	status = "disabled";
+};
+
+&elm {
+	status = "okay";
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&gpio0 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio1 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio2 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&gpio3 {
+	u-boot,dm-spl;
+	ti,no-reset-on-init;
+};
+
+&wdt2 {
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,zx-cutoff-ratio = <40>;
+		ti,min_deviation = <60>;
+		ti,max_deviation = <600>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+
+		bnr-buttons {
+			Home-Button {};
+		};
+	};
+
+	adc {
+		ti,adc-channels = <5 6 7>;
+	};
+};
+
+&timer6 {		/* used for cpsw end device */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&timer7 {		/* used for cpsw end device */
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&wdt2 {
+	status = "okay";
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&tscadc {
+	status = "okay";
+};
+
+&dcan0 {
+	status = "okay";
+};
+
+&dcan1 {
+	status = "okay";
+};
+
+&sham {
+	status = "disabled";
+};
+
+&aes {
+	status = "disabled";
+};
+
+&rng {
+	status = "disabled";
+};
diff --git a/arch/arm/dts/am335x-chiliboard-u-boot.dtsi b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi
new file mode 100644
index 0000000..4f9d308
--- /dev/null
+++ b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+ or X11
+/*
+ * Copyright (C) 2018 Grinn Sp. z o.o. -- http://www.grinn-global.com/
+ * Author: Marcin Niestroj <m.niestroj@grinn-global.com>
+ */
+
+/ {
+	chosen {
+		stdout-path = &uart0;
+	};
+};
diff --git a/arch/arm/dts/am335x-chiliboard.dts b/arch/arm/dts/am335x-chiliboard.dts
new file mode 100644
index 0000000..59431b2
--- /dev/null
+++ b/arch/arm/dts/am335x-chiliboard.dts
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
+ * Author: Rostislav Lisovy <lisovy@jablotron.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "am335x-chilisom.dtsi"
+
+/ {
+	model = "AM335x Chiliboard";
+	compatible = "grinn,am335x-chiliboard", "grinn,am335x-chilisom",
+		     "ti,am33xx";
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_gpio_pins>;
+
+		led0 {
+			label = "led0";
+			gpios = <&gpio3 7 GPIO_ACTIVE_LOW>;
+			default-state = "keep";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led1 {
+			label = "led1";
+			gpios = <&gpio3 8 GPIO_ACTIVE_LOW>;
+			default-state = "keep";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)  /* mii1_crs.rmii1_crs */
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxerr.rmii1_rxerr */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txen.rmii1_txen */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd1.rmii1_txd1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd0.rmii1_txd0 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxd1.rmii1_rxd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxd0.rmii1_rxd0 */
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* rmii1_ref_clk.rmii_ref_clk */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
+			/* mdio_clk.mdio_clk */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	usb1_drvvbus: usb1_drvvbus {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */
+		>;
+	};
+
+	sd_pins: pinmux_sd_card {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+			AM33XX_IOPAD(0x8f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+			AM33XX_IOPAD(0x8f8, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+			AM33XX_IOPAD(0x8fc, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+			AM33XX_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+			AM33XX_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+			AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
+	led_gpio_pins: led_gpio_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9e4, PIN_OUTPUT | MUX_MODE7) /* emu0.gpio3_7 */
+			AM33XX_IOPAD(0x9e8, PIN_OUTPUT | MUX_MODE7) /* emu1.gpio3_8 */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&ldo4_reg {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+};
+
+/* Ethernet */
+&mac {
+	slaves = <1>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rmii";
+};
+
+&phy_sel {
+	rmii-clock-ext;
+};
+
+/* USB */
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb1_drvvbus>;
+
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+/* microSD */
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd_pins>;
+	vmmc-supply = <&ldo4_reg>;
+	bus-width = <0x4>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&tps {
+	interrupt-parent = <&intc>;
+	interrupts = <7>; /* NNMI */
+
+	charger {
+		status = "okay";
+	};
+
+	pwrbutton {
+		status = "okay";
+	};
+};
diff --git a/arch/arm/dts/am335x-chilisom.dtsi b/arch/arm/dts/am335x-chilisom.dtsi
new file mode 100644
index 0000000..1b43ebd
--- /dev/null
+++ b/arch/arm/dts/am335x-chilisom.dtsi
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
+ * Author: Rostislav Lisovy <lisovy@jablotron.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "am33xx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "Grinn AM335x ChiliSOM";
+	compatible = "grinn,am335x-chilisom", "ti,am33xx";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&dcdc2_reg>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	nandflash_pins: nandflash_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			AM33XX_IOPAD(0x810, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			AM33XX_IOPAD(0x814, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			AM33XX_IOPAD(0x818, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			AM33XX_IOPAD(0x81c, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+
+			AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* gpmc_csn0.gpmc_csn0 */
+			AM33XX_IOPAD(0x890, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* gpmc_advn_ale.gpmc_advn_ale */
+			AM33XX_IOPAD(0x894, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* gpmc_oen_ren.gpmc_oen_ren */
+			AM33XX_IOPAD(0x898, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* gpmc_wen.gpmc_wen */
+			AM33XX_IOPAD(0x89c, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+	regulators {
+		dcdc1_reg: regulator@0 {
+			regulator-name = "vdds_dpr";
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			regulator-name = "vio,vrtc,vdds";
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			regulator-name = "vdd_3v3aux";
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo3_reg: regulator@5 {
+			regulator-name = "vdd_1v8";
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			regulator-name = "vdd_3v3d";
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
+};
+
+&rtc {
+	system-power-controller;
+
+	pinctrl-0 = <&ext_wakeup>;
+	pinctrl-names = "default";
+
+	ext_wakeup: ext-wakeup {
+		pins = "ext_wakeup0";
+		input-enable;
+	};
+};
+
+/* NAND Flash */
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins>;
+	ranges = <0 0 0x08000000 0x01000000>; /* CS0 0 @addr 0x08000000, size 0x01000000 */
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>;	/* CS0, offset 0, IO size 4 */
+		interrupt-parent = <&gpmc>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
+		ti,nand-ecc-opt = "bch8";
+		ti,elm-id = <&elm>;
+		nand-bus-width = <8>;
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+	};
+};
diff --git a/arch/arm/dts/am335x-draco.dts b/arch/arm/dts/am335x-draco.dts
new file mode 100644
index 0000000..25d0480
--- /dev/null
+++ b/arch/arm/dts/am335x-draco.dts
@@ -0,0 +1,152 @@
+/*
+ * Support for Siemens DRACO board
+ *
+ * Copyright (C) 2014 - Lukas Stockmann <lukas.stockmann@siemens.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-draco.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Siemens DRACO";
+	compatible = "siemens,draco", "ti,am33xx";
+
+	/* ethernet alias is needed for the MAC address passing from U-Boot */
+	aliases {
+		ethernet0 = &cpsw_emac0;
+		mdio-gpio0 = &mdio0;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		button0 {
+			label = "button0";
+			gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_F1>; /* button0 */
+		};
+		button1 {
+			label = "button1";
+			gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_F2>; /* button1 */
+		};
+	};
+
+	ocp {
+		debugss: debugss@4b000000 {
+			compatible = "ti,debugss";
+			ti,hwmods = "debugss";
+			reg = <0x4b000000 1000000>;
+			status = "disabled";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpio_mux_pins>;
+
+	gpio_mux_pins: gpio_mux_pins {
+		pinctrl-single,pins = <
+			0x1d0 (PIN_INPUT | MUX_MODE0)	/* tms jtag */
+			0x1d4 (PIN_INPUT | MUX_MODE0)	/* tdi jtag */
+			0x1d8 (PIN_OUTPUT | MUX_MODE0)	/* tdo jtag */
+			0x1dc (PIN_INPUT | MUX_MODE0)	/* tck jtag */
+			0x1e0 (PIN_INPUT | MUX_MODE0)	/* trstn jtag */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			0x0E8 (PIN_INPUT_PULLUP | MUX_MODE7)	/* lcd_plck FIX STO should be a OUTPUT driven high*/
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_crs.rmii1_crs_dv */
+			0x114 (PIN_OUTPUT | MUX_MODE1)		/* mii1_txen.mii1_txen */
+			0x124 (PIN_OUTPUT | MUX_MODE1)		/* mii1_txd1.mii1_txd1 */
+			0x128 (PIN_OUTPUT | MUX_MODE1)		/* mii1_txd0.mii1_txd0 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd1.mii1_rxd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd0.mii1_rxd0 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* rmii1_refclk.rmii1_refclk */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	gpio_mdio_default: gpio_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO via GPIO */
+			0x148 (PIN_INPUT | MUX_MODE7)	/* mdio_data.mdio_data GPIO0_0 */
+			0x14c (PIN_OUTPUT | MUX_MODE7)	/* mdio_clk.mdio_clk GPIO0_1 */
+		>;
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	slaves = <1>;			/* use only one emac if */
+
+	mdio0: gpio {
+		compatible = "virtual,mdio-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_mdio_default>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+		gpios = <&gpio0 1 GPIO_ACTIVE_HIGH	/* MDIO-CLK */
+			 &gpio0 0 GPIO_ACTIVE_HIGH>;	/* MDIO-DATA */
+
+		phy0: ethernet-phy@1 {
+			reg = <0>;
+		};
+	};
+};
+
+/* Disable davinci/am335x mdio interface on this platform */
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "disabled";
+};
+
+&cpsw_emac0 {
+	phy_id = <&mdio0>, <0>;
+	phy-mode = "rmii";
+};
+
+&phy_sel {
+	rmii-clock-ext;
+};
diff --git a/arch/arm/dts/am335x-draco.dtsi b/arch/arm/dts/am335x-draco.dtsi
new file mode 100644
index 0000000..b38ff55
--- /dev/null
+++ b/arch/arm/dts/am335x-draco.dtsi
@@ -0,0 +1,169 @@
+/*
+ * Common support for Siemens Draco SOM (AM335x based)
+ *
+ * Copyright (C) 2013,2014 - Stefan Roese <sr@denx.de>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/ {
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x08000000>; /* 128 MB */
+	};
+
+	ocp {
+		uart0: serial@44e09000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins>;
+			status = "okay";
+		};
+
+		i2c0: i2c@44e0b000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins>;
+
+			status = "okay";
+			clock-frequency = <400000>;
+
+			eeprom: eeprom@50 {
+				compatible = "atmel,24c128";
+				reg = <0x50>;
+				pagesize = <64>;
+			};
+		};
+
+		musb: usb@47400000 {
+			status = "okay";
+
+			control@44e10620 {
+				status = "okay";
+			};
+
+			usb-phy@47401300 {
+				status = "okay";
+			};
+
+			usb-phy@47401b00 {
+				status = "okay";
+			};
+
+			usb@47401000 {
+				status = "okay";
+			};
+
+			usb@47401800 {
+				status = "okay";
+				dr_mode = "host";
+			};
+
+			dma-controller@47402000  {
+				status = "okay";
+			};
+		};
+	};
+};
+
+&am33xx_pinmux {
+		i2c0_pins: pinmux_i2c0_pins {
+			pinctrl-single,pins = <
+				0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+				0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+			>;
+		};
+
+		uart0_pins: pinmux_uart0_pins {
+			pinctrl-single,pins = <
+				0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+				0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+			>;
+		};
+
+		nandflash_pins: nandflash_pins {
+			pinctrl-single,pins = <
+				0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+				0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+				0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+				0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+				0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+				0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+				0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+				0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+				0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+				0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+				0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+				0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+				0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+				0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+				0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+			>;
+		};
+	};
+
+
+&timer3 {
+	status = "disabled";
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins>;
+
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+
+	nand@0,0 {
+		reg = <0 0 0>; /* CS0, offset 0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+	};
+};
+
+/* disable the RTC node as its not accessible on the draco/dxr2 board */
+&rtc {
+	status = "disabled";
+	ti,hwmods = "disabled";
+};
diff --git a/arch/arm/dts/am335x-evm-u-boot.dtsi b/arch/arm/dts/am335x-evm-u-boot.dtsi
new file mode 100644
index 0000000..0341600
--- /dev/null
+++ b/arch/arm/dts/am335x-evm-u-boot.dtsi
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+
+&mmc3 {
+	status = "disabled";
+};
diff --git a/arch/arm/dts/am335x-evm.dts b/arch/arm/dts/am335x-evm.dts
new file mode 100644
index 0000000..fe27207
--- /dev/null
+++ b/arch/arm/dts/am335x-evm.dts
@@ -0,0 +1,764 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "TI AM335x EVM";
+	compatible = "ti,am335x-evm", "ti,am33xx";
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	lis3_reg: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "lis3_reg";
+		regulator-boot-on;
+	};
+
+	wlan_en_reg: fixedregulator@2 {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+
+		/* WLAN_EN GPIO for this board - Bank1, pin16 */
+		gpio = <&gpio1 16 0>;
+
+		/* WLAN card specific delay */
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
+
+	matrix_keypad: matrix_keypad@0 {
+		compatible = "gpio-matrix-keypad";
+		debounce-delay-ms = <5>;
+		col-scan-delay-us = <2>;
+
+		row-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH		/* Bank1, pin25 */
+			     &gpio1 26 GPIO_ACTIVE_HIGH		/* Bank1, pin26 */
+			     &gpio1 27 GPIO_ACTIVE_HIGH>;	/* Bank1, pin27 */
+
+		col-gpios = <&gpio1 21 GPIO_ACTIVE_HIGH		/* Bank1, pin21 */
+			     &gpio1 22 GPIO_ACTIVE_HIGH>;	/* Bank1, pin22 */
+
+		linux,keymap = <0x0000008b	/* MENU */
+				0x0100009e	/* BACK */
+				0x02000069	/* LEFT */
+				0x0001006a	/* RIGHT */
+				0x0101001c	/* ENTER */
+				0x0201006c>;	/* DOWN */
+	};
+
+	gpio_keys: volume_keys@0 {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		switch@9 {
+			label = "volume-up";
+			linux,code = <115>;
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+			gpio-key,wakeup;
+		};
+
+		switch@10 {
+			label = "volume-down";
+			linux,code = <114>;
+			gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+			gpio-key,wakeup;
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 0>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
+
+	panel {
+		compatible = "ti,tilcdc,panel";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins_s0>;
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <32>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+
+		display-timings {
+			800x480p62 {
+				clock-frequency = <30000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <39>;
+				hback-porch = <39>;
+				hsync-len = <47>;
+				vback-porch = <29>;
+				vfront-porch = <13>;
+				vsync-len = <2>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+
+	sound {
+		compatible = "ti,da830-evm-audio";
+		ti,model = "AM335x-EVM";
+		ti,audio-codec = <&tlv320aic3106>;
+		ti,mcasp-controller = <&mcasp1>;
+		ti,codec-clock-rate = <12000000>;
+		ti,audio-routing =
+			"Headphone Jack",       "HPLOUT",
+			"Headphone Jack",       "HPROUT",
+			"LINE1L",               "Line In",
+			"LINE1R",               "Line In";
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>;
+
+	matrix_keypad_s0: matrix_keypad_s0 {
+		pinctrl-single,pins = <
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a9.gpio1_25 */
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a10.gpio1_26 */
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a11.gpio1_27 */
+		>;
+	};
+
+	volume_keys_s0: volume_keys_s0 {
+		pinctrl-single,pins = <
+			0x150 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* spi0_sclk.gpio0_2 */
+			0x154 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* spi0_d0.gpio0_3 */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x158 (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d1.i2c1_sda */
+			0x15c (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			0x178 (PIN_INPUT | MUX_MODE0)		/* uart1_ctsn.uart1_ctsn */
+			0x17C (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_rtsn.uart1_rtsn */
+			0x180 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_rxd.uart1_rxd */
+			0x184 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_txd.uart1_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	nandflash_pins_s0: nandflash_pins_s0 {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+
+	ecap0_pins: backlight_pins {
+		pinctrl-single,pins = <
+			0x164 0x0	/* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
+	mmc3_pins: pinmux_mmc3_pins {
+		pinctrl-single,pins = <
+			0x44 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_a1.mmc2_dat0, INPUT_PULLUP | MODE3 */
+			0x48 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_a2.mmc2_dat1, INPUT_PULLUP | MODE3 */
+			0x4C (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_a3.mmc2_dat2, INPUT_PULLUP | MODE3 */
+			0x78 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_ben1.mmc2_dat3, INPUT_PULLUP | MODE3 */
+			0x88 (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_csn3.mmc2_cmd, INPUT_PULLUP | MODE3 */
+			0x8C (PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_clk.mmc2_clk, INPUT_PULLUP | MODE3 */
+		>;
+	};
+
+	wlan_pins: pinmux_wlan_pins {
+		pinctrl-single,pins = <
+			0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a0.gpio1_16 */
+			0x19C (PIN_INPUT | MUX_MODE7)		/* mcasp0_ahclkr.gpio3_17 */
+			0x1AC (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* mcasp0_ahclkx.gpio3_21 */
+		>;
+	};
+
+	lcd_pins_s0: lcd_pins_s0 {
+		pinctrl-single,pins = <
+			0x20 (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad8.lcd_data23 */
+			0x24 (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad9.lcd_data22 */
+			0x28 (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad10.lcd_data21 */
+			0x2c (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad11.lcd_data20 */
+			0x30 (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad12.lcd_data19 */
+			0x34 (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad13.lcd_data18 */
+			0x38 (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad14.lcd_data17 */
+			0x3c (PIN_OUTPUT | MUX_MODE1)		/* gpmc_ad15.lcd_data16 */
+			0xa0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data0.lcd_data0 */
+			0xa4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data1.lcd_data1 */
+			0xa8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data2.lcd_data2 */
+			0xac (PIN_OUTPUT | MUX_MODE0)		/* lcd_data3.lcd_data3 */
+			0xb0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data4.lcd_data4 */
+			0xb4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data5.lcd_data5 */
+			0xb8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data6.lcd_data6 */
+			0xbc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data7.lcd_data7 */
+			0xc0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data8.lcd_data8 */
+			0xc4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data9.lcd_data9 */
+			0xc8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data10.lcd_data10 */
+			0xcc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data11.lcd_data11 */
+			0xd0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data12.lcd_data12 */
+			0xd4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data13.lcd_data13 */
+			0xd8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data14.lcd_data14 */
+			0xdc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data15.lcd_data15 */
+			0xe0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_vsync.lcd_vsync */
+			0xe4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_hsync.lcd_hsync */
+			0xe8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_pclk.lcd_pclk */
+			0xec (PIN_OUTPUT | MUX_MODE0)		/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+	am335x_evm_audio_pins: am335x_evm_audio_pins {
+		pinctrl-single,pins = <
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
+			0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
+		>;
+	};
+
+	dcan1_pins_default: dcan1_pins_default {
+		pinctrl-single,pins = <
+			0x168 (PIN_OUTPUT | MUX_MODE2) /* uart0_ctsn.d_can1_tx */
+			0x16c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart0_rtsn.d_can1_rx */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+	clock-frequency = <100000>;
+
+	lis331dlh: lis331dlh@18 {
+		compatible = "st,lis331dlh", "st,lis3lv02d";
+		reg = <0x18>;
+		Vdd-supply = <&lis3_reg>;
+		Vdd_IO-supply = <&lis3_reg>;
+
+		st,click-single-x;
+		st,click-single-y;
+		st,click-single-z;
+		st,click-thresh-x = <10>;
+		st,click-thresh-y = <10>;
+		st,click-thresh-z = <10>;
+		st,irq1-click;
+		st,irq2-click;
+		st,wakeup-x-lo;
+		st,wakeup-x-hi;
+		st,wakeup-y-lo;
+		st,wakeup-y-hi;
+		st,wakeup-z-lo;
+		st,wakeup-z-hi;
+		st,min-limit-x = <120>;
+		st,min-limit-y = <120>;
+		st,min-limit-z = <140>;
+		st,max-limit-x = <550>;
+		st,max-limit-y = <550>;
+		st,max-limit-z = <750>;
+	};
+
+	tsl2550: tsl2550@39 {
+		compatible = "taos,tsl2550";
+		reg = <0x39>;
+	};
+
+	tmp275: tmp275@48 {
+		compatible = "ti,tmp275";
+		reg = <0x48>;
+	};
+
+	tlv320aic3106: tlv320aic3106@1b {
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		status = "okay";
+
+		/* Regulators */
+		AVDD-supply = <&vaux2_reg>;
+		IOVDD-supply = <&vaux2_reg>;
+		DRVDD-supply = <&vaux2_reg>;
+		DVDD-supply = <&vbat>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&elm {
+	status = "okay";
+};
+
+&epwmss0 {
+	status = "okay";
+
+	ecap0: ecap@48300100 {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ecap0_pins>;
+	};
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins_s0>;
+	ranges = <0 0 0x08000000 0x1000000>;	/* CS0: 16MB for NAND */
+	nand@0,0 {
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		ti,nand-ecc-opt = "bch8";
+		ti,elm-id = <&elm>;
+		nand-bus-width = <8>;
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+		/* MTD partition table */
+		/* All SPL-* partitions are sized to minimal length
+		 * which can be independently programmable. For
+		 * NAND flash this is equal to size of erase-block */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "NAND.SPL";
+			reg = <0x00000000 0x000020000>;
+		};
+		partition@1 {
+			label = "NAND.SPL.backup1";
+			reg = <0x00020000 0x00020000>;
+		};
+		partition@2 {
+			label = "NAND.SPL.backup2";
+			reg = <0x00040000 0x00020000>;
+		};
+		partition@3 {
+			label = "NAND.SPL.backup3";
+			reg = <0x00060000 0x00020000>;
+		};
+		partition@4 {
+			label = "NAND.u-boot-spl-os";
+			reg = <0x00080000 0x00040000>;
+		};
+		partition@5 {
+			label = "NAND.u-boot";
+			reg = <0x000C0000 0x00100000>;
+		};
+		partition@6 {
+			label = "NAND.u-boot-env";
+			reg = <0x001C0000 0x00020000>;
+		};
+		partition@7 {
+			label = "NAND.u-boot-env.backup1";
+			reg = <0x001E0000 0x00020000>;
+		};
+		partition@8 {
+			label = "NAND.kernel";
+			reg = <0x00200000 0x00800000>;
+		};
+		partition@9 {
+			label = "NAND.file-system";
+			reg = <0x00A00000 0x0F600000>;
+		};
+	};
+};
+
+#include "tps65910.dtsi"
+
+&mcasp1 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&am335x_evm_audio_pins>;
+
+		status = "okay";
+
+		op-mode = <0>;          /* MCASP_IIS_MODE */
+		tdm-slots = <2>;
+		/* 4 serializers */
+		serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+			0 0 1 2
+		>;
+		tx-num-evt = <32>;
+		rx-num-evt = <32>;
+};
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii-txid";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii-txid";
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+		ti,charge-delay = <0x400>;
+	};
+
+	adc {
+		ti,adc-channels = <4 5 6 7>;
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&mmc3 {
+	/* these are on the crossbar and are outlined in the
+	   xbar-event-map element */
+	dmas = <&edma 12 0
+		&edma 13 0>;
+	dma-names = "tx", "rx";
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins &wlan_pins>;
+	ti,non-removable;
+	ti,needs-special-hs-handling;
+	cap-power-off-card;
+	keep-power-in-suspend;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@0 {
+		compatible = "ti,wl1835";
+		reg = <2>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&edma {
+	ti,edma-xbar-event-map = /bits/ 16 <1 12
+					    2 13>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&dcan1 {
+	status = "disabled";	/* Enable only if Profile 1 is selected */
+	pinctrl-names = "default";
+	pinctrl-0 = <&dcan1_pins_default>;
+};
diff --git a/arch/arm/dts/am335x-evmsk.dts b/arch/arm/dts/am335x-evmsk.dts
new file mode 100644
index 0000000..0767578
--- /dev/null
+++ b/arch/arm/dts/am335x-evmsk.dts
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * AM335x Starter Kit
+ * http://www.ti.com/tool/tmdssk3358
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "TI AM335x EVM-SK";
+	compatible = "ti,am335x-evmsk", "ti,am33xx";
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	lis3_reg: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "lis3_reg";
+		regulator-boot-on;
+	};
+
+	wl12xx_vmmc: fixedregulator@2 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&wl12xx_gpio>;
+		compatible = "regulator-fixed";
+		regulator-name = "vwl1271";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio1 29 0>;
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
+
+	vtt_fixed: fixedregulator@3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vtt";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		gpio = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+	};
+
+	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds_s0>;
+
+		compatible = "gpio-leds";
+
+		led@1 {
+			label = "evmsk:green:usr0";
+			gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "evmsk:green:usr1";
+			gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "evmsk:green:mmc0";
+			gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led@4 {
+			label = "evmsk:green:heartbeat";
+			gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
+
+	gpio_buttons: gpio_buttons@0 {
+		compatible = "gpio-keys";
+
+		switch@1 {
+			label = "button0";
+			linux,code = <0x100>;
+			gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+		};
+
+		switch@2 {
+			label = "button1";
+			linux,code = <0x101>;
+			gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+		};
+
+		switch@3 {
+			label = "button2";
+			linux,code = <0x102>;
+			gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
+			wakeup-source;
+		};
+
+		switch@4 {
+			label = "button3";
+			linux,code = <0x103>;
+			gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap2 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 58 61 66 75 90 125 170 255>;
+		default-brightness-level = <8>;
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "AM335x-EVMSK";
+		simple-audio-card,widgets =
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack",	"HPLOUT",
+			"Headphone Jack",	"HPROUT";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&sound_master>;
+		simple-audio-card,frame-master = <&sound_master>;
+		simple-audio-card,bitclock-inversion;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcasp1>;
+		};
+
+		sound_master: simple-audio-card,codec {
+			sound-dai = <&tlv320aic3106>;
+			system-clock-frequency = <24000000>;
+		};
+	};
+
+	panel {
+		compatible = "ti,tilcdc,panel";
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&lcd_pins_default>;
+		pinctrl-1 = <&lcd_pins_sleep>;
+		status = "okay";
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <32>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+		display-timings {
+			480x272 {
+				hactive         = <480>;
+				vactive         = <272>;
+				hback-porch     = <43>;
+				hfront-porch    = <8>;
+				hsync-len       = <4>;
+				vback-porch     = <12>;
+				vfront-porch    = <4>;
+				vsync-len       = <10>;
+				clock-frequency = <9000000>;
+				hsync-active    = <0>;
+				vsync-active    = <0>;
+			};
+		};
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
+
+	lcd_pins_default: lcd_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad8.lcd_data23 */
+			AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad9.lcd_data22 */
+			AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad10.lcd_data21 */
+			AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad11.lcd_data20 */
+			AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad12.lcd_data19 */
+			AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad13.lcd_data18 */
+			AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad14.lcd_data17 */
+			AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1)	/* gpmc_ad15.lcd_data16 */
+			AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data0.lcd_data0 */
+			AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data1.lcd_data1 */
+			AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data2.lcd_data2 */
+			AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)	/* lcd_data3.lcd_data3 */
+			AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data4.lcd_data4 */
+			AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data5.lcd_data5 */
+			AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data6.lcd_data6 */
+			AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)	/* lcd_data7.lcd_data7 */
+			AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data8.lcd_data8 */
+			AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data9.lcd_data9 */
+			AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data10.lcd_data10 */
+			AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)	/* lcd_data11.lcd_data11 */
+			AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)	/* lcd_data12.lcd_data12 */
+			AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)	/* lcd_data13.lcd_data13 */
+			AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)	/* lcd_data14.lcd_data14 */
+			AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)	/* lcd_data15.lcd_data15 */
+			AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)	/* lcd_vsync.lcd_vsync */
+			AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)	/* lcd_hsync.lcd_hsync */
+			AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)	/* lcd_pclk.lcd_pclk */
+			AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)	/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+	lcd_pins_sleep: lcd_pins_sleep {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x820, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad8.lcd_data23 */
+			AM33XX_IOPAD(0x824, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad9.lcd_data22 */
+			AM33XX_IOPAD(0x828, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad10.lcd_data21 */
+			AM33XX_IOPAD(0x82c, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad11.lcd_data20 */
+			AM33XX_IOPAD(0x830, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad12.lcd_data19 */
+			AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad13.lcd_data18 */
+			AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad14.lcd_data17 */
+			AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad15.lcd_data16 */
+			AM33XX_IOPAD(0x8a0, PULL_DISABLE | MUX_MODE7)	/* lcd_data0.lcd_data0 */
+			AM33XX_IOPAD(0x8a4, PULL_DISABLE | MUX_MODE7)	/* lcd_data1.lcd_data1 */
+			AM33XX_IOPAD(0x8a8, PULL_DISABLE | MUX_MODE7)	/* lcd_data2.lcd_data2 */
+			AM33XX_IOPAD(0x8ac, PULL_DISABLE | MUX_MODE7)	/* lcd_data3.lcd_data3 */
+			AM33XX_IOPAD(0x8b0, PULL_DISABLE | MUX_MODE7)	/* lcd_data4.lcd_data4 */
+			AM33XX_IOPAD(0x8b4, PULL_DISABLE | MUX_MODE7)	/* lcd_data5.lcd_data5 */
+			AM33XX_IOPAD(0x8b8, PULL_DISABLE | MUX_MODE7)	/* lcd_data6.lcd_data6 */
+			AM33XX_IOPAD(0x8bc, PULL_DISABLE | MUX_MODE7)	/* lcd_data7.lcd_data7 */
+			AM33XX_IOPAD(0x8c0, PULL_DISABLE | MUX_MODE7)	/* lcd_data8.lcd_data8 */
+			AM33XX_IOPAD(0x8c4, PULL_DISABLE | MUX_MODE7)	/* lcd_data9.lcd_data9 */
+			AM33XX_IOPAD(0x8c8, PULL_DISABLE | MUX_MODE7)	/* lcd_data10.lcd_data10 */
+			AM33XX_IOPAD(0x8cc, PULL_DISABLE | MUX_MODE7)	/* lcd_data11.lcd_data11 */
+			AM33XX_IOPAD(0x8d0, PULL_DISABLE | MUX_MODE7)	/* lcd_data12.lcd_data12 */
+			AM33XX_IOPAD(0x8d4, PULL_DISABLE | MUX_MODE7)	/* lcd_data13.lcd_data13 */
+			AM33XX_IOPAD(0x8d8, PULL_DISABLE | MUX_MODE7)	/* lcd_data14.lcd_data14 */
+			AM33XX_IOPAD(0x8dc, PULL_DISABLE | MUX_MODE7)	/* lcd_data15.lcd_data15 */
+			AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_vsync.lcd_vsync */
+			AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_hsync.lcd_hsync */
+			AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_pclk.lcd_pclk */
+			AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+
+	user_leds_s0: user_leds_s0 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x810, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad4.gpio1_4 */
+			AM33XX_IOPAD(0x814, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad5.gpio1_5 */
+			AM33XX_IOPAD(0x818, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad6.gpio1_6 */
+			AM33XX_IOPAD(0x81c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad7.gpio1_7 */
+		>;
+	};
+
+	gpio_keys_s0: gpio_keys_s0 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x894, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_oen_ren.gpio2_3 */
+			AM33XX_IOPAD(0x890, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_advn_ale.gpio2_2 */
+			AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_wait0.gpio0_30 */
+			AM33XX_IOPAD(0x89c, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ben0_cle.gpio2_5 */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	ecap2_pins: backlight_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x99c, MUX_MODE4)	/* mcasp0_ahclkr.ecap2_in_pwm2_out */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
+			AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
+			AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+
+			/* Slave 2 */
+			AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
+			AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value*/
+			AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
+	mcasp1_pins: mcasp1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
+			AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
+		>;
+	};
+
+	mcasp1_pins_sleep: mcasp1_pins_sleep {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_31 */
+			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+			AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+		>;
+	};
+
+	wl12xx_gpio: pinmux_wl12xx_gpio {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_csn0.gpio1_29 */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+
+	lis331dlh: lis331dlh@18 {
+		compatible = "st,lis331dlh", "st,lis3lv02d";
+		reg = <0x18>;
+		Vdd-supply = <&lis3_reg>;
+		Vdd_IO-supply = <&lis3_reg>;
+
+		st,click-single-x;
+		st,click-single-y;
+		st,click-single-z;
+		st,click-thresh-x = <10>;
+		st,click-thresh-y = <10>;
+		st,click-thresh-z = <10>;
+		st,irq1-click;
+		st,irq2-click;
+		st,wakeup-x-lo;
+		st,wakeup-x-hi;
+		st,wakeup-y-lo;
+		st,wakeup-y-hi;
+		st,wakeup-z-lo;
+		st,wakeup-z-hi;
+		st,min-limit-x = <120>;
+		st,min-limit-y = <120>;
+		st,min-limit-z = <140>;
+		st,max-limit-x = <550>;
+		st,max-limit-y = <550>;
+		st,max-limit-z = <750>;
+	};
+
+	tlv320aic3106: tlv320aic3106@1b {
+		#sound-dai-cells = <0>;
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		status = "okay";
+
+		/* Regulators */
+		AVDD-supply = <&vaux2_reg>;
+		IOVDD-supply = <&vaux2_reg>;
+		DRVDD-supply = <&vaux2_reg>;
+		DVDD-supply = <&vbat>;
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&epwmss2 {
+	status = "okay";
+
+	ecap2: ecap@48304100 {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ecap2_pins>;
+	};
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	dual_emac = <1>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <2>;
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&gpio0 {
+	ti,no-reset-on-init;
+};
+
+&mmc2 {
+	status = "okay";
+	vmmc-supply = <&wl12xx_vmmc>;
+	ti,non-removable;
+	bus-width = <4>;
+	cap-power-off-card;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1271";
+		reg = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
+		ref-clock-frequency = <38400000>;
+	};
+};
+
+&mcasp1 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&mcasp1_pins>;
+	pinctrl-1 = <&mcasp1_pins_sleep>;
+
+	status = "okay";
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	/* 4 serializers */
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+		0 0 1 2
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+	};
+};
+
+&lcdc {
+      status = "okay";
+};
diff --git a/arch/arm/dts/am335x-icev2.dts b/arch/arm/dts/am335x-icev2.dts
new file mode 100644
index 0000000..debc6f6
--- /dev/null
+++ b/arch/arm/dts/am335x-icev2.dts
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * AM335x ICE V2 board
+ * http://www.ti.com/tool/tmdsice3359
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	model = "TI AM3359 ICE-V2";
+	compatible = "ti,am3359-icev2", "ti,am33xx";
+
+	chosen {
+		stdout-path = &uart3;
+		tick-timer = &timer2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	vtt_fixed: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vtt";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		gpio = <&gpio0 18 GPIO_ACTIVE_HIGH>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+	};
+
+	leds@0 {
+		compatible = "gpio-leds";
+
+		led@0 {
+			label = "out0";
+			gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@1 {
+			label = "out1";
+			gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "out2";
+			gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "out3";
+			gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@4 {
+			label = "out4";
+			gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@5 {
+			label = "out5";
+			gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@6 {
+			label = "out6";
+			gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@7 {
+			label = "out7";
+			gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+
+	/* Tricolor status LEDs */
+	leds@1 {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds>;
+
+		led@0 {
+			label = "status0:red:cpu0";
+			gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu0";
+		};
+
+		led@1 {
+			label = "status0:green:usr";
+			gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "status0:yellow:usr";
+			gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "status1:red:mmc0";
+			gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc0";
+		};
+
+		led@4 {
+			label = "status1:green:usr";
+			gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@5 {
+			label = "status1:yellow:usr";
+			gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	user_leds: user_leds {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */
+			AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] */
+			AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7) /* (D14) xdma_event_intr1.gpio0[20] */
+			AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE7) /* (U9) gpmc_csn1.gpio1[30] */
+			AM33XX_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] */
+		>;
+	};
+
+	mmc0_pins_default: mmc0_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */
+			AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */
+			AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */
+			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
+			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
+			AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* (C15) spi0_cs1.mmc0_sdcd */
+		>;
+	};
+
+	i2c0_pins_default: i2c0_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */
+			AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */
+		>;
+	};
+
+	spi0_pins_default: spi0_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */
+			AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */
+			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */
+			AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */
+		>;
+	};
+
+	uart3_pins_default: uart3_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */
+			AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLUP | MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1, RMII mode */
+			AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLUP | MUX_MODE1))	/* mii1_crs.rmii1_crs_dv */
+			AM33XX_IOPAD(0x944, (PIN_INPUT_PULLUP | MUX_MODE0))	/* rmii1_refclk.rmii1_refclk */
+			AM33XX_IOPAD(0x940, (PIN_INPUT_PULLUP | MUX_MODE1))	/* mii1_rxd0.rmii1_rxd0 */
+			AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLUP | MUX_MODE1))	/* mii1_rxd1.rmii1_rxd1 */
+			AM33XX_IOPAD(0x910, (PIN_INPUT_PULLUP | MUX_MODE1))	/* mii1_rxerr.rmii1_rxerr */
+			AM33XX_IOPAD(0x928, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))	/* mii1_txd0.rmii1_txd0 */
+			AM33XX_IOPAD(0x924, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))	/* mii1_txd1.rmii1_txd1 */
+			AM33XX_IOPAD(0x914, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))	/* mii1_txen.rmii1_txen */
+			/* Slave 2, RMII mode */
+			AM33XX_IOPAD(0x870, (PIN_INPUT_PULLUP | MUX_MODE3))	/* gpmc_wait0.rmii2_crs_dv */
+			AM33XX_IOPAD(0x908, (PIN_INPUT_PULLUP | MUX_MODE1))	/* mii1_col.rmii2_refclk */
+			AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLUP | MUX_MODE3))	/* gpmc_a11.rmii2_rxd0 */
+			AM33XX_IOPAD(0x868, (PIN_INPUT_PULLUP | MUX_MODE3))	/* gpmc_a10.rmii2_rxd1 */
+			AM33XX_IOPAD(0x874, (PIN_INPUT_PULLUP | MUX_MODE3))	/* gpmc_wpn.rmii2_rxerr */
+			AM33XX_IOPAD(0x854, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))	/* gpmc_a5.rmii2_txd0 */
+			AM33XX_IOPAD(0x850, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))	/* gpmc_a4.rmii2_txd1 */
+			AM33XX_IOPAD(0x840, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))	/* gpmc_a0.rmii2_txen */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x944, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x940, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x910, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x928, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x924, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x914, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+
+			/* Slave 2 reset value */
+			AM33XX_IOPAD(0x870, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x908, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x868, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x874, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x854, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x850, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x840, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			AM33XX_IOPAD(0x948, (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0))	/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x94c, (PIN_OUTPUT_PULLUP | MUX_MODE0))			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM33XX_IOPAD(0x948, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+			AM33XX_IOPAD(0x94c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+		>;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_default>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: power-controller@2d {
+		reg = <0x2d>;
+	};
+
+	tpic2810: gpio@60 {
+		compatible = "ti,tpic2810";
+		reg = <0x60>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1326000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+};
+
+&gpio0 {
+	/* Do not idle the GPIO used for holding the VTT regulator */
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+
+	p7 {
+		gpio-hog;
+		gpios = <7 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "FET_SWITCH_CTRL";
+	};
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins_default>;
+	status = "okay";
+};
+
+&gpio3 {
+	p4 {
+		gpio-hog;
+		gpios = <4 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "PR1_MII_CTRL";
+	};
+
+	p10 {
+		gpio-hog;
+		gpios = <10 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "MUX_MII_CTRL";
+	};
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <3>;
+	phy-mode = "rmii";
+	dual_emac_res_vlan = <2>;
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+	dual_emac;
+};
+
+&phy_sel {
+	rmii-clock-ext;
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+	reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
+	reset-delay-us = <2>;   /* PHY datasheet states 1uS min */
+};
diff --git a/arch/arm/dts/am335x-pdu001-u-boot.dtsi b/arch/arm/dts/am335x-pdu001-u-boot.dtsi
new file mode 100644
index 0000000..84a07bd
--- /dev/null
+++ b/arch/arm/dts/am335x-pdu001-u-boot.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 EETS GmbH - https://www.eets.ch/
+ */
+
+/ {
+	ocp {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&l4_wkup {
+	u-boot,dm-pre-reloc;
+};
+
+&scm {
+	u-boot,dm-pre-reloc;
+};
+
+&am33xx_pinmux {
+	u-boot,dm-pre-reloc;
+};
+
+&uart3_pins {
+	u-boot,dm-pre-reloc;
+};
+
+&uart3 {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc1 {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc1_pins {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc2 {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc2_pins {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/am335x-pdu001.dts b/arch/arm/dts/am335x-pdu001.dts
new file mode 100644
index 0000000..3a5e9526
--- /dev/null
+++ b/arch/arm/dts/am335x-pdu001.dts
@@ -0,0 +1,594 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * pdu001.dts
+ *
+ * EETS GmbH PDU001 board device tree file
+ *
+ * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+ *
+ * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/leds-pca9532.h>
+
+/ {
+	model = "EETS,PDU001";
+	compatible = "eets,pdu001", "ti,am33xx";
+
+	chosen {
+		stdout-path = &uart3;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <3600000>;
+		regulator-max-microvolt = <3600000>;
+		regulator-boot-on;
+	};
+
+	lis3_reg: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "lis3_reg";
+		regulator-boot-on;
+	};
+
+	panel {
+		compatible = "ti,tilcdc,panel";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins_s0>;
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <16>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+
+		display-timings {
+			240x320p16 {
+				clock-frequency = <6500000>;
+				hactive = <240>;
+				vactive = <320>;
+				hfront-porch = <6>;
+				hback-porch = <6>;
+				hsync-len = <1>;
+				vback-porch = <6>;
+				vfront-porch = <6>;
+				vsync-len = <1>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				pixelclk-active = <1>;
+				de-active = <0>;
+			};
+		};
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&clkout2_pin>;
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d1.i2c1_sda */
+			AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_clk.i2c2_sda */
+			AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d0.i2c2_scl */
+		>;
+	};
+
+	spi1_pins: pinmux_spi1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE3)		/* mcasp0_aclkx.spi1_sclk */
+			AM33XX_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3)		/* mcasp0_fsx.spi1_d0 */
+			AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcasp0_axr0.spi1_d1 */
+			AM33XX_IOPAD(0x99C, PIN_OUTPUT | MUX_MODE3)		/* mcasp0_ahclkr.spi1_cs0 */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x96C, PIN_OUTPUT | MUX_MODE7)		/* uart0_rtsn.gpio1_9 */
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_rxd.uart1_rxd */
+			AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_txd.uart1_txd */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE1)	/* spi0_cs1.uart3_rxd */
+			AM33XX_IOPAD(0x964, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* ecap0_in_pwm0_out.uart3_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Port 1 (emac0) */
+			AM33XX_IOPAD(0x908, PIN_INPUT | MUX_MODE0)		/* mii1_col.mii1_col */
+			AM33XX_IOPAD(0x90C, PIN_INPUT | MUX_MODE0)		/* mii1_crs.mii1_crs */
+			AM33XX_IOPAD(0x910, PIN_INPUT | MUX_MODE0)		/* mii1_rxer.mii1_rxer */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT | MUX_MODE0)		/* mii1_txen.mii1_txen */
+			AM33XX_IOPAD(0x918, PIN_INPUT | MUX_MODE0)		/* mii1_rxdv.mii1_rxdv */
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd3.mii1_txd3 */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd2.mii1_txd2 */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd1.mii1_txd1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd0.mii1_txd0 */
+			AM33XX_IOPAD(0x92c, PIN_INPUT | MUX_MODE0)		/* mii1_txclk.mii1_txclk */
+			AM33XX_IOPAD(0x930, PIN_INPUT | MUX_MODE0)		/* mii1_rxclk.mii1_rxclk */
+			AM33XX_IOPAD(0x934, PIN_INPUT | MUX_MODE0)		/* mii1_rxd3.mii1_rxd3 */
+			AM33XX_IOPAD(0x938, PIN_INPUT | MUX_MODE0)		/* mii1_rxd2.mii1_rxd2 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT | MUX_MODE0)		/* mii1_rxd1.mii1_rxd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE0)		/* mii1_rxd0.mii1_rxd0 */
+
+			/* Port 2 (emac1) */
+			AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE1)		/* mii2_txen.gpmc_a0 */
+			AM33XX_IOPAD(0x844, PIN_INPUT | MUX_MODE1)		/* mii2_rxdv.gpmc_a1 */
+			AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd3.gpmc_a2 */
+			AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd2.gpmc_a3 */
+			AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd1.gpmc_a4 */
+			AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd0.gpmc_a5 */
+			AM33XX_IOPAD(0x858, PIN_INPUT | MUX_MODE1)		/* mii2_txclk.gpmc_a6 */
+			AM33XX_IOPAD(0x85c, PIN_INPUT | MUX_MODE1)		/* mii2_rxclk.gpmc_a7 */
+			AM33XX_IOPAD(0x860, PIN_INPUT | MUX_MODE1)		/* mii2_rxd3.gpmc_a8 */
+			AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE1)		/* mii2_rxd2.gpmc_a9 */
+			AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE1)		/* mii2_rxd1.gpmc_a10 */
+			AM33XX_IOPAD(0x86C, PIN_INPUT | MUX_MODE1)		/* mii2_rxd0.gpmc_a11 */
+			AM33XX_IOPAD(0x870, PIN_INPUT | MUX_MODE1)		/* mii2_crs.gpmc_wait0 */
+			AM33XX_IOPAD(0x874, PIN_INPUT | MUX_MODE1)		/* mii2_rxer.gpmc_wpn */
+			AM33XX_IOPAD(0x878, PIN_INPUT | MUX_MODE1)		/* mii2_col.gpmc_ben1 */
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		/* eMMC */
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat3 */
+			AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat2 */
+			AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat1 */
+			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat0 */
+			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_clk */
+			AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_cmd */
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		/* SD cardcage */
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad3.mmc1_dat3 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad2.mmc1_dat2 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad1.mmc1_dat1 */
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad0.mmc1_dat0 */
+			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn1.mmc1_clk */
+			AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn2.mmc1_cmd */
+			/* card change signal for frontpanel SD cardcage */
+			AM33XX_IOPAD(0x890, PIN_INPUT | MUX_MODE7)		/* gpmc_advn_ale.gpio2_2 */
+		>;
+	};
+
+	lcd_pins_s0: lcd_pins_s0 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data0.lcd_data0 */
+			AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data1.lcd_data1 */
+			AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data2.lcd_data2 */
+			AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)		/* lcd_data3.lcd_data3 */
+			AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data4.lcd_data4 */
+			AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data5.lcd_data5 */
+			AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data6.lcd_data6 */
+			AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)		/* lcd_data7.lcd_data7 */
+			AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data8.lcd_data8 */
+			AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data9.lcd_data9 */
+			AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data10.lcd_data10 */
+			AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)		/* lcd_data11.lcd_data11 */
+			AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data12.lcd_data12 */
+			AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data13.lcd_data13 */
+			AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data14.lcd_data14 */
+			AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)		/* lcd_data15.lcd_data15 */
+			AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)		/* lcd_vsync.lcd_vsync */
+			AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)		/* lcd_hsync.lcd_hsync */
+			AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)		/* lcd_pclk.lcd_pclk */
+			AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)		/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+	dcan0_pins: pinmux_dcan0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2)		/* uart1_ctsn.d_can0_tx */
+			AM33XX_IOPAD(0x97c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* uart1_rtsn.d_can0_rx */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	rts-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+	rs485-rts-active-high;
+	rs485-rts-delay = <0 0>;
+	linux,rs485-enabled-at-boot-time;
+
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+
+	m2_eeprom: m2_eeprom@50 {
+		compatible = "atmel,24c256";
+		reg = <0x50>;
+		status = "okay";
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+	clock-frequency = <100000>;
+
+	board_24aa025e48: board_24aa025e48@50 {
+		compatible = "microchip,24aa025e48";
+		reg = <0x50>;
+	};
+
+	backplane_24aa025e48: backplane_24aa025e48@53 {
+		compatible = "microchip,24aa025e48";
+		reg = <0x53>;
+	};
+
+	pca9532: pca9532@60 {
+		compatible = "nxp,pca9532";
+		reg = <0x60>;
+		psc0 = <0x97>;
+		pwm0 = <0x80>;
+		psc1 = <0x97>;
+		pwm1 = <0x10>;
+
+		run.red@0 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		run.green@1 {
+			type = <PCA9532_TYPE_LED>;
+			default-state = "on";
+		};
+		s2.red@2 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		s2.green@3 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		s1.yellow@4 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		s1.green@5 {
+			type = <PCA9532_TYPE_LED>;
+		};
+	};
+
+	pca9530: pca9530@61 {
+		compatible = "nxp,pca9530";
+		reg = <0x61>;
+
+		tft-panel@0 {
+			type = <PCA9532_TYPE_LED>;
+			linux,default-trigger = "backlight";
+			default-state = "on";
+		};
+	};
+
+	mcp79400: mcp79400@6f {
+		compatible = "microchip,mcp7940x";
+		reg = <0x6f>;
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins>;
+	ti,pindir-d0-out-d1-in;
+	status = "okay";
+
+	cfaf240320a032t {
+		compatible = "orise,otm3225a";
+		reg = <0>;
+		spi-max-frequency = <1000000>;
+		// SPI mode 3
+		spi-cpol;
+		spi-cpha;
+		status = "okay";
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+/*
+ * Disable soc's rtc as we have no VBAT for it. This makes the board
+ * rtc (Microchip MCP79400) the default rtc device 'rtc0'.
+ */
+&rtc {
+	status = "disabled";
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&elm {
+	status = "okay";
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-name = "ldo_vrtc";
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-name = "buck_vdd_ddr";
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits */
+			regulator-name = "buck_vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits */
+			regulator-name = "buck_vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-name = "boost_res";
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-name = "ldo_vdig1";
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-name = "ldo_vdig2";
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-name = "ldo_vpll";
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-name = "ldo_vdac";
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-name = "ldo_vaux1";
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-name = "ldo_vaux2";
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-name = "ldo_vaux33";
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-name = "ldo_vmmc";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		vbb_reg: regulator@13 {
+			regulator-name = "bat_vbb";
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpsw_default>;
+	dual_emac;			/* no switch, two distinct MACs */
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&davinci_mdio_default>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "mii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "mii";
+	dual_emac_res_vlan = <2>;
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x01 0x10 0x22 0x33>;
+		ti,charge-delay = <0x400>;
+	};
+
+	adc {
+		ti,adc-channels = <4 5 6 7>;
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	non-removable;
+};
+
+&mmc2 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+	cd-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&dcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dcan0_pins>;
+};
diff --git a/arch/arm/dts/am335x-pxm2.dtsi b/arch/arm/dts/am335x-pxm2.dtsi
new file mode 100644
index 0000000..d9243d5
--- /dev/null
+++ b/arch/arm/dts/am335x-pxm2.dtsi
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2014 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * Based on:
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am33xx.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	backlight0: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 0>;
+		brightness-levels = <0 2 5 7 10 12 15 17 20 22 25 28 30 33 35
+				     38 40 43 45 48 51 53 56 58 61 63 66 68 71
+				     73 76 79 81 84 86 89 91 94 96 99 102 104
+				     107 109 112 114 117 119 122 124 127 130
+				     132 135 137 140 142 145 147 150 153 155
+				     158 160 163 165 168 170 173 175 178 181
+				     183 186 188 191 193 196 198 201 204 206
+				     209 211 214 216 219 221 224 226 229 232
+				     234 237 239 242 244 247 249 252 255>;
+		default-brightness-level = <80>;
+		power-supply = <&backlight_reg>;
+		enable-gpios = <&gpio3 16 0>;
+	};
+
+	backlight_reg: fixedregulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "backlight_reg";
+		regulator-boot-on;
+	};
+
+	gpio_keys: restart-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		restart0 {
+			label = "restart";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
+			gpio-key,wakeup;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_blue {
+			label = "blue";
+			gpios = <&gpio3 20 0>;
+		};
+		led_green {
+			label = "green";
+			gpios = <&gpio1 31 0>;
+		};
+		led_red {
+			label = "red";
+			gpios = <&gpio3 21 0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	reg_lcd_3v3: fixedregulator1 {
+		compatible = "regulator-gpio";
+                regulator-name = "lcd-3v3";
+		regulator-min-microvolt = <1800000>;
+                regulator-max-microvolt = <3300000>;
+		regulator-type = "voltage";
+		startup-delay-us = <100>;
+		states = <1800000 0x1
+			  2900000 0x0>;
+		enable-at-boot;
+                gpios = <&gpio3 19 0>;
+                enable-active-high;
+        };
+
+	vbat: fixedregulator2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	vmmc: fixedregulator3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii-txid";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii-txid";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&elm {
+	status = "okay";
+};
+
+&epwmss0 {
+	status = "okay";
+
+	ecap0: ecap@48300100 {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ecap0_pins>;
+	};
+};
+
+&gpmc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins>;
+	status = "okay";
+
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+
+	nand@0,0 {
+		reg = <0 0 0>; /* CS0, offset 0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+	eeprom: eeprom@50 {
+		compatible = "atmel,24c128";
+		reg = <0x50>;
+		pagesize = <32>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <100000>;
+	status = "okay";
+
+	tsl2563: tsl2563@49 {
+		compatible = "amstaos,tsl2563";
+		reg = <0x49>;
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	clock-frequency = <100000>;
+	status = "okay";
+
+	egalax_ts@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <24 2>;
+		wakeup-gpios = <&gpio1 25 0>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc>;
+	bus-width = <4>;
+	cd-gpios = <&gpio0 6 0>;
+	wp-gpios = <&gpio3 18 0>;
+	status = "okay";
+};
+
+&phy_sel {
+	rgmii-no-delay;
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&clkout2_pin &gpio_pin>;
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	ecap0_pins: ecap_pins {
+		pinctrl-single,pins = <
+			0x198 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* mcasp0_axr0.gpio3_16 Backlight enable */
+			0x164 (MUX_MODE0)	/* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
+		>;
+	};
+
+
+	gpio_pin: gpio_pin {
+		pinctrl-single,pins = <
+			0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a6.gpio1_22 touch reset */
+			0x60 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_a8.gpio1_24 touch irq */
+			0x64 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_a9.gpio1_25 touch power */
+			0x6c (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_a11.gpio1_27 pad14 to DFU */
+			0x21c (MUX_MODE0)	/* usb0_drvvbus */
+			0x234 (MUX_MODE0)	/* usb1_drvvbus */
+			0x1a0 (PIN_INPUT_PULLUP | MUX_MODE4)	/* mcasp0_aclkr.mmc0_sdwp */
+			0x160 (PIN_INPUT_PULLUP | MUX_MODE5)	/* spi0_cs1.mmc0_sdcd */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x158 (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d1.i2c1_sda */
+			0x15c (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			0x150 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)	/* spi0_sclk.i2c2_sda */
+			0x154 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)	/* spi0_cs0.i2c2_scl */
+		>;
+	};
+
+	lcd_pins_s0: lcd_pins_s0 {
+		pinctrl-single,pins = <
+			0x20 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad8.lcd_data23 */
+			0x24 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad9.lcd_data22 */
+			0x28 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad10.lcd_data21 */
+			0x2c (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad11.lcd_data20 */
+			0x30 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad12.lcd_data19 */
+			0x34 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad13.lcd_data18 */
+			0x38 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad14.lcd_data17 */
+			0x3c (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad15.lcd_data16 */
+			0xa0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data0.lcd_data0 */
+			0xa4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data1.lcd_data1 */
+			0xa8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data2.lcd_data2 */
+			0xac (PIN_OUTPUT | MUX_MODE0)		/* lcd_data3.lcd_data3 */
+			0xb0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data4.lcd_data4 */
+			0xb4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data5.lcd_data5 */
+			0xb8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data6.lcd_data6 */
+			0xbc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data7.lcd_data7 */
+			0xc0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data8.lcd_data8 */
+			0xc4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data9.lcd_data9 */
+			0xc8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data10.lcd_data10 */
+			0xcc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data11.lcd_data11 */
+			0xd0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data12.lcd_data12 */
+			0xd4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data13.lcd_data13 */
+			0xd8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data14.lcd_data14 */
+			0xdc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data15.lcd_data15 */
+			0xe0 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_vsync.lcd_vsync */
+			0xe4 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_hsync.lcd_hsync */
+			0xe8 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_pclk.lcd_pclk */
+			0xec (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_ac_bias_en.lcd_ac_bias_en */
+			0x194 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* mcasp0_fsx.gpio3_15 LCD enable */
+		>;
+	};
+
+	nandflash_pins: pinmux_nandflash_pins {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0 */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+};
+
+&wdt2 {
+	wdt-keep-enabled;
+};
diff --git a/arch/arm/dts/am335x-pxm50.dts b/arch/arm/dts/am335x-pxm50.dts
new file mode 100644
index 0000000..f4e66d2
--- /dev/null
+++ b/arch/arm/dts/am335x-pxm50.dts
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am335x-pxm2.dtsi"
+
+/ {
+	model = "PXM2/PXM50";
+	compatible = "ti,am335x-evm", "ti,am33xx";
+
+		panel {
+			compatible = "ti,tilcdc,panel";
+			backlight = <&backlight0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&lcd_pins_s0>;
+			enable-gpios = <&gpio3 15 0>;
+			status = "okay";
+
+			panel-info {
+				ac-bias           = <255>;
+				ac-bias-intrpt    = <0>;
+				dma-burst-sz      = <16>;
+				bpp               = <32>;
+				fdd               = <0x80>;
+				sync-edge         = <0>;
+				sync-ctrl         = <1>;
+				raster-order      = <0>;
+				fifo-th           = <0>;
+				tft-alt-mode      = <0>;
+				invert-pxl-clk    = <0>;
+			};
+
+			display-timings {
+				native-mode = <&timing1>;
+
+				timing1: 1376x768p50 {
+					clock-frequency = <60000000>;
+					hactive = <1376>;
+					vactive = <768>;
+					hfront-porch = <14>;
+					hback-porch = <64>;
+					hsync-len = <56>;
+					vback-porch = <28>;
+					vfront-porch = <1>;
+					vsync-len = <6>;
+					hsync-active = <1>;
+					vsync-active = <1>;
+				};
+			};
+		};
+};
diff --git a/arch/arm/dts/am335x-rut.dts b/arch/arm/dts/am335x-rut.dts
new file mode 100644
index 0000000..a5716a9
--- /dev/null
+++ b/arch/arm/dts/am335x-rut.dts
@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2014 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * Based on:
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "RUT";
+	compatible = "ti,am335x-evm", "ti,am33xx";
+
+	buzzer {
+		compatible = "pwm-beeper";
+		pwms = <&ecap0 0 16000 0>;
+	};
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&dcdc2_reg>;
+		};
+	};
+
+	gpio_keys: powerfail-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		pwr-fail0 {
+			label = "power-fail";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
+			gpio-key,wakeup;
+		};
+
+		pwr-fail1 {
+			label = "power-fail-redundant";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+			gpio-key,wakeup;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_green {
+			label = "rut:green:debug:run_mode";
+			gpios = <&gpio3 20 1>;
+			/* activelow = 1, default trigger heartbeat */
+		};
+		led_yellow {
+			label = "rut:debug:yellow:osc_ch1";
+			gpios = <&gpio0 17 1>;
+			/* activelow = 1, default trigger mmc0 */
+		};
+		led_red {
+			label = "rut:debug:red:osc_ch2";
+			gpios = <&gpio0 16 1>;
+			/* activelow = 1, default trigger debug_osc_ch2 */
+		};
+		/* optional */
+		led_alive {
+			label = "rut:alive";
+			gpios = <&gpio0 15 1>;
+			linux,default-trigger = "heartbeat";
+			/* activelow = 1, default trigger heartbeat */
+		};
+
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	panel {
+		compatible = "ti,tilcdc,panel";
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins_s0>;
+		status = "okay";
+
+		/* FORMIKE_KWH043ST20_F01 */
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <16>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+			tft-alt-mode      = <0>;
+			invert-pxl-clk    = <1>;
+		};
+
+		display-timings {
+			native-mode = <&timing1>;
+			timing1: 480x800p60 {
+				clock-frequency = <29925000>;
+				hactive = <480>;
+				vactive = <800>;
+				hfront-porch = <50>;
+				hback-porch = <50>;
+				hsync-len = <50>;
+				vback-porch = <50>;
+				vfront-porch = <50>;
+				vsync-len = <50>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+
+	vmmc: fixedregulator3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	watchdog {
+		compatible = "linux,wdt-gpio";
+		gpios = <&gpio0 14 0>;
+		hw_algo = "level";
+		hw_margin_ms = <30000>;
+	};
+};
+
+&aes {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rmii";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rmii";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+	gpios = <&gpio2 18 0>;
+
+        ethernet_phy: ethernet-phy@1 {
+                compatible = "ethernet-phy-id2000.5ce1";
+                reg = <1>;
+		natsemi,master_mode_fixup;
+        };
+};
+
+&elm {
+	status = "okay";
+};
+
+&epwmss0 {
+	status = "okay";
+
+	ecap0: ecap@48300100 {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ecap0_pins>;
+	};
+};
+
+&epwmss1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&epwmss1_pins>;
+};
+
+&gpmc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins>;
+	status = "okay";
+
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+
+	nand@0,0 {
+		reg = <0 0 0>; /* CS0, offset 0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <57>;
+		gpmc,cs-wr-off-ns = <57>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <57>;
+		gpmc,adv-wr-off-ns = <57>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <48>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <57>;
+		gpmc,access-ns = <38>;
+		gpmc,rd-cycle-ns = <67>;
+		gpmc,wr-cycle-ns = <67>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <96>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	eeprom: eeprom@50 {
+		compatible = "atmel,24c128";
+		reg = <0x50>;
+		pagesize = <32>;
+	};
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <100000>;
+	status = "okay";
+
+	atmel: atmel_mxt_ts@4a {
+		compatible = "atmel,maxtouch";
+		reg = <0x4a>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 8>;
+		gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>;
+	};
+
+	temp@48 {
+		compatible = "st,ds75";
+		reg = <0x4c>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	status = "okay";
+};
+
+&phy_sel {
+	rmii-clock-ext;
+};
+
+&sham {
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+	status = "okay";
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "mx25l25635e";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <24000000>;
+
+		partition@0 {
+			label = "dummy";
+			reg = <0x0000000 0x8000>;
+		};
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins>;
+	status = "okay";
+
+	lcd_init: lcd@0 {
+		compatible = "formike,kwh043st20";
+		reg = <0>;
+		reset-gpios = <&gpio3 19 0>;
+		spi-max-frequency = <1200000>;
+		spi-cpol;
+		spi-cpha;
+		power-on-delay = <10>;
+		reset-delay = <10>;
+	};
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+	backlight0: backlight {
+		isel = <1>;  /* 1 - ISET1, 2 ISET2 */
+		fdim = <1000>; /* TPS65217_BL_FDIM_100HZ */
+		default-brightness = <80>;
+	};
+
+	regulators {
+		dcdc1_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		ldo3_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			regulator-always-on;
+		};
+	};
+};
+
+&tscadc {
+	status = "okay";
+	adc {
+		ti,adc-channels = <4 5 6 7>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0 {
+	dr_mode = "device";
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&clkout2_pin &gpio_pin>;
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxerr.mii1_rxerr */
+			0x114 (MUX_MODE1)	/* mii1_txen.mii1_txen */
+			0x124 (MUX_MODE1)	/* mii1_txd1.mii1_txd1 */
+			0x128 (MUX_MODE1)	/* mii1_txd0.mii1_txd0 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd1.mii1_rxd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd0.mii1_rxd0 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii1_refclk */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	ecap0_pins: ecap_pins {
+		pinctrl-single,pins = <
+			0x164 (MUX_MODE0)	/* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 buzzer frequency: ecap.0 */
+		>;
+	};
+
+	epwmss1_pins: epwmss_pins {
+		pinctrl-single,pins = <
+			0x48 (PIN_INPUT | MUX_MODE7)	/* gpmc_a2.gpio1_18 buzzer frequency: ehrpwm1A high-Z due to connected to ecap0 by R0469 */
+			0x4c (MUX_MODE6)	/* gpmc_a3.ehrpwm1B buzzer volume pwm */
+		>;
+	};
+
+	gpio_pin: gpio_pin {
+		pinctrl-single,pins = <
+			0x6c (PIN_INPUT | MUX_MODE7)		/* gpmc_a11.gpio1_27 PWR_FAIL_GPIO_SPARE */
+			0x78 (PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)	/* gpmc_be1n.gpio1_28 TOUCH_CHANGE_N */
+			0x88 (PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)		/* gpmc_csn3.gpio2_0 RUT_GPIO0_GPIO */
+			0x118 (PIN_INPUT | MUX_MODE7)		/* gmii1_rxdv.gpio3_4 PWR_FAIL_GPIO */
+			0x11c (MUX_MODE7)			/* mii1_txd3.gpio0_16 DEBUG_OSC_CH2_GPIO */
+			0x120 (MUX_MODE7)			/* mii1_txd2.gpio0_17 DEBUG_OSC_CH1_GPIO */
+			0x134 (MUX_MODE7)			/* gmii1_rxd3.gpio2_18 PHY_RSTn_GPIO */
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gmii1_rxd2.gpio2_19 PHY_INT_GPIO */
+			0x180 (MUX_MODE7)			/* uart1_rxd.gpio0_14 WATCHDOG_TRIGGER_GPIO */
+			0x184 (MUX_MODE7)			/* uart1_txd.gpio0_15 ALIVE_LED_N_GPIO */
+			0x1a0 (MUX_MODE7)			/* mcasp0_aclkr.gpio3_18 MAXTOUCH_RESET_GPIO */
+			0x1a4 (MUX_MODE7)			/* mcasp0_fsr.gpio3_19 DISPLAY_RESET_GPIO */
+			0x1a8 (MUX_MODE7)			/* mcasp0_axr1.gpio3_20 DEBUG_RUN_MODE_GPIO */
+			0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* mcasp0_ahclkx.gpio3_21 NORFLASH_WP_GPIO */
+			0x1b0 (PIN_OUTPUT | MUX_MODE3)		/* xdma_event_intr0.clkout1 */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x168 (PIN_INPUT | MUX_MODE3)	/* uart0_ctsn.i2c1_sda */
+			0x16c (PIN_INPUT | MUX_MODE3)	/* uart0.rtsn.i2c1_scl */
+		>;
+	};
+
+	lcd_pins_s0: lcd_pins_s0 {
+		pinctrl-single,pins = <
+			0x20 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad8.lcd_data23 */
+			0x24 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad9.lcd_data22 */
+			0x28 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad10.lcd_data21 */
+			0x2c (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad11.lcd_data20 */
+			0x30 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad12.lcd_data19 */
+			0x34 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad13.lcd_data18 */
+			0x38 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad14.lcd_data17 */
+			0x3c (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* gpmc_ad15.lcd_data16 */
+			0xa0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data0.lcd_data0 */
+			0xa4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data1.lcd_data1 */
+			0xa8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data2.lcd_data2 */
+			0xac (PIN_OUTPUT | MUX_MODE0)		/* lcd_data3.lcd_data3 */
+			0xb0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data4.lcd_data4 */
+			0xb4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data5.lcd_data5 */
+			0xb8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data6.lcd_data6 */
+			0xbc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data7.lcd_data7 */
+			0xc0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data8.lcd_data8 */
+			0xc4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data9.lcd_data9 */
+			0xc8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data10.lcd_data10 */
+			0xcc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data11.lcd_data11 */
+			0xd0 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data12.lcd_data12 */
+			0xd4 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data13.lcd_data13 */
+			0xd8 (PIN_OUTPUT | MUX_MODE0)		/* lcd_data14.lcd_data14 */
+			0xdc (PIN_OUTPUT | MUX_MODE0)		/* lcd_data15.lcd_data15 */
+			0xe0 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_vsync.lcd_vsync */
+			0xe4 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_hsync.lcd_hsync */
+			0xe8 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_pclk.lcd_pclk */
+			0xec (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+	mmc1_pins: mmc1_pins {
+		pinctrl-single,pins = <
+			0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat0.mmc0_dat0 */
+			0xf4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat1.mmc0_dat1 */
+			0xf8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat2.mmc0_dat2 */
+			0xfc (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat3.mmc0_dat3 */
+			0x100 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_clk.mmc0_clk */
+			0x104 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_cmd.mmc0_cmd */
+		>;
+	};
+
+	nandflash_pins: pinmux_nandflash_pins {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0 */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+
+	spi0_pins: pinmux_spi0_pins {
+		pinctrl-single,pins = <
+			0x150 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* spi0_sclk.spi0_sclk */
+			0x154 (PIN_INPUT_PULLUP | MUX_MODE0)	/* spi0_d0.spi0_d0 */
+			0x158 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* spi0_d1.spi0_d1 */
+			0x15c (PIN_INPUT_PULLUP | MUX_MODE0)	/* spi0_CS0.spi0_CS0 */
+		>;
+	};
+
+	spi1_pins: pinmux_spi1_pins {
+		pinctrl-single,pins = <
+			0x190 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcasp0_aclkx.spi1_sclk */
+			0x194 (PIN_INPUT_PULLUP | MUX_MODE3)	/* mcasp0_fsx.spi1_d0 */
+			0x198 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcasp0_axr0.spi1_d1 */
+			0x19c (PIN_INPUT_PULLUP | MUX_MODE3)	/* mcasp0_ahclkr.spi1_cs0 */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+};
diff --git a/arch/arm/dts/am33xx-clocks.dtsi b/arch/arm/dts/am33xx-clocks.dtsi
new file mode 100644
index 0000000..95d5c9d
--- /dev/null
+++ b/arch/arm/dts/am33xx-clocks.dtsi
@@ -0,0 +1,625 @@
+/*
+ * Device Tree Source for AM33xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+&scm_clocks {
+	sys_clkin_ck: sys_clkin_ck@40 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
+		ti,bit-shift = <22>;
+		reg = <0x0040>;
+	};
+
+	adc_tsc_fck: adc_tsc_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dcan0_fck: dcan0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dcan1_fck: dcan1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	mcasp0_fck: mcasp0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	mcasp1_fck: mcasp1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	smartreflex0_fck: smartreflex0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	smartreflex1_fck: smartreflex1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	sha0_fck: sha0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	aes0_fck: aes0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	rng_fck: rng_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	ehrpwm0_tbclk: ehrpwm0_tbclk@44e10664 {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <0>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm1_tbclk: ehrpwm1_tbclk@44e10664 {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <1>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm2_tbclk: ehrpwm2_tbclk@44e10664 {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <2>;
+		reg = <0x0664>;
+	};
+};
+&prcm_clocks {
+	clk_32768_ck: clk_32768_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	clk_rc32k_ck: clk_rc32k_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32000>;
+	};
+
+	virt_19200000_ck: virt_19200000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <19200000>;
+	};
+
+	virt_24000000_ck: virt_24000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	virt_25000000_ck: virt_25000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <25000000>;
+	};
+
+	virt_26000000_ck: virt_26000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <26000000>;
+	};
+
+	tclkin_ck: tclkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <12000000>;
+	};
+
+	dpll_core_ck: dpll_core_ck@490 {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-core-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0490>, <0x045c>, <0x0468>;
+	};
+
+	dpll_core_x2_ck: dpll_core_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-x2-clock";
+		clocks = <&dpll_core_ck>;
+	};
+
+	dpll_core_m4_ck: dpll_core_m4_ck@480 {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		reg = <0x0480>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_core_m5_ck: dpll_core_m5_ck@484 {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		reg = <0x0484>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_core_m6_ck: dpll_core_m6_ck@4d8 {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		reg = <0x04d8>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_mpu_ck: dpll_mpu_ck@488 {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0488>, <0x0420>, <0x042c>;
+	};
+
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a8 {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_mpu_ck>;
+		ti,max-div = <31>;
+		reg = <0x04a8>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_ddr_ck: dpll_ddr_ck@494 {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-no-gate-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0494>, <0x0434>, <0x0440>;
+	};
+
+	dpll_ddr_m2_ck: dpll_ddr_m2_ck@4a0 {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_ddr_ck>;
+		ti,max-div = <31>;
+		reg = <0x04a0>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_ddr_m2_div2_ck: dpll_ddr_m2_div2_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_ddr_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	dpll_disp_ck: dpll_disp_ck@498 {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-no-gate-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x0498>, <0x0448>, <0x0454>;
+	};
+
+	dpll_disp_m2_ck: dpll_disp_m2_ck@4a4 {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_disp_ck>;
+		ti,max-div = <31>;
+		reg = <0x04a4>;
+		ti,index-starts-at-one;
+		ti,set-rate-parent;
+	};
+
+	dpll_per_ck: dpll_per_ck@48c {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-no-gate-j-type-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x048c>, <0x0470>, <0x049c>;
+	};
+
+	dpll_per_m2_ck: dpll_per_m2_ck@4ac {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_ck>;
+		ti,max-div = <31>;
+		reg = <0x04ac>;
+		ti,index-starts-at-one;
+	};
+
+	dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	dpll_per_m2_div4_ck: dpll_per_m2_div4_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	clk_24mhz: clk_24mhz {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <8>;
+	};
+
+	clkdiv32k_ck: clkdiv32k_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&clk_24mhz>;
+		clock-mult = <1>;
+		clock-div = <732>;
+	};
+
+	l3_gclk: l3_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	pruss_ocp_gclk: pruss_ocp_gclk@530 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&l3_gclk>, <&dpll_disp_m2_ck>;
+		reg = <0x0530>;
+	};
+
+	mmu_fck: mmu_fck@914 {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_core_m4_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x0914>;
+	};
+
+	timer1_fck: timer1_fck@528 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>;
+		reg = <0x0528>;
+	};
+
+	timer2_fck: timer2_fck@508 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x0508>;
+	};
+
+	timer3_fck: timer3_fck@50c {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x050c>;
+	};
+
+	timer4_fck: timer4_fck@510 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x0510>;
+	};
+
+	timer5_fck: timer5_fck@518 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x0518>;
+	};
+
+	timer6_fck: timer6_fck@51c {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x051c>;
+	};
+
+	timer7_fck: timer7_fck@504 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x0504>;
+	};
+
+	usbotg_fck: usbotg_fck@47c {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_per_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x047c>;
+	};
+
+	dpll_core_m4_div2_ck: dpll_core_m4_div2_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	ieee5000_fck: ieee5000_fck@e4 {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x00e4>;
+	};
+
+	wdt1_fck: wdt1_fck@538 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x0538>;
+	};
+
+	l4_rtc_gclk: l4_rtc_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	l4hs_gclk: l4hs_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l3s_gclk: l3s_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l4fw_gclk: l4fw_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l4ls_gclk: l4ls_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	sysclk_div_ck: sysclk_div_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	cpsw_125mhz_gclk: cpsw_125mhz_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m5_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@520 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_core_m5_ck>, <&dpll_core_m4_ck>;
+		reg = <0x0520>;
+	};
+
+	gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@53c {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+		reg = <0x053c>;
+	};
+
+	lcd_gclk: lcd_gclk@534 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>;
+		reg = <0x0534>;
+		ti,set-rate-parent;
+	};
+
+	mmc_clk: mmc_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@52c {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x052c>;
+	};
+
+	gfx_fck_div_ck: gfx_fck_div_ck@52c {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&gfx_fclk_clksel_ck>;
+		reg = <0x052c>;
+		ti,max-div = <2>;
+	};
+
+	sysclkout_pre_ck: sysclkout_pre_ck@700 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>;
+		reg = <0x0700>;
+	};
+
+	clkout2_div_ck: clkout2_div_ck@700 {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sysclkout_pre_ck>;
+		ti,bit-shift = <3>;
+		ti,max-div = <8>;
+		reg = <0x0700>;
+	};
+
+	clkout2_ck: clkout2_ck@700 {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkout2_div_ck>;
+		ti,bit-shift = <7>;
+		reg = <0x0700>;
+	};
+};
+
+&prcm {
+	l4_per_cm: l4_per_cm@0 {
+		compatible = "ti,omap4-cm";
+		reg = <0x0 0x200>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x0 0x200>;
+
+		l4_per_clkctrl: clk@14 {
+			compatible = "ti,clkctrl";
+			reg = <0x14 0x13c>;
+			#clock-cells = <2>;
+		};
+	};
+
+	l4_wkup_cm: l4_wkup_cm@400 {
+		compatible = "ti,omap4-cm";
+		reg = <0x400 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x400 0x100>;
+
+		l4_wkup_clkctrl: clk@4 {
+			compatible = "ti,clkctrl";
+			reg = <0x4 0xd4>;
+			#clock-cells = <2>;
+		};
+	};
+
+	mpu_cm: mpu_cm@600 {
+		compatible = "ti,omap4-cm";
+		reg = <0x600 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x600 0x100>;
+
+		mpu_clkctrl: clk@4 {
+			compatible = "ti,clkctrl";
+			reg = <0x4 0x4>;
+			#clock-cells = <2>;
+		};
+	};
+
+	l4_rtc_cm: l4_rtc_cm@800 {
+		compatible = "ti,omap4-cm";
+		reg = <0x800 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x800 0x100>;
+
+		l4_rtc_clkctrl: clk@0 {
+			compatible = "ti,clkctrl";
+			reg = <0x0 0x4>;
+			#clock-cells = <2>;
+		};
+	};
+
+	gfx_l3_cm: gfx_l3_cm@900 {
+		compatible = "ti,omap4-cm";
+		reg = <0x900 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x900 0x100>;
+
+		gfx_l3_clkctrl: clk@4 {
+			compatible = "ti,clkctrl";
+			reg = <0x4 0x4>;
+			#clock-cells = <2>;
+		};
+	};
+
+	l4_cefuse_cm: l4_cefuse_cm@a00 {
+		compatible = "ti,omap4-cm";
+		reg = <0xa00 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0xa00 0x100>;
+
+		l4_cefuse_clkctrl: clk@20 {
+			compatible = "ti,clkctrl";
+			reg = <0x20 0x4>;
+			#clock-cells = <2>;
+		};
+	};
+};
diff --git a/arch/arm/dts/am33xx.dtsi b/arch/arm/dts/am33xx.dtsi
new file mode 100644
index 0000000..d3dd6a1
--- /dev/null
+++ b/arch/arm/dts/am33xx.dtsi
@@ -0,0 +1,1046 @@
+/*
+ * Device Tree Source for AM33XX SoC
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/clock/am3.h>
+
+/ {
+	compatible = "ti,am33xx";
+	interrupt-parent = <&intc>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	chosen { };
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		serial5 = &uart5;
+		d-can0 = &dcan0;
+		d-can1 = &dcan1;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		phy0 = &usb0_phy;
+		phy1 = &usb1_phy;
+		ethernet0 = &cpsw_emac0;
+		ethernet1 = &cpsw_emac1;
+		spi0 = &spi0;
+		spi1 = &spi1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			compatible = "arm,cortex-a8";
+			device_type = "cpu";
+			reg = <0>;
+
+			operating-points-v2 = <&cpu0_opp_table>;
+
+			clocks = <&dpll_mpu_ck>;
+			clock-names = "cpu";
+
+			clock-latency = <300000>; /* From omap-cpufreq driver */
+		};
+	};
+
+	cpu0_opp_table: opp-table {
+		compatible = "operating-points-v2-ti-cpu";
+		syscon = <&scm_conf>;
+
+		/*
+		 * The three following nodes are marked with opp-suspend
+		 * because the can not be enabled simultaneously on a
+		 * single SoC.
+		 */
+		opp50-300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+			opp-microvolt = <950000 931000 969000>;
+			opp-supported-hw = <0x06 0x0010>;
+			opp-suspend;
+		};
+
+		opp100-275000000 {
+			opp-hz = /bits/ 64 <275000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x01 0x00FF>;
+			opp-suspend;
+		};
+
+		opp100-300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x06 0x0020>;
+			opp-suspend;
+		};
+
+		opp100-500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x01 0xFFFF>;
+		};
+
+		opp100-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x06 0x0040>;
+		};
+
+		opp120-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1200000 1176000 1224000>;
+			opp-supported-hw = <0x01 0xFFFF>;
+		};
+
+		opp120-720000000 {
+			opp-hz = /bits/ 64 <720000000>;
+			opp-microvolt = <1200000 1176000 1224000>;
+			opp-supported-hw = <0x06 0x0080>;
+		};
+
+		oppturbo-720000000 {
+			opp-hz = /bits/ 64 <720000000>;
+			opp-microvolt = <1260000 1234800 1285200>;
+			opp-supported-hw = <0x01 0xFFFF>;
+		};
+
+		oppturbo-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1260000 1234800 1285200>;
+			opp-supported-hw = <0x06 0x0100>;
+		};
+
+		oppnitro-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <1325000 1298500 1351500>;
+			opp-supported-hw = <0x04 0x0200>;
+		};
+	};
+
+	pmu@4b000000 {
+		compatible = "arm,cortex-a8-pmu";
+		interrupts = <3>;
+		reg = <0x4b000000 0x1000000>;
+		ti,hwmods = "debugss";
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is used for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap3-mpu";
+			ti,hwmods = "mpu";
+			pm-sram = <&pm_sram_code
+				   &pm_sram_data>;
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the AM33XX interconnect.
+	 * The real AM33XX interconnect network is quite complex. Since
+	 * it will not bring real advantage to represent that in DT
+	 * for the moment, just use a fake OCP bus entry to represent
+	 * the whole bus hierarchy.
+	 */
+	ocp {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main";
+
+		l4_wkup: l4_wkup@44c00000 {
+			compatible = "ti,am3-l4-wkup", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x44c00000 0x280000>;
+
+			wkup_m3: wkup_m3@100000 {
+				compatible = "ti,am3352-wkup-m3";
+				reg = <0x100000 0x4000>,
+				      <0x180000	0x2000>;
+				reg-names = "umem", "dmem";
+				ti,hwmods = "wkup_m3";
+				ti,pm-firmware = "am335x-pm-firmware.elf";
+			};
+
+			prcm: prcm@200000 {
+				compatible = "ti,am3-prcm", "simple-bus";
+				reg = <0x200000 0x4000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x200000 0x4000>;
+
+				prcm_clocks: clocks {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+
+				prcm_clockdomains: clockdomains {
+				};
+			};
+
+			scm: scm@210000 {
+				compatible = "ti,am3-scm", "simple-bus";
+				reg = <0x210000 0x2000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				#pinctrl-cells = <1>;
+				ranges = <0 0x210000 0x2000>;
+
+				am33xx_pinmux: pinmux@800 {
+					compatible = "pinctrl-single";
+					reg = <0x800 0x238>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+					#pinctrl-cells = <1>;
+					pinctrl-single,register-width = <32>;
+					pinctrl-single,function-mask = <0x7f>;
+				};
+
+				scm_conf: scm_conf@0 {
+					compatible = "syscon", "simple-bus";
+					reg = <0x0 0x800>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					ranges = <0 0 0x800>;
+
+					scm_clocks: clocks {
+						#address-cells = <1>;
+						#size-cells = <0>;
+					};
+				};
+
+				wkup_m3_ipc: wkup_m3_ipc@1324 {
+					compatible = "ti,am3352-wkup-m3-ipc";
+					reg = <0x1324 0x24>;
+					interrupts = <78>;
+					ti,rproc = <&wkup_m3>;
+					mboxes = <&mailbox &mbox_wkupm3>;
+				};
+
+				edma_xbar: dma-router@f90 {
+					compatible = "ti,am335x-edma-crossbar";
+					reg = <0xf90 0x40>;
+					#dma-cells = <3>;
+					dma-requests = <32>;
+					dma-masters = <&edma>;
+				};
+
+				scm_clockdomains: clockdomains {
+				};
+			};
+		};
+
+		intc: interrupt-controller@48200000 {
+			compatible = "ti,am33xx-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x48200000 0x1000>;
+		};
+
+		edma: edma@49000000 {
+			compatible = "ti,edma3-tpcc";
+			ti,hwmods = "tpcc";
+			reg =	<0x49000000 0x10000>;
+			reg-names = "edma3_cc";
+			interrupts = <12 13 14>;
+			interrupt-names = "edma3_ccint", "edma3_mperr",
+					  "edma3_ccerrint";
+			dma-requests = <64>;
+			#dma-cells = <2>;
+
+			ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>,
+				   <&edma_tptc2 0>;
+
+			ti,edma-memcpy-channels = <20 21>;
+		};
+
+		edma_tptc0: tptc@49800000 {
+			compatible = "ti,edma3-tptc";
+			ti,hwmods = "tptc0";
+			reg =	<0x49800000 0x100000>;
+			interrupts = <112>;
+			interrupt-names = "edma3_tcerrint";
+		};
+
+		edma_tptc1: tptc@49900000 {
+			compatible = "ti,edma3-tptc";
+			ti,hwmods = "tptc1";
+			reg =	<0x49900000 0x100000>;
+			interrupts = <113>;
+			interrupt-names = "edma3_tcerrint";
+		};
+
+		edma_tptc2: tptc@49a00000 {
+			compatible = "ti,edma3-tptc";
+			ti,hwmods = "tptc2";
+			reg =	<0x49a00000 0x100000>;
+			interrupts = <114>;
+			interrupt-names = "edma3_tcerrint";
+		};
+
+		gpio0: gpio@44e07000 {
+			compatible = "ti,omap4-gpio";
+			ti,hwmods = "gpio1";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x44e07000 0x1000>;
+			interrupts = <96>;
+		};
+
+		gpio1: gpio@4804c000 {
+			compatible = "ti,omap4-gpio";
+			ti,hwmods = "gpio2";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x4804c000 0x1000>;
+			interrupts = <98>;
+		};
+
+		gpio2: gpio@481ac000 {
+			compatible = "ti,omap4-gpio";
+			ti,hwmods = "gpio3";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x481ac000 0x1000>;
+			interrupts = <32>;
+		};
+
+		gpio3: gpio@481ae000 {
+			compatible = "ti,omap4-gpio";
+			ti,hwmods = "gpio4";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x481ae000 0x1000>;
+			interrupts = <62>;
+		};
+
+		uart0: serial@44e09000 {
+			compatible = "ti,am3352-uart", "ti,omap3-uart";
+			ti,hwmods = "uart1";
+			clock-frequency = <48000000>;
+			reg = <0x44e09000 0x2000>;
+			interrupts = <72>;
+			status = "disabled";
+			dmas = <&edma 26 0>, <&edma 27 0>;
+			dma-names = "tx", "rx";
+		};
+
+		uart1: serial@48022000 {
+			compatible = "ti,am3352-uart", "ti,omap3-uart";
+			ti,hwmods = "uart2";
+			clock-frequency = <48000000>;
+			reg = <0x48022000 0x2000>;
+			interrupts = <73>;
+			status = "disabled";
+			dmas = <&edma 28 0>, <&edma 29 0>;
+			dma-names = "tx", "rx";
+		};
+
+		uart2: serial@48024000 {
+			compatible = "ti,am3352-uart", "ti,omap3-uart";
+			ti,hwmods = "uart3";
+			clock-frequency = <48000000>;
+			reg = <0x48024000 0x2000>;
+			interrupts = <74>;
+			status = "disabled";
+			dmas = <&edma 30 0>, <&edma 31 0>;
+			dma-names = "tx", "rx";
+		};
+
+		uart3: serial@481a6000 {
+			compatible = "ti,am3352-uart", "ti,omap3-uart";
+			ti,hwmods = "uart4";
+			clock-frequency = <48000000>;
+			reg = <0x481a6000 0x2000>;
+			interrupts = <44>;
+			status = "disabled";
+		};
+
+		uart4: serial@481a8000 {
+			compatible = "ti,am3352-uart", "ti,omap3-uart";
+			ti,hwmods = "uart5";
+			clock-frequency = <48000000>;
+			reg = <0x481a8000 0x2000>;
+			interrupts = <45>;
+			status = "disabled";
+		};
+
+		uart5: serial@481aa000 {
+			compatible = "ti,am3352-uart", "ti,omap3-uart";
+			ti,hwmods = "uart6";
+			clock-frequency = <48000000>;
+			reg = <0x481aa000 0x2000>;
+			interrupts = <46>;
+			status = "disabled";
+		};
+
+		i2c0: i2c@44e0b000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c1";
+			reg = <0x44e0b000 0x1000>;
+			interrupts = <70>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@4802a000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c2";
+			reg = <0x4802a000 0x1000>;
+			interrupts = <71>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@4819c000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c3";
+			reg = <0x4819c000 0x1000>;
+			interrupts = <30>;
+			status = "disabled";
+		};
+
+		mmc1: mmc@48060000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc1";
+			ti,dual-volt;
+			ti,needs-special-reset;
+			ti,needs-special-hs-handling;
+			dmas = <&edma_xbar 24 0 0
+				&edma_xbar 25 0 0>;
+			dma-names = "tx", "rx";
+			interrupts = <64>;
+			reg = <0x48060000 0x1000>;
+			status = "disabled";
+		};
+
+		mmc2: mmc@481d8000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc2";
+			ti,needs-special-reset;
+			dmas = <&edma 2 0
+				&edma 3 0>;
+			dma-names = "tx", "rx";
+			interrupts = <28>;
+			reg = <0x481d8000 0x1000>;
+			status = "disabled";
+		};
+
+		mmc3: mmc@47810000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc3";
+			ti,needs-special-reset;
+			interrupts = <29>;
+			reg = <0x47810000 0x1000>;
+			status = "disabled";
+		};
+
+		hwspinlock: spinlock@480ca000 {
+			compatible = "ti,omap4-hwspinlock";
+			reg = <0x480ca000 0x1000>;
+			ti,hwmods = "spinlock";
+			#hwlock-cells = <1>;
+		};
+
+		wdt2: wdt@44e35000 {
+			compatible = "ti,omap3-wdt";
+			ti,hwmods = "wd_timer2";
+			reg = <0x44e35000 0x1000>;
+			interrupts = <91>;
+		};
+
+		dcan0: can@481cc000 {
+			compatible = "ti,am3352-d_can";
+			ti,hwmods = "d_can0";
+			reg = <0x481cc000 0x2000>;
+			clocks = <&dcan0_fck>;
+			clock-names = "fck";
+			syscon-raminit = <&scm_conf 0x644 0>;
+			interrupts = <52>;
+			status = "disabled";
+		};
+
+		dcan1: can@481d0000 {
+			compatible = "ti,am3352-d_can";
+			ti,hwmods = "d_can1";
+			reg = <0x481d0000 0x2000>;
+			clocks = <&dcan1_fck>;
+			clock-names = "fck";
+			syscon-raminit = <&scm_conf 0x644 1>;
+			interrupts = <55>;
+			status = "disabled";
+		};
+
+		mailbox: mailbox@480c8000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x480C8000 0x200>;
+			interrupts = <77>;
+			ti,hwmods = "mailbox";
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <8>;
+			mbox_wkupm3: wkup_m3 {
+				ti,mbox-send-noirq;
+				ti,mbox-tx = <0 0 0>;
+				ti,mbox-rx = <0 0 3>;
+			};
+		};
+
+		timer1: timer@44e31000 {
+			compatible = "ti,am335x-timer-1ms";
+			reg = <0x44e31000 0x400>;
+			interrupts = <67>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+			clocks = <&timer1_fck>;
+			clock-names = "fck";
+		};
+
+		timer2: timer@48040000 {
+			compatible = "ti,am335x-timer";
+			reg = <0x48040000 0x400>;
+			interrupts = <68>;
+			ti,hwmods = "timer2";
+			clocks = <&timer2_fck>;
+			clock-names = "fck";
+		};
+
+		timer3: timer@48042000 {
+			compatible = "ti,am335x-timer";
+			reg = <0x48042000 0x400>;
+			interrupts = <69>;
+			ti,hwmods = "timer3";
+		};
+
+		timer4: timer@48044000 {
+			compatible = "ti,am335x-timer";
+			reg = <0x48044000 0x400>;
+			interrupts = <92>;
+			ti,hwmods = "timer4";
+			ti,timer-pwm;
+		};
+
+		timer5: timer@48046000 {
+			compatible = "ti,am335x-timer";
+			reg = <0x48046000 0x400>;
+			interrupts = <93>;
+			ti,hwmods = "timer5";
+			ti,timer-pwm;
+		};
+
+		timer6: timer@48048000 {
+			compatible = "ti,am335x-timer";
+			reg = <0x48048000 0x400>;
+			interrupts = <94>;
+			ti,hwmods = "timer6";
+			ti,timer-pwm;
+		};
+
+		timer7: timer@4804a000 {
+			compatible = "ti,am335x-timer";
+			reg = <0x4804a000 0x400>;
+			interrupts = <95>;
+			ti,hwmods = "timer7";
+			ti,timer-pwm;
+		};
+
+		rtc: rtc@44e3e000 {
+			compatible = "ti,am3352-rtc", "ti,da830-rtc";
+			reg = <0x44e3e000 0x1000>;
+			interrupts = <75
+				      76>;
+			ti,hwmods = "rtc";
+			clocks = <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+			clock-names = "int-clk";
+		};
+
+		spi0: spi@48030000 {
+			compatible = "ti,omap4-mcspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x48030000 0x400>;
+			interrupts = <65>;
+			ti,spi-num-cs = <2>;
+			ti,hwmods = "spi0";
+			dmas = <&edma 16 0
+				&edma 17 0
+				&edma 18 0
+				&edma 19 0>;
+			dma-names = "tx0", "rx0", "tx1", "rx1";
+			status = "disabled";
+		};
+
+		spi1: spi@481a0000 {
+			compatible = "ti,omap4-mcspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x481a0000 0x400>;
+			interrupts = <125>;
+			ti,spi-num-cs = <2>;
+			ti,hwmods = "spi1";
+			dmas = <&edma 42 0
+				&edma 43 0
+				&edma 44 0
+				&edma 45 0>;
+			dma-names = "tx0", "rx0", "tx1", "rx1";
+			status = "disabled";
+		};
+
+		usb: usb@47400000 {
+			compatible = "ti,am33xx-usb";
+			reg = <0x47400000 0x1000>;
+			ranges;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ti,hwmods = "usb_otg_hs";
+			status = "disabled";
+
+			usb_ctrl_mod: control@44e10620 {
+				compatible = "ti,am335x-usb-ctrl-module";
+				reg = <0x44e10620 0x10
+					0x44e10648 0x4>;
+				reg-names = "phy_ctrl", "wakeup";
+				status = "disabled";
+			};
+
+			usb0_phy: usb-phy@47401300 {
+				compatible = "ti,am335x-usb-phy";
+				reg = <0x47401300 0x100>;
+				reg-names = "phy";
+				status = "disabled";
+				ti,ctrl_mod = <&usb_ctrl_mod>;
+				#phy-cells = <0>;
+			};
+
+			usb0: usb@47401000 {
+				compatible = "ti,musb-am33xx";
+				status = "disabled";
+				reg = <0x47401400 0x400
+					0x47401000 0x200>;
+				reg-names = "mc", "control";
+
+				interrupts = <18>;
+				interrupt-names = "mc";
+				dr_mode = "otg";
+				mentor,multipoint = <1>;
+				mentor,num-eps = <16>;
+				mentor,ram-bits = <12>;
+				mentor,power = <500>;
+				phys = <&usb0_phy>;
+
+				dmas = <&cppi41dma  0 0 &cppi41dma  1 0
+					&cppi41dma  2 0 &cppi41dma  3 0
+					&cppi41dma  4 0 &cppi41dma  5 0
+					&cppi41dma  6 0 &cppi41dma  7 0
+					&cppi41dma  8 0 &cppi41dma  9 0
+					&cppi41dma 10 0 &cppi41dma 11 0
+					&cppi41dma 12 0 &cppi41dma 13 0
+					&cppi41dma 14 0 &cppi41dma  0 1
+					&cppi41dma  1 1 &cppi41dma  2 1
+					&cppi41dma  3 1 &cppi41dma  4 1
+					&cppi41dma  5 1 &cppi41dma  6 1
+					&cppi41dma  7 1 &cppi41dma  8 1
+					&cppi41dma  9 1 &cppi41dma 10 1
+					&cppi41dma 11 1 &cppi41dma 12 1
+					&cppi41dma 13 1 &cppi41dma 14 1>;
+				dma-names =
+					"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+					"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
+					"rx14", "rx15",
+					"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
+					"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
+					"tx14", "tx15";
+			};
+
+			usb1_phy: usb-phy@47401b00 {
+				compatible = "ti,am335x-usb-phy";
+				reg = <0x47401b00 0x100>;
+				reg-names = "phy";
+				status = "disabled";
+				ti,ctrl_mod = <&usb_ctrl_mod>;
+				#phy-cells = <0>;
+			};
+
+			usb1: usb@47401800 {
+				compatible = "ti,musb-am33xx";
+				status = "disabled";
+				reg = <0x47401c00 0x400
+					0x47401800 0x200>;
+				reg-names = "mc", "control";
+				interrupts = <19>;
+				interrupt-names = "mc";
+				dr_mode = "otg";
+				mentor,multipoint = <1>;
+				mentor,num-eps = <16>;
+				mentor,ram-bits = <12>;
+				mentor,power = <500>;
+				phys = <&usb1_phy>;
+
+				dmas = <&cppi41dma 15 0 &cppi41dma 16 0
+					&cppi41dma 17 0 &cppi41dma 18 0
+					&cppi41dma 19 0 &cppi41dma 20 0
+					&cppi41dma 21 0 &cppi41dma 22 0
+					&cppi41dma 23 0 &cppi41dma 24 0
+					&cppi41dma 25 0 &cppi41dma 26 0
+					&cppi41dma 27 0 &cppi41dma 28 0
+					&cppi41dma 29 0 &cppi41dma 15 1
+					&cppi41dma 16 1 &cppi41dma 17 1
+					&cppi41dma 18 1 &cppi41dma 19 1
+					&cppi41dma 20 1 &cppi41dma 21 1
+					&cppi41dma 22 1 &cppi41dma 23 1
+					&cppi41dma 24 1 &cppi41dma 25 1
+					&cppi41dma 26 1 &cppi41dma 27 1
+					&cppi41dma 28 1 &cppi41dma 29 1>;
+				dma-names =
+					"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+					"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
+					"rx14", "rx15",
+					"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
+					"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
+					"tx14", "tx15";
+			};
+
+			cppi41dma: dma-controller@47402000 {
+				compatible = "ti,am3359-cppi41";
+				reg =  <0x47400000 0x1000
+					0x47402000 0x1000
+					0x47403000 0x1000
+					0x47404000 0x4000>;
+				reg-names = "glue", "controller", "scheduler", "queuemgr";
+				interrupts = <17>;
+				interrupt-names = "glue";
+				#dma-cells = <2>;
+				#dma-channels = <30>;
+				#dma-requests = <256>;
+				status = "disabled";
+			};
+		};
+
+		epwmss0: epwmss@48300000 {
+			compatible = "ti,am33xx-pwmss";
+			reg = <0x48300000 0x10>;
+			ti,hwmods = "epwmss0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges = <0x48300100 0x48300100 0x80   /* ECAP */
+				  0x48300180 0x48300180 0x80   /* EQEP */
+				  0x48300200 0x48300200 0x80>; /* EHRPWM */
+
+			ecap0: ecap@48300100 {
+				compatible = "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48300100 0x80>;
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
+				interrupts = <31>;
+				interrupt-names = "ecap0";
+				status = "disabled";
+			};
+
+			ehrpwm0: pwm@48300200 {
+				compatible = "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48300200 0x80>;
+				clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
+				status = "disabled";
+			};
+		};
+
+		epwmss1: epwmss@48302000 {
+			compatible = "ti,am33xx-pwmss";
+			reg = <0x48302000 0x10>;
+			ti,hwmods = "epwmss1";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges = <0x48302100 0x48302100 0x80   /* ECAP */
+				  0x48302180 0x48302180 0x80   /* EQEP */
+				  0x48302200 0x48302200 0x80>; /* EHRPWM */
+
+			ecap1: ecap@48302100 {
+				compatible = "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48302100 0x80>;
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
+				interrupts = <47>;
+				interrupt-names = "ecap1";
+				status = "disabled";
+			};
+
+			ehrpwm1: pwm@48302200 {
+				compatible = "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48302200 0x80>;
+				clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
+				status = "disabled";
+			};
+		};
+
+		epwmss2: epwmss@48304000 {
+			compatible = "ti,am33xx-pwmss";
+			reg = <0x48304000 0x10>;
+			ti,hwmods = "epwmss2";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges = <0x48304100 0x48304100 0x80   /* ECAP */
+				  0x48304180 0x48304180 0x80   /* EQEP */
+				  0x48304200 0x48304200 0x80>; /* EHRPWM */
+
+			ecap2: ecap@48304100 {
+				compatible = "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48304100 0x80>;
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
+				interrupts = <61>;
+				interrupt-names = "ecap2";
+				status = "disabled";
+			};
+
+			ehrpwm2: pwm@48304200 {
+				compatible = "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48304200 0x80>;
+				clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
+				status = "disabled";
+			};
+		};
+
+		mac: ethernet@4a100000 {
+			compatible = "ti,am335x-cpsw","ti,cpsw";
+			ti,hwmods = "cpgmac0";
+			clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>;
+			clock-names = "fck", "cpts";
+			cpdma_channels = <8>;
+			ale_entries = <1024>;
+			bd_ram_size = <0x2000>;
+			mac_control = <0x20>;
+			slaves = <2>;
+			active_slave = <0>;
+			cpts_clock_mult = <0x80000000>;
+			cpts_clock_shift = <29>;
+			reg = <0x4a100000 0x800
+			       0x4a101200 0x100>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/*
+			 * c0_rx_thresh_pend
+			 * c0_rx_pend
+			 * c0_tx_pend
+			 * c0_misc_pend
+			 */
+			interrupts = <40 41 42 43>;
+			ranges;
+			syscon = <&scm_conf>;
+			status = "disabled";
+
+			davinci_mdio: mdio@4a101000 {
+				compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				ti,hwmods = "davinci_mdio";
+				bus_freq = <1000000>;
+				reg = <0x4a101000 0x100>;
+				status = "disabled";
+			};
+
+			cpsw_emac0: slave@4a100200 {
+				/* Filled in by U-Boot */
+				mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			cpsw_emac1: slave@4a100300 {
+				/* Filled in by U-Boot */
+				mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			phy_sel: cpsw-phy-sel@44e10650 {
+				compatible = "ti,am3352-cpsw-phy-sel";
+				reg= <0x44e10650 0x4>;
+				reg-names = "gmii-sel";
+			};
+		};
+
+		ocmcram: ocmcram@40300000 {
+			compatible = "mmio-sram";
+			reg = <0x40300000 0x10000>; /* 64k */
+			ranges = <0x0 0x40300000 0x10000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			pm_sram_code: pm-sram-code@0 {
+				compatible = "ti,sram";
+				reg = <0x0 0x1000>;
+				protect-exec;
+			};
+
+			pm_sram_data: pm-sram-data@1000 {
+				compatible = "ti,sram";
+				reg = <0x1000 0x1000>;
+				pool;
+			};
+		};
+
+		elm: elm@48080000 {
+			compatible = "ti,am3352-elm";
+			reg = <0x48080000 0x2000>;
+			interrupts = <4>;
+			ti,hwmods = "elm";
+			status = "disabled";
+		};
+
+		lcdc: lcdc@4830e000 {
+			compatible = "ti,am33xx-tilcdc";
+			reg = <0x4830e000 0x1000>;
+			interrupts = <36>;
+			ti,hwmods = "lcdc";
+			status = "disabled";
+		};
+
+		tscadc: tscadc@44e0d000 {
+			compatible = "ti,am3359-tscadc";
+			reg = <0x44e0d000 0x1000>;
+			interrupts = <16>;
+			ti,hwmods = "adc_tsc";
+			status = "disabled";
+			dmas = <&edma 53 0>, <&edma 57 0>;
+			dma-names = "fifo0", "fifo1";
+
+			tsc {
+				compatible = "ti,am3359-tsc";
+			};
+			am335x_adc: adc {
+				#io-channel-cells = <1>;
+				compatible = "ti,am3359-adc";
+			};
+		};
+
+		emif: emif@4c000000 {
+			compatible = "ti,emif-am3352";
+			reg = <0x4c000000 0x1000000>;
+			ti,hwmods = "emif";
+			interrupts = <101>;
+			sram = <&pm_sram_code
+				&pm_sram_data>;
+			ti,no-idle;
+		};
+
+		gpmc: gpmc@50000000 {
+			compatible = "ti,am3352-gpmc";
+			ti,hwmods = "gpmc";
+			ti,no-idle-on-init;
+			reg = <0x50000000 0x2000>;
+			interrupts = <100>;
+			dmas = <&edma 52 0>;
+			dma-names = "rxtx";
+			gpmc,num-cs = <7>;
+			gpmc,num-waitpins = <2>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			status = "disabled";
+		};
+
+		sham: sham@53100000 {
+			compatible = "ti,omap4-sham";
+			ti,hwmods = "sham";
+			reg = <0x53100000 0x200>;
+			interrupts = <109>;
+			dmas = <&edma 36 0>;
+			dma-names = "rx";
+		};
+
+		aes: aes@53500000 {
+			compatible = "ti,omap4-aes";
+			ti,hwmods = "aes";
+			reg = <0x53500000 0xa0>;
+			interrupts = <103>;
+			dmas = <&edma 6 0>,
+			       <&edma 5 0>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp0: mcasp@48038000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp0";
+			reg = <0x48038000 0x2000>,
+			      <0x46000000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <80>, <81>;
+			interrupt-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 8 2>,
+				<&edma 9 2>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp1: mcasp@4803c000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp1";
+			reg = <0x4803C000 0x2000>,
+			      <0x46400000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <82>, <83>;
+			interrupt-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 10 2>,
+				<&edma 11 2>;
+			dma-names = "tx", "rx";
+		};
+
+		rng: rng@48310000 {
+			compatible = "ti,omap4-rng";
+			ti,hwmods = "rng";
+			reg = <0x48310000 0x2000>;
+			interrupts = <111>;
+		};
+	};
+};
+
+#include "am33xx-clocks.dtsi"
diff --git a/arch/arm/dts/am3517-evm-u-boot.dtsi b/arch/arm/dts/am3517-evm-u-boot.dtsi
new file mode 100644
index 0000000..59df819
--- /dev/null
+++ b/arch/arm/dts/am3517-evm-u-boot.dtsi
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017
+ * Logic PD - http://www.logicpd.com
+ */
+
+/ {
+	chosen {
+		stdout-path = &uart3;
+	};
+};
+
+&uart1 {
+	reg-shift = <2>;
+};
+
+&uart2 {
+	reg-shift = <2>;
+};
+
+&uart3 {
+	reg-shift = <2>;
+};
diff --git a/arch/arm/dts/am3517-evm-ui.dtsi b/arch/arm/dts/am3517-evm-ui.dtsi
new file mode 100644
index 0000000..e841918
--- /dev/null
+++ b/arch/arm/dts/am3517-evm-ui.dtsi
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 Logic PD, Inc - http://www.logicpd.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/input/input.h>
+
+/ {
+	codec1 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "tlv320aic23-hifi";
+
+		simple-audio-card,widgets =
+			"Microphone", "Mic In",
+			"Line", "Line In",
+			"Line", "Line Out";
+
+		simple-audio-card,routing =
+			"Line Out", "LOUT",
+			"Line Out", "ROUT",
+			"LLINEIN", "Line In",
+			"RLINEIN", "Line In",
+			"MICIN", "Mic In";
+
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&sound_master>;
+		simple-audio-card,frame-master = <&sound_master>;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcbsp1>;
+		};
+
+		sound_master: simple-audio-card,codec {
+			sound-dai = <&tlv320aic23_1>;
+			system-clock-frequency = <12000000>;
+		};
+	};
+
+	codec2 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "tlv320aic23-hifi";
+
+		simple-audio-card,widgets =
+			"Microphone", "Mic In",
+			"Line", "Line In",
+			"Line", "Line Out";
+
+		simple-audio-card,routing =
+			"Line Out", "LOUT",
+			"Line Out", "ROUT",
+			"LLINEIN", "Line In",
+			"RLINEIN", "Line In",
+			"MICIN", "Mic In";
+
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&sound_master2>;
+		simple-audio-card,frame-master = <&sound_master2>;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcbsp2>;
+		};
+
+		sound_master2: simple-audio-card,codec {
+			sound-dai = <&tlv320aic23_2>;
+			system-clock-frequency = <12000000>;
+		};
+	};
+
+	expander-keys {
+		compatible = "gpio-keys-polled";
+		poll-interval = <100>;
+
+		record {
+			label = "Record";
+			/* linux,code = <BTN_0>; */
+			gpios = <&tca6416_2 15 GPIO_ACTIVE_LOW>;
+		};
+
+		play {
+			label = "Play";
+			linux,code = <KEY_PLAY>;
+			gpios = <&tca6416_2 14 GPIO_ACTIVE_LOW>;
+		};
+
+		Stop {
+			label = "Stop";
+			linux,code = <KEY_STOP>;
+			gpios = <&tca6416_2 13 GPIO_ACTIVE_LOW>;
+		};
+
+		fwd {
+			label = "FWD";
+			linux,code = <KEY_FASTFORWARD>;
+			gpios = <&tca6416_2 12 GPIO_ACTIVE_LOW>;
+		};
+
+		rwd {
+			label = "RWD";
+			linux,code = <KEY_REWIND>;
+			gpios = <&tca6416_2 11 GPIO_ACTIVE_LOW>;
+		};
+
+		shift {
+			label = "Shift";
+			linux,code = <KEY_LEFTSHIFT>;
+			gpios = <&tca6416_2 10 GPIO_ACTIVE_LOW>;
+		};
+
+		Mode {
+			label = "Mode";
+			linux,code = <BTN_MODE>;
+			gpios = <&tca6416_2 9 GPIO_ACTIVE_LOW>;
+		};
+
+		Menu {
+			label = "Menu";
+			linux,code = <KEY_MENU>;
+			gpios = <&tca6416_2 8 GPIO_ACTIVE_LOW>;
+		};
+
+		Up {
+			label = "Up";
+			linux,code = <KEY_UP>;
+			gpios = <&tca6416_2 7 GPIO_ACTIVE_LOW>;
+		};
+
+		Down {
+			label = "Down";
+			linux,code = <KEY_DOWN>;
+			gpios = <&tca6416_2 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&i2c2 {
+	/* Audio codecs */
+	tlv320aic23_1: codec@1a {
+		compatible = "ti,tlv320aic23";
+		reg = <0x1a>;
+		#sound-dai-cells= <0>;
+		status = "okay";
+	};
+
+	tlv320aic23_2: codec@1b {
+		compatible = "ti,tlv320aic23";
+		reg = <0x1b>;
+		#sound-dai-cells= <0>;
+		status = "okay";
+	};
+};
+
+&i2c3 {
+	/* Audio codecs */
+	tlv320aic23_3: codec@1a {
+		compatible = "ti,tlv320aic23";
+		reg = <0x1a>;
+		#sound-dai-cells= <0>;
+		status = "okay";
+	};
+
+	/* GPIO Expanders */
+	tca6416_2: gpio@20 {
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		vcc-supply = <&vdd_io_reg>;
+	};
+
+	tca6416_3: gpio@21 {
+		compatible = "ti,tca6416";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		vcc-supply = <&vdd_io_reg>;
+	};
+
+	/* TVP5146 Analog Video decoder input */
+	tvp5146@5c {
+		compatible = "ti,tvp5146m2";
+		reg = <0x5c>;
+	};
+};
+
+&mcbsp1 {
+	status = "ok";
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp1_pins>;
+};
+
+&mcbsp2 {
+	status = "ok";
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp2_pins>;
+};
+
+&omap3_pmx_core {
+	mcbsp1_pins: pinmux_mcbsp1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2190, PIN_OUTPUT | MUX_MODE0)	/* mcbsp1_dx.mcbsp1_dx */
+			OMAP3_CORE1_IOPAD(0x2192, PIN_INPUT | MUX_MODE0)	/* mcbsp1_dx.mcbsp1_dr */
+			OMAP3_CORE1_IOPAD(0x2196, PIN_INPUT | MUX_MODE0)	/* mcbsp_clks.mcbsp1_fsx */
+			OMAP3_CORE1_IOPAD(0x2198, PIN_INPUT | MUX_MODE0)	/* mcbsp1_clkx.mcbsp1_clkx */
+		>;
+	};
+
+	mcbsp2_pins: pinmux_mcbsp2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0)	/* mcbsp2_fsx.mcbsp2_fsx */
+			OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0)	/* mcbsp2_clkx.mcbsp2_clkx */
+			OMAP3_CORE1_IOPAD(0x2140, PIN_INPUT | MUX_MODE0)	/* mcbsp2_dr.mcbsp2.dr */
+			OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0)	/* mcbsp2_dx.mcbsp2_dx */
+		>;
+	};
+};
diff --git a/arch/arm/dts/am3517-evm.dts b/arch/arm/dts/am3517-evm.dts
new file mode 100644
index 0000000..1e2bb68
--- /dev/null
+++ b/arch/arm/dts/am3517-evm.dts
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am3517.dtsi"
+#include "am3517-som.dtsi"
+#include "am3517-evm-ui.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
+	compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
+
+	aliases {
+		display0 = &lcd0;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+        vmmc_fixed: vmmc {
+                compatible = "regulator-fixed";
+                regulator-name = "vmmc_fixed";
+                regulator-min-microvolt = <3300000>;
+                regulator-max-microvolt = <3300000>;
+        };
+
+	gpio-keys {
+		compatible = "gpio-keys-polled";
+		poll-interval = <100>;
+
+		user_pb {
+			label = "User Push Button";
+			linux,code = <BTN_0>;
+			gpios = <&tca6416 5 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_1 {
+			label = "User Switch 1";
+			linux,code = <BTN_1>;
+			gpios = <&tca6416 8 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_2 {
+			label = "User Switch 2";
+			linux,code = <BTN_2>;
+			gpios = <&tca6416 9 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_3 {
+			label = "User Switch 3";
+			linux,code = <BTN_3>;
+			gpios = <&tca6416 10 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_4 {
+			label = "User Switch 4";
+			linux,code = <BTN_4>;
+			gpios = <&tca6416 11 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_5 {
+			label = "User Switch 5";
+			linux,code = <BTN_5>;
+			gpios = <&tca6416 12 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_6 {
+			label = "User Switch 6";
+			linux,code = <BTN_6>;
+			gpios = <&tca6416 13 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_7 {
+			label = "User Switch 7";
+			linux,code = <BTN_7>;
+			gpios = <&tca6416 14 GPIO_ACTIVE_LOW>;
+		};
+
+		user_sw_8 {
+			label = "User Switch 8";
+			linux,code = <BTN_8>;
+			gpios = <&tca6416 15 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
+
+		user_led_1 {
+			label = "am3517evm:green:user_led_1";
+			gpios = <&tca6416 7 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+		};
+
+		user_led_2 {
+			label = "am3517evm:green:user_led_2";
+			gpios = <&tca6416 6 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+		};
+
+		user_led_3 {
+			label = "am3517evm:green:user_led_3";
+			gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0"; /* SD/MMC card activity */
+		};
+
+		user_led_4 {
+			label = "am3517evm:green:user_led_4";
+			gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	lcd0: display@0 {
+		compatible = "panel-dpi";
+		label = "15";
+		status = "okay";
+		pinctrl-names = "default";
+		enable-gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>;	/* gpio176, lcd INI */
+		vcc-supply = <&vdd_io_reg>;
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dpi_out>;
+			};
+		};
+
+		panel-timing {
+			clock-frequency = <9000000>;
+			hactive = <480>;
+			vactive = <272>;
+			hfront-porch = <3>;
+			hback-porch = <2>;
+			hsync-len = <42>;
+			vback-porch = <3>;
+			vfront-porch = <4>;
+			vsync-len = <11>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+	};
+
+	bl: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		power-supply = <&vdd_io_reg>;
+		pinctrl-0 = <&backlight_pins>;
+		pwms = <&pwm11 0 5000000 0>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+		default-brightness-level = <7>;
+		enable-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>; /* gpio_182 */
+	};
+
+	pwm11: dmtimer-pwm@11 {
+		compatible = "ti,omap-dmtimer-pwm";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm_pins>;
+		ti,timers = <&timer11>;
+		#pwm-cells = <3>;
+	};
+
+	/* HS USB Host PHY on PORT 1 */
+	hsusb1_phy: hsusb1_phy {
+		compatible = "usb-nop-xceiv";
+		reset-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* gpio_57 */
+		#phy-cells = <0>;
+	};
+};
+
+&davinci_emac {
+	     status = "okay";
+};
+
+&davinci_mdio {
+	     status = "okay";
+};
+
+&dss {
+	status = "ok";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_dpi_pins>;
+
+	vdds_dsi-supply = <&vdd_io_reg>;
+	vdda_video-supply = <&vdd_io_reg>;
+
+	port {
+		dpi_out: endpoint {
+			remote-endpoint = <&lcd_in>;
+			data-lines = <16>;
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+	/* User DIP swithes [1:8] / User LEDS [1:2] */
+	tca6416: gpio@21 {
+		compatible = "ti,tca6416";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		vcc-supply = <&vdd_io_reg>;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+};
+
+&mmc1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&vmmc_fixed>;
+	bus-width = <4>;
+	wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */
+	cd-gpios = <&gpio4 31 GPIO_ACTIVE_LOW>; /* gpio_127 */
+};
+
+&mmc3 {
+      status = "disabled";
+};
+
+&usbhshost {
+	port1-mode = "ehci-phy";
+};
+
+&usbhsehci {
+	phys = <&hsusb1_phy>;
+};
+
+&omap3_pmx_core {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb1_rst_pins>;
+
+	leds_pins: pinmux_leds_pins {
+		pinctrl-single,pins = <
+			OMAP3_WKUP_IOPAD(0x2a24, PIN_OUTPUT_PULLUP | MUX_MODE4)	/* jtag_emu0.gpio_11 */
+			OMAP3_WKUP_IOPAD(0x2a26, PIN_OUTPUT_PULLUP | MUX_MODE4)	/* jtag_emu1.gpio_31 */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_clk.sdmmc1_clk */
+			OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_cmd.sdmmc1_cmd */
+			OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat0.sdmmc1_dat0 */
+			OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat1.sdmmc1_dat1 */
+			OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat2.sdmmc1_dat2 */
+			OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat3.sdmmc1_dat3 */
+			OMAP3_CORE1_IOPAD(0x2150, PIN_INPUT_PULLUP | MUX_MODE4) /* sdmmc1_dat4.gpio_126 */
+			OMAP3_CORE1_IOPAD(0x2152, PIN_INPUT_PULLUP | MUX_MODE4) /* sdmmc1_dat5.gpio_127 */
+		>;
+	};
+
+	pwm_pins: pinmux_pwm_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21dc, PIN_OUTPUT | MUX_MODE1)       /* mcspi2_cs0.gpt11_pwm */
+		>;
+	};
+
+	backlight_pins: pinmux_backlight_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21de, PIN_OUTPUT | MUX_MODE4)       /* mcspi2_cs1.gpio_182 */
+		>;
+	};
+
+	dss_dpi_pins: pinmux_dss_dpi_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21d2, PIN_OUTPUT | MUX_MODE4)       /* mcspi1_cs2.gpio_176 */
+			OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)       /* dss_pclk.dss_pclk */
+			OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0)       /* dss_hsync.dss_hsync */
+			OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0)       /* dss_vsync.dss_vsync */
+			OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0)       /* dss_acbias.dss_acbias */
+			OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0)       /* dss_data0.dss_data0 */
+			OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0)       /* dss_data1.dss_data1 */
+			OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0)       /* dss_data2.dss_data2 */
+			OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0)       /* dss_data3.dss_data3 */
+			OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0)       /* dss_data4.dss_data4 */
+			OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0)       /* dss_data5.dss_data5 */
+			OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0)       /* dss_data6.dss_data6 */
+			OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0)       /* dss_data7.dss_data7 */
+			OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0)       /* dss_data8.dss_data8 */
+			OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0)       /* dss_data9.dss_data9 */
+			OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0)       /* dss_data10.dss_data10 */
+			OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0)       /* dss_data11.dss_data11 */
+			OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0)       /* dss_data12.dss_data12 */
+			OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0)       /* dss_data13.dss_data13 */
+			OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0)       /* dss_data14.dss_data14 */
+			OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0)       /* dss_data15.dss_data15 */
+		>;
+	};
+
+	hsusb1_rst_pins: pinmux_hsusb1_rst_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20ba, PIN_OUTPUT | MUX_MODE4)	/* gpmc_ncs6.gpio_57 */
+		>;
+	};
+};
+
+&omap3_pmx_core2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb1_pins>;
+
+	hsusb1_pins: pinmux_hsusb1_pins {
+		pinctrl-single,pins = <
+			OMAP3430_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3)	/* etk_clk.hsusb1_stp */
+			OMAP3430_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3)	/* etk_ctl.hsusb1_clk */
+			OMAP3430_CORE2_IOPAD(0x25ec, PIN_INPUT | MUX_MODE3)	/* etk_d8.hsusb1_dir */
+			OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE3)	/* etk_d9.hsusb1_nxt */
+			OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE3)	/* etk_d0.hsusb1_data0 */
+			OMAP3430_CORE2_IOPAD(0x25de, PIN_INPUT | MUX_MODE3)	/* etk_d1.hsusb1_data1 */
+			OMAP3430_CORE2_IOPAD(0x25e0, PIN_INPUT | MUX_MODE3)	/* etk_d2.hsusb1_data2 */
+			OMAP3430_CORE2_IOPAD(0x25ea, PIN_INPUT | MUX_MODE3)	/* etk_d7.hsusb1_data3 */
+			OMAP3430_CORE2_IOPAD(0x25e4, PIN_INPUT | MUX_MODE3)	/* etk_d4.hsusb1_data4 */
+			OMAP3430_CORE2_IOPAD(0x25e6, PIN_INPUT | MUX_MODE3)	/* etk_d5.hsusb1_data5 */
+			OMAP3430_CORE2_IOPAD(0x25e8, PIN_INPUT | MUX_MODE3)	/* etk_d6.hsusb1_data6 */
+			OMAP3430_CORE2_IOPAD(0x25e2, PIN_INPUT | MUX_MODE3)	/* etk_d3.hsusb1_data7 */
+		>;
+	};
+};
diff --git a/arch/arm/dts/am3517-som.dtsi b/arch/arm/dts/am3517-som.dtsi
new file mode 100644
index 0000000..b1c988e
--- /dev/null
+++ b/arch/arm/dts/am3517-som.dtsi
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2016 Derald D. Woods <woods.technical@gmail.com>
+ *
+ * Based on am3517-evm.dts
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd_core_reg>;
+		};
+	};
+
+	wl12xx_buffer: wl12xx_buf {
+		compatible = "regulator-fixed";
+		regulator-name = "wl1271_buf";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wl12xx_buffer_pins>;
+		gpio = <&gpio5 1 GPIO_ACTIVE_LOW>; /* gpio 129 */
+		regulator-always-on;
+		vin-supply = <&vdd_1v8_reg>;
+	};
+
+	wl12xx_vmmc2: wl12xx_vmmc2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vwl1271";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wl12xx_wkup_pins>;
+		gpio = <&gpio1 3 GPIO_ACTIVE_HIGH >; /* gpio 3 */
+		startup-delay-us = <70000>;
+		enable-active-high;
+		regulator-always-on;
+		vin-supply = <&wl12xx_buffer>;
+	};
+};
+
+&gpmc {
+	ranges = <0 0 0x30000000 0x1000000>;	/* CS0: 16MB for NAND */
+
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		linux,mtd-name = "micron,mt29f4g16abchch";
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		nand-bus-width = <16>;
+		ti,nand-ecc-opt = "bch8";
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+		gpmc,device-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+
+	s35390a: s35390a@30 {
+		compatible = "sii,s35390a";
+		reg = <0x30>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&rtc_pins>;
+		interrupts-extended = <&gpio2 23 IRQ_TYPE_EDGE_FALLING>; /* gpio_55 */
+	};
+
+	tps: tps65023@48 {
+		compatible = "ti,tps65023";
+		reg = <0x48>;
+
+		regulators {
+			vdd_core_reg: VDCDC1 {
+				regulator-name = "vdd_core";
+				regulator-always-on;
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+			};
+
+			vdd_io_reg: VDCDC2 {
+				regulator-name = "vdd_io";
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vdd_1v8_reg: VDCDC3 {
+				regulator-name = "vdd_1v8";
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			vdd_usb18_reg: LDO1 {
+				regulator-name = "vdd_usb18";
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			vdd_usb33_reg: LDO2 {
+				regulator-name = "vdd_usb33";
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+		};
+	};
+
+	touchscreen: tsc2004@4b {
+		compatible = "ti,tsc2004";
+		reg = <0x4b>;
+
+		vio-supply = <&vdd_io_reg>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&tsc2004_pins>;
+		interrupts-extended = <&gpio3 1 IRQ_TYPE_EDGE_RISING>; /* gpio_65 */
+
+		touchscreen-fuzz-x = <4>;
+		touchscreen-fuzz-y = <7>;
+		touchscreen-fuzz-pressure = <2>;
+		touchscreen-size-x = <480>;
+		touchscreen-size-y = <272>;
+		touchscreen-max-pressure = <2048>;
+
+		ti,x-plate-ohms = <280>;
+		ti,esd-recovery-timeout-ms = <8000>;
+	};
+};
+
+&mmc2 {
+	interrupts-extended = <&intc 86 /* &omap3_pmx_core 0x12c */>;
+
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+	vmmc-supply = <&wl12xx_vmmc2>;
+	non-removable;
+	bus-width = <4>;
+	cap-power-off-card;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1271";
+		reg = <2>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <10 IRQ_TYPE_EDGE_RISING>; /* gpio_170 */
+		ref-clock-frequency = <26000000>;
+		tcxo-clock-frequency = <26000000>;
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+
+	bluetooth {
+		compatible = "ti,wl1271-st";
+		enable-gpios = <&gpio2 24 GPIO_ACTIVE_HIGH>; /* gpio 56 */
+		max-speed = <3000000>;
+	};
+};
+
+&omap3_pmx_core {
+
+	wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4)  /* mmc1_dat7.gpio_129 */
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_clk.mmc2_clk */
+			OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_cmd.mmc2_cmd */
+			OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat0.mmc2_dat0 */
+			OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat1.mmc2_dat1 */
+			OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat2.mmc2_dat2 */
+			OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat3.mmc2_dat3 */
+			OMAP3_CORE1_IOPAD(0x2164, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat4.mmc2_dir_dat0 */
+			OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat5.mmc2_dir_dat1 */
+			OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat6.mmc2_dir_cmd */
+			OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT | MUX_MODE1) /* mmc2_dat7.mmc2_clkin */
+			OMAP3_CORE1_IOPAD(0x21c6, PIN_INPUT_PULLUP | MUX_MODE4)	/* hdq_sio.gpio_170 */
+		>;
+	};
+
+	rtc_pins: pinmux_rtc_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20b6, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_ncs4.gpio_55 */
+		>;
+	};
+
+	tsc2004_pins: pinmux_tsc2004_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20d2, PIN_INPUT | MUX_MODE4) /* gpmc_wait3.gpio_65 */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0)		/* uart2_cts */
+			OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* uart2_rts */
+			OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)		/* uart2_tx */
+			OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)		/* uart2_rx */
+			OMAP3_CORE1_IOPAD(0x20b8, PIN_INPUT | MUX_MODE0)		/* gpio_56 */
+		>;
+	};
+};
+
+&omap3_pmx_wkup {
+
+	wl12xx_wkup_pins: pinmux_wl12xx_wkup_pins {
+		pinctrl-single,pins = <
+			OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4)	/* sys_boot1.gpio_3 */
+		>;
+	};
+};
diff --git a/arch/arm/dts/am3517-u-boot.dtsi b/arch/arm/dts/am3517-u-boot.dtsi
new file mode 100644
index 0000000..374499d
--- /dev/null
+++ b/arch/arm/dts/am3517-u-boot.dtsi
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017
+ * Logic PD - http://www.logicpd.com
+ */
+
+&uart4 {
+	reg-shift = <2>;
+};
diff --git a/arch/arm/dts/am3517.dtsi b/arch/arm/dts/am3517.dtsi
new file mode 100644
index 0000000..23ea381
--- /dev/null
+++ b/arch/arm/dts/am3517.dtsi
@@ -0,0 +1,112 @@
+/*
+ * Device Tree Source for am3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include "omap3.dtsi"
+
+/ {
+	aliases {
+		serial3 = &uart4;
+		can = &hecc;
+	};
+
+	ocp@68000000 {
+		am35x_otg_hs: am35x_otg_hs@5c040000 {
+			compatible = "ti,omap3-musb";
+			ti,hwmods = "am35x_otg_hs";
+			status = "disabled";
+			reg = <0x5c040000 0x1000>;
+			interrupts = <71>;
+			interrupt-names = "mc";
+		};
+
+		davinci_emac: ethernet@5c000000 {
+			compatible = "ti,am3517-emac";
+			ti,hwmods = "davinci_emac";
+			status = "disabled";
+			reg = <0x5c000000 0x30000>;
+			interrupts = <67 68 69 70>;
+			syscon = <&scm_conf>;
+			ti,davinci-ctrl-reg-offset = <0x10000>;
+			ti,davinci-ctrl-mod-reg-offset = <0>;
+			ti,davinci-ctrl-ram-offset = <0x20000>;
+			ti,davinci-ctrl-ram-size = <0x2000>;
+			ti,davinci-rmii-en = /bits/ 8 <1>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			clocks = <&emac_ick>;
+			clock-names = "ick";
+		};
+
+		davinci_mdio: ethernet@5c030000 {
+			compatible = "ti,davinci_mdio";
+			ti,hwmods = "davinci_mdio";
+			status = "disabled";
+			reg = <0x5c030000 0x1000>;
+			bus_freq = <1000000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&emac_fck>;
+			clock-names = "fck";
+		};
+
+		uart4: serial@4809e000 {
+			compatible = "ti,omap3-uart";
+			ti,hwmods = "uart4";
+			status = "disabled";
+			reg = <0x4809e000 0x400>;
+			interrupts = <84>;
+			dmas = <&sdma 55 &sdma 54>;
+			dma-names = "tx", "rx";
+			clock-frequency = <48000000>;
+		};
+
+		omap3_pmx_core2: pinmux@480025d8 {
+			compatible = "ti,omap3-padconf", "pinctrl-single";
+			reg = <0x480025d8 0x24>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#pinctrl-cells = <1>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			pinctrl-single,register-width = <16>;
+			pinctrl-single,function-mask = <0xff1f>;
+		};
+
+		hecc: can@5c050000 {
+			compatible = "ti,am3517-hecc";
+			status = "disabled";
+			reg = <0x5c050000 0x80>,
+			      <0x5c053000 0x180>,
+			      <0x5c052000 0x200>;
+			reg-names = "hecc", "hecc-ram", "mbx";
+			interrupts = <24>;
+			clocks = <&hecc_ck>;
+		};
+	};
+};
+
+/* Table Table 5-79 of the TRM shows 480ab000 is reserved */
+&usb_otg_hs {
+	status = "disabled";
+};
+
+&iva {
+	status = "disabled";
+};
+
+&mailbox {
+	status = "disabled";
+};
+
+&mmu_isp {
+	status = "disabled";
+};
+
+/include/ "am35xx-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/dts/am35xx-clocks.dtsi b/arch/arm/dts/am35xx-clocks.dtsi
new file mode 100644
index 0000000..00dd1f0
--- /dev/null
+++ b/arch/arm/dts/am35xx-clocks.dtsi
@@ -0,0 +1,128 @@
+/*
+ * Device Tree Source for OMAP3 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+&scm_clocks {
+	emac_ick: emac_ick@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x032c>;
+		ti,bit-shift = <1>;
+	};
+
+	emac_fck: emac_fck@32c {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&rmii_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <9>;
+	};
+
+	vpfe_ick: vpfe_ick@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x032c>;
+		ti,bit-shift = <2>;
+	};
+
+	vpfe_fck: vpfe_fck@32c {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&pclk_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <10>;
+	};
+
+	hsotgusb_ick_am35xx: hsotgusb_ick_am35xx@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x032c>;
+		ti,bit-shift = <0>;
+	};
+
+	hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@32c {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <8>;
+	};
+
+	hecc_ck: hecc_ck@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&sys_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <3>;
+	};
+};
+&cm_clocks {
+	ipss_ick: ipss_ick@a10 {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-interface-clock";
+		clocks = <&core_l3_ick>;
+		reg = <0x0a10>;
+		ti,bit-shift = <4>;
+	};
+
+	rmii_ck: rmii_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <50000000>;
+	};
+
+	pclk_ck: pclk_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <27000000>;
+	};
+
+	uart4_ick_am35xx: uart4_ick_am35xx@a10 {
+		#clock-cells = <0>;
+		compatible = "ti,omap3-interface-clock";
+		clocks = <&core_l4_ick>;
+		reg = <0x0a10>;
+		ti,bit-shift = <23>;
+	};
+
+	uart4_fck_am35xx: uart4_fck_am35xx@a00 {
+		#clock-cells = <0>;
+		compatible = "ti,wait-gate-clock";
+		clocks = <&core_48m_fck>;
+		reg = <0x0a00>;
+		ti,bit-shift = <23>;
+	};
+};
+
+&cm_clockdomains {
+	core_l3_clkdm: core_l3_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&sdrc_ick>, <&ipss_ick>, <&emac_ick>, <&vpfe_ick>,
+			 <&hsotgusb_ick_am35xx>, <&hsotgusb_fck_am35xx>,
+			 <&hecc_ck>;
+	};
+
+	core_l4_clkdm: core_l4_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>,
+			 <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>,
+			 <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+			 <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+			 <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+			 <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+			 <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+			 <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+			 <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+			 <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+			 <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+			 <&uart4_ick_am35xx>, <&uart4_fck_am35xx>;
+	};
+};
diff --git a/arch/arm/dts/am4372-generic-u-boot.dtsi b/arch/arm/dts/am4372-generic-u-boot.dtsi
new file mode 100644
index 0000000..6ba5c16
--- /dev/null
+++ b/arch/arm/dts/am4372-generic-u-boot.dtsi
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "am4372-u-boot.dtsi"
+
+/{
+	ocp {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&i2c0 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/am4372-generic.dts b/arch/arm/dts/am4372-generic.dts
new file mode 100644
index 0000000..b8a2bb8
--- /dev/null
+++ b/arch/arm/dts/am4372-generic.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Device Tree Source for Generic AM4372 EVM
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+
+#include "am4372.dtsi"
+
+/ {
+	compatible = "ti,am4372", "ti,am43";
+	model = "Texas Instruments AM4372 Generic";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/am4372-u-boot.dtsi b/arch/arm/dts/am4372-u-boot.dtsi
new file mode 100644
index 0000000..99922ca
--- /dev/null
+++ b/arch/arm/dts/am4372-u-boot.dtsi
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+&am43xx_control_usb2phy1 {
+	compatible = "ti,control-phy-usb2-am437", "syscon";
+};
+
+&am43xx_control_usb2phy2 {
+	compatible = "ti,control-phy-usb2-am437", "syscon";
+};
+
+&ocp2scp0 {
+	compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp", "simple-bus";
+};
+
+&ocp2scp1 {
+	compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp", "simple-bus";
+};
+
+&dwc3_1 {
+	u-boot,dm-spl;
+};
+
+&usb1 {
+	u-boot,dm-spl;
+};
+
+&usb2_phy1 {
+	u-boot,dm-spl;
+};
+
+&am43xx_control_usb2phy1 {
+	u-boot,dm-spl;
+};
+
+&ocp2scp0 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/am4372.dtsi b/arch/arm/dts/am4372.dtsi
new file mode 100644
index 0000000..6f60a32
--- /dev/null
+++ b/arch/arm/dts/am4372.dtsi
@@ -0,0 +1,1009 @@
+/*
+ * Device Tree Source for AM4372 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "ti,am4372", "ti,am43";
+	interrupt-parent = <&wakeupgen>;
+
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		serial0 = &uart0;
+		ethernet0 = &cpsw_emac0;
+		ethernet1 = &cpsw_emac1;
+		spi0 = &qspi;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu: cpu@0 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <0>;
+
+			clocks = <&dpll_mpu_ck>;
+			clock-names = "cpu";
+
+			clock-latency = <300000>; /* From omap-cpufreq driver */
+		};
+	};
+
+	gic: interrupt-controller@48241000 {
+		compatible = "arm,cortex-a9-gic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48241000 0x1000>,
+		      <0x48240100 0x0100>;
+		interrupt-parent = <&gic>;
+	};
+
+	wakeupgen: interrupt-controller@48281000 {
+		compatible = "ti,omap4-wugen-mpu";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48281000 0x1000>;
+		interrupt-parent = <&gic>;
+	};
+
+	l2-cache-controller@48242000 {
+		compatible = "arm,pl310-cache";
+		reg = <0x48242000 0x1000>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	ocp {
+		compatible = "ti,am4372-l3-noc", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main";
+		reg = <0x44000000 0x400000
+		       0x44800000 0x400000>;
+		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+
+		l4_wkup: l4_wkup@44c00000 {
+			compatible = "ti,am4-l4-wkup", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x44c00000 0x287000>;
+
+			prcm: prcm@1f0000 {
+				compatible = "ti,am4-prcm";
+				reg = <0x1f0000 0x11000>;
+
+				prcm_clocks: clocks {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+
+				prcm_clockdomains: clockdomains {
+				};
+			};
+
+			scm: scm@210000 {
+				compatible = "ti,am4-scm", "simple-bus";
+				reg = <0x210000 0x4000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x210000 0x4000>;
+
+				am43xx_pinmux: pinmux@800 {
+					compatible = "ti,am437-padconf",
+						     "pinctrl-single";
+					reg = <0x800 0x31c>;
+					#interrupt-cells = <1>;
+					interrupt-controller;
+					pinctrl-single,register-width = <32>;
+					pinctrl-single,function-mask = <0xffffffff>;
+				};
+
+				scm_conf: scm_conf@0 {
+					compatible = "syscon";
+					reg = <0x0 0x800>;
+
+					scm_clocks: clocks {
+						#address-cells = <1>;
+						#size-cells = <0>;
+					};
+				};
+
+				scm_clockdomains: clockdomains {
+				};
+			};
+		};
+
+		emif: emif@4c000000 {
+			compatible = "ti,emif-am4372";
+			reg = <0x4c000000 0x1000000>;
+			ti,hwmods = "emif";
+		};
+
+		edma: edma@49000000 {
+			compatible = "ti,edma3";
+			ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
+			reg =	<0x49000000 0x10000>,
+				<0x44e10f90 0x10>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+		};
+
+		uart0: serial@44e09000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x44e09000 0x2000>;
+			reg-shift = <2>;
+			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart1";
+		};
+
+		uart1: serial@48022000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x48022000 0x2000>;
+			reg-shift = <2>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart2";
+			status = "disabled";
+		};
+
+		uart2: serial@48024000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x48024000 0x2000>;
+			reg-shift = <2>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart3";
+			status = "disabled";
+		};
+
+		uart3: serial@481a6000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x481a6000 0x2000>;
+			reg-shift = <2>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart4";
+			status = "disabled";
+		};
+
+		uart4: serial@481a8000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x481a8000 0x2000>;
+			reg-shift = <2>;
+			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart5";
+			status = "disabled";
+		};
+
+		uart5: serial@481aa000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x481aa000 0x2000>;
+			reg-shift = <2>;
+			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart6";
+			status = "disabled";
+		};
+
+		mailbox: mailbox@480C8000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x480C8000 0x200>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "mailbox";
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <8>;
+			mbox_wkupm3: wkup_m3 {
+				ti,mbox-tx = <0 0 0>;
+				ti,mbox-rx = <0 0 3>;
+			};
+		};
+
+		timer1: timer@44e31000 {
+			compatible = "ti,am4372-timer-1ms","ti,am335x-timer-1ms";
+			reg = <0x44e31000 0x400>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-alwon;
+			ti,hwmods = "timer1";
+		};
+
+		timer2: timer@48040000  {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48040000  0x400>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@48042000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48042000 0x400>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer3";
+			status = "disabled";
+		};
+
+		timer4: timer@48044000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48044000 0x400>;
+			interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer4";
+			status = "disabled";
+		};
+
+		timer5: timer@48046000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48046000 0x400>;
+			interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer5";
+			status = "disabled";
+		};
+
+		timer6: timer@48048000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48048000 0x400>;
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer6";
+			status = "disabled";
+		};
+
+		timer7: timer@4804a000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x4804a000 0x400>;
+			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer7";
+			status = "disabled";
+		};
+
+		timer8: timer@481c1000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x481c1000 0x400>;
+			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer8";
+			status = "disabled";
+		};
+
+		timer9: timer@4833d000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x4833d000 0x400>;
+			interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer9";
+			status = "disabled";
+		};
+
+		timer10: timer@4833f000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x4833f000 0x400>;
+			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer10";
+			status = "disabled";
+		};
+
+		timer11: timer@48341000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48341000 0x400>;
+			interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer11";
+			status = "disabled";
+		};
+
+		counter32k: counter@44e86000 {
+			compatible = "ti,am4372-counter32k","ti,omap-counter32k";
+			reg = <0x44e86000 0x40>;
+			ti,hwmods = "counter_32k";
+		};
+
+		rtc: rtc@44e3e000 {
+			compatible = "ti,am4372-rtc","ti,da830-rtc";
+			reg = <0x44e3e000 0x1000>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "rtc";
+			status = "disabled";
+		};
+
+		wdt: wdt@44e35000 {
+			compatible = "ti,am4372-wdt","ti,omap3-wdt";
+			reg = <0x44e35000 0x1000>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "wd_timer2";
+		};
+
+		gpio0: gpio@44e07000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x44e07000 0x1000>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio1";
+			status = "disabled";
+		};
+
+		gpio1: gpio@4804c000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x4804c000 0x1000>;
+			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio2";
+			status = "disabled";
+		};
+
+		gpio2: gpio@481ac000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x481ac000 0x1000>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio3";
+			status = "disabled";
+		};
+
+		gpio3: gpio@481ae000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x481ae000 0x1000>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio4";
+			status = "disabled";
+		};
+
+		gpio4: gpio@48320000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x48320000 0x1000>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio5";
+			status = "disabled";
+		};
+
+		gpio5: gpio@48322000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x48322000 0x1000>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio6";
+			status = "disabled";
+		};
+
+		hwspinlock: spinlock@480ca000 {
+			compatible = "ti,omap4-hwspinlock";
+			reg = <0x480ca000 0x1000>;
+			ti,hwmods = "spinlock";
+			#hwlock-cells = <1>;
+		};
+
+		i2c0: i2c@44e0b000 {
+			compatible = "ti,am4372-i2c","ti,omap4-i2c";
+			reg = <0x44e0b000 0x1000>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "i2c1";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@4802a000 {
+			compatible = "ti,am4372-i2c","ti,omap4-i2c";
+			reg = <0x4802a000 0x1000>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "i2c2";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@4819c000 {
+			compatible = "ti,am4372-i2c","ti,omap4-i2c";
+			reg = <0x4819c000 0x1000>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "i2c3";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi0: spi@48030000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x48030000 0x400>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi0";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		mmc1: mmc@48060000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x48060000 0x1000>;
+			ti,hwmods = "mmc1";
+			ti,dual-volt;
+			ti,needs-special-reset;
+			dmas = <&edma 24
+				&edma 25>;
+			dma-names = "tx", "rx";
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		mmc2: mmc@481d8000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x481d8000 0x1000>;
+			ti,hwmods = "mmc2";
+			ti,needs-special-reset;
+			dmas = <&edma 2
+				&edma 3>;
+			dma-names = "tx", "rx";
+			interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		mmc3: mmc@47810000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x47810000 0x1000>;
+			ti,hwmods = "mmc3";
+			ti,needs-special-reset;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		spi1: spi@481a0000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x481a0000 0x400>;
+			interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi1";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi2: spi@481a2000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x481a2000 0x400>;
+			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi2";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi3: spi@481a4000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x481a4000 0x400>;
+			interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi3";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi4: spi@48345000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x48345000 0x400>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi4";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		mac: ethernet@4a100000 {
+			compatible = "ti,am4372-cpsw","ti,cpsw";
+			reg = <0x4a100000 0x800
+			       0x4a101200 0x100>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ti,hwmods = "cpgmac0";
+			clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>;
+			clock-names = "fck", "cpts";
+			status = "disabled";
+			cpdma_channels = <8>;
+			ale_entries = <1024>;
+			bd_ram_size = <0x2000>;
+			no_bd_ram = <0>;
+			rx_descs = <64>;
+			mac_control = <0x20>;
+			slaves = <2>;
+			active_slave = <0>;
+			cpts_clock_mult = <0x80000000>;
+			cpts_clock_shift = <29>;
+			syscon = <&scm_conf>;
+			ranges;
+
+			davinci_mdio: mdio@4a101000 {
+				compatible = "ti,am4372-mdio","ti,davinci_mdio";
+				reg = <0x4a101000 0x100>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				ti,hwmods = "davinci_mdio";
+				bus_freq = <1000000>;
+				status = "disabled";
+			};
+
+			cpsw_emac0: slave@4a100200 {
+				/* Filled in by U-Boot */
+				mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			cpsw_emac1: slave@4a100300 {
+				/* Filled in by U-Boot */
+				mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			phy_sel: cpsw-phy-sel@44e10650 {
+				compatible = "ti,am43xx-cpsw-phy-sel";
+				reg= <0x44e10650 0x4>;
+				reg-names = "gmii-sel";
+			};
+		};
+
+		epwmss0: epwmss@48300000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48300000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss0";
+			status = "disabled";
+
+			ecap0: ecap@48300100 {
+				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48300100 0x80>;
+				ti,hwmods = "ecap0";
+				status = "disabled";
+			};
+
+			ehrpwm0: ehrpwm@48300200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48300200 0x80>;
+				ti,hwmods = "ehrpwm0";
+				status = "disabled";
+			};
+		};
+
+		epwmss1: epwmss@48302000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48302000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss1";
+			status = "disabled";
+
+			ecap1: ecap@48302100 {
+				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48302100 0x80>;
+				ti,hwmods = "ecap1";
+				status = "disabled";
+			};
+
+			ehrpwm1: ehrpwm@48302200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48302200 0x80>;
+				ti,hwmods = "ehrpwm1";
+				status = "disabled";
+			};
+		};
+
+		epwmss2: epwmss@48304000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48304000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss2";
+			status = "disabled";
+
+			ecap2: ecap@48304100 {
+				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48304100 0x80>;
+				ti,hwmods = "ecap2";
+				status = "disabled";
+			};
+
+			ehrpwm2: ehrpwm@48304200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48304200 0x80>;
+				ti,hwmods = "ehrpwm2";
+				status = "disabled";
+			};
+		};
+
+		epwmss3: epwmss@48306000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48306000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss3";
+			status = "disabled";
+
+			ehrpwm3: ehrpwm@48306200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48306200 0x80>;
+				ti,hwmods = "ehrpwm3";
+				status = "disabled";
+			};
+		};
+
+		epwmss4: epwmss@48308000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48308000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss4";
+			status = "disabled";
+
+			ehrpwm4: ehrpwm@48308200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48308200 0x80>;
+				ti,hwmods = "ehrpwm4";
+				status = "disabled";
+			};
+		};
+
+		epwmss5: epwmss@4830a000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x4830a000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss5";
+			status = "disabled";
+
+			ehrpwm5: ehrpwm@4830a200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x4830a200 0x80>;
+				ti,hwmods = "ehrpwm5";
+				status = "disabled";
+			};
+		};
+
+		tscadc: tscadc@44e0d000 {
+			compatible = "ti,am3359-tscadc";
+			reg = <0x44e0d000 0x1000>;
+			ti,hwmods = "adc_tsc";
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&adc_tsc_fck>;
+			clock-names = "fck";
+			status = "disabled";
+
+			tsc {
+				compatible = "ti,am3359-tsc";
+			};
+
+			adc {
+				#io-channel-cells = <1>;
+				compatible = "ti,am3359-adc";
+			};
+
+		};
+
+		sham: sham@53100000 {
+			compatible = "ti,omap5-sham";
+			ti,hwmods = "sham";
+			reg = <0x53100000 0x300>;
+			dmas = <&edma 36>;
+			dma-names = "rx";
+			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		aes: aes@53501000 {
+			compatible = "ti,omap4-aes";
+			ti,hwmods = "aes";
+			reg = <0x53501000 0xa0>;
+			interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&edma 6
+				&edma 5>;
+			dma-names = "tx", "rx";
+		};
+
+		des: des@53701000 {
+			compatible = "ti,omap4-des";
+			ti,hwmods = "des";
+			reg = <0x53701000 0xa0>;
+			interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&edma 34
+				&edma 33>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp0: mcasp@48038000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp0";
+			reg = <0x48038000 0x2000>,
+			      <0x46000000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 8>,
+			       <&edma 9>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp1: mcasp@4803C000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp1";
+			reg = <0x4803C000 0x2000>,
+			      <0x46400000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 10>,
+			       <&edma 11>;
+			dma-names = "tx", "rx";
+		};
+
+		elm: elm@48080000 {
+			compatible = "ti,am3352-elm";
+			reg = <0x48080000 0x2000>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "elm";
+			clocks = <&l4ls_gclk>;
+			clock-names = "fck";
+			status = "disabled";
+		};
+
+		gpmc: gpmc@50000000 {
+			compatible = "ti,am3352-gpmc";
+			ti,hwmods = "gpmc";
+			clocks = <&l3s_gclk>;
+			clock-names = "fck";
+			reg = <0x50000000 0x2000>;
+			interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+			gpmc,num-cs = <7>;
+			gpmc,num-waitpins = <2>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			status = "disabled";
+		};
+
+		am43xx_control_usb2phy1: control-phy@44e10620 {
+			compatible = "ti,control-phy-usb2-am437";
+			reg = <0x44e10620 0x4>;
+			reg-names = "power";
+		};
+
+		am43xx_control_usb2phy2: control-phy@0x44e10628 {
+			compatible = "ti,control-phy-usb2-am437";
+			reg = <0x44e10628 0x4>;
+			reg-names = "power";
+		};
+
+		ocp2scp0: ocp2scp@483a8000 {
+			compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "ocp2scp0";
+
+			usb2_phy1: phy@483a8000 {
+				compatible = "ti,am437x-usb2";
+				reg = <0x483a8000 0x8000>;
+				ctrl-module = <&am43xx_control_usb2phy1>;
+				clocks = <&usb_phy0_always_on_clk32k>,
+					 <&usb_otg_ss0_refclk960m>;
+				clock-names = "wkupclk", "refclk";
+				#phy-cells = <0>;
+				status = "disabled";
+			};
+		};
+
+		ocp2scp1: ocp2scp@483e8000 {
+			compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "ocp2scp1";
+
+			usb2_phy2: phy@483e8000 {
+				compatible = "ti,am437x-usb2";
+				reg = <0x483e8000 0x8000>;
+				ctrl-module = <&am43xx_control_usb2phy2>;
+				clocks = <&usb_phy1_always_on_clk32k>,
+					 <&usb_otg_ss1_refclk960m>;
+				clock-names = "wkupclk", "refclk";
+				#phy-cells = <0>;
+				status = "disabled";
+			};
+		};
+
+		dwc3_1: omap_dwc3@48380000 {
+			compatible = "ti,am437x-dwc3";
+			ti,hwmods = "usb_otg_ss0";
+			reg = <0x48380000 0x10000>;
+			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			utmi-mode = <1>;
+			ranges;
+
+			usb1: usb@48390000 {
+				compatible = "synopsys,dwc3";
+				reg = <0x48390000 0x10000>;
+				interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+				phys = <&usb2_phy1>;
+				phy-names = "usb2-phy";
+				maximum-speed = "high-speed";
+				dr_mode = "otg";
+				status = "disabled";
+				snps,dis_u3_susphy_quirk;
+				snps,dis_u2_susphy_quirk;
+			};
+		};
+
+		dwc3_2: omap_dwc3@483c0000 {
+			compatible = "ti,am437x-dwc3";
+			ti,hwmods = "usb_otg_ss1";
+			reg = <0x483c0000 0x10000>;
+			interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			utmi-mode = <1>;
+			ranges;
+
+			usb2: usb@483d0000 {
+				compatible = "synopsys,dwc3";
+				reg = <0x483d0000 0x10000>;
+				interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+				phys = <&usb2_phy2>;
+				phy-names = "usb2-phy";
+				maximum-speed = "high-speed";
+				dr_mode = "otg";
+				status = "disabled";
+				snps,dis_u3_susphy_quirk;
+				snps,dis_u2_susphy_quirk;
+			};
+		};
+
+		qspi: qspi@47900000 {
+			compatible = "ti,am4372-qspi";
+			reg = <0x47900000 0x100>,
+			      <0x30000000 0x4000000>;
+			reg-names = "qspi_base", "qspi_mmap";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "qspi";
+			interrupts = <0 138 0x4>;
+			num-cs = <4>;
+			status = "disabled";
+		};
+
+		hdq: hdq@48347000 {
+			compatible = "ti,am4372-hdq";
+			reg = <0x48347000 0x1000>;
+			interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&func_12m_clk>;
+			clock-names = "fck";
+			ti,hwmods = "hdq1w";
+			status = "disabled";
+		};
+
+		dss: dss@4832a000 {
+			compatible = "ti,omap3-dss";
+			reg = <0x4832a000 0x200>;
+			status = "disabled";
+			ti,hwmods = "dss_core";
+			clocks = <&disp_clk>;
+			clock-names = "fck";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			dispc: dispc@4832a400 {
+				compatible = "ti,omap3-dispc";
+				reg = <0x4832a400 0x400>;
+				interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+				ti,hwmods = "dss_dispc";
+				clocks = <&disp_clk>;
+				clock-names = "fck";
+			};
+
+			rfbi: rfbi@4832a800 {
+				compatible = "ti,omap3-rfbi";
+				reg = <0x4832a800 0x100>;
+				ti,hwmods = "dss_rfbi";
+				clocks = <&disp_clk>;
+				clock-names = "fck";
+				status = "disabled";
+			};
+		};
+
+		ocmcram: ocmcram@40300000 {
+			compatible = "mmio-sram";
+			reg = <0x40300000 0x40000>; /* 256k */
+		};
+
+		dcan0: can@481cc000 {
+			compatible = "ti,am4372-d_can", "ti,am3352-d_can";
+			ti,hwmods = "d_can0";
+			clocks = <&dcan0_fck>;
+			clock-names = "fck";
+			reg = <0x481cc000 0x2000>;
+			syscon-raminit = <&scm_conf 0x644 0>;
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		dcan1: can@481d0000 {
+			compatible = "ti,am4372-d_can", "ti,am3352-d_can";
+			ti,hwmods = "d_can1";
+			clocks = <&dcan1_fck>;
+			clock-names = "fck";
+			reg = <0x481d0000 0x2000>;
+			syscon-raminit = <&scm_conf 0x644 1>;
+			interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		vpfe0: vpfe@48326000 {
+			compatible = "ti,am437x-vpfe";
+			reg = <0x48326000 0x2000>;
+			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "vpfe0";
+			status = "disabled";
+		};
+
+		vpfe1: vpfe@48328000 {
+			compatible = "ti,am437x-vpfe";
+			reg = <0x48328000 0x2000>;
+			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "vpfe1";
+			status = "disabled";
+		};
+	};
+};
+
+/include/ "am43xx-clocks.dtsi"
diff --git a/arch/arm/dts/am437x-gp-evm-u-boot.dtsi b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi
new file mode 100644
index 0000000..d950d32
--- /dev/null
+++ b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ * Based on "dra7.dtsi"
+ */
+
+#include "am4372-u-boot.dtsi"
+
+/{
+	ocp {
+		u-boot,dm-spl;
+	};
+};
+
+&uart0 {
+	u-boot,dm-spl;
+};
+
+&mmc1 {
+	u-boot,dm-spl;
+};
+
+&mac {
+	u-boot,dm-spl;
+};
+
+&davinci_mdio {
+	u-boot,dm-spl;
+};
+
+&cpsw_emac0 {
+	u-boot,dm-spl;
+};
+
+&phy_sel {
+	u-boot,dm-spl;
+};
+
+&i2c0 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/am437x-gp-evm.dts b/arch/arm/dts/am437x-gp-evm.dts
new file mode 100644
index 0000000..142bfc5
--- /dev/null
+++ b/arch/arm/dts/am437x-gp-evm.dts
@@ -0,0 +1,798 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* AM437x GP EVM */
+
+/dts-v1/;
+
+#include "am4372.dtsi"
+#include <dt-bindings/pinctrl/am43xx.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "TI AM437x GP EVM";
+	compatible = "ti,am437x-gp-evm","ti,am4372","ti,am43";
+
+	aliases {
+		display0 = &lcd0;
+		serial3 = &uart3;
+	};
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	vmmcsd_fixed: fixedregulator-sd {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+	};
+
+	vtt_fixed: fixedregulator-vtt {
+		compatible = "regulator-fixed";
+		regulator-name = "vtt_fixed";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>;
+	};
+
+	vmmcwl_fixed: fixedregulator-mmcwl {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcwl_fixed";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio1 20 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
+
+	matrix_keypad: matrix_keypad@0 {
+		compatible = "gpio-matrix-keypad";
+		debounce-delay-ms = <5>;
+		col-scan-delay-us = <2>;
+
+		row-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH /* Bank3, pin21 */
+				&gpio4 3 GPIO_ACTIVE_HIGH /* Bank4, pin3 */
+				&gpio4 2 GPIO_ACTIVE_HIGH>; /* Bank4, pin2 */
+
+		col-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH /* Bank3, pin19 */
+				&gpio3 20 GPIO_ACTIVE_HIGH>; /* Bank3, pin20 */
+
+		linux,keymap = <0x00000201      /* P1 */
+				0x00010202      /* P2 */
+				0x01000067      /* UP */
+				0x0101006a      /* RIGHT */
+				0x02000069      /* LEFT */
+				0x0201006c>;      /* DOWN */
+		};
+
+	lcd0: display {
+		compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+		label = "lcd";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins>;
+
+		/*
+		 * SelLCDorHDMI, LOW to select HDMI. This is not really the
+		 * panel's enable GPIO, but we don't have HDMI driver support nor
+		 * support to switch between two displays, so using this gpio as
+		 * panel's enable should be safe.
+		 */
+		enable-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>;
+
+		panel-timing {
+			clock-frequency = <33000000>;
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <210>;
+			hback-porch = <16>;
+			hsync-len = <30>;
+			vback-porch = <10>;
+			vfront-porch = <22>;
+			vsync-len = <13>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dpi_out>;
+			};
+		};
+	};
+
+	/* fixed 12MHz oscillator */
+	refclk: oscillator {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <12000000>;
+	};
+
+};
+
+&am43xx_pinmux {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&wlan_pins_default>;
+	pinctrl-1 = <&wlan_pins_sleep>;
+
+	i2c0_pins: i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: i2c1_pins {
+		pinctrl-single,pins = <
+			0x15c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_cs0.i2c1_scl */
+			0x158 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_d1.i2c1_sda  */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
+	ecap0_pins: backlight_pins {
+		pinctrl-single,pins = <
+			0x164 MUX_MODE0       /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
+		>;
+	};
+
+	pixcir_ts_pins: pixcir_ts_pins {
+		pinctrl-single,pins = <
+			0x264 (PIN_INPUT_PULLUP | MUX_MODE7)  /* spi2_d0.gpio3_22 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_txen */
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rxctl */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_txd3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_txd2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_txd1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_txd0 */
+			0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rmii1_tclk */
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rmii1_rclk */
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rxd3 */
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rxd2 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rxd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rxd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	nand_flash_x8: nand_flash_x8 {
+		pinctrl-single,pins = <
+			0x26c(PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* spi2_cs0.gpio/eMMCorNANDsel */
+			0x0  (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4  (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8  (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc  (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT  | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpmc_wpn */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+
+	dss_pins: dss_pins {
+		pinctrl-single,pins = <
+			0x020 (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */
+			0x024 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x028 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x02c (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x030 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x034 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x038 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+			0x03c (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 15 -> DSS DATA 16 */
+			0x0a0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */
+			0x0a4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0a8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0ac (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0b0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0b4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0b8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0bc (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0c0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0c4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0c8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0cc (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0d0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0d4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0d8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+			0x0dc (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */
+			0x0e0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */
+			0x0e4 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */
+			0x0e8 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */
+			0x0ec (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */
+
+		>;
+	};
+
+	lcd_pins: lcd_pins {
+		pinctrl-single,pins = <
+			/* GPIO 5_8 to select LCD / HDMI */
+			0x238 (PIN_OUTPUT_PULLUP | MUX_MODE7)
+		>;
+	};
+
+	dcan0_default: dcan0_default_pins {
+		pinctrl-single,pins = <
+			0x178 (PIN_OUTPUT | MUX_MODE2)		/* uart1_ctsn.d_can0_tx */
+			0x17c (PIN_INPUT_PULLUP | MUX_MODE2)	/* uart1_rtsn.d_can0_rx */
+		>;
+	};
+
+	dcan1_default: dcan1_default_pins {
+		pinctrl-single,pins = <
+			0x180 (PIN_OUTPUT | MUX_MODE2)		/* uart1_rxd.d_can1_tx */
+			0x184 (PIN_INPUT_PULLUP | MUX_MODE2)	/* uart1_txd.d_can1_rx */
+		>;
+	};
+
+	vpfe0_pins_default: vpfe0_pins_default {
+		pinctrl-single,pins = <
+			0x1B0 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_hd mode 0*/
+			0x1B4 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_vd mode 0*/
+			0x1C0 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_pclk mode 0*/
+			0x1C4 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data8 mode 0*/
+			0x1C8 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data9 mode 0*/
+			0x208 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data0 mode 0*/
+			0x20C (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data1 mode 0*/
+			0x210 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data2 mode 0*/
+			0x214 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data3 mode 0*/
+			0x218 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data4 mode 0*/
+			0x21C (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data5 mode 0*/
+			0x220 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data6 mode 0*/
+			0x224 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data7 mode 0*/
+		>;
+	};
+
+	vpfe0_pins_sleep: vpfe0_pins_sleep {
+		pinctrl-single,pins = <
+			0x1B0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_hd mode 0*/
+			0x1B4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_vd mode 0*/
+			0x1C0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_pclk mode 0*/
+			0x1C4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data8 mode 0*/
+			0x1C8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data9 mode 0*/
+			0x208 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data0 mode 0*/
+			0x20C (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data1 mode 0*/
+			0x210 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data2 mode 0*/
+			0x214 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data3 mode 0*/
+			0x218 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data4 mode 0*/
+			0x21C (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data5 mode 0*/
+			0x220 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data6 mode 0*/
+			0x224 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam0_data7 mode 0*/
+		>;
+	};
+
+	vpfe1_pins_default: vpfe1_pins_default {
+		pinctrl-single,pins = <
+			0x1CC (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data9 mode 0*/
+			0x1D0 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data8 mode 0*/
+			0x1D4 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_hd mode 0*/
+			0x1D8 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_vd mode 0*/
+			0x1DC (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_pclk mode 0*/
+			0x1E8 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data0 mode 0*/
+			0x1EC (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data1 mode 0*/
+			0x1F0 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data2 mode 0*/
+			0x1F4 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data3 mode 0*/
+			0x1F8 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data4 mode 0*/
+			0x1FC (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data5 mode 0*/
+			0x200 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data6 mode 0*/
+			0x204 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data7 mode 0*/
+		>;
+	};
+
+	vpfe1_pins_sleep: vpfe1_pins_sleep {
+		pinctrl-single,pins = <
+			0x1CC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data9 mode 0*/
+			0x1D0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data8 mode 0*/
+			0x1D4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_hd mode 0*/
+			0x1D8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_vd mode 0*/
+			0x1DC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_pclk mode 0*/
+			0x1E8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data0 mode 0*/
+			0x1EC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data1 mode 0*/
+			0x1F0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data2 mode 0*/
+			0x1F4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data3 mode 0*/
+			0x1F8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data4 mode 0*/
+			0x1FC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data5 mode 0*/
+			0x200 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data6 mode 0*/
+			0x204 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)  /* cam1_data7 mode 0*/
+		>;
+	};
+
+	mmc3_pins_default: pinmux_mmc3_pins_default {
+		pinctrl-single,pins = <
+			0x8c (PIN_INPUT_PULLUP | MUX_MODE3)      /* gpmc_clk.mmc2_clk */
+			0x88 (PIN_INPUT_PULLUP | MUX_MODE3)      /* gpmc_csn3.mmc2_cmd */
+			0x44 (PIN_INPUT_PULLUP | MUX_MODE3)      /* gpmc_a1.mmc2_dat0 */
+			0x48 (PIN_INPUT_PULLUP | MUX_MODE3)      /* gpmc_a2.mmc2_dat1 */
+			0x4c (PIN_INPUT_PULLUP | MUX_MODE3)      /* gpmc_a3.mmc2_dat2 */
+			0x78 (PIN_INPUT_PULLUP | MUX_MODE3)      /* gpmc_be1n.mmc2_dat3 */
+		>;
+	};
+
+	mmc3_pins_sleep: pinmux_mmc3_pins_sleep {
+		pinctrl-single,pins = <
+			0x8c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_clk.mmc2_clk */
+			0x88 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_csn3.mmc2_cmd */
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a1.mmc2_dat0 */
+			0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a2.mmc2_dat1 */
+			0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a3.mmc2_dat2 */
+			0x78 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_be1n.mmc2_dat3 */
+		>;
+	};
+
+	wlan_pins_default: pinmux_wlan_pins_default {
+		pinctrl-single,pins = <
+			0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)		/* gpmc_a4.gpio1_20 WL_EN */
+			0x5c (PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7)	/* gpmc_a7.gpio1_23 WL_IRQ*/
+			0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)		/* gpmc_a0.gpio1_16 BT_EN*/
+		>;
+	};
+
+	wlan_pins_sleep: pinmux_wlan_pins_sleep {
+		pinctrl-single,pins = <
+			0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)		/* gpmc_a4.gpio1_20 WL_EN */
+			0x5c (PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7)	/* gpmc_a7.gpio1_23 WL_IRQ*/
+			0x40 (PIN_OUTPUT_PULLUP | MUX_MODE7)		/* gpmc_a0.gpio1_16 BT_EN*/
+		>;
+	};
+
+	uart3_pins: uart3_pins {
+		pinctrl-single,pins = <
+			0x228 (PIN_INPUT | MUX_MODE0)		/* uart3_rxd.uart3_rxd */
+			0x22c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart3_txd.uart3_txd */
+			0x230 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart3_ctsn.uart3_ctsn */
+			0x234 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart3_rtsn.uart3_rtsn */
+		>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <100000>;
+
+	tps65218: tps65218@24 {
+		reg = <0x24>;
+		compatible = "ti,tps65218";
+		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		dcdc1: regulator-dcdc1 {
+			compatible = "ti,tps65218-dcdc1";
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc2: regulator-dcdc2 {
+			compatible = "ti,tps65218-dcdc2";
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1378000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3: regulator-dcdc3 {
+			compatible = "ti,tps65218-dcdc3";
+			regulator-name = "vdcdc3";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+		dcdc5: regulator-dcdc5 {
+			compatible = "ti,tps65218-dcdc5";
+			regulator-name = "v1_0bat";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+		};
+
+		dcdc6: regulator-dcdc6 {
+			compatible = "ti,tps65218-dcdc6";
+			regulator-name = "v1_8bat";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldo1: regulator-ldo1 {
+			compatible = "ti,tps65218-ldo1";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
+
+	ov2659@30 {
+		compatible = "ovti,ov2659";
+		reg = <0x30>;
+
+		clocks = <&refclk 0>;
+		clock-names = "xvclk";
+
+		port {
+			ov2659_0: endpoint {
+				remote-endpoint = <&vpfe1_ep>;
+				link-frequencies = /bits/ 64 <70000000>;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	pixcir_ts@5c {
+		compatible = "pixcir,pixcir_tangoc";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pixcir_ts_pins>;
+		reg = <0x5c>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <22 0>;
+
+		attb-gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <600>;
+	};
+
+	ov2659@30 {
+		compatible = "ovti,ov2659";
+		reg = <0x30>;
+
+		clocks = <&refclk 0>;
+		clock-names = "xvclk";
+
+		port {
+			ov2659_1: endpoint {
+				remote-endpoint = <&vpfe0_ep>;
+				link-frequencies = /bits/ 64 <70000000>;
+			};
+		};
+	};
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&tscadc {
+	status = "okay";
+
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+	};
+};
+
+&ecap0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ecap0_pins>;
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio3 {
+	status = "okay";
+};
+
+&gpio4 {
+	status = "okay";
+};
+
+&gpio5 {
+	status = "okay";
+	ti,no-reset-on-init;
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&mmc3 {
+	/* disable MMC3 as SDIO is not supported in U-Boot */
+	status = "disabled";
+	/* these are on the crossbar and are outlined in the
+	   xbar-event-map element */
+	dmas = <&edma 30
+		&edma 31>;
+	dma-names = "tx", "rx";
+	vmmc-supply = <&vmmcwl_fixed>;
+	bus-width = <4>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&mmc3_pins_default>;
+	pinctrl-1 = <&mmc3_pins_sleep>;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	ti,non-removable;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@0 {
+		compatible = "ti,wl1835";
+		reg = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&edma {
+	ti,edma-xbar-event-map = /bits/ 16 <1 30
+					    2 31>;
+};
+
+&uart3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
+
+&usb2_phy1 {
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usb2_phy2 {
+	status = "okay";
+};
+
+&usb2 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&mac {
+	slaves = <1>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii";
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_flash_x8>;
+	ranges = <0 0 0 0x01000000>;	/* minimum GPMC partition = 16MB */
+	nand@0,0 {
+		reg = <0 0 4>;		/* device IO registers */
+		ti,nand-ecc-opt = "bch16";
+		ti,elm-id = <&elm>;
+		nand-bus-width = <8>;
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <40>;
+		gpmc,cs-wr-off-ns = <40>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <25>;
+		gpmc,adv-wr-off-ns = <25>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <20>;
+		gpmc,oe-on-ns = <3>;
+		gpmc,oe-off-ns = <30>;
+		gpmc,access-ns = <30>;
+		gpmc,rd-cycle-ns = <40>;
+		gpmc,wr-cycle-ns = <40>;
+		gpmc,wait-pin = <0>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+		/* MTD partition table */
+		/* All SPL-* partitions are sized to minimal length
+		 * which can be independently programmable. For
+		 * NAND flash this is equal to size of erase-block */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "NAND.SPL";
+			reg = <0x00000000 0x00040000>;
+		};
+		partition@1 {
+			label = "NAND.SPL.backup1";
+			reg = <0x00040000 0x00040000>;
+		};
+		partition@2 {
+			label = "NAND.SPL.backup2";
+			reg = <0x00080000 0x00040000>;
+		};
+		partition@3 {
+			label = "NAND.SPL.backup3";
+			reg = <0x000c0000 0x00040000>;
+		};
+		partition@4 {
+			label = "NAND.u-boot-spl-os";
+			reg = <0x00100000 0x00080000>;
+		};
+		partition@5 {
+			label = "NAND.u-boot";
+			reg = <0x00180000 0x00100000>;
+		};
+		partition@6 {
+			label = "NAND.u-boot-env";
+			reg = <0x00280000 0x00040000>;
+		};
+		partition@7 {
+			label = "NAND.u-boot-env.backup1";
+			reg = <0x002c0000 0x00040000>;
+		};
+		partition@8 {
+			label = "NAND.kernel";
+			reg = <0x00300000 0x00700000>;
+		};
+		partition@9 {
+			label = "NAND.file-system";
+			reg = <0x00a00000 0x1f600000>;
+		};
+	};
+};
+
+&dss {
+	status = "ok";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_pins>;
+
+	port {
+		dpi_out: endpoint@0 {
+			remote-endpoint = <&lcd_in>;
+			data-lines = <24>;
+		};
+	};
+};
+
+&dcan0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&dcan0_default>;
+	status = "okay";
+};
+
+&dcan1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&dcan1_default>;
+	status = "okay";
+};
+
+&vpfe0 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&vpfe0_pins_default>;
+	pinctrl-1 = <&vpfe0_pins_sleep>;
+
+	port {
+		vpfe0_ep: endpoint {
+			remote-endpoint = <&ov2659_1>;
+			ti,am437x-vpfe-interface = <0>;
+			bus-width = <8>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+		};
+	};
+};
+
+&vpfe1 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&vpfe1_pins_default>;
+	pinctrl-1 = <&vpfe1_pins_sleep>;
+
+	port {
+		vpfe1_ep: endpoint {
+			remote-endpoint = <&ov2659_0>;
+			ti,am437x-vpfe-interface = <0>;
+			bus-width = <8>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+		};
+	};
+};
diff --git a/arch/arm/dts/am437x-idk-evm-u-boot.dtsi b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi
new file mode 100644
index 0000000..3aa9195
--- /dev/null
+++ b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "am4372-u-boot.dtsi"
+
+/{
+	ocp {
+		u-boot,dm-spl;
+	};
+};
+
+&uart0 {
+	u-boot,dm-spl;
+};
+
+&i2c0 {
+	u-boot,dm-spl;
+};
+
+&mmc1 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/am437x-idk-evm.dts b/arch/arm/dts/am437x-idk-evm.dts
new file mode 100644
index 0000000..28e3e1b
--- /dev/null
+++ b/arch/arm/dts/am437x-idk-evm.dts
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "am4372.dtsi"
+#include <dt-bindings/pinctrl/am43xx.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "TI AM437x Industrial Development Kit";
+	compatible = "ti,am437x-idk-evm","ti,am4372","ti,am43";
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	v24_0d: fixed-regulator-v24_0d {
+		compatible = "regulator-fixed";
+		regulator-name = "V24_0D";
+		regulator-min-microvolt = <24000000>;
+		regulator-max-microvolt = <24000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	v3_3d: fixed-regulator-v3_3d {
+		compatible = "regulator-fixed";
+		regulator-name = "V3_3D";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&v24_0d>;
+	};
+
+	vdd_corereg: fixed-regulator-vdd_corereg {
+		compatible = "regulator-fixed";
+		regulator-name = "VDD_COREREG";
+		regulator-min-microvolt = <1100000>;
+		regulator-max-microvolt = <1100000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&v24_0d>;
+	};
+
+	vdd_core: fixed-regulator-vdd_core {
+		compatible = "regulator-fixed";
+		regulator-name = "VDD_CORE";
+		regulator-min-microvolt = <1100000>;
+		regulator-max-microvolt = <1100000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vdd_corereg>;
+	};
+
+	v1_8dreg: fixed-regulator-v1_8dreg{
+		compatible = "regulator-fixed";
+		regulator-name = "V1_8DREG";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&v24_0d>;
+	};
+
+	v1_8d: fixed-regulator-v1_8d{
+		compatible = "regulator-fixed";
+		regulator-name = "V1_8D";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&v1_8dreg>;
+	};
+
+	v1_5dreg: fixed-regulator-v1_5dreg{
+		compatible = "regulator-fixed";
+		regulator-name = "V1_5DREG";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&v24_0d>;
+	};
+
+	v1_5d: fixed-regulator-v1_5d{
+		compatible = "regulator-fixed";
+		regulator-name = "V1_5D";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&v1_5dreg>;
+	};
+
+	gpio_keys: gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_keys_pins_default>;
+
+		switch@0 {
+			label = "power-button";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	/* fixed 32k external oscillator clock */
+	clk_32k_rtc: clk_32k_rtc {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+};
+
+&am43xx_pinmux {
+	gpio_keys_pins_default: gpio_keys_pins_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x9b8, PIN_INPUT | MUX_MODE7)	/* cam0_field.gpio4_2 */
+		>;
+	};
+
+	i2c0_pins_default: i2c0_pins_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x988, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */
+			AM4372_IOPAD(0x98c, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c0_pins_sleep: i2c0_pins_sleep {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x98c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	i2c2_pins_default: i2c2_pins_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x9e8, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data1.i2c2_scl */
+			AM4372_IOPAD(0x9ec, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data0.i2c2_sda */
+		>;
+	};
+
+	i2c2_pins_sleep: i2c2_pins_sleep {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x9e8, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x9ec, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc1_pins_default: pinmux_mmc1_pins_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+			AM4372_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+			AM4372_IOPAD(0x9f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+			AM4372_IOPAD(0x9f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+			AM4372_IOPAD(0x9f8, PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+			AM4372_IOPAD(0x9fc, PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+			AM4372_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
+	mmc1_pins_sleep: pinmux_mmc1_pins_sleep {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x900, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x904, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x9f0, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x9f4, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x9f8, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x9fc, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x960, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	ecap0_pins_default: backlight_pins_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x964, PIN_OUTPUT | MUX_MODE0) /* ecap0_in_pwm0_out.ecap0_in_pwm0_out */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
+			AM4372_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			AM4372_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			AM4372_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			AM4372_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td2 */
+			AM4372_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td3 */
+			AM4372_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rmii1_rclk */
+			AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+			AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			AM4372_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd2 */
+			AM4372_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd3 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			AM4372_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	qspi_pins_default: qspi_pins_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE3)	/* gpmc_csn0.qspi_csn */
+			AM4372_IOPAD(0x888, PIN_OUTPUT | MUX_MODE2)		/* gpmc_csn3.qspi_clk */
+			AM4372_IOPAD(0x890, PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_advn_ale.qspi_d0 */
+			AM4372_IOPAD(0x894, PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_oen_ren.qspi_d1 */
+			AM4372_IOPAD(0x898, PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_wen.qspi_d2 */
+			AM4372_IOPAD(0x89c, PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_be0n_cle.qspi_d3 */
+		>;
+	};
+
+	qspi_pins_sleep: qspi_pins_sleep{
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x87c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x888, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x890, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x894, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x898, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x89c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c0_pins_default>;
+	pinctrl-1 = <&i2c0_pins_sleep>;
+	clock-frequency = <400000>;
+
+	at24@50 {
+		compatible = "at24,24c256";
+		pagesize = <64>;
+		reg = <0x50>;
+	};
+
+	tps: tps62362@60 {
+		compatible = "ti,tps62362";
+		reg = <0x60>;
+		regulator-name = "VDD_MPU";
+		regulator-min-microvolt = <950000>;
+		regulator-max-microvolt = <1330000>;
+		regulator-boot-on;
+		regulator-always-on;
+		ti,vsel0-state-high;
+		ti,vsel1-state-high;
+		vin-supply = <&v3_3d>;
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&i2c2_pins_default>;
+	pinctrl-1 = <&i2c2_pins_sleep>;
+	clock-frequency = <100000>;
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&ecap0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ecap0_pins_default>;
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio4 {
+	status = "okay";
+};
+
+&gpio5 {
+	status = "okay";
+};
+
+&mmc1 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_sleep>;
+	vmmc-supply = <&v3_3d>;
+	bus-width = <4>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&qspi {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&qspi_pins_default>;
+	pinctrl-1 = <&qspi_pins_sleep>;
+
+	spi-max-frequency = <48000000>;
+	m25p80@0 {
+		compatible = "mx66l51235l", "spi-flash";
+		spi-max-frequency = <48000000>;
+		reg = <0>;
+		spi-cpol;
+		spi-cpha;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/*
+		 * MTD partition table.  The ROM checks the first 512KiB for a
+		 * valid file to boot(XIP).
+		 */
+		partition@0 {
+			label = "QSPI.U_BOOT";
+			reg = <0x00000000 0x000080000>;
+		};
+		partition@1 {
+			label = "QSPI.U_BOOT.backup";
+			reg = <0x00080000 0x00080000>;
+		};
+		partition@2 {
+			label = "QSPI.U-BOOT-SPL_OS";
+			reg = <0x00100000 0x00010000>;
+		};
+		partition@3 {
+			label = "QSPI.U_BOOT_ENV";
+			reg = <0x00110000 0x00010000>;
+		};
+		partition@4 {
+			label = "QSPI.U-BOOT-ENV.backup";
+			reg = <0x00120000 0x00010000>;
+		};
+		partition@5 {
+			label = "QSPI.KERNEL";
+			reg = <0x00130000 0x0800000>;
+		};
+		partition@6 {
+			label = "QSPI.FILESYSTEM";
+			reg = <0x00930000 0x36D0000>;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii";
+};
+
+&rtc {
+	clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
+	clock-names = "ext-clk", "int-clk";
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
+
+&cpu {
+	cpu0-supply = <&tps>;
+};
diff --git a/arch/arm/dts/am437x-sk-evm-u-boot.dtsi b/arch/arm/dts/am437x-sk-evm-u-boot.dtsi
new file mode 100644
index 0000000..3aa9195
--- /dev/null
+++ b/arch/arm/dts/am437x-sk-evm-u-boot.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "am4372-u-boot.dtsi"
+
+/{
+	ocp {
+		u-boot,dm-spl;
+	};
+};
+
+&uart0 {
+	u-boot,dm-spl;
+};
+
+&i2c0 {
+	u-boot,dm-spl;
+};
+
+&mmc1 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/am437x-sk-evm.dts b/arch/arm/dts/am437x-sk-evm.dts
new file mode 100644
index 0000000..927d8d3
--- /dev/null
+++ b/arch/arm/dts/am437x-sk-evm.dts
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* AM437x SK EVM */
+
+/dts-v1/;
+
+#include "am4372.dtsi"
+#include <dt-bindings/pinctrl/am43xx.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "TI AM437x SK EVM";
+	compatible = "ti,am437x-sk-evm","ti,am4372","ti,am43";
+
+	aliases {
+		display0 = &lcd0;
+	};
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
+
+	sound {
+		compatible = "ti,da830-evm-audio";
+		ti,model = "AM437x-SK-EVM";
+		ti,audio-codec = <&tlv320aic3106>;
+		ti,mcasp-controller = <&mcasp1>;
+		ti,codec-clock-rate = <24000000>;
+		ti,audio-routing =
+			"Headphone Jack",       "HPLOUT",
+			"Headphone Jack",       "HPROUT";
+	};
+
+	matrix_keypad: matrix_keypad@0 {
+		compatible = "gpio-matrix-keypad";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&matrix_keypad_pins>;
+
+		debounce-delay-ms = <5>;
+		col-scan-delay-us = <5>;
+
+		row-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH		/* Bank5, pin5 */
+				&gpio5 6 GPIO_ACTIVE_HIGH>;	/* Bank5, pin6 */
+
+		col-gpios = <&gpio5 13 GPIO_ACTIVE_HIGH		/* Bank5, pin13 */
+				&gpio5 4 GPIO_ACTIVE_HIGH>;	/* Bank5, pin4 */
+
+		linux,keymap = <
+				MATRIX_KEY(0, 0, KEY_DOWN)
+				MATRIX_KEY(0, 1, KEY_RIGHT)
+				MATRIX_KEY(1, 0, KEY_LEFT)
+				MATRIX_KEY(1, 1, KEY_UP)
+			>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
+
+		led@0 {
+			label = "am437x-sk:red:heartbeat";
+			gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 0 */
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led@1 {
+			label = "am437x-sk:green:mmc1";
+			gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 1 */
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "am437x-sk:blue:cpu0";
+			gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 2 */
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "am437x-sk:blue:usr3";
+			gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;	/* Bank 5, pin 3 */
+			default-state = "off";
+		};
+	};
+
+	lcd0: display {
+		compatible = "newhaven,nhd-4.3-480272ef-atxl", "panel-dpi";
+		label = "lcd";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins>;
+
+		enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+
+		panel-timing {
+			clock-frequency = <9000000>;
+			hactive = <480>;
+			vactive = <272>;
+			hfront-porch = <2>;
+			hback-porch = <2>;
+			hsync-len = <41>;
+			vfront-porch = <2>;
+			vback-porch = <2>;
+			vsync-len = <10>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dpi_out>;
+			};
+		};
+	};
+};
+
+&am43xx_pinmux {
+	matrix_keypad_pins: matrix_keypad_pins {
+		pinctrl-single,pins = <
+			0x24c (PIN_OUTPUT | MUX_MODE7)	/* gpio5_13.gpio5_13 */
+			0x250 (PIN_OUTPUT | MUX_MODE7)	/* spi4_sclk.gpio5_4 */
+			0x254 (PIN_INPUT | MUX_MODE7)	/* spi4_d0.gpio5_5 */
+			0x258 (PIN_INPUT | MUX_MODE7)	/* spi4_d1.gpio5_5 */
+		>;
+	};
+
+	leds_pins: leds_pins {
+		pinctrl-single,pins = <
+			0x228 (PIN_OUTPUT | MUX_MODE7)	/* uart3_rxd.gpio5_2 */
+			0x22c (PIN_OUTPUT | MUX_MODE7)	/* uart3_txd.gpio5_3 */
+			0x230 (PIN_OUTPUT | MUX_MODE7)	/* uart3_ctsn.gpio5_0 */
+			0x234 (PIN_OUTPUT | MUX_MODE7)	/* uart3_rtsn.gpio5_1 */
+		>;
+	};
+
+	i2c0_pins: i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: i2c1_pins {
+		pinctrl-single,pins = <
+			0x15c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_cs0.i2c1_scl */
+			0x158 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_d1.i2c1_sda  */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x0f0 (PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+			0x0f4 (PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+			0x0f8 (PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+			0x0fc (PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+			0x100 (PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+			0x104 (PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+			0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+		>;
+	};
+
+	ecap0_pins: backlight_pins {
+		pinctrl-single,pins = <
+			0x164 (PIN_OUTPUT | MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */
+		>;
+	};
+
+	edt_ft5306_ts_pins: edt_ft5306_ts_pins {
+		pinctrl-single,pins = <
+			0x74 (PIN_INPUT | MUX_MODE7)	/* gpmc_wpn.gpio0_31 */
+			0x78 (PIN_OUTPUT | MUX_MODE7)	/* gpmc_be1n.gpio1_28 */
+		>;
+	};
+
+	vpfe0_pins_default: vpfe0_pins_default {
+		pinctrl-single,pins = <
+			0x1b0 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_hd mode 0*/
+			0x1b4 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_vd mode 0*/
+			0x1b8 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_field mode 0*/
+			0x1bc (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_wen mode 0*/
+			0x1c0 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_pclk mode 0*/
+			0x1c4 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data8 mode 0*/
+			0x1c8 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data9 mode 0*/
+			0x208 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data0 mode 0*/
+			0x20c (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data1 mode 0*/
+			0x210 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data2 mode 0*/
+			0x214 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data3 mode 0*/
+			0x218 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data4 mode 0*/
+			0x21c (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data5 mode 0*/
+			0x220 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data6 mode 0*/
+			0x224 (PIN_INPUT_PULLUP | MUX_MODE0)  /* cam0_data7 mode 0*/
+		>;
+	};
+
+	vpfe0_pins_sleep: vpfe0_pins_sleep {
+		pinctrl-single,pins = <
+			0x1b0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x1b4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x1b8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x1bc (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x1c0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x1c4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x1c8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x208 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x20c (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x210 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x214 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x218 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x21c (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x220 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			0x224 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x12c (PIN_OUTPUT | MUX_MODE2)	/* mii1_txclk.rmii1_tclk */
+			0x114 (PIN_OUTPUT | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			0x128 (PIN_OUTPUT | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			0x124 (PIN_OUTPUT | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			0x120 (PIN_OUTPUT | MUX_MODE2)	/* mii1_txd0.rgmii1_td2 */
+			0x11c (PIN_OUTPUT | MUX_MODE2)	/* mii1_txd1.rgmii1_td3 */
+			0x130 (PIN_INPUT | MUX_MODE2)	/* mii1_rxclk.rmii1_rclk */
+			0x118 (PIN_INPUT | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			0x140 (PIN_INPUT | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+			0x13c (PIN_INPUT | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			0x138 (PIN_INPUT | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd2 */
+			0x134 (PIN_INPUT | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd3 */
+
+			/* Slave 2 */
+			0x58 (PIN_OUTPUT | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			0x40 (PIN_OUTPUT | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			0x54 (PIN_OUTPUT | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			0x50 (PIN_OUTPUT | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			0x4c (PIN_OUTPUT | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			0x48 (PIN_OUTPUT | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			0x5c (PIN_INPUT | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			0x44 (PIN_INPUT | MUX_MODE2)	/* gpmc_a1.rgmii2_rtcl */
+			0x6c (PIN_INPUT | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+			0x68 (PIN_INPUT | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			0x64 (PIN_INPUT | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			0x60 (PIN_INPUT | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value */
+			0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	dss_pins: dss_pins {
+		pinctrl-single,pins = <
+			0x020 (PIN_OUTPUT | MUX_MODE1)	/* gpmc ad 8 -> DSS DATA 23 */
+			0x024 (PIN_OUTPUT | MUX_MODE1)
+			0x028 (PIN_OUTPUT | MUX_MODE1)
+			0x02c (PIN_OUTPUT | MUX_MODE1)
+			0x030 (PIN_OUTPUT | MUX_MODE1)
+			0x034 (PIN_OUTPUT | MUX_MODE1)
+			0x038 (PIN_OUTPUT | MUX_MODE1)
+			0x03c (PIN_OUTPUT | MUX_MODE1)	/* gpmc ad 15 -> DSS DATA 16 */
+			0x0a0 (PIN_OUTPUT | MUX_MODE0)	/* DSS DATA 0 */
+			0x0a4 (PIN_OUTPUT | MUX_MODE0)
+			0x0a8 (PIN_OUTPUT | MUX_MODE0)
+			0x0ac (PIN_OUTPUT | MUX_MODE0)
+			0x0b0 (PIN_OUTPUT | MUX_MODE0)
+			0x0b4 (PIN_OUTPUT | MUX_MODE0)
+			0x0b8 (PIN_OUTPUT | MUX_MODE0)
+			0x0bc (PIN_OUTPUT | MUX_MODE0)
+			0x0c0 (PIN_OUTPUT | MUX_MODE0)
+			0x0c4 (PIN_OUTPUT | MUX_MODE0)
+			0x0c8 (PIN_OUTPUT | MUX_MODE0)
+			0x0cc (PIN_OUTPUT | MUX_MODE0)
+			0x0d0 (PIN_OUTPUT | MUX_MODE0)
+			0x0d4 (PIN_OUTPUT | MUX_MODE0)
+			0x0d8 (PIN_OUTPUT | MUX_MODE0)
+			0x0dc (PIN_OUTPUT | MUX_MODE0)	/* DSS DATA 15 */
+			0x0e0 (PIN_OUTPUT | MUX_MODE0)	/* DSS VSYNC */
+			0x0e4 (PIN_OUTPUT | MUX_MODE0)	/* DSS HSYNC */
+			0x0e8 (PIN_OUTPUT | MUX_MODE0)	/* DSS PCLK */
+			0x0ec (PIN_OUTPUT | MUX_MODE0)	/* DSS AC BIAS EN */
+
+		>;
+	};
+
+	qspi_pins: qspi_pins {
+		pinctrl-single,pins = <
+			0x7c (PIN_OUTPUT | MUX_MODE3)	/* gpmc_csn0.qspi_csn */
+			0x88 (PIN_OUTPUT | MUX_MODE2)	/* gpmc_csn3.qspi_clk */
+			0x90 (PIN_INPUT | MUX_MODE3)	/* gpmc_advn_ale.qspi_d0 */
+			0x94 (PIN_INPUT | MUX_MODE3)	/* gpmc_oen_ren.qspi_d1 */
+			0x98 (PIN_INPUT | MUX_MODE3)	/* gpmc_wen.qspi_d2 */
+			0x9c (PIN_INPUT | MUX_MODE3)	/* gpmc_be0n_cle.qspi_d3 */
+		>;
+	};
+
+	mcasp1_pins: mcasp1_pins {
+		pinctrl-single,pins = <
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4)	/* mii1_crs.mcasp1_aclkx */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4)	/* mii1_rxerr.mcasp1_fsx */
+			0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4)	/* mii1_col.mcasp1_axr2 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4)	/* rmii1_ref_clk.mcasp1_axr3 */
+		>;
+	};
+
+	lcd_pins: lcd_pins {
+		pinctrl-single,pins = <
+			0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpcm_ad7.gpio1_7 */
+		>;
+	};
+
+	usb1_pins: usb1_pins {
+		pinctrl-single,pins = <
+			0x2c0 (PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */
+		>;
+	};
+
+	usb2_pins: usb2_pins {
+		pinctrl-single,pins = <
+			0x2c4 (PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */
+		>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <400000>;
+
+	tps@24 {
+		compatible = "ti,tps65218";
+		reg = <0x24>;
+		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		dcdc1: regulator-dcdc1 {
+			compatible = "ti,tps65218-dcdc1";
+			/* VDD_CORE limits min of OPP50 and max of OPP100 */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc2: regulator-dcdc2 {
+			compatible = "ti,tps65218-dcdc2";
+			/* VDD_MPU limits min of OPP50 and max of OPP_NITRO */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1378000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3: regulator-dcdc3 {
+			compatible = "ti,tps65218-dcdc3";
+			regulator-name = "vdds_ddr";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc4: regulator-dcdc4 {
+			compatible = "ti,tps65218-dcdc4";
+			regulator-name = "v3_3d";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1: regulator-ldo1 {
+			compatible = "ti,tps65218-ldo1";
+			regulator-name = "v1_8d";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		power-button {
+			compatible = "ti,tps65218-pwrbutton";
+			status = "okay";
+			interrupts = <3 IRQ_TYPE_EDGE_BOTH>;
+		};
+	};
+
+	at24@50 {
+		compatible = "at24,24c256";
+		pagesize = <64>;
+		reg = <0x50>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <400000>;
+
+	edt-ft5306@38 {
+		status = "okay";
+		compatible = "edt,edt-ft5306", "edt,edt-ft5x06";
+		pinctrl-names = "default";
+		pinctrl-0 = <&edt_ft5306_ts_pins>;
+
+		reg = <0x38>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <31 0>;
+
+		reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
+
+		touchscreen-size-x = <480>;
+		touchscreen-size-y = <272>;
+	};
+
+	tlv320aic3106: tlv320aic3106@1b {
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		status = "okay";
+
+		/* Regulators */
+		AVDD-supply = <&dcdc4>;
+		IOVDD-supply = <&dcdc4>;
+		DRVDD-supply = <&dcdc4>;
+		DVDD-supply = <&ldo1>;
+	};
+
+	lis331dlh@18 {
+		compatible = "st,lis331dlh";
+		reg = <0x18>;
+		status = "okay";
+
+		Vdd-supply = <&dcdc4>;
+		Vdd_IO-supply = <&dcdc4>;
+		interrupts-extended = <&gpio1 6 0>, <&gpio2 1 0>;
+	};
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&ecap0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ecap0_pins>;
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio5 {
+	status = "okay";
+};
+
+&mmc1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+
+	vmmc-supply = <&dcdc4>;
+	bus-width = <4>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&usb2_phy1 {
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "peripheral";
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb1_pins>;
+};
+
+&usb2_phy2 {
+	status = "okay";
+};
+
+&usb2 {
+	dr_mode = "host";
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb2_pins>;
+};
+
+&qspi {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&qspi_pins>;
+
+	spi-max-frequency = <48000000>;
+	m25p80@0 {
+		compatible = "mx66l51235l","spi-flash";
+		spi-max-frequency = <48000000>;
+		reg = <0>;
+		spi-cpol;
+		spi-cpha;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* MTD partition table.
+		 * The ROM checks the first 512KiB
+		 * for a valid file to boot(XIP).
+		 */
+		partition@0 {
+			label = "QSPI.U_BOOT";
+			reg = <0x00000000 0x000080000>;
+		};
+		partition@1 {
+			label = "QSPI.U_BOOT.backup";
+			reg = <0x00080000 0x00080000>;
+		};
+		partition@2 {
+			label = "QSPI.U-BOOT-SPL_OS";
+			reg = <0x00100000 0x00010000>;
+		};
+		partition@3 {
+			label = "QSPI.U_BOOT_ENV";
+			reg = <0x00110000 0x00010000>;
+		};
+		partition@4 {
+			label = "QSPI.U-BOOT-ENV.backup";
+			reg = <0x00120000 0x00010000>;
+		};
+		partition@5 {
+			label = "QSPI.KERNEL";
+			reg = <0x00130000 0x0800000>;
+		};
+		partition@6 {
+			label = "QSPI.FILESYSTEM";
+			reg = <0x00930000 0x36D0000>;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	dual_emac = <1>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <4>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <5>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <2>;
+};
+
+&elm {
+	status = "okay";
+};
+
+&mcasp1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcasp1_pins>;
+
+	status = "okay";
+
+	op-mode = <0>;
+	tdm-slots = <2>;
+	serial-dir = <
+		0 0 1 2
+	>;
+
+	tx-num-evt = <1>;
+	rx-num-evt = <1>;
+};
+
+&dss {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_pins>;
+
+	port {
+		dpi_out: endpoint@0 {
+			remote-endpoint = <&lcd_in>;
+			data-lines = <24>;
+		};
+	};
+};
+
+&rtc {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
+
+&cpu {
+	cpu0-supply = <&dcdc2>;
+};
+
+&vpfe0 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&vpfe0_pins_default>;
+	pinctrl-1 = <&vpfe0_pins_sleep>;
+
+	/* Camera port */
+	port {
+		vpfe0_ep: endpoint {
+			/* remote-endpoint = <&sensor>; add once we have it */
+			ti,am437x-vpfe-interface = <0>;
+			bus-width = <8>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+		};
+	};
+};
diff --git a/arch/arm/dts/am43x-epos-evm.dts b/arch/arm/dts/am43x-epos-evm.dts
new file mode 100644
index 0000000..fa4d1e3
--- /dev/null
+++ b/arch/arm/dts/am43x-epos-evm.dts
@@ -0,0 +1,806 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* AM43x EPOS EVM */
+
+/dts-v1/;
+
+#include "am4372.dtsi"
+#include <dt-bindings/pinctrl/am43xx.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/sound/tlv320aic31xx-micbias.h>
+
+/ {
+	model = "TI AM43x EPOS EVM";
+	compatible = "ti,am43x-epos-evm","ti,am438x","ti,am43";
+
+	aliases {
+		display0 = &lcd0;
+	};
+
+	chosen {
+		stdout-path = &uart0;
+		tick-timer = &timer2;
+	};
+
+	vmmcsd_fixed: fixedregulator-sd {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	lcd0: display {
+		compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+		label = "lcd";
+
+		panel-timing {
+			clock-frequency = <33000000>;
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <210>;
+			hback-porch = <16>;
+			hsync-len = <30>;
+			vback-porch = <10>;
+			vfront-porch = <22>;
+			vsync-len = <13>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			de-active = <1>;
+			pixelclk-active = <1>;
+		};
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dpi_out>;
+			};
+		};
+	};
+
+	matrix_keypad: matrix_keypad@0 {
+		compatible = "gpio-matrix-keypad";
+		debounce-delay-ms = <5>;
+		col-scan-delay-us = <2>;
+
+		row-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH		/* Bank0, pin12 */
+			     &gpio0 13 GPIO_ACTIVE_HIGH		/* Bank0, pin13 */
+			     &gpio0 14 GPIO_ACTIVE_HIGH		/* Bank0, pin14 */
+			     &gpio0 15 GPIO_ACTIVE_HIGH>;	/* Bank0, pin15 */
+
+		col-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH		/* Bank3, pin9 */
+			     &gpio3 10 GPIO_ACTIVE_HIGH		/* Bank3, pin10 */
+			     &gpio2 18 GPIO_ACTIVE_HIGH		/* Bank2, pin18 */
+			     &gpio2 19 GPIO_ACTIVE_HIGH>;	/* Bank2, pin19 */
+
+		linux,keymap = <0x00000201	/* P1 */
+			0x01000204	/* P4 */
+			0x02000207	/* P7 */
+			0x0300020a	/* NUMERIC_STAR */
+			0x00010202	/* P2 */
+			0x01010205	/* P5 */
+			0x02010208	/* P8 */
+			0x03010200	/* P0 */
+			0x00020203	/* P3 */
+			0x01020206	/* P6 */
+			0x02020209	/* P9 */
+			0x0302020b	/* NUMERIC_POUND */
+			0x00030067	/* UP */
+			0x0103006a	/* RIGHT */
+			0x0203006c	/* DOWN */
+			0x03030069>;	/* LEFT */
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
+
+	sound0: sound@0 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "AM43-EPOS-EVM";
+		simple-audio-card,widgets =
+			"Microphone", "Microphone Jack",
+			"Headphone", "Headphone Jack",
+			"Speaker", "Speaker";
+		simple-audio-card,routing =
+			"MIC1LP", "Microphone Jack",
+			"MIC1RP", "Microphone Jack",
+			"MIC1LP", "MICBIAS",
+			"MIC1RP", "MICBIAS",
+			"Headphone Jack", "HPL",
+			"Headphone Jack", "HPR",
+			"Speaker", "SPL",
+			"Speaker", "SPR";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&sound0_master>;
+		simple-audio-card,frame-master = <&sound0_master>;
+		simple-audio-card,bitclock-inversion;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcasp1>;
+			system-clock-frequency = <12000000>;
+		};
+
+		sound0_master: simple-audio-card,codec {
+			sound-dai = <&tlv320aic3111>;
+			system-clock-frequency = <12000000>;
+		};
+	};
+};
+
+&am43xx_pinmux {
+		cpsw_default: cpsw_default {
+			pinctrl-single,pins = <
+				/* Slave 1 */
+				AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_crs.rmii1_crs */
+				AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxerr.rmii1_rxerr */
+				AM4372_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txen.rmii1_txen */
+				AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxdv.rmii1_rxdv */
+				AM4372_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd1.rmii1_txd1 */
+				AM4372_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd0.rmii1_txd0 */
+				AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd1.rmii1_rxd1 */
+				AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd0.rmii1_rxd0 */
+				AM4372_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* rmii1_refclk.rmii1_refclk */
+			>;
+		};
+
+		cpsw_sleep: cpsw_sleep {
+			pinctrl-single,pins = <
+				/* Slave 1 reset value */
+				AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			>;
+		};
+
+		davinci_mdio_default: davinci_mdio_default {
+			pinctrl-single,pins = <
+				/* MDIO */
+				AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+				AM4372_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+			>;
+		};
+
+		davinci_mdio_sleep: davinci_mdio_sleep {
+			pinctrl-single,pins = <
+				/* MDIO reset value */
+				AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			>;
+		};
+
+		i2c0_pins: pinmux_i2c0_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x988, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+				AM4372_IOPAD(0x98c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+			>;
+		};
+
+		nand_flash_x8: nand_flash_x8 {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a0.SELQSPIorNAND/GPIO */
+				AM4372_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+				AM4372_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+				AM4372_IOPAD(0x808, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+				AM4372_IOPAD(0x80c, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+				AM4372_IOPAD(0x810, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+				AM4372_IOPAD(0x814, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+				AM4372_IOPAD(0x818, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+				AM4372_IOPAD(0x81c, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+				AM4372_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+				AM4372_IOPAD(0x874, PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpmc_wpn */
+				AM4372_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+				AM4372_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+				AM4372_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+				AM4372_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+				AM4372_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+			>;
+		};
+
+		ecap0_pins: backlight_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x964, MUX_MODE0)         /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
+			>;
+		};
+
+		i2c2_pins: pinmux_i2c2_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x9c0, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE8)    /* i2c2_sda.i2c2_sda */
+				AM4372_IOPAD(0x9c4, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE8)    /* i2c2_scl.i2c2_scl */
+			>;
+		};
+
+		spi0_pins: pinmux_spi0_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x950, PIN_INPUT | MUX_MODE0)           /* spi0_clk.spi0_clk */
+				AM4372_IOPAD(0x954, PIN_OUTPUT | MUX_MODE0)           /* spi0_d0.spi0_d0 */
+				AM4372_IOPAD(0x958, PIN_INPUT | MUX_MODE0)           /* spi0_d1.spi0_d1 */
+				AM4372_IOPAD(0x95c, PIN_OUTPUT | MUX_MODE0)          /* spi0_cs0.spi0_cs0 */
+			>;
+		};
+
+		spi1_pins: pinmux_spi1_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x990, PIN_INPUT | MUX_MODE3)           /* mcasp0_aclkx.spi1_clk */
+				AM4372_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3)           /* mcasp0_fsx.spi1_d0 */
+				AM4372_IOPAD(0x998, PIN_INPUT | MUX_MODE3)           /* mcasp0_axr0.spi1_d1 */
+				AM4372_IOPAD(0x99c, PIN_OUTPUT | MUX_MODE3)          /* mcasp0_ahclkr.spi1_cs0 */
+			>;
+		};
+
+		mmc1_pins: pinmux_mmc1_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+			>;
+		};
+
+		qspi1_default: qspi1_default {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x87c, PIN_INPUT_PULLUP | MUX_MODE3)
+				AM4372_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE2)
+				AM4372_IOPAD(0x890, PIN_INPUT_PULLUP | MUX_MODE3)
+				AM4372_IOPAD(0x894, PIN_INPUT_PULLUP | MUX_MODE3)
+				AM4372_IOPAD(0x898, PIN_INPUT_PULLUP | MUX_MODE3)
+				AM4372_IOPAD(0x89c, PIN_INPUT_PULLUP | MUX_MODE3)
+			>;
+		};
+
+		pixcir_ts_pins: pixcir_ts_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_a1.gpio1_17 */
+			>;
+		};
+
+		hdq_pins: pinmux_hdq_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0xa34, PIN_INPUT_PULLUP | MUX_MODE1)    /* cam1_wen.hdq_gpio */
+			>;
+		};
+
+		dss_pins: dss_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x820, PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */
+				AM4372_IOPAD(0x824, PIN_OUTPUT_PULLUP | MUX_MODE1)
+				AM4372_IOPAD(0x828, PIN_OUTPUT_PULLUP | MUX_MODE1)
+				AM4372_IOPAD(0x82c, PIN_OUTPUT_PULLUP | MUX_MODE1)
+				AM4372_IOPAD(0x830, PIN_OUTPUT_PULLUP | MUX_MODE1)
+				AM4372_IOPAD(0x834, PIN_OUTPUT_PULLUP | MUX_MODE1)
+				AM4372_IOPAD(0x838, PIN_OUTPUT_PULLUP | MUX_MODE1)
+				AM4372_IOPAD(0x83c, PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 15 -> DSS DATA 16 */
+				AM4372_IOPAD(0x8a0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */
+				AM4372_IOPAD(0x8a4, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8a8, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8ac, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8b0, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8b4, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8B8, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8bc, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8c0, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8c4, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8c8, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8cc, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8d0, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8d4, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8d8, PIN_OUTPUT_PULLUP | MUX_MODE0)
+				AM4372_IOPAD(0x8dc, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */
+				AM4372_IOPAD(0x8e0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */
+				AM4372_IOPAD(0x8e4, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */
+				AM4372_IOPAD(0x8e8, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */
+				AM4372_IOPAD(0x8ec, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */
+			>;
+		};
+
+		display_mux_pins: display_mux_pins {
+			pinctrl-single,pins = <
+				/* GPMC CLK -> GPIO 2_1 to select LCD / HDMI */
+				AM4372_IOPAD(0x88C, PIN_OUTPUT_PULLUP | MUX_MODE7)
+			>;
+		};
+
+		vpfe1_pins_default: vpfe1_pins_default {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x9cc, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data9 mode 0 */
+				AM4372_IOPAD(0x9d0, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data8 mode 0 */
+				AM4372_IOPAD(0x9d4, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_hd mode 0 */
+				AM4372_IOPAD(0x9d8, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_vd mode 0 */
+				AM4372_IOPAD(0x9dc, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_pclk mode 0 */
+				AM4372_IOPAD(0x9e8, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data0 mode 0 */
+				AM4372_IOPAD(0x9ec, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data1 mode 0 */
+				AM4372_IOPAD(0x9f0, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data2 mode 0 */
+				AM4372_IOPAD(0x9f4, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data3 mode 0 */
+				AM4372_IOPAD(0x9f8, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data4 mode 0 */
+				AM4372_IOPAD(0x9fc, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data5 mode 0 */
+				AM4372_IOPAD(0xa00, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data6 mode 0 */
+				AM4372_IOPAD(0xa04, PIN_INPUT_PULLUP | MUX_MODE0)  /* cam1_data7 mode 0 */
+			>;
+		};
+
+		vpfe1_pins_sleep: vpfe1_pins_sleep {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x9cc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9d0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9d4, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9d8, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9dc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9e8, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9ec, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9f0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9f4, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9f8, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0x9fc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0xa00, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+				AM4372_IOPAD(0xa04, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
+			>;
+		};
+
+		mcasp1_pins: mcasp1_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_ACLKR/MCASP1_ACLKX */
+				AM4372_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_FSR/MCASP1_FSX */
+				AM4372_IOPAD(0x9a8, PIN_OUTPUT_PULLDOWN | MUX_MODE3)/* MCASP0_AXR1/MCASP1_AXR0 */
+				AM4372_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_AHCLKX/MCASP1_AXR1 */
+			>;
+		};
+
+		mcasp1_sleep_pins: mcasp1_sleep_pins {
+			pinctrl-single,pins = <
+				AM4372_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x9a8, PIN_INPUT_PULLDOWN | MUX_MODE7)
+				AM4372_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			>;
+		};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <16>;
+	phy-mode = "rmii";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rmii";
+};
+
+&phy_sel {
+	rmii-clock-ext;
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	clock-frequency = <400000>;
+
+	tps65218: tps65218@24 {
+		reg = <0x24>;
+		compatible = "ti,tps65218";
+		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		dcdc1: regulator-dcdc1 {
+			compatible = "ti,tps65218-dcdc1";
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc2: regulator-dcdc2 {
+			compatible = "ti,tps65218-dcdc2";
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912000>;
+			regulator-max-microvolt = <1378000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3: regulator-dcdc3 {
+			compatible = "ti,tps65218-dcdc3";
+			regulator-name = "vdcdc3";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc4: regulator-dcdc4 {
+			compatible = "ti,tps65218-dcdc4";
+			regulator-name = "vdcdc4";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc5: regulator-dcdc5 {
+			compatible = "ti,tps65218-dcdc5";
+			regulator-name = "v1_0bat";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+		};
+
+		dcdc6: regulator-dcdc6 {
+			compatible = "ti,tps65218-dcdc6";
+			regulator-name = "v1_8bat";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldo1: regulator-ldo1 {
+			compatible = "ti,tps65218-ldo1";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
+
+	at24@50 {
+		compatible = "at24,24c256";
+		pagesize = <64>;
+		reg = <0x50>;
+	};
+
+	pixcir_ts@5c {
+		compatible = "pixcir,pixcir_tangoc";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pixcir_ts_pins>;
+		reg = <0x5c>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
+
+		attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
+
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <600>;
+	};
+
+	tlv320aic3111: tlv320aic3111@18 {
+		#sound-dai-cells = <0>;
+		compatible = "ti,tlv320aic3111";
+		reg = <0x18>;
+		status = "okay";
+
+		ai31xx-micbias-vg = <MICBIAS_2_0V>;
+
+		/* Regulators */
+		HPVDD-supply = <&dcdc4>; /* v3_3AUD -> V3_3D -> DCDC4 */
+		SPRVDD-supply = <&vbat>; /* vbat */
+		SPLVDD-supply = <&vbat>; /* vbat */
+		AVDD-supply = <&dcdc4>; /* v3_3AUD -> V3_3D -> DCDC4 */
+		IOVDD-supply = <&dcdc4>; /* V3_3D -> DCDC4 */
+		DVDD-supply = <&ldo1>; /* V1_8AUD -> V1_8D -> LDO1 */
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	status = "okay";
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&display_mux_pins>;
+	status = "okay";
+
+	p1 {
+		/*
+		 * SelLCDorHDMI selects between display and audio paths:
+		 * Low: HDMI display with audio via HDMI
+		 * High: LCD display with analog audio via aic3111 codec
+		 */
+		gpio-hog;
+		gpios = <1 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "SelLCDorHDMI";
+	};
+};
+
+&gpio3 {
+	status = "okay";
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	status = "okay";	/* Disable QSPI when enabling GPMC (NAND) */
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_flash_x8>;
+	ranges = <0 0 0x08000000 0x01000000>;	/* CS0 space. Min partition = 16MB */
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		interrupt-parent = <&gpmc>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		ti,nand-ecc-opt = "bch16";
+		ti,elm-id = <&elm>;
+		nand-bus-width = <8>;
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <40>; /* tCEA + tCHZ + 1 */
+		gpmc,cs-wr-off-ns = <40>;
+		gpmc,adv-on-ns = <0>;  /* cs-on-ns */
+		gpmc,adv-rd-off-ns = <25>; /* min( tALH + tALS + 1) */
+		gpmc,adv-wr-off-ns = <25>; /* min( tALH + tALS + 1) */
+		gpmc,we-on-ns = <0>;   /* cs-on-ns */
+		gpmc,we-off-ns = <20>; /* we-on-time + tWP + 2 */
+		gpmc,oe-on-ns = <3>;  /* cs-on-ns + tRR + 2 */
+		gpmc,oe-off-ns = <30>; /* oe-on-ns + tRP + 2 */
+		gpmc,access-ns = <30>; /* tCEA + 4*/
+		gpmc,rd-cycle-ns = <40>;
+		gpmc,wr-cycle-ns = <40>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+		/* MTD partition table */
+		/* All SPL-* partitions are sized to minimal length
+		 * which can be independently programmable. For
+		 * NAND flash this is equal to size of erase-block */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "NAND.SPL";
+			reg = <0x00000000 0x00040000>;
+		};
+		partition@1 {
+			label = "NAND.SPL.backup1";
+			reg = <0x00040000 0x00040000>;
+		};
+		partition@2 {
+			label = "NAND.SPL.backup2";
+			reg = <0x00080000 0x00040000>;
+		};
+		partition@3 {
+			label = "NAND.SPL.backup3";
+			reg = <0x000C0000 0x00040000>;
+		};
+		partition@4 {
+			label = "NAND.u-boot-spl-os";
+			reg = <0x00100000 0x00080000>;
+		};
+		partition@5 {
+			label = "NAND.u-boot";
+			reg = <0x00180000 0x00100000>;
+		};
+		partition@6 {
+			label = "NAND.u-boot-env";
+			reg = <0x00280000 0x00040000>;
+		};
+		partition@7 {
+			label = "NAND.u-boot-env.backup1";
+			reg = <0x002C0000 0x00040000>;
+		};
+		partition@8 {
+			label = "NAND.kernel";
+			reg = <0x00300000 0x00700000>;
+		};
+		partition@9 {
+			label = "NAND.file-system";
+			reg = <0x00a00000 0x1f600000>;
+		};
+	};
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&tscadc {
+	status = "okay";
+
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+	};
+};
+
+&ecap0 {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ecap0_pins>;
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins>;
+	status = "okay";
+};
+
+&usb2_phy1 {
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usb2_phy2 {
+	status = "okay";
+};
+
+&usb2 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&qspi {
+	status = "disabled";	/* Disable GPMC (NAND) when enabling QSPI */
+	pinctrl-names = "default";
+	pinctrl-0 = <&qspi1_default>;
+
+	spi-max-frequency = <48000000>;
+	m25p80@0 {
+		compatible = "mx66l51235l";
+		spi-max-frequency = <48000000>;
+		reg = <0>;
+		spi-cpol;
+		spi-cpha;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* MTD partition table.
+		 * The ROM checks the first 512KiB
+		 * for a valid file to boot(XIP).
+		 */
+		partition@0 {
+			label = "QSPI.U_BOOT";
+			reg = <0x00000000 0x000080000>;
+		};
+		partition@1 {
+			label = "QSPI.U_BOOT.backup";
+			reg = <0x00080000 0x00080000>;
+		};
+		partition@2 {
+			label = "QSPI.U-BOOT-SPL_OS";
+			reg = <0x00100000 0x00010000>;
+		};
+		partition@3 {
+			label = "QSPI.U_BOOT_ENV";
+			reg = <0x00110000 0x00010000>;
+		};
+		partition@4 {
+			label = "QSPI.U-BOOT-ENV.backup";
+			reg = <0x00120000 0x00010000>;
+		};
+		partition@5 {
+			label = "QSPI.KERNEL";
+			reg = <0x00130000 0x0800000>;
+		};
+		partition@6 {
+			label = "QSPI.FILESYSTEM";
+			reg = <0x00930000 0x36D0000>;
+		};
+	};
+};
+
+&hdq {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdq_pins>;
+};
+
+&dss {
+	status = "ok";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_pins>;
+
+	port {
+		dpi_out: endpoint@0 {
+			remote-endpoint = <&lcd_in>;
+			data-lines = <24>;
+		};
+	};
+};
+
+&vpfe1 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&vpfe1_pins_default>;
+	pinctrl-1 = <&vpfe1_pins_sleep>;
+
+	port {
+		vpfe1_ep: endpoint {
+			/* remote-endpoint = <&sensor>; add once we have it */
+			ti,am437x-vpfe-interface = <0>;
+			bus-width = <8>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+		};
+	};
+};
+
+&mcasp1 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&mcasp1_pins>;
+	pinctrl-1 = <&mcasp1_sleep_pins>;
+
+	status = "okay";
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	/* 4 serializer */
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+		1 2 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&synctimer_32kclk {
+	assigned-clocks = <&mux_synctimer32k_ck>;
+	assigned-clock-parents = <&clkdiv32k_ick>;
+};
diff --git a/arch/arm/dts/am43xx-clocks.dtsi b/arch/arm/dts/am43xx-clocks.dtsi
new file mode 100644
index 0000000..d0c0dfa
--- /dev/null
+++ b/arch/arm/dts/am43xx-clocks.dtsi
@@ -0,0 +1,757 @@
+/*
+ * Device Tree Source for AM43xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+&scm_clocks {
+	sys_clkin_ck: sys_clkin_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sysboot_freq_sel_ck>, <&crystal_freq_sel_ck>;
+		ti,bit-shift = <31>;
+		reg = <0x0040>;
+	};
+
+	crystal_freq_sel_ck: crystal_freq_sel_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
+		ti,bit-shift = <29>;
+		reg = <0x0040>;
+	};
+
+	sysboot_freq_sel_ck: sysboot_freq_sel_ck@44e10040 {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
+		ti,bit-shift = <22>;
+		reg = <0x0040>;
+	};
+
+	adc_tsc_fck: adc_tsc_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dcan0_fck: dcan0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dcan1_fck: dcan1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	mcasp0_fck: mcasp0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	mcasp1_fck: mcasp1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	smartreflex0_fck: smartreflex0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	smartreflex1_fck: smartreflex1_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	sha0_fck: sha0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	aes0_fck: aes0_fck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	ehrpwm0_tbclk: ehrpwm0_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <0>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm1_tbclk: ehrpwm1_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <1>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm2_tbclk: ehrpwm2_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <2>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm3_tbclk: ehrpwm3_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <4>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm4_tbclk: ehrpwm4_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <5>;
+		reg = <0x0664>;
+	};
+
+	ehrpwm5_tbclk: ehrpwm5_tbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&l4ls_gclk>;
+		ti,bit-shift = <6>;
+		reg = <0x0664>;
+	};
+};
+&prcm_clocks {
+	clk_32768_ck: clk_32768_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	clk_rc32k_ck: clk_rc32k_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	virt_19200000_ck: virt_19200000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <19200000>;
+	};
+
+	virt_24000000_ck: virt_24000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	virt_25000000_ck: virt_25000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <25000000>;
+	};
+
+	virt_26000000_ck: virt_26000000_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <26000000>;
+	};
+
+	tclkin_ck: tclkin_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <26000000>;
+	};
+
+	dpll_core_ck: dpll_core_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-core-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x2d20>, <0x2d24>, <0x2d2c>;
+	};
+
+	dpll_core_x2_ck: dpll_core_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-x2-clock";
+		clocks = <&dpll_core_ck>;
+	};
+
+	dpll_core_m4_ck: dpll_core_m4_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2d38>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_m5_ck: dpll_core_m5_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2d3c>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_core_m6_ck: dpll_core_m6_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_core_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2d40>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_mpu_ck: dpll_mpu_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x2d60>, <0x2d64>, <0x2d6c>;
+	};
+
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_mpu_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2d70>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_ddr_ck: dpll_ddr_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x2da0>, <0x2da4>, <0x2dac>;
+	};
+
+	dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_ddr_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2db0>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_disp_ck: dpll_disp_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x2e20>, <0x2e24>, <0x2e2c>;
+	};
+
+	dpll_disp_m2_ck: dpll_disp_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_disp_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2e30>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+		ti,set-rate-parent;
+	};
+
+	dpll_per_ck: dpll_per_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-j-type-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x2de0>, <0x2de4>, <0x2dec>;
+	};
+
+	dpll_per_m2_ck: dpll_per_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_per_ck>;
+		ti,max-div = <127>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2df0>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	dpll_per_m2_div4_ck: dpll_per_m2_div4_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <4>;
+	};
+
+	clk_24mhz: clk_24mhz {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <8>;
+	};
+
+	clkdiv32k_ck: clkdiv32k_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&clk_24mhz>;
+		clock-mult = <1>;
+		clock-div = <732>;
+	};
+
+	clkdiv32k_ick: clkdiv32k_ick {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x2a38>;
+	};
+
+	sysclk_div: sysclk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	pruss_ocp_gclk: pruss_ocp_gclk {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sysclk_div>, <&dpll_disp_m2_ck>;
+		reg = <0x4248>;
+	};
+
+	clk_32k_tpm_ck: clk_32k_tpm_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	timer1_fck: timer1_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>, <&clk_32k_tpm_ck>;
+		reg = <0x4200>;
+	};
+
+	timer2_fck: timer2_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x4204>;
+	};
+
+	timer3_fck: timer3_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x4208>;
+	};
+
+	timer4_fck: timer4_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x420c>;
+	};
+
+	timer5_fck: timer5_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x4210>;
+	};
+
+	timer6_fck: timer6_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x4214>;
+	};
+
+	timer7_fck: timer7_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+		reg = <0x4218>;
+	};
+
+	wdt1_fck: wdt1_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>;
+		reg = <0x422c>;
+	};
+
+	l3_gclk: l3_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	dpll_core_m4_div2_ck: dpll_core_m4_div2_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sysclk_div>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	l4hs_gclk: l4hs_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l3s_gclk: l3s_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	l4ls_gclk: l4ls_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m4_div2_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	cpsw_125mhz_gclk: cpsw_125mhz_gclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m5_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	cpsw_cpts_rft_clk: cpsw_cpts_rft_clk {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sysclk_div>, <&dpll_core_m5_ck>, <&dpll_disp_m2_ck>;
+		reg = <0x4238>;
+	};
+
+	clk_32k_mosc_ck: clk_32k_mosc_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>, <&clk_32k_mosc_ck>, <&clk_32k_tpm_ck>;
+		reg = <0x4240>;
+	};
+
+	gpio0_dbclk: gpio0_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&gpio0_dbclk_mux_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x2b68>;
+	};
+
+	gpio1_dbclk: gpio1_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <8>;
+		reg = <0x8c78>;
+	};
+
+	gpio2_dbclk: gpio2_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <8>;
+		reg = <0x8c80>;
+	};
+
+	gpio3_dbclk: gpio3_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <8>;
+		reg = <0x8c88>;
+	};
+
+	gpio4_dbclk: gpio4_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <8>;
+		reg = <0x8c90>;
+	};
+
+	gpio5_dbclk: gpio5_dbclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkdiv32k_ick>;
+		ti,bit-shift = <8>;
+		reg = <0x8c98>;
+	};
+
+	mmc_clk: mmc_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	gfx_fclk_clksel_ck: gfx_fclk_clksel_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&sysclk_div>, <&dpll_per_m2_ck>;
+		ti,bit-shift = <1>;
+		reg = <0x423c>;
+	};
+
+	gfx_fck_div_ck: gfx_fck_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&gfx_fclk_clksel_ck>;
+		reg = <0x423c>;
+		ti,max-div = <2>;
+	};
+
+	disp_clk: disp_clk {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>;
+		reg = <0x4244>;
+		ti,set-rate-parent;
+	};
+
+	dpll_extdev_ck: dpll_extdev_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-clock";
+		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+		reg = <0x2e60>, <0x2e64>, <0x2e6c>;
+	};
+
+	dpll_extdev_m2_ck: dpll_extdev_m2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_extdev_ck>;
+		ti,max-div = <127>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2e70>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	mux_synctimer32k_ck: mux_synctimer32k_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>, <&clkdiv32k_ick>;
+		reg = <0x4230>;
+	};
+
+	synctimer_32kclk: synctimer_32kclk {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&mux_synctimer32k_ck>;
+		ti,bit-shift = <8>;
+		reg = <0x2a30>;
+	};
+
+	timer8_fck: timer8_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+		reg = <0x421c>;
+	};
+
+	timer9_fck: timer9_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+		reg = <0x4220>;
+	};
+
+	timer10_fck: timer10_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+		reg = <0x4224>;
+	};
+
+	timer11_fck: timer11_fck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+		reg = <0x4228>;
+	};
+
+	cpsw_50m_clkdiv: cpsw_50m_clkdiv {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_core_m5_ck>;
+		clock-mult = <1>;
+		clock-div = <1>;
+	};
+
+	cpsw_5m_clkdiv: cpsw_5m_clkdiv {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&cpsw_50m_clkdiv>;
+		clock-mult = <1>;
+		clock-div = <10>;
+	};
+
+	dpll_ddr_x2_ck: dpll_ddr_x2_ck {
+		#clock-cells = <0>;
+		compatible = "ti,am3-dpll-x2-clock";
+		clocks = <&dpll_ddr_ck>;
+	};
+
+	dpll_ddr_m4_ck: dpll_ddr_m4_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&dpll_ddr_x2_ck>;
+		ti,max-div = <31>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2db8>;
+		ti,index-starts-at-one;
+		ti,invert-autoidle-bit;
+	};
+
+	dpll_per_clkdcoldo: dpll_per_clkdcoldo {
+		#clock-cells = <0>;
+		compatible = "ti,fixed-factor-clock";
+		clocks = <&dpll_per_ck>;
+		ti,clock-mult = <1>;
+		ti,clock-div = <1>;
+		ti,autoidle-shift = <8>;
+		reg = <0x2e14>;
+		ti,invert-autoidle-bit;
+	};
+
+	dll_aging_clk_div: dll_aging_clk_div {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin_ck>;
+		reg = <0x4250>;
+		ti,dividers = <8>, <16>, <32>;
+	};
+
+	div_core_25m_ck: div_core_25m_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sysclk_div>;
+		clock-mult = <1>;
+		clock-div = <8>;
+	};
+
+	func_12m_clk: func_12m_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_per_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <16>;
+	};
+
+	vtp_clk_div: vtp_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&sys_clkin_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
+	usbphy_32khz_clkmux: usbphy_32khz_clkmux {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>;
+		reg = <0x4260>;
+	};
+
+	usb_phy0_always_on_clk32k: usb_phy0_always_on_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&usbphy_32khz_clkmux>;
+		ti,bit-shift = <8>;
+		reg = <0x2a40>;
+	};
+
+	usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&usbphy_32khz_clkmux>;
+		ti,bit-shift = <8>;
+		reg = <0x2a48>;
+	};
+
+	usb_otg_ss0_refclk960m: usb_otg_ss0_refclk960m {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_per_clkdcoldo>;
+		ti,bit-shift = <8>;
+		reg = <0x8a60>;
+	};
+
+	usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&dpll_per_clkdcoldo>;
+		ti,bit-shift = <8>;
+		reg = <0x8a68>;
+	};
+};
diff --git a/arch/arm/dts/am571x-idk.dts b/arch/arm/dts/am571x-idk.dts
new file mode 100644
index 0000000..debf946
--- /dev/null
+++ b/arch/arm/dts/am571x-idk.dts
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "dra72x.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "am57xx-idk-common.dtsi"
+#include "dra72x-mmc-iodelay.dtsi"
+
+/ {
+	model = "TI AM5718 IDK";
+	compatible = "ti,am5718-idk", "ti,am5718", "ti,dra7";
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x40000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		cpu0-led {
+			label = "status0:red:cpu0";
+			gpios = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu0";
+		};
+
+		usr0-led {
+			label = "status0:green:usr";
+			gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		heartbeat-led {
+			label = "status0:blue:heartbeat";
+			gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+
+		usr1-led {
+			label = "status1:red:usr";
+			gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		usr2-led {
+			label = "status1:green:usr";
+			gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		mmc0-led {
+			label = "status1:blue:mmc0";
+			gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc0";
+		};
+	};
+};
+
+&omap_dwc3_2 {
+	extcon = <&extcon_usb2>;
+};
+
+&extcon_usb2 {
+	id-gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>;
+	vbus-gpio = <&gpio7 22 GPIO_ACTIVE_HIGH>;
+};
+
+&mailbox5 {
+	status = "okay";
+	mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp1_ipc3x: mbox_dsp1_ipc3x {
+		status = "okay";
+	};
+};
+
+&mailbox6 {
+	status = "okay";
+	mbox_ipu2_ipc3x: mbox_ipu2_ipc3x {
+		status = "okay";
+	};
+};
+
+&pcie1_rc {
+	status = "okay";
+	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+};
+
+&pcie1_ep {
+	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+};
+
+&mmc1 {
+	pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_hs>;
+	pinctrl-2 = <&mmc1_pins_sdr12>;
+	pinctrl-3 = <&mmc1_pins_sdr25>;
+	pinctrl-4 = <&mmc1_pins_sdr50>;
+	pinctrl-5 = <&mmc1_pins_ddr50_rev20 &mmc1_iodelay_ddr50_conf>;
+	pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
+};
+
+&mmc2 {
+	pinctrl-names = "default", "hs", "ddr_1_8v";
+	pinctrl-0 = <&mmc2_pins_default>;
+	pinctrl-1 = <&mmc2_pins_hs>;
+	pinctrl-2 = <&mmc2_pins_ddr_rev20 &mmc2_iodelay_ddr_conf>;
+};
diff --git a/arch/arm/dts/am572x-idk-common.dtsi b/arch/arm/dts/am572x-idk-common.dtsi
new file mode 100644
index 0000000..c6d858b
--- /dev/null
+++ b/arch/arm/dts/am572x-idk-common.dtsi
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "am57xx-idk-common.dtsi"
+
+/ {
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>;
+	};
+
+	status-leds {
+		compatible = "gpio-leds";
+		cpu0-led {
+			label = "status0:red:cpu0";
+			gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu0";
+		};
+
+		usr0-led {
+			label = "status0:green:usr";
+			gpios = <&gpio3 11 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		heartbeat-led {
+			label = "status0:blue:heartbeat";
+			gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+
+		cpu1-led {
+			label = "status1:red:cpu1";
+			gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu1";
+		};
+
+		usr1-led {
+			label = "status1:green:usr";
+			gpios = <&gpio7 23 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		mmc0-led {
+			label = "status1:blue:mmc0";
+			gpios = <&gpio7 22 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc0";
+		};
+	};
+};
+
+&omap_dwc3_2 {
+	extcon = <&extcon_usb2>;
+};
+
+&extcon_usb2 {
+	id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+	vbus-gpio = <&gpio3 26 GPIO_ACTIVE_HIGH>;
+};
+
+&sn65hvs882 {
+	load-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
+};
+
+&pcie1_rc {
+	status = "okay";
+	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+};
+
+&pcie1_ep {
+	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+};
+
+&mailbox5 {
+	status = "okay";
+	mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp1_ipc3x: mbox_dsp1_ipc3x {
+		status = "okay";
+	};
+};
+
+&mailbox6 {
+	status = "okay";
+	mbox_ipu2_ipc3x: mbox_ipu2_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp2_ipc3x: mbox_dsp2_ipc3x {
+		status = "okay";
+	};
+};
diff --git a/arch/arm/dts/am572x-idk.dts b/arch/arm/dts/am572x-idk.dts
new file mode 100644
index 0000000..9212931
--- /dev/null
+++ b/arch/arm/dts/am572x-idk.dts
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "dra74x.dtsi"
+#include "am572x-idk-common.dtsi"
+#include "am57xx-idk-common.dtsi"
+#include "dra74x-mmc-iodelay.dtsi"
+
+/ {
+	model = "TI AM5728 IDK";
+	compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74",
+		     "ti,dra7";
+};
+
+&mmc1 {
+	pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_hs>;
+	pinctrl-2 = <&mmc1_pins_sdr12>;
+	pinctrl-3 = <&mmc1_pins_sdr25>;
+	pinctrl-4 = <&mmc1_pins_sdr50>;
+	pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>;
+	pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
+};
+
+&mmc2 {
+	pinctrl-names = "default", "hs", "ddr_1_8v";
+	pinctrl-0 = <&mmc2_pins_default>;
+	pinctrl-1 = <&mmc2_pins_hs>;
+	pinctrl-2 = <&mmc2_pins_ddr_rev20>;
+};
diff --git a/arch/arm/dts/am574x-idk.dts b/arch/arm/dts/am574x-idk.dts
new file mode 100644
index 0000000..41e12a3
--- /dev/null
+++ b/arch/arm/dts/am574x-idk.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+
+/dts-v1/;
+
+#include "dra76x.dtsi"
+#include "am572x-idk-common.dtsi"
+
+/ {
+	model = "TI AM5748 IDK";
+	compatible = "ti,am5728-idk", "ti,dra762", "ti,dra7";
+};
+
+&qspi {
+	spi-max-frequency = <96000000>;
+	m25p80@0 {
+		spi-max-frequency = <96000000>;
+	};
+};
diff --git a/arch/arm/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/dts/am57xx-beagle-x15-common.dtsi
new file mode 100644
index 0000000..49aeecd
--- /dev/null
+++ b/arch/arm/dts/am57xx-beagle-x15-common.dtsi
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "dra74x.dtsi"
+#include "am57xx-commercial-grade.dtsi"
+#include "dra74x-mmc-iodelay.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	compatible = "ti,am572x-beagle-x15", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7";
+
+	aliases {
+		rtc0 = &mcp_rtc;
+		rtc1 = &tps659038_rtc;
+		rtc2 = &rtc;
+		display0 = &hdmi0;
+	};
+
+	chosen {
+		stdout-path = &uart3;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>;
+	};
+
+	vdd_3v3: fixedregulator-vdd_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_3v3";
+		vin-supply = <&regen1>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	aic_dvdd: fixedregulator-aic_dvdd {
+		compatible = "regulator-fixed";
+		regulator-name = "aic_dvdd_fixed";
+		vin-supply = <&vdd_3v3>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vtt_fixed: fixedregulator-vtt {
+		/* TPS51200 */
+		compatible = "regulator-fixed";
+		regulator-name = "vtt_fixed";
+		vin-supply = <&smps3_reg>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0 {
+			label = "beagle-x15:usr0";
+			gpios = <&gpio7 9 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led1 {
+			label = "beagle-x15:usr1";
+			gpios = <&gpio7 8 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led2 {
+			label = "beagle-x15:usr2";
+			gpios = <&gpio7 14 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led3 {
+			label = "beagle-x15:usr3";
+			gpios = <&gpio7 15 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "disk-activity";
+			default-state = "off";
+		};
+	};
+
+	gpio_fan: gpio_fan {
+		/* Based on 5v 500mA AFB02505HHB */
+		compatible = "gpio-fan";
+		gpios =  <&tps659038_gpio 2 GPIO_ACTIVE_HIGH>;
+		gpio-fan,speed-map = <0     0>,
+				     <13000 1>;
+		#cooling-cells = <2>;
+	};
+
+	hdmi0: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+
+		type = "a";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&tpd12s015_out>;
+			};
+		};
+	};
+
+	tpd12s015: encoder {
+		compatible = "ti,tpd12s015";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				tpd12s015_in: endpoint {
+					remote-endpoint = <&hdmi_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				tpd12s015_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+
+	sound0: sound0 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "BeagleBoard-X15";
+		simple-audio-card,widgets =
+			"Line", "Line Out",
+			"Line", "Line In";
+		simple-audio-card,routing =
+			"Line Out",	"LLOUT",
+			"Line Out",	"RLOUT",
+			"MIC2L",	"Line In",
+			"MIC2R",	"Line In";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&sound0_master>;
+		simple-audio-card,frame-master = <&sound0_master>;
+		simple-audio-card,bitclock-inversion;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcasp3>;
+		};
+
+		sound0_master: simple-audio-card,codec {
+			sound-dai = <&tlv320aic3104>;
+			clocks = <&clkout2_clk>;
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps659038: tps659038@58 {
+		compatible = "ti,tps659038";
+		reg = <0x58>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		#interrupt-cells = <2>;
+		interrupt-controller;
+
+		ti,system-power-controller;
+		ti,palmas-override-powerhold;
+
+		tps659038_pmic {
+			compatible = "ti,tps659038-pmic";
+
+			regulators {
+				smps12_reg: smps12 {
+					/* VDD_MPU */
+					regulator-name = "smps12";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps3_reg: smps3 {
+					/* VDD_DDR */
+					regulator-name = "smps3";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps45_reg: smps45 {
+					/* VDD_DSPEVE, VDD_IVA, VDD_GPU */
+					regulator-name = "smps45";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps6_reg: smps6 {
+					/* VDD_CORE */
+					regulator-name = "smps6";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				/* SMPS7 unused */
+
+				smps8_reg: smps8 {
+					/* VDD_1V8 */
+					regulator-name = "smps8";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				/* SMPS9 unused */
+
+				ldo1_reg: ldo1 {
+					/* VDD_SD / VDDSHV8  */
+					regulator-name = "ldo1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo2_reg: ldo2 {
+					/* VDD_SHV5 */
+					regulator-name = "ldo2";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo3_reg: ldo3 {
+					/* VDDA_1V8_PHYA */
+					regulator-name = "ldo3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo4_reg: ldo4 {
+					/* VDDA_1V8_PHYB */
+					regulator-name = "ldo4";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo9_reg: ldo9 {
+					/* VDD_RTC */
+					regulator-name = "ldo9";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldoln_reg: ldoln {
+					/* VDDA_1V8_PLL */
+					regulator-name = "ldoln";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldousb_reg: ldousb {
+					/* VDDA_3V_USB: VDDA_USBHS33 */
+					regulator-name = "ldousb";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+				};
+
+				regen1: regen1 {
+					/* VDD_3V3_ON */
+					regulator-name = "regen1";
+					regulator-boot-on;
+					regulator-always-on;
+				};
+			};
+		};
+
+		tps659038_rtc: tps659038_rtc {
+			compatible = "ti,palmas-rtc";
+			interrupt-parent = <&tps659038>;
+			interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+			wakeup-source;
+		};
+
+		tps659038_pwr_button: tps659038_pwr_button {
+			compatible = "ti,palmas-pwrbutton";
+			interrupt-parent = <&tps659038>;
+			interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+			wakeup-source;
+			ti,palmas-long-press-seconds = <12>;
+		};
+
+		tps659038_gpio: tps659038_gpio {
+			compatible = "ti,palmas-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		extcon_usb2: tps659038_usb {
+			compatible = "ti,palmas-usb-vid";
+			ti,enable-vbus-detection;
+			vbus-gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+		};
+
+	};
+
+	tmp102: tmp102@48 {
+		compatible = "ti,tmp102";
+		reg = <0x48>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+		#thermal-sensor-cells = <1>;
+	};
+
+	tlv320aic3104: tlv320aic3104@18 {
+		#sound-dai-cells = <0>;
+		compatible = "ti,tlv320aic3104";
+		reg = <0x18>;
+		assigned-clocks = <&clkoutmux2_clk_mux>;
+		assigned-clock-parents = <&sys_clk2_dclk_div>;
+
+		status = "okay";
+		adc-settle-ms = <40>;
+
+		AVDD-supply = <&vdd_3v3>;
+		IOVDD-supply = <&vdd_3v3>;
+		DRVDD-supply = <&vdd_3v3>;
+		DVDD-supply = <&aic_dvdd>;
+	};
+
+	eeprom: eeprom@50 {
+		compatible = "atmel,24c32";
+		reg = <0x50>;
+	};
+};
+
+&i2c3 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	mcp_rtc: rtc@6f {
+		compatible = "microchip,mcp7941x";
+		reg = <0x6f>;
+		interrupts-extended = <&crossbar_mpu GIC_SPI 2 IRQ_TYPE_EDGE_RISING>,
+				      <&dra7_pmx_core 0x424>;
+		interrupt-names = "irq", "wakeup";
+
+		vcc-supply = <&vdd_3v3>;
+		wakeup-source;
+	};
+};
+
+&gpio7 {
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&cpu0 {
+	cpu0-supply = <&smps12_reg>;
+	voltage-tolerance = <1>;
+};
+
+&uart3 {
+	status = "okay";
+	interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+			      <&dra7_pmx_core 0x3f8>;
+};
+
+&davinci_mdio {
+	phy0: ethernet-phy@1 {
+		reg = <1>;
+	};
+
+	phy1: ethernet-phy@2 {
+		reg = <2>;
+	};
+};
+
+&mac {
+	status = "okay";
+	dual_emac;
+};
+
+&cpsw_emac0 {
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy-handle = <&phy1>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <2>;
+};
+
+&mmc1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins_default>;
+
+	bus-width = <4>;
+	cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */
+};
+
+&mmc2 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_default>;
+
+	vmmc-supply = <&vdd_3v3>;
+	bus-width = <8>;
+	ti,non-removable;
+	cap-mmc-dual-data-rate;
+};
+
+&sata {
+	status = "okay";
+};
+
+&usb2_phy1 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb1 {
+	dr_mode = "host";
+};
+
+&omap_dwc3_2 {
+	extcon = <&extcon_usb2>;
+};
+
+&usb2 {
+	/*
+	 * Stand alone usage is peripheral only.
+	 * However, with some resistor modifications
+	 * this port can be used via expansion connectors
+	 * as "host" or "dual-role". If so, provide
+	 * the necessary dr_mode override in the expansion
+	 * board's DT.
+	 */
+	dr_mode = "peripheral";
+};
+
+&cpu_trips {
+	cpu_alert1: cpu_alert1 {
+		temperature = <50000>; /* millicelsius */
+		hysteresis = <2000>; /* millicelsius */
+		type = "active";
+	};
+};
+
+&cpu_cooling_maps {
+	map1 {
+		trip = <&cpu_alert1>;
+		cooling-device = <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+	};
+};
+
+&thermal_zones {
+	board_thermal: board_thermal {
+		polling-delay-passive = <1250>; /* milliseconds */
+		polling-delay = <1500>; /* milliseconds */
+
+				/* sensor       ID */
+		thermal-sensors = <&tmp102     0>;
+
+		board_trips: trips {
+			board_alert0: board_alert {
+				temperature = <40000>; /* millicelsius */
+				hysteresis = <2000>; /* millicelsius */
+				type = "active";
+			};
+
+			board_crit: board_crit {
+				temperature = <105000>; /* millicelsius */
+				hysteresis = <0>; /* millicelsius */
+				type = "critical";
+			};
+		};
+
+		board_cooling_maps: cooling-maps {
+			map0 {
+				trip = <&board_alert0>;
+				cooling-device =
+				  <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+			};
+		};
+       };
+};
+
+&dss {
+	status = "ok";
+
+	vdda_video-supply = <&ldoln_reg>;
+};
+
+&hdmi {
+	status = "ok";
+	vdda-supply = <&ldo4_reg>;
+
+	port {
+		hdmi_out: endpoint {
+			remote-endpoint = <&tpd12s015_in>;
+		};
+	};
+};
+
+&pcie1_rc {
+	status = "ok";
+	gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
+};
+
+&pcie1_ep {
+	gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
+};
+
+&mcasp3 {
+	#sound-dai-cells = <0>;
+	assigned-clocks = <&mcasp3_ahclkx_mux>;
+	assigned-clock-parents = <&sys_clkin2>;
+	status = "okay";
+
+	op-mode = <0>;	/* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	/* 4 serializers */
+	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
+		1 2 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&mailbox5 {
+	status = "okay";
+	mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp1_ipc3x: mbox_dsp1_ipc3x {
+		status = "okay";
+	};
+};
+
+&mailbox6 {
+	status = "okay";
+	mbox_ipu2_ipc3x: mbox_ipu2_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp2_ipc3x: mbox_dsp2_ipc3x {
+		status = "okay";
+	};
+};
diff --git a/arch/arm/dts/am57xx-beagle-x15-revb1.dts b/arch/arm/dts/am57xx-beagle-x15-revb1.dts
new file mode 100644
index 0000000..5a77b33
--- /dev/null
+++ b/arch/arm/dts/am57xx-beagle-x15-revb1.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am57xx-beagle-x15-common.dtsi"
+
+/ {
+	model = "TI AM5728 BeagleBoard-X15 rev B1";
+};
+
+&tpd12s015 {
+	gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>,	/* gpio7_10, CT CP HPD */
+		<&gpio2 30 GPIO_ACTIVE_HIGH>,	/* gpio2_30, LS OE */
+		<&gpio7 12 GPIO_ACTIVE_HIGH>;	/* gpio7_12/sp1_cs2, HPD */
+};
+
+&mmc1 {
+	pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_hs>;
+	pinctrl-2 = <&mmc1_pins_sdr12>;
+	pinctrl-3 = <&mmc1_pins_sdr25>;
+	pinctrl-4 = <&mmc1_pins_sdr50>;
+	pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev11_conf>;
+	pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev11_conf>;
+	vmmc-supply = <&vdd_3v3>;
+	vqmmc-supply = <&ldo1_reg>;
+};
+
+&mmc2 {
+	pinctrl-names = "default", "hs", "ddr_1_8v";
+	pinctrl-0 = <&mmc2_pins_default>;
+	pinctrl-1 = <&mmc2_pins_hs>;
+	pinctrl-2 = <&mmc2_pins_ddr_3_3v_rev11 &mmc2_iodelay_ddr_3_3v_rev11_conf>;
+};
+
+/* errata i880 "Ethernet RGMII2 Limited to 10/100 Mbps" */
+&phy1 {
+	max-speed = <100>;
+};
diff --git a/arch/arm/dts/am57xx-beagle-x15-revc.dts b/arch/arm/dts/am57xx-beagle-x15-revc.dts
new file mode 100644
index 0000000..17c41da
--- /dev/null
+++ b/arch/arm/dts/am57xx-beagle-x15-revc.dts
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am57xx-beagle-x15-common.dtsi"
+
+/ {
+	model = "TI AM5728 BeagleBoard-X15 rev C";
+};
+
+&tpd12s015 {
+	gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>,	/* gpio7_10, CT CP HPD */
+		<&gpio2 30 GPIO_ACTIVE_HIGH>,	/* gpio2_30, LS OE */
+		<&gpio7 12 GPIO_ACTIVE_HIGH>;	/* gpio7_12/sp1_cs2, HPD */
+};
+
+&mmc1 {
+	pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_hs>;
+	pinctrl-2 = <&mmc1_pins_sdr12>;
+	pinctrl-3 = <&mmc1_pins_sdr25>;
+	pinctrl-4 = <&mmc1_pins_sdr50>;
+	pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>;
+	pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
+	vmmc-supply = <&vdd_3v3>;
+	vqmmc-supply = <&ldo1_reg>;
+};
+
+&mmc2 {
+	pinctrl-names = "default", "hs", "ddr_1_8v";
+	pinctrl-0 = <&mmc2_pins_default>;
+	pinctrl-1 = <&mmc2_pins_hs>;
+	pinctrl-2 = <&mmc2_pins_ddr_rev20>;
+};
diff --git a/arch/arm/dts/am57xx-beagle-x15.dts b/arch/arm/dts/am57xx-beagle-x15.dts
new file mode 100644
index 0000000..8d9bdf1
--- /dev/null
+++ b/arch/arm/dts/am57xx-beagle-x15.dts
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am57xx-beagle-x15-common.dtsi"
+
+/ {
+	/* NOTE: This describes the "original" pre-production A2 revision */
+	model = "TI AM5728 BeagleBoard-X15";
+};
+
+&tpd12s015 {
+	gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>,	/* gpio7_10, CT CP HPD */
+		<&gpio6 28 GPIO_ACTIVE_HIGH>,	/* gpio6_28, LS OE */
+		<&gpio7 12 GPIO_ACTIVE_HIGH>;	/* gpio7_12/sp1_cs2, HPD */
+};
+
+&mmc1 {
+	pinctrl-names = "default", "hs";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_hs>;
+
+	vmmc-supply = <&ldo1_reg>;
+	/delete-property/ sd-uhs-sdr104;
+	/delete-property/ sd-uhs-sdr50;
+	/delete-property/ sd-uhs-ddr50;
+	/delete-property/ sd-uhs-sdr25;
+	/delete-property/ sd-uhs-sdr12;
+};
+
+&mmc2 {
+	pinctrl-names = "default", "hs", "ddr_1_8v";
+	pinctrl-0 = <&mmc2_pins_default>;
+	pinctrl-1 = <&mmc2_pins_hs>;
+	pinctrl-2 = <&mmc2_pins_ddr_3_3v_rev11 &mmc2_iodelay_ddr_3_3v_rev11_conf>;
+	/delete-property/ mmc-hs200-1_8v;
+};
+
+/* errata i880 "Ethernet RGMII2 Limited to 10/100 Mbps" */
+&phy1 {
+	max-speed = <100>;
+};
diff --git a/arch/arm/dts/am57xx-cl-som-am57x.dts b/arch/arm/dts/am57xx-cl-som-am57x.dts
new file mode 100644
index 0000000..203266f
--- /dev/null
+++ b/arch/arm/dts/am57xx-cl-som-am57x.dts
@@ -0,0 +1,617 @@
+/*
+ * Support for CompuLab CL-SOM-AM57x System-on-Module
+ *
+ * Copyright (C) 2015 CompuLab Ltd. - http://www.compulab.co.il/
+ * Author: Dmitry Lifshitz <lifshitz@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "dra74x.dtsi"
+
+/ {
+	model = "CompuLab CL-SOM-AM57x";
+	compatible = "compulab,cl-som-am57x", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7";
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x20000000>; /* 512 MB - minimal configuration */
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins_default>;
+
+		led0 {
+			label = "cl-som-am57x:green";
+			gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
+
+	vdd_3v3: fixedregulator-vdd_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	ads7846reg: fixedregulator-ads7846-reg {
+		compatible = "regulator-fixed";
+		regulator-name = "ads7846-reg";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	sound0: sound0 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "CL-SOM-AM57x-Sound-Card";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink0_master>;
+		simple-audio-card,frame-master = <&dailink0_master>;
+		simple-audio-card,widgets =
+					"Headphone", "Headphone Jack",
+					"Microphone", "Microphone Jack",
+					"Line", "Line Jack";
+		simple-audio-card,routing =
+					"Headphone Jack", "RHPOUT",
+					"Headphone Jack", "LHPOUT",
+					"LLINEIN", "Line Jack",
+					"MICIN", "Mic Bias",
+					"Mic Bias", "Microphone Jack";
+
+		dailink0_master: simple-audio-card,cpu {
+			sound-dai = <&mcasp3>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&wm8731>;
+			system-clock-frequency = <12000000>;
+		};
+	};
+};
+
+&dra7_pmx_core {
+	leds_pins_default: leds_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x347c, PIN_OUTPUT | MUX_MODE14)	/* gpmc_a15.gpio2_5 */
+		>;
+	};
+
+	i2c1_pins_default: i2c1_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_sda.sda */
+			DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_scl.scl */
+		>;
+	};
+
+	i2c3_pins_default: i2c3_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x36a4, PIN_INPUT| MUX_MODE10)	/* mcasp1_aclkx.i2c3_sda */
+			DRA7XX_CORE_IOPAD(0x36a8, PIN_INPUT| MUX_MODE10)	/* mcasp1_fsx.i2c3_scl */
+		>;
+	};
+
+	i2c4_pins_default: i2c4_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x36ac, PIN_INPUT| MUX_MODE10)	/* mcasp1_acl.i2c4_sda */
+			DRA7XX_CORE_IOPAD(0x36b0, PIN_INPUT| MUX_MODE10)	/* mcasp1_fsr.i2c4_scl */
+		>;
+	};
+
+	tps659038_pins_default: tps659038_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3818, PIN_INPUT_PULLUP | MUX_MODE14) /* wakeup0.gpio1_0 */
+		>;
+	};
+
+	mmc2_pins_default: mmc2_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
+			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
+			DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
+			DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
+			DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
+			DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
+			DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
+			DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
+			DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
+			DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
+		>;
+	};
+
+	qspi1_pins: pinmux_qspi1_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3474, PIN_INPUT | MUX_MODE1)	/* gpmc_a13.qspi1_rtclk */
+			DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1)	/* gpmc_a16.qspi1_d0 */
+			DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1)	/* gpmc_a17.qspi1_d1 */
+			DRA7XX_CORE_IOPAD(0x3488, PIN_INPUT | MUX_MODE1)	/* qpmc_a18.qspi1_sclk */
+			DRA7XX_CORE_IOPAD(0x34b8, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_cs2.qspi1_cs0 */
+			DRA7XX_CORE_IOPAD(0x34bc, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_cs3.qspi1_cs1 */
+		>;
+	};
+
+	cpsw_pins_default: cpsw_pins_default {
+		pinctrl-single,pins = <
+			/* Slave at addr 0x0 */
+			DRA7XX_CORE_IOPAD(0x3650, PIN_OUTPUT | MUX_MODE0)	/* rgmii0_tclk */
+			DRA7XX_CORE_IOPAD(0x3654, PIN_OUTPUT | MUX_MODE0)	/* rgmii0_tctl */
+			DRA7XX_CORE_IOPAD(0x3658, PIN_OUTPUT | MUX_MODE0)	/* rgmii0_td3 */
+			DRA7XX_CORE_IOPAD(0x365c, PIN_OUTPUT | MUX_MODE0)	/* rgmii0_td2 */
+			DRA7XX_CORE_IOPAD(0x3660, PIN_OUTPUT | MUX_MODE0)	/* rgmii0_td1 */
+			DRA7XX_CORE_IOPAD(0x3664, PIN_OUTPUT | MUX_MODE0)	/* rgmii0_td0 */
+			DRA7XX_CORE_IOPAD(0x3668, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rclk */
+			DRA7XX_CORE_IOPAD(0x366c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rctl */
+			DRA7XX_CORE_IOPAD(0x3670, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd3 */
+			DRA7XX_CORE_IOPAD(0x3674, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd2 */
+			DRA7XX_CORE_IOPAD(0x3678, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd1 */
+			DRA7XX_CORE_IOPAD(0x367c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd0 */
+
+			/* Slave at addr 0x1 */
+			DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d12.rgmii1_tclk */
+			DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d13.rgmii1_tctl */
+			DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d14.rgmii1_td3 */
+			DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d15.rgmii1_td2 */
+			DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d16.rgmii1_td1 */
+			DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d17.rgmii1_td0 */
+			DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d18.rgmii1_rclk */
+			DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d19.rgmii1_rctl */
+			DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d20.rgmii1_rd3 */
+			DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d21.rgmii1_rd2 */
+			DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d22.rgmii1_rd1 */
+			DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d23.rgmii1_rd0 */
+		>;
+	};
+
+	cpsw_pins_sleep: cpsw_pins_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			DRA7XX_CORE_IOPAD(0x3650, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3654, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3658, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x365c, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3660, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3664, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3668, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x366c, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3670, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3674, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3678, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x367c, PIN_INPUT | MUX_MODE15)
+
+			/* Slave 2 */
+			DRA7XX_CORE_IOPAD(0x3598, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x359c, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35a0, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35a4, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35a8, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35ac, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE15)
+		>;
+	};
+
+	davinci_mdio_pins_default: davinci_mdio_pins_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			DRA7XX_CORE_IOPAD(0x3590, PIN_OUTPUT_PULLUP | MUX_MODE3)/* vin2a_d10.mdio_mclk */
+			DRA7XX_CORE_IOPAD(0x3594, PIN_INPUT_PULLUP | MUX_MODE3)	/* vin2a_d11.mdio_d */
+		>;
+	};
+
+	davinci_mdio_pins_sleep: davinci_mdio_pins_sleep {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3590, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3594, PIN_INPUT | MUX_MODE15)
+		>;
+	};
+
+	ads7846_pins: pinmux_ads7846_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3464, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpmc_a9.gpio1_31 */
+		>;
+	};
+
+	mcasp3_pins_default: mcasp3_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_aclkx.mcasp3_aclkx */
+			DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_fsx.mcasp3_fsx */
+			DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr0.mcasp3_axr0 */
+			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr1.mcasp3_axr1 */
+		>;
+	};
+
+	mcasp3_pins_sleep: mcasp3_pins_sleep {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x372c, PIN_INPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT | MUX_MODE15)
+		>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&i2c4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_pins_default>;
+	clock-frequency = <400000>;
+
+	tps659038: tps659038@58 {
+		compatible = "ti,tps659038";
+		reg = <0x58>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&tps659038_pins_default>;
+
+		#interrupt-cells = <2>;
+		interrupt-controller;
+
+		ti,system-power-controller;
+
+		tps659038_pmic {
+			compatible = "ti,tps659038-pmic";
+
+			regulators {
+				smps12_reg: smps12 {
+					/* VDD_MPU */
+					regulator-name = "smps12";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps3_reg: smps3 {
+					/* VDD_DDR */
+					regulator-name = "smps3";
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps45_reg: smps45 {
+					/* VDD_DSPEVE */
+					regulator-name = "smps45";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps6_reg: smps6 {
+					/* VDD_GPU */
+					regulator-name = "smps6";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps7_reg: smps7 {
+					/* VDD_CORE */
+					regulator-name = "smps7";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1160000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps8_reg: smps8 {
+					/* VDD_IVA */
+					regulator-name = "smps8";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps9_reg: smps9 {
+					/* PMIC_3V3 */
+					regulator-name = "smps9";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+
+				ldo1_reg: ldo1 {
+					/* VDD_SD / VDDSHV8  */
+					regulator-name = "ldo1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo2_reg: ldo2 {
+					/* VDD_1V8 */
+					regulator-name = "ldo2";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo3_reg: ldo3 {
+					/* VDDA_1V8_PHYA - supplies VDDA_SATA, VDDA_USB1/2/3 */
+					regulator-name = "ldo3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo4_reg: ldo4 {
+					/* VDDA_1V8_PHYB - supplies VDDA_HDMI, VDDA_PCIE/0/1 */
+					regulator-name = "ldo4";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo9_reg: ldo9 {
+					/* VDD_RTC */
+					regulator-name = "ldo9";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldoln_reg: ldoln {
+					/* VDDA_1V8_PLL */
+					regulator-name = "ldoln";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldousb_reg: ldousb {
+					/* VDDA_3V_USB: VDDA_USBHS33 */
+					regulator-name = "ldousb";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				/* regen1 not used */
+			};
+		};
+
+		tps659038_pwr_button: tps659038_pwr_button {
+			compatible = "ti,palmas-pwrbutton";
+			interrupt-parent = <&tps659038>;
+			interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+			wakeup-source;
+			ti,palmas-long-press-seconds = <12>;
+		};
+
+		tps659038_gpio: tps659038_gpio {
+			compatible = "ti,palmas-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	rtc0: rtc@56 {
+		compatible = "emmicro,em3027";
+		reg = <0x56>;
+	};
+
+	eeprom_module: atmel@50 {
+		compatible = "atmel,24c08";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	wm8731: wm8731@1a {
+		#sound-dai-cells = <0>;
+		compatible = "wlf,wm8731";
+		reg = <0x1a>;
+		status = "okay";
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&smps12_reg>;
+	voltage-tolerance = <1>;
+};
+
+&sata {
+	status = "okay";
+};
+
+&mailbox5 {
+	status = "okay";
+	mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp1_ipc3x: mbox_dsp1_ipc3x {
+		status = "okay";
+	};
+};
+
+&mailbox6 {
+	status = "okay";
+	mbox_ipu2_ipc3x: mbox_ipu2_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp2_ipc3x: mbox_dsp2_ipc3x {
+		status = "okay";
+	};
+};
+
+&mmc2 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_default>;
+
+	vmmc-supply = <&vdd_3v3>;
+	bus-width = <8>;
+	ti,non-removable;
+	cap-mmc-dual-data-rate;
+};
+
+&qspi {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&qspi1_pins>;
+
+	spi-max-frequency = <48000000>;
+
+	spi_flash: spi_flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,m25p80", "jedec,spi-nor";
+		reg = <0>;				/* CS0 */
+		spi-max-frequency = <48000000>;
+
+		partition@0 {
+			label = "uboot";
+			reg = <0x0 0xc0000>;
+		};
+
+		partition@c0000 {
+			label = "uboot environment";
+			reg = <0xc0000 0x40000>;
+		};
+
+		partition@100000 {
+			label = "reserved";
+			reg = <0x100000 0x0>;
+		};
+	};
+
+	/* touch controller */
+	ads7846@0 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&ads7846_pins>;
+
+		compatible = "ti,ads7846";
+		vcc-supply = <&ads7846reg>;
+
+		reg = <1>;                              /* CS1 */
+		spi-max-frequency = <1500000>;
+
+		interrupt-parent = <&gpio1>;
+		interrupts = <31 0>;
+		pendown-gpio = <&gpio1 31 0>;
+
+
+		ti,x-min = /bits/ 16 <0x0>;
+		ti,x-max = /bits/ 16 <0x0fff>;
+		ti,y-min = /bits/ 16 <0x0>;
+		ti,y-max = /bits/ 16 <0x0fff>;
+
+		ti,x-plate-ohms = /bits/ 16 <180>;
+		ti,pressure-max = /bits/ 16 <255>;
+
+		ti,debounce-max = /bits/ 16 <30>;
+		ti,debounce-tol = /bits/ 16 <10>;
+		ti,debounce-rep = /bits/ 16 <1>;
+
+		wakeup-source;
+	};
+};
+
+&mac {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_pins_default>;
+	pinctrl-1 = <&cpsw_pins_sleep>;
+	dual_emac;
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <0>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <1>;
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_pins_default>;
+	pinctrl-1 = <&davinci_mdio_pins_sleep>;
+};
+
+&usb2_phy1 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb1 {
+	dr_mode = "host";
+};
+
+&usb2 {
+	dr_mode = "host";
+};
+
+&mcasp3 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&mcasp3_pins_default>;
+	pinctrl-1 = <&mcasp3_pins_sleep>;
+	status = "okay";
+
+	op-mode = <0>;	/* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	/* 4 serializers */
+	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
+		1 2 0 0
+	>;
+};
+
+&gpio3 {
+	status = "okay";
+	ti,no-reset-on-init;
+};
+
+&gpio2 {
+	status = "okay";
+	ti,no-reset-on-init;
+};
diff --git a/arch/arm/dts/am57xx-commercial-grade.dtsi b/arch/arm/dts/am57xx-commercial-grade.dtsi
new file mode 100644
index 0000000..3eed6e0
--- /dev/null
+++ b/arch/arm/dts/am57xx-commercial-grade.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+&cpu_alert0 {
+	temperature = <80000>; /* milliCelsius */
+};
+
+&cpu_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&gpu_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&core_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&dspeve_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&iva_crit {
+	temperature = <90000>; /* milliCelsius */
+};
diff --git a/arch/arm/dts/am57xx-idk-common.dtsi b/arch/arm/dts/am57xx-idk-common.dtsi
new file mode 100644
index 0000000..fa5a078
--- /dev/null
+++ b/arch/arm/dts/am57xx-idk-common.dtsi
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am57xx-industrial-grade.dtsi"
+
+/ {
+	aliases {
+		rtc0 = &tps659038_rtc;
+		rtc1 = &rtc;
+	};
+
+	chosen {
+		stdout-path = &uart3;
+	};
+
+	vmain: fixedregulator-vmain {
+		compatible = "regulator-fixed";
+		regulator-name = "VMAIN";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	v3_3d: fixedregulator-v3_3d {
+		compatible = "regulator-fixed";
+		regulator-name = "V3_3D";
+		vin-supply = <&smps9_reg>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vtt_fixed: fixedregulator-vtt {
+		/* TPS51200 */
+		compatible = "regulator-fixed";
+		regulator-name = "vtt_fixed";
+		vin-supply = <&v3_3d>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	leds-iio {
+		status = "disabled";
+		compatible = "gpio-leds";
+		led-out0 {
+			label = "out0";
+			gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out1 {
+			label = "out1";
+			gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out2 {
+			label = "out2";
+			gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out3 {
+			label = "out3";
+			gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out4 {
+			label = "out4";
+			gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out5 {
+			label = "out5";
+			gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out6 {
+			label = "out6";
+			gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out7 {
+			label = "out7";
+			gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&dra7_pmx_core {
+	dcan1_pins_default: dcan1_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* dcan1_tx */
+			DRA7XX_CORE_IOPAD(0x37d4, PIN_INPUT_PULLUP | MUX_MODE0)		/* dcan1_rx */
+		>;
+	};
+
+	dcan1_pins_sleep: dcan1_pins_sleep {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP)	/* dcan1_tx.off */
+			DRA7XX_CORE_IOPAD(0x37d4, MUX_MODE15 | PULL_UP)	/* dcan1_rx.off */
+		>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps659038: tps659038@58 {
+		compatible = "ti,tps659038";
+		reg = <0x58>;
+		interrupts-extended = <&gpio6 16 IRQ_TYPE_LEVEL_HIGH
+			       &dra7_pmx_core 0x418>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		ti,system-power-controller;
+		ti,palmas-override-powerhold;
+
+		tps659038_pmic {
+			compatible = "ti,tps659038-pmic";
+
+			smps12-in-supply = <&vmain>;
+			smps3-in-supply = <&vmain>;
+			smps45-in-supply = <&vmain>;
+			smps6-in-supply = <&vmain>;
+			smps7-in-supply = <&vmain>;
+			smps8-in-supply = <&vmain>;
+			smps9-in-supply = <&vmain>;
+			ldo1-in-supply = <&vmain>;
+			ldo2-in-supply = <&vmain>;
+			ldo3-in-supply = <&vmain>;
+			ldo4-in-supply = <&vmain>;
+			ldo9-in-supply = <&vmain>;
+			ldoln-in-supply = <&vmain>;
+			ldousb-in-supply = <&vmain>;
+			ldortc-in-supply = <&vmain>;
+
+			regulators {
+				smps12_reg: smps12 {
+					/* VDD_MPU */
+					regulator-name = "smps12";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps3_reg: smps3 {
+					/* VDD_DDR EMIF1 EMIF2 */
+					regulator-name = "smps3";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps45_reg: smps45 {
+					/* VDD_DSPEVE on AM572 */
+					/* VDD_IVA + VDD_DSP on AM571 */
+					regulator-name = "smps45";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps6_reg: smps6 {
+					/* VDD_GPU */
+					regulator-name = "smps6";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps7_reg: smps7 {
+					/* VDD_CORE */
+					regulator-name = "smps7";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps8_reg: smps8 {
+					/* 5728 - VDD_IVAHD */
+					/* 5718 - N.C. test point */
+					regulator-name = "smps8";
+				};
+
+				smps9_reg: smps9 {
+					/* VDD_3_3D */
+					regulator-name = "smps9";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo1_reg: ldo1 {
+					/* VDDSHV8 - VSDMMC  */
+					/* NOTE: on rev 1.3a, data supply */
+					regulator-name = "ldo1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo2_reg: ldo2 {
+					/* VDDSH18V */
+					regulator-name = "ldo2";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo3_reg: ldo3 {
+					/* R1.3a 572x V1_8PHY_LDO3: USB, SATA */
+					regulator-name = "ldo3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo4_reg: ldo4 {
+					/* R1.3a 572x V1_8PHY_LDO4: PCIE, HDMI*/
+					regulator-name = "ldo4";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				/* LDO5-8 unused */
+
+				ldo9_reg: ldo9 {
+					/* VDD_RTC  */
+					regulator-name = "ldo9";
+					regulator-min-microvolt = <840000>;
+					regulator-max-microvolt = <1160000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldoln_reg: ldoln {
+					/* VDDA_1V8_PLL */
+					regulator-name = "ldoln";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldousb_reg: ldousb {
+					/* VDDA_3V_USB: VDDA_USBHS33 */
+					regulator-name = "ldousb";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldortc_reg: ldortc {
+					/* VDDA_RTC  */
+					regulator-name = "ldortc";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				regen1: regen1 {
+					/* VDD_3V3_ON */
+					regulator-name = "regen1";
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				regen2: regen2 {
+					/* Needed for PMIC internal resource */
+					regulator-name = "regen2";
+					regulator-boot-on;
+					regulator-always-on;
+				};
+			};
+		};
+
+		tps659038_rtc: tps659038_rtc {
+			compatible = "ti,palmas-rtc";
+			interrupt-parent = <&tps659038>;
+			interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+			wakeup-source;
+		};
+
+		tps659038_pwr_button: tps659038_pwr_button {
+			compatible = "ti,palmas-pwrbutton";
+			interrupt-parent = <&tps659038>;
+			interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+			wakeup-source;
+			ti,palmas-long-press-seconds = <12>;
+		};
+
+		tps659038_gpio: tps659038_gpio {
+			compatible = "ti,palmas-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		extcon_usb2: tps659038_usb {
+			compatible = "ti,palmas-usb-vid";
+			ti,enable-vbus-detection;
+			ti,enable-id-detection;
+			/* ID & VBUS GPIOs provided in board dts */
+		};
+	};
+
+	tpic2810: tpic2810@60 {
+		compatible = "ti,tpic2810";
+		reg = <0x60>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&mcspi3 {
+	status = "okay";
+	ti,pindir-d0-out-d1-in;
+
+	sn65hvs882: sn65hvs882@0 {
+		compatible = "pisosr-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		reg = <0>;
+		spi-max-frequency = <1000000>;
+		spi-cpol;
+	};
+};
+
+&uart3 {
+	status = "okay";
+	interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH
+			       &dra7_pmx_core 0x248>;
+};
+
+&rtc {
+	status = "okay";
+	ext-clk-src;
+};
+
+&mac {
+	status = "okay";
+	dual_emac;
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <2>;
+};
+
+&usb2_phy1 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb1 {
+	dr_mode = "host";
+};
+
+&usb2 {
+	dr_mode = "peripheral";
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&v3_3d>;
+	vqmmc-supply = <&ldo1_reg>;
+	bus-width = <4>;
+	cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */
+};
+
+&mmc2 {
+	status = "okay";
+	vmmc-supply = <&v3_3d>;
+	bus-width = <8>;
+	ti,non-removable;
+	max-frequency = <96000000>;
+	no-1-8-v;
+	/delete-property/ mmc-hs200-1_8v;
+};
+
+&dcan1 {
+	status = "okay";
+	pinctrl-names = "default", "sleep", "active";
+	pinctrl-0 = <&dcan1_pins_sleep>;
+	pinctrl-1 = <&dcan1_pins_sleep>;
+	pinctrl-2 = <&dcan1_pins_default>;
+};
+
+&qspi {
+	status = "okay";
+
+	spi-max-frequency = <76800000>;
+	m25p80@0 {
+		compatible = "s25fl256s1", "jedec,spi-nor";
+		spi-max-frequency = <76800000>;
+		reg = <0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* MTD partition table.
+		 * The ROM checks the first four physical blocks
+		 * for a valid file to boot and the flash here is
+		 * 64KiB block size.
+		 */
+		partition@0 {
+			label = "QSPI.SPL";
+			reg = <0x00000000 0x000040000>;
+		};
+		partition@1 {
+			label = "QSPI.u-boot";
+			reg = <0x00040000 0x00100000>;
+		};
+		partition@2 {
+			label = "QSPI.u-boot-spl-os";
+			reg = <0x00140000 0x00080000>;
+		};
+		partition@3 {
+			label = "QSPI.u-boot-env";
+			reg = <0x001c0000 0x00010000>;
+		};
+		partition@4 {
+			label = "QSPI.u-boot-env.backup1";
+			reg = <0x001d0000 0x0010000>;
+		};
+		partition@5 {
+			label = "QSPI.kernel";
+			reg = <0x001e0000 0x0800000>;
+		};
+		partition@6 {
+			label = "QSPI.file-system";
+			reg = <0x009e0000 0x01620000>;
+		};
+	};
+};
diff --git a/arch/arm/dts/am57xx-industrial-grade.dtsi b/arch/arm/dts/am57xx-industrial-grade.dtsi
new file mode 100644
index 0000000..422f953
--- /dev/null
+++ b/arch/arm/dts/am57xx-industrial-grade.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+&cpu_alert0 {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&cpu_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&gpu_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&core_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&dspeve_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&iva_crit {
+	temperature = <105000>; /* milliCelsius */
+};
diff --git a/arch/arm/dts/am57xx-sbc-am57x.dts b/arch/arm/dts/am57xx-sbc-am57x.dts
new file mode 100644
index 0000000..31f9be6
--- /dev/null
+++ b/arch/arm/dts/am57xx-sbc-am57x.dts
@@ -0,0 +1,179 @@
+/*
+ * Support for CompuLab SBC-AM57x single board computer
+ *
+ * Copyright (C) 2015 CompuLab Ltd. - http://www.compulab.co.il/
+ * Author: Dmitry Lifshitz <lifshitz@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include "am57xx-cl-som-am57x.dts"
+#include "compulab-sb-som.dtsi"
+
+/ {
+	model = "CompuLab CL-SOM-AM57x on SB-SOM-AM57x";
+	compatible = "compulab,sbc-am57x", "compulab,cl-som-am57x", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7";
+
+	aliases {
+		display0 = &lcd0;
+		display1 = &hdmi;
+	};
+};
+
+&dra7_pmx_core {
+	uart3_pins_default: uart3_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3648, PIN_INPUT_SLEW | MUX_MODE0)	/* uart3_rxd */
+			DRA7XX_CORE_IOPAD(0x364c, PIN_INPUT_SLEW | MUX_MODE0)	/* uart3_txd */
+		>;
+	};
+
+	mmc1_pins_default: mmc1_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
+			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_cmd.cmd */
+			DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
+			DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
+			DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
+			DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
+			DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14)	/* mmc1_sdcd.gpio6_27 */
+			DRA7XX_CORE_IOPAD(0x377c, PIN_INPUT | MUX_MODE14)	/* mmc1_sdwp.gpio6_28 */
+		>;
+	};
+
+	usb1_pins: pinmux_usb1_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
+		>;
+	};
+
+	i2c5_pins_default: i2c5_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT| MUX_MODE10)	/* mcasp1_axr0.i2c5_sda */
+			DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT| MUX_MODE10)	/* mcasp1_axr1.i2c5_scl */
+		>;
+	};
+
+	lcd_pins_default: lcd_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3564, PIN_OUTPUT | MUX_MODE14)      /* vin2a_vsync0.gpio4_0 */
+		>;
+	};
+
+	hdmi_pins: pinmux_hdmi_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1)	/* i2c2_sda.hdmi1_ddc_scl */
+			DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1)	/* i2c2_scl.hdmi1_ddc_sda */
+		>;
+	};
+
+	hdmi_conn_pins: pinmux_hdmi_conn_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT | MUX_MODE14)	/* spi1_cs2.gpio7_12 */
+		>;
+	};
+};
+
+&uart3 {
+	status = "okay";
+	interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+			      <&dra7_pmx_core 0x3f8>;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins_default>;
+};
+
+&mmc1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins_default>;
+
+	vmmc-supply = <&ldo1_reg>;
+	bus-width = <4>;
+	cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>;
+};
+
+&usb1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb1_pins>;
+};
+
+&i2c5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_pins_default>;
+	clock-frequency = <400000>;
+
+	eeprom_base: atmel@54 {
+		compatible = "atmel,24c08";
+		reg = <0x54>;
+		pagesize = <16>;
+	};
+
+	pca9555: pca9555@20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&dss {
+	status = "ok";
+
+	vdda_video-supply = <&ldoln_reg>;
+
+	port {
+		dpi_lcd_out: endpoint {
+			remote-endpoint = <&lcd_in>;
+			data-lines = <24>;
+		};
+	};
+};
+
+&lcd0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_pins_default>;
+
+	enable-gpios = <&pca9555 14 GPIO_ACTIVE_HIGH
+			&gpio4 0 GPIO_ACTIVE_HIGH>;
+
+	port {
+		lcd_in: endpoint {
+			remote-endpoint = <&dpi_lcd_out>;
+			data-lines = <24>;
+		};
+	};
+};
+
+&hdmi {
+	status = "ok";
+	vdda-supply = <&ldo4_reg>;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_pins>;
+
+	port {
+		hdmi_out: endpoint {
+			remote-endpoint = <&hdmi_connector_in>;
+			lanes = <1 0 3 2 5 4 7 6>;
+		};
+	};
+};
+
+&hdmi_conn {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_conn_pins>;
+
+	hpd-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+
+	port {
+		hdmi_connector_in: endpoint {
+			remote-endpoint = <&hdmi_out>;
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi
new file mode 100644
index 0000000..0b2a78d
--- /dev/null
+++ b/arch/arm/dts/armada-370-xp.dtsi
@@ -0,0 +1,334 @@
+/*
+ * Device Tree Include file for Marvell Armada 370 and Armada XP SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Ben Dooks <ben.dooks@codethink.co.uk>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file contains the definitions that are common to the Armada
+ * 370 and Armada XP SoC.
+ */
+
+/include/ "skeleton64.dtsi"
+
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
+/ {
+	model = "Marvell Armada 370 and XP SoC";
+	compatible = "marvell,armada-370-xp";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			compatible = "marvell,sheeva-v7";
+			device_type = "cpu";
+			reg = <0>;
+		};
+	};
+
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts-extended = <&mpic 3>;
+	};
+
+	soc {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+		interrupt-parent = <&mpic>;
+		pcie-mem-aperture = <0xf8000000 0x7e00000>;
+		pcie-io-aperture  = <0xffe00000 0x100000>;
+
+		devbus-bootcs {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs0 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs1 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs2 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs3 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		internal-regs {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+			u-boot,dm-pre-reloc;
+
+			rtc@10300 {
+				compatible = "marvell,orion-rtc";
+				reg = <0x10300 0x20>;
+				interrupts = <50>;
+			};
+
+			spi0: spi@10600 {
+				reg = <0x10600 0x28>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				interrupts = <30>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			spi1: spi@10680 {
+				reg = <0x10680 0x28>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <1>;
+				interrupts = <92>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <31>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@11100 {
+				compatible = "marvell,mv64xxx-i2c";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <32>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			uart0: serial@12000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <41>;
+				reg-io-width = <1>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			uart1: serial@12100 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <42>;
+				reg-io-width = <1>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			pinctrl: pin-ctrl@18000 {
+				reg = <0x18000 0x38>;
+			};
+
+			coredivclk: corediv-clock@18740 {
+				compatible = "marvell,armada-370-corediv-clock";
+				reg = <0x18740 0xc>;
+				#clock-cells = <1>;
+				clocks = <&mainpll>;
+				clock-output-names = "nand";
+			};
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>,
+				      <0x20250 0x8>;
+			};
+
+			mpic: interrupt-controller@20a00 {
+				compatible = "marvell,mpic";
+				#interrupt-cells = <1>;
+				#size-cells = <1>;
+				interrupt-controller;
+				msi-controller;
+			};
+
+			coherency-fabric@20200 {
+				compatible = "marvell,coherency-fabric";
+				reg = <0x20200 0xb0>, <0x21010 0x1c>;
+			};
+
+			timer@20300 {
+				reg = <0x20300 0x30>, <0x21040 0x30>;
+				interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
+			};
+
+			watchdog@20300 {
+				reg = <0x20300 0x34>, <0x20704 0x4>;
+			};
+
+			pmsu@22000 {
+				compatible = "marvell,armada-370-pmsu";
+				reg = <0x22000 0x1000>;
+			};
+
+			usb@50000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x50000 0x500>;
+				interrupts = <45>;
+				status = "disabled";
+			};
+
+			usb@51000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x51000 0x500>;
+				interrupts = <46>;
+				status = "disabled";
+			};
+
+			eth0: ethernet@70000 {
+				reg = <0x70000 0x4000>;
+				interrupts = <8>;
+				clocks = <&gateclk 4>;
+				status = "disabled";
+			};
+
+			mdio: mdio {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "marvell,orion-mdio";
+				reg = <0x72004 0x4>;
+				clocks = <&gateclk 4>;
+			};
+
+			eth1: ethernet@74000 {
+				reg = <0x74000 0x4000>;
+				interrupts = <10>;
+				clocks = <&gateclk 3>;
+				status = "disabled";
+			};
+
+			sata@a0000 {
+				compatible = "marvell,armada-370-sata";
+				reg = <0xa0000 0x5000>;
+				interrupts = <55>;
+				clocks = <&gateclk 15>, <&gateclk 30>;
+				clock-names = "0", "1";
+				status = "disabled";
+			};
+
+			nand@d0000 {
+				compatible = "marvell,armada370-nand";
+				reg = <0xd0000 0x54>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				interrupts = <113>;
+				clocks = <&coredivclk 0>;
+				status = "disabled";
+			};
+
+			mvsdio@d4000 {
+				compatible = "marvell,orion-sdio";
+				reg = <0xd4000 0x200>;
+				interrupts = <54>;
+				clocks = <&gateclk 17>;
+				bus-width = <4>;
+				cap-sdio-irq;
+				cap-sd-highspeed;
+				cap-mmc-highspeed;
+				status = "disabled";
+			};
+		};
+	};
+
+	clocks {
+		/* 2 GHz fixed main PLL */
+		mainpll: mainpll {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <2000000000>;
+		};
+	};
+ };
diff --git a/arch/arm/dts/armada-371x.dtsi b/arch/arm/dts/armada-371x.dtsi
new file mode 100644
index 0000000..c9e5325
--- /dev/null
+++ b/arch/arm/dts/armada-371x.dtsi
@@ -0,0 +1,53 @@
+/*
+ * Device Tree Include file for Marvell Armada 371x family of SoCs
+ * (also named 88F3710)
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-37xx.dtsi"
+
+/ {
+	model = "Marvell Armada 3710 SoC";
+	compatible = "marvell,armada3710", "marvell,armada3700";
+};
diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
new file mode 100644
index 0000000..770c08a
--- /dev/null
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -0,0 +1,164 @@
+/*
+ * Device Tree file for Marvell Armada 3720 development board
+ * (DB-88F3720-DDR3)
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "armada-372x.dtsi"
+
+/ {
+	model = "Marvell Armada 3720 Development Board DB-88F3720-DDR3";
+	compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		i2c0 = &i2c0;
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+	};
+};
+
+&comphy {
+	phy0 {
+		phy-type = <PHY_TYPE_PEX0>;
+		phy-speed = <PHY_SPEED_2_5G>;
+	};
+
+	phy1 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+};
+
+&eth0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>, <&smi_pins>;
+	status = "okay";
+	phy-mode = "rgmii";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+/* CON3 */
+&sata {
+	status = "okay";
+};
+
+&sdhci0 {
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdio_pins>;
+	status = "okay";
+};
+
+&sdhci1 {
+	non-removable;
+	bus-width = <8>;
+	mmc-ddr-1_8v;
+	mmc-hs400-1_8v;
+	marvell,pad-type = "fixed-1-8v";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc_pins>;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	mmccard: mmccard@0 {
+		compatible = "mmc-card";
+		reg = <0>;
+	};
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_quad_pins>;
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p128", "spi-flash";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+	};
+};
+
+/* Exported on the micro USB connector CON32 through an FTDI */
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
+
+/* CON29 */
+&usb2 {
+	status = "okay";
+};
+
+/* CON31 */
+&usb3 {
+	status = "okay";
+};
+
+/* CON17 */
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie_pins>;
+	reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/armada-3720-espressobin.dts b/arch/arm/dts/armada-3720-espressobin.dts
new file mode 100644
index 0000000..7bfccb0
--- /dev/null
+++ b/arch/arm/dts/armada-3720-espressobin.dts
@@ -0,0 +1,150 @@
+/*
+ * Device Tree file for Marvell Armada 3720 community board
+ * (ESPRESSOBin)
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Konstantin Porotchkin <kostap@marvell.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "armada-372x.dtsi"
+
+/ {
+	model = "Marvell Armada 3720 Community Board ESPRESSOBin";
+	compatible = "marvell,armada-3720-espressobin", "marvell,armada3720", "marvell,armada3710";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		i2c0 = &i2c0;
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+	};
+};
+
+&comphy {
+	max-lanes = <3>;
+	phy0 {
+		phy-type = <PHY_TYPE_PEX0>;
+		phy-speed = <PHY_SPEED_2_5G>;
+	};
+
+	phy1 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+
+	phy2 {
+		phy-type = <PHY_TYPE_SATA0>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>, <&smi_pins>;
+	phy-mode = "rgmii";
+	phy_addr = <0x1>;
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+/* CON3 */
+&sata {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_quad_pins>;
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p128", "spi-flash";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+	};
+};
+
+/* Exported on the micro USB connector CON32 through an FTDI */
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
+
+/* CON29 */
+&usb2 {
+	status = "okay";
+};
+
+/* CON31 */
+&usb3 {
+	status = "okay";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie_pins>;
+	reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts
new file mode 100644
index 0000000..7babc16
--- /dev/null
+++ b/arch/arm/dts/armada-3720-turris-mox.dts
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+ or X11
+/*
+ * Device Tree file for CZ.NIC Turris Mox Board
+ * 2018 by Marek Behun <marek.behun@nic.cz>
+ *
+ * Based on armada-3720-espressobin.dts by:
+ *   Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *   Konstantin Porotchkin <kostap@marvell.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-372x.dtsi"
+
+/ {
+	model = "CZ.NIC Turris Mox Board";
+	compatible = "cznic,turris-mox", "marvell,armada3720",
+		     "marvell,armada3710";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		i2c0 = &i2c0;
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+	};
+
+	reg_usb3_vbus: usb3_vbus@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "usb3-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		shutdown-delay-us = <1000000>;
+		gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>;
+		regulator-boot-on;
+	};
+
+	mdio {
+		eth_phy1: ethernet-phy@1 {
+			reg = <1>;
+		};
+	};
+};
+
+&comphy {
+	max-lanes = <3>;
+	phy0 {
+		phy-type = <PHY_TYPE_SGMII1>;
+		phy-speed = <PHY_SPEED_3_125G>;
+	};
+
+	phy1 {
+		phy-type = <PHY_TYPE_PEX0>;
+		phy-speed = <PHY_SPEED_2_5G>;
+	};
+
+	phy2 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>, <&smi_pins>;
+	phy-mode = "rgmii";
+	phy = <&eth_phy1>;
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&sdhci1 {
+	bus-width = <4>;
+	status = "okay";
+};
+
+&pinctrl_nb {
+	spi_cs1_pins: spi-cs1-pins {
+		groups = "spi_cs1";
+		function = "spi";
+	};
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_cs1_pins>;
+	assigned-clocks = <&nb_periph_clk 7>;
+	assigned-clock-parents = <&tbg 1>;
+	assigned-clock-rates = <20000000>;
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,s25fl064l", "spi-flash";
+		reg = <0>;
+		spi-max-frequency = <20000000>;
+		m25p,fast-read;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
+
+&usb2 {
+	status = "okay";
+};
+
+&usb3 {
+	vbus-supply = <&reg_usb3_vbus>;
+	status = "okay";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie_pins>;
+	reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>;
+	status = "disabled";
+};
diff --git a/arch/arm/dts/armada-372x.dtsi b/arch/arm/dts/armada-372x.dtsi
new file mode 100644
index 0000000..5120296
--- /dev/null
+++ b/arch/arm/dts/armada-372x.dtsi
@@ -0,0 +1,62 @@
+/*
+ * Device Tree Include file for Marvell Armada 372x family of SoCs
+ * (also named 88F3720)
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-37xx.dtsi"
+
+/ {
+	model = "Marvell Armada 3720 SoC";
+	compatible = "marvell,armada3720", "marvell,armada3710";
+
+	cpus {
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53","arm,armv8";
+			reg = <0x1>;
+			enable-method = "psci";
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-375-db.dts b/arch/arm/dts/armada-375-db.dts
new file mode 100644
index 0000000..343349b
--- /dev/null
+++ b/arch/arm/dts/armada-375-db.dts
@@ -0,0 +1,216 @@
+/*
+ * Device Tree file for Marvell Armada 375 evaluation board
+ * (DB-88F6720)
+ *
+ *  Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-375.dtsi"
+
+/ {
+	model = "Marvell Armada 375 Development Board";
+	compatible = "marvell,a375-db", "marvell,armada375";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		/* So that mvebu u-boot can update the MAC addresses */
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>; /* 1 GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x09) 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x05) 0 0xf1110000 0x10000>;
+
+		internal-regs {
+			spi@10600 {
+				pinctrl-0 = <&spi0_pins>;
+				pinctrl-names = "default";
+				/*
+				 * SPI conflicts with NAND, so we disable it
+				 * here, and select NAND as the enabled device
+				 * by default.
+				 */
+				status = "okay";
+				u-boot,dm-pre-reloc;
+
+				spi-flash@0 {
+					u-boot,dm-pre-reloc;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q128a13", "jedec,spi-nor";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+			};
+
+			i2c@11000 {
+				status = "okay";
+				clock-frequency = <100000>;
+				pinctrl-0 = <&i2c0_pins>;
+				pinctrl-names = "default";
+			};
+
+			i2c@11100 {
+				status = "okay";
+				clock-frequency = <100000>;
+				pinctrl-0 = <&i2c1_pins>;
+				pinctrl-names = "default";
+			};
+
+			serial@12000 {
+				u-boot,dm-pre-reloc;
+				status = "okay";
+			};
+
+			pinctrl {
+				sdio_st_pins: sdio-st-pins {
+					marvell,pins = "mpp44", "mpp45";
+					marvell,function = "gpio";
+				};
+			};
+
+			sata@a0000 {
+				status = "okay";
+				nr-ports = <2>;
+			};
+
+			nand: nand@d0000 {
+				pinctrl-0 = <&nand_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				num-cs = <1>;
+				marvell,nand-keep-config;
+				marvell,nand-enable-arbiter;
+				nand-on-flash-bbt;
+				nand-ecc-strength = <4>;
+				nand-ecc-step-size = <512>;
+
+				partition@0 {
+					label = "U-Boot";
+					reg = <0 0x800000>;
+				};
+				partition@800000 {
+					label = "Linux";
+					reg = <0x800000 0x800000>;
+				};
+				partition@1000000 {
+					label = "Filesystem";
+					reg = <0x1000000 0x3f000000>;
+				};
+			};
+
+			usb@54000 {
+				status = "okay";
+			};
+
+			usb3@58000 {
+				status = "okay";
+			};
+
+			mvsdio@d4000 {
+				pinctrl-0 = <&sdio_pins &sdio_st_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				cd-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+				wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 {
+					reg = <0>;
+				};
+
+				phy3: ethernet-phy@3 {
+					reg = <3>;
+				};
+			};
+
+			ethernet@f0000 {
+				status = "okay";
+
+				eth0@c4000 {
+					status = "okay";
+					phy = <&phy0>;
+					phy-mode = "rgmii-id";
+				};
+
+				eth1@c5000 {
+					status = "okay";
+					phy = <&phy3>;
+					phy-mode = "gmii";
+				};
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * standard PCIe slots on the board.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi
new file mode 100644
index 0000000..249c41c
--- /dev/null
+++ b/arch/arm/dts/armada-375.dtsi
@@ -0,0 +1,658 @@
+/*
+ * Device Tree Include file for Marvell Armada 375 family SoC
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/phy/phy.h>
+
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
+/ {
+	model = "Marvell Armada 375 family SoC";
+	compatible = "marvell,armada375";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	clocks {
+		/* 2 GHz fixed main PLL */
+		mainpll: mainpll {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1000000000>;
+		};
+		/* 25 MHz reference crystal */
+		refclk: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "marvell,armada-375-smp";
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts-extended = <&mpic 3>;
+	};
+
+	soc {
+		compatible = "marvell,armada375-mbus", "simple-bus";
+		u-boot,dm-pre-reloc;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+		interrupt-parent = <&gic>;
+		pcie-mem-aperture = <0xe0000000 0x8000000>;
+		pcie-io-aperture  = <0xe8000000 0x100000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
+		};
+
+		devbus-bootcs {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs0 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs1 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs2 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs3 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		internal-regs {
+			compatible = "simple-bus";
+			u-boot,dm-pre-reloc;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+			L2: cache-controller@8000 {
+				compatible = "arm,pl310-cache";
+				reg = <0x8000 0x1000>;
+				cache-unified;
+				cache-level = <2>;
+				arm,double-linefill-incr = <1>;
+				arm,double-linefill-wrap = <0>;
+				arm,double-linefill = <1>;
+				prefetch-data = <1>;
+			};
+
+			scu@c000 {
+				compatible = "arm,cortex-a9-scu";
+				reg = <0xc000 0x58>;
+			};
+
+			timer@c600 {
+				compatible = "arm,cortex-a9-twd-timer";
+				reg = <0xc600 0x20>;
+				interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
+				clocks = <&coreclk 2>;
+			};
+
+			gic: interrupt-controller@d000 {
+				compatible = "arm,cortex-a9-gic";
+				#interrupt-cells = <3>;
+				#size-cells = <0>;
+				interrupt-controller;
+				reg = <0xd000 0x1000>,
+				      <0xc100 0x100>;
+			};
+
+			mdio {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "marvell,orion-mdio";
+				reg = <0xc0054 0x4>;
+				clocks = <&gateclk 19>;
+			};
+
+			/* Network controller */
+			ethernet@f0000 {
+				compatible = "marvell,armada-375-pp2";
+				reg = <0xf0000 0xa000>, /* Packet Processor regs */
+				      <0xc0000 0x3060>, /* LMS regs */
+				      <0xc4000 0x100>,  /* eth0 regs */
+				      <0xc5000 0x100>;  /* eth1 regs */
+				clocks = <&gateclk 3>, <&gateclk 19>;
+				clock-names = "pp_clk", "gop_clk";
+				status = "disabled";
+
+				eth0: eth0@c4000 {
+					interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+					port-id = <0>;
+					status = "disabled";
+				};
+
+				eth1: eth1@c5000 {
+					interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+					port-id = <1>;
+					status = "disabled";
+				};
+			};
+
+			rtc@10300 {
+				compatible = "marvell,orion-rtc";
+				reg = <0x10300 0x20>;
+				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			spi0: spi@10600 {
+				compatible = "marvell,armada-375-spi",
+						"marvell,orion-spi";
+				reg = <0x10600 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			spi1: spi@10680 {
+				compatible = "marvell,armada-375-spi",
+						"marvell,orion-spi";
+				reg = <0x10680 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <1>;
+				interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@11100 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11100 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			uart0: serial@12000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			uart1: serial@12100 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			pinctrl {
+				compatible = "marvell,mv88f6720-pinctrl";
+				reg = <0x18000 0x24>;
+
+				i2c0_pins: i2c0-pins {
+					marvell,pins = "mpp14",  "mpp15";
+					marvell,function = "i2c0";
+				};
+
+				i2c1_pins: i2c1-pins {
+					marvell,pins = "mpp61",  "mpp62";
+					marvell,function = "i2c1";
+				};
+
+				nand_pins: nand-pins {
+					marvell,pins = "mpp0", "mpp1", "mpp2",
+						"mpp3", "mpp4", "mpp5",
+						"mpp6", "mpp7", "mpp8",
+						"mpp9", "mpp10", "mpp11",
+						"mpp12", "mpp13";
+					marvell,function = "nand";
+				};
+
+				sdio_pins: sdio-pins {
+					marvell,pins = "mpp24",  "mpp25", "mpp26",
+						     "mpp27", "mpp28", "mpp29";
+					marvell,function = "sd";
+				};
+
+				spi0_pins: spi0-pins {
+					marvell,pins = "mpp0",  "mpp1", "mpp4",
+						     "mpp5", "mpp8", "mpp9";
+					marvell,function = "spi0";
+				};
+			};
+
+			gpio0: gpio@18100 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18100 0x40>;
+				ngpios = <32>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			gpio1: gpio@18140 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18140 0x40>;
+				ngpios = <32>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			gpio2: gpio@18180 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18180 0x40>;
+				ngpios = <3>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			system-controller@18200 {
+				compatible = "marvell,armada-375-system-controller";
+				reg = <0x18200 0x100>;
+			};
+
+			gateclk: clock-gating-control@18220 {
+				compatible = "marvell,armada-375-gating-clock";
+				reg = <0x18220 0x4>;
+				clocks = <&coreclk 0>;
+				#clock-cells = <1>;
+			};
+
+			usbcluster: usb-cluster@18400 {
+				compatible = "marvell,armada-375-usb-cluster";
+				reg = <0x18400 0x4>;
+				#phy-cells = <1>;
+			};
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			mpic: interrupt-controller@20a00 {
+				compatible = "marvell,mpic";
+				reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+				#interrupt-cells = <1>;
+				#size-cells = <1>;
+				interrupt-controller;
+				msi-controller;
+				interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			timer@20300 {
+				compatible = "marvell,armada-375-timer", "marvell,armada-370-timer";
+				reg = <0x20300 0x30>, <0x21040 0x30>;
+				interrupts-extended = <&gic  GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+						      <&mpic 5>,
+						      <&mpic 6>;
+				clocks = <&coreclk 0>, <&refclk>;
+				clock-names = "nbclk", "fixed";
+			};
+
+			watchdog@20300 {
+				compatible = "marvell,armada-375-wdt";
+				reg = <0x20300 0x34>, <0x20704 0x4>, <0x18254 0x4>;
+				clocks = <&coreclk 0>, <&refclk>;
+				clock-names = "nbclk", "fixed";
+			};
+
+			cpurst@20800 {
+				compatible = "marvell,armada-370-cpu-reset";
+				reg = <0x20800 0x10>;
+			};
+
+			coherency-fabric@21010 {
+				compatible = "marvell,armada-375-coherency-fabric";
+				reg = <0x21010 0x1c>;
+			};
+
+			usb@50000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x50000 0x500>;
+				interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 18>;
+				phys = <&usbcluster PHY_TYPE_USB2>;
+				phy-names = "usb";
+				status = "disabled";
+			};
+
+			usb@54000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x54000 0x500>;
+				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 26>;
+				status = "disabled";
+			};
+
+			usb3@58000 {
+				compatible = "marvell,armada-375-xhci";
+				reg = <0x58000 0x20000>,<0x5b880 0x80>;
+				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 16>;
+				phys = <&usbcluster PHY_TYPE_USB3>;
+				phy-names = "usb";
+				status = "disabled";
+			};
+
+			xor@60800 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60800 0x100
+				       0x60A00 0x100>;
+				clocks = <&gateclk 22>;
+				status = "okay";
+
+				xor00 {
+					interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor01 {
+					interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			xor@60900 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+				clocks = <&gateclk 23>;
+				status = "okay";
+
+				xor10 {
+					interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor11 {
+					interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			crypto@90000 {
+				compatible = "marvell,armada-375-crypto";
+				reg = <0x90000 0x10000>;
+				reg-names = "regs";
+				interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 30>, <&gateclk 31>,
+					 <&gateclk 28>, <&gateclk 29>;
+				clock-names = "cesa0", "cesa1",
+					      "cesaz0", "cesaz1";
+				marvell,crypto-srams = <&crypto_sram0>,
+						       <&crypto_sram1>;
+				marvell,crypto-sram-size = <0x800>;
+			};
+
+			sata@a0000 {
+				compatible = "marvell,orion-sata";
+				reg = <0xa0000 0x5000>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 14>, <&gateclk 20>;
+				clock-names = "0", "1";
+				status = "disabled";
+			};
+
+			nand@d0000 {
+				compatible = "marvell,armada370-nand";
+				reg = <0xd0000 0x54>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 11>;
+				status = "disabled";
+			};
+
+			mvsdio@d4000 {
+				compatible = "marvell,orion-sdio";
+				reg = <0xd4000 0x200>;
+				interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 17>;
+				bus-width = <4>;
+				cap-sdio-irq;
+				cap-sd-highspeed;
+				cap-mmc-highspeed;
+				status = "disabled";
+			};
+
+			thermal@e8078 {
+				compatible = "marvell,armada375-thermal";
+				reg = <0xe8078 0x4>, <0xe807c 0x8>;
+				status = "okay";
+			};
+
+			coreclk: mvebu-sar@e8204 {
+				compatible = "marvell,armada-375-core-clock";
+				reg = <0xe8204 0x04>;
+				#clock-cells = <1>;
+			};
+
+			coredivclk: corediv-clock@e8250 {
+				compatible = "marvell,armada-375-corediv-clock";
+				reg = <0xe8250 0xc>;
+				#clock-cells = <1>;
+				clocks = <&mainpll>;
+				clock-output-names = "nand";
+			};
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-370-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0 MEM */
+				0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0 IO  */
+				0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 1 MEM */
+				0x81000000 0x2 0       MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 1 IO  */>;
+
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <1>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+
+		};
+
+		crypto_sram0: sa-sram0 {
+			compatible = "mmio-sram";
+			reg = <MBUS_ID(0x09, 0x09) 0 0x800>;
+			clocks = <&gateclk 30>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0x09, 0x09) 0 0x800>;
+		};
+
+		crypto_sram1: sa-sram1 {
+			compatible = "mmio-sram";
+			reg = <MBUS_ID(0x09, 0x05) 0 0x800>;
+			clocks = <&gateclk 31>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>;
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
new file mode 100644
index 0000000..a1052ad
--- /dev/null
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -0,0 +1,341 @@
+/*
+ * Device Tree Include file for Marvell Armada 37xx family of SoCs.
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/comphy/comphy_data.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Marvell Armada 37xx SoC";
+	compatible = "marvell,armada3700";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0>;
+			enable-method = "psci";
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		internal-regs {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			/* 32M internal register @ 0xd000_0000 */
+			ranges = <0x0 0x0 0xd0000000 0x2000000>;
+
+			uart0: serial@12000 {
+				compatible = "marvell,armada-3700-uart";
+				reg = <0x12000 0x400>;
+				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			wdt: watchdog-timer@8300 {
+				compatible = "marvell,armada-3700-wdt";
+				reg = <0xd064 0x4>,
+				      <0x8300 0x40>;
+			};
+
+			nb_periph_clk: nb-periph-clk@13000 {
+				compatible = "marvell,armada-3700-periph-clock-nb";
+				reg = <0x13000 0x100>;
+				clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>;
+				#clock-cells = <1>;
+			};
+
+			sb_periph_clk: sb-periph-clk@18000 {
+				compatible = "marvell,armada-3700-periph-clock-sb";
+				reg = <0x18000 0x100>;
+				clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>;
+				#clock-cells = <1>;
+			};
+
+			tbg: tbg@13200 {
+				compatible = "marvell,armada-3700-tbg-clock";
+				reg = <0x13200 0x100>;
+				#clock-cells = <1>;
+			};
+
+			pinctrl_nb: pinctrl-nb@13800 {
+				compatible = "marvell,armada3710-nb-pinctrl",
+				"syscon", "simple-mfd";
+				reg = <0x13800 0x100>, <0x13C00 0x20>;
+				gpionb: gpionb {
+					#gpio-cells = <2>;
+					gpio-ranges = <&pinctrl_nb 0 0 36>;
+					gpio-controller;
+					interrupts =
+					<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+
+				};
+
+				spi_quad_pins: spi-quad-pins {
+					groups = "spi_quad";
+					function = "spi";
+				};
+
+				i2c1_pins: i2c1-pins {
+					groups = "i2c1";
+					function = "i2c";
+				};
+
+				i2c2_pins: i2c2-pins {
+					groups = "i2c2";
+					function = "i2c";
+				};
+
+				uart1_pins: uart1-pins {
+					groups = "uart1";
+					function = "uart";
+				};
+
+				uart2_pins: uart2-pins {
+					groups = "uart2";
+					function = "uart";
+				};
+
+				mmc_pins: mmc-pins {
+					groups = "emmc_nb";
+					function = "emmc";
+				};
+			};
+
+			pinctrl_sb: pinctrl-sb@18800 {
+				compatible = "marvell,armada3710-sb-pinctrl",
+				"syscon", "simple-mfd";
+				reg = <0x18800 0x100>, <0x18C00 0x20>;
+				gpiosb: gpiosb {
+					#gpio-cells = <2>;
+					gpio-ranges = <&pinctrl_sb 0 0 30>;
+					gpio-controller;
+					interrupts =
+					<GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+				};
+
+				rgmii_pins: mii-pins {
+					groups = "rgmii";
+					function = "mii";
+				};
+
+				smi_pins: smi-pins {
+					groups = "smi";
+					function = "smi";
+				};
+
+				sdio_pins: sdio-pins {
+					groups = "sdio_sb";
+					function = "sdio";
+				};
+
+				pcie_pins: pcie-pins {
+					groups = "pcie1";
+					function = "gpio";
+				};
+			};
+
+			usb3: usb@58000 {
+				compatible = "marvell,armada3700-xhci",
+				"generic-xhci";
+				reg = <0x58000 0x4000>;
+				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			usb2: usb@5e000 {
+				compatible = "marvell,armada3700-ehci";
+				reg = <0x5e000 0x450>;
+				status = "disabled";
+			};
+
+			xor@60900 {
+				compatible = "marvell,armada-3700-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+
+				xor10 {
+					interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+				};
+				xor11 {
+					interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+				};
+			};
+
+			sdhci0: sdhci@d0000 {
+				compatible = "marvell,armada-3700-sdhci",
+				"marvell,sdhci-xenon";
+				reg = <0xd0000 0x300
+				       0x1e808 0x4>;
+				status = "disabled";
+			};
+
+			sdhci1: sdhci@d8000 {
+				compatible = "marvell,armada-3700-sdhci",
+				"marvell,sdhci-xenon";
+				reg = <0xd8000 0x300
+				       0x17808 0x4>;
+				status = "disabled";
+			};
+
+			sata: sata@e0000 {
+				compatible = "marvell,armada-3700-ahci";
+				reg = <0xe0000 0x2000>;
+				interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			gic: interrupt-controller@1d00000 {
+				compatible = "arm,gic-v3";
+				#interrupt-cells = <3>;
+				interrupt-controller;
+				reg = <0x1d00000 0x10000>, /* GICD */
+				      <0x1d40000 0x40000>; /* GICR */
+			};
+
+			eth0: neta@30000 {
+				compatible = "marvell,armada-3700-neta";
+				reg = <0x30000 0x20>;
+				status = "disabled";
+			};
+
+			eth1: neta@40000 {
+				compatible = "marvell,armada-3700-neta";
+				reg = <0x40000 0x20>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@11000 {
+				compatible = "marvell,armada-3700-i2c";
+				reg = <0x11000 0x100>;
+				status = "disabled";
+			};
+
+			spi0: spi@10600 {
+				compatible = "marvell,armada-3700-spi";
+				reg = <0x10600 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#clock-cells = <0>;
+				spi-max-frequency = <50000000>;
+				clocks = <&nb_periph_clk 7>;
+				status = "disabled";
+			};
+
+			comphy: comphy@18300 {
+				compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700";
+				reg = <0x18300 0x28>,
+				      <0x1f300 0x3d000>;
+				mux-bitcount = <4>;
+				mux-lane-order = <1 0 2>;
+				max-lanes = <3>;
+			};
+		};
+
+		pcie0: pcie@d0070000 {
+			compatible = "marvell,armada-37xx-pcie";
+			reg = <0 0xd0070000 0 0x20000>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			num-lanes = <1>;
+			status = "disabled";
+
+			bus-range = <0 0xff>;
+			ranges = <0x82000000 0 0xe8000000
+				 0 0xe8000000 0 0x1000000 /* Port 0 MEM */
+				 0x81000000 0 0xe9000000
+				 0 0xe9000000 0 0x10000>; /* Port 0 IO*/
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-380.dtsi b/arch/arm/dts/armada-380.dtsi
new file mode 100644
index 0000000..5102d19
--- /dev/null
+++ b/arch/arm/dts/armada-380.dtsi
@@ -0,0 +1,152 @@
+/*
+ * Device Tree Include file for Marvell Armada 380 SoC.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-38x.dtsi"
+
+/ {
+	model = "Marvell Armada 380 family SoC";
+	compatible = "marvell,armada380";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "marvell,armada-380-smp";
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+	};
+
+	soc {
+		internal-regs {
+			pinctrl@18000 {
+				compatible = "marvell,mv88f6810-pinctrl";
+			};
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-370-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+				0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 1 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 1 IO  */
+				0x82000000 0x3 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 2 MEM */
+				0x81000000 0x3 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 2 IO  */>;
+
+			/* x1 port */
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 8>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@3,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <2>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-385-amc.dts b/arch/arm/dts/armada-385-amc.dts
new file mode 100644
index 0000000..d4d127f
--- /dev/null
+++ b/arch/arm/dts/armada-385-amc.dts
@@ -0,0 +1,166 @@
+/*
+ * Device Tree file for Marvell Armada 385 development board
+ * (DB-88F6820-AMC)
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "armada-385.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Marvell Armada 385 AMC";
+	compatible = "marvell,a385-amc", "marvell,armada385", "marvell,armada380";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth2;
+		i2c0 = &i2c0;
+		spi1 = &spi1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000>; /* 2 GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			i2c@11000 {
+				clock-frequency = <100000>;
+				u-boot,i2c-slave-addr = <0x0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c0_pins>;
+				status = "okay";
+			};
+
+			serial@12000 {
+				/*
+				 * Exported on the micro USB connector CON16
+				 * through an FTDI
+				 */
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart0_pins>;
+				status = "okay";
+				u-boot,dm-pre-reloc;
+			};
+
+			ethernet@34000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "sgmii";
+			};
+
+			usb@58000 {
+				status = "okay";
+			};
+
+			ethernet@70000 {
+				pinctrl-names = "default";
+				/*
+				 * The Reference Clock 0 is used to provide a
+				 * clock to the PHY
+				 */
+				pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>;
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii-id";
+			};
+
+
+			mdio@72004 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&mdio_pins>;
+
+				phy0: ethernet-phy@1 {
+					reg = <1>;
+				};
+
+				phy1: ethernet-phy@0 {
+					reg = <0>;
+				};
+			};
+
+			flash@d0000 {
+				status = "okay";
+				num-cs = <1>;
+				marvell,nand-keep-config;
+				marvell,nand-enable-arbiter;
+				nand-on-flash-bbt;
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+		};
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins>;
+	status = "okay";
+	u-boot,dm-pre-reloc;
+
+	spi-flash@0 {
+		u-boot,dm-pre-reloc;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p128", "jedec,spi-nor", "spi-flash";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+	};
+};
+
+&refclk {
+	clock-frequency = <20000000>;
+};
diff --git a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
new file mode 100644
index 0000000..904429b
--- /dev/null
+++ b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ */
+
+/ {
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2cmux;
+		spi0 = &spi0;
+	};
+};
+
+&i2c0 {
+	u-boot,dm-pre-reloc;
+
+	i2cmux: i2cmux@70 {
+		u-boot,dm-pre-reloc;
+
+		i2c@0 {
+			u-boot,dm-pre-reloc;
+		};
+
+		i2c@1 {
+			u-boot,dm-pre-reloc;
+		};
+
+		i2c@5 {
+			u-boot,dm-pre-reloc;
+
+			/* ATSHA204A at address 0x64 */
+			atsha204a@64 {
+				u-boot,dm-pre-reloc;
+				compatible = "atmel,atsha204a";
+				reg = <0x64>;
+			};
+		};
+	};
+};
+
+&spi0 {
+	u-boot,dm-pre-reloc;
+
+	spi-flash@0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/armada-385-turris-omnia.dts b/arch/arm/dts/armada-385-turris-omnia.dts
new file mode 100644
index 0000000..28eede1
--- /dev/null
+++ b/arch/arm/dts/armada-385-turris-omnia.dts
@@ -0,0 +1,392 @@
+/*
+ * Device Tree file for the Turris Omnia
+ *
+ * Copyright (C) 2016 Uwe Kleine-König <uwe@kleine-koenig.org>
+ * Copyright (C) 2016 Tomas Hlavacek <tmshlvkc@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "armada-385.dtsi"
+
+/ {
+	model = "Turris Omnia";
+	compatible = "cznic,turris-omnia", "marvell,armada385", "marvell,armada380";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>; /* 1024 MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
+
+		internal-regs {
+
+			/* USB part of the PCIe2/USB 2.0 port */
+			usb@58000 {
+				status = "okay";
+			};
+
+			sata@a8000 {
+				status = "okay";
+			};
+
+			sdhci@d8000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&sdhci_pins>;
+				status = "okay";
+
+				bus-width = <8>;
+				no-1-8-v;
+				non-removable;
+			};
+
+			usb3@f0000 {
+				status = "okay";
+			};
+
+			usb3@f8000 {
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+
+			pcie@3,0 {
+				/* Port 2, Lane 0 */
+				status = "okay";
+			};
+		};
+	};
+};
+
+/* Connected to 88E6176 switch, port 6 */
+&eth0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ge0_rgmii_pins>;
+	status = "okay";
+	phy-mode = "rgmii";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+/* Connected to 88E6176 switch, port 5 */
+&eth1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ge1_rgmii_pins>;
+	status = "okay";
+	phy-mode = "rgmii";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+/* WAN port */
+&eth2 {
+	status = "okay";
+	phy-mode = "sgmii";
+	phy = <&phy1>;
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	i2cmux@70 {
+		compatible = "nxp,pca9547";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+		status = "okay";
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			/* STM32F0 command interface at address 0x2a */
+			/* leds device (in STM32F0) at address 0x2b */
+
+			eeprom@54 {
+				compatible = "at,24c64";
+				reg = <0x54>;
+
+				/* The EEPROM contains data for bootloader.
+				 * Contents:
+				 * 	struct omnia_eeprom {
+				 * 		u32 magic; (=0x0341a034 in LE)
+				 *		u32 ramsize; (in GiB)
+				 * 		char regdomain[4];
+				 * 		u32 crc32;
+				 * 	};
+				 */
+			};
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			/* routed to PCIe0/mSATA connector (CN7A) */
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+
+			/* routed to PCIe1/USB2 connector (CN61A) */
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			/* routed to PCIe2 connector (CN62A) */
+		};
+
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+
+			/* routed to SFP+ */
+		};
+
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+
+			/* ATSHA204A at address 0x64 */
+		};
+
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+
+			/* exposed on pin header */
+		};
+
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+
+			pcawan: gpio@71 {
+				/*
+				 * GPIO expander for SFP+ signals and
+				 * and phy irq
+				 */
+				compatible = "nxp,pca9538";
+				reg = <0x71>;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&pcawan_pins>;
+
+				interrupt-parent = <&gpio1>;
+				interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+		};
+	};
+};
+
+&mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio_pins>;
+	status = "okay";
+
+	phy1: phy@1 {
+		status = "okay";
+		compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+
+		/* irq is connected to &pcawan pin 7 */
+	};
+
+	/* Switch MV88E6176 at address 0x10 */
+	switch@10 {
+		compatible = "marvell,mv88e6085";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		dsa,member = <0 0>;
+
+		reg = <0x10>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			ports@0 {
+				reg = <0>;
+				label = "lan0";
+			};
+
+			ports@1 {
+				reg = <1>;
+				label = "lan1";
+			};
+
+			ports@2 {
+				reg = <2>;
+				label = "lan2";
+			};
+
+			ports@3 {
+				reg = <3>;
+				label = "lan3";
+			};
+
+			ports@4 {
+				reg = <4>;
+				label = "lan4";
+			};
+
+			ports@5 {
+				reg = <5>;
+				label = "cpu";
+				ethernet = <&eth1>;
+				phy-mode = "rgmii-id";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+
+			/* port 6 is connected to eth0 */
+		};
+	};
+};
+
+&pinctrl {
+	pcawan_pins: pcawan-pins {
+		marvell,pins = "mpp46";
+		marvell,function = "gpio";
+	};
+
+	spi0cs0_pins: spi0cs0-pins {
+		marvell,pins = "mpp25";
+		marvell,function = "spi0";
+	};
+
+	spi0cs1_pins: spi0cs1-pins {
+		marvell,pins = "mpp26";
+		marvell,function = "spi0";
+	};
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins &spi0cs0_pins>;
+	status = "okay";
+
+	spi-nor@0 {
+		compatible = "spansion,s25fl164k", "jedec,spi-nor";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				reg = <0x0 0x00100000>;
+				label = "U-Boot";
+			};
+
+			partition@100000 {
+				reg = <0x00100000 0x00700000>;
+				label = "Rescue system";
+			};
+		};
+	};
+
+	/* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */
+};
+
+&uart0 {
+	/* Pin header CN10 */
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&uart1 {
+	/* Pin header CN11 */
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/armada-385.dtsi b/arch/arm/dts/armada-385.dtsi
new file mode 100644
index 0000000..8e67d2c
--- /dev/null
+++ b/arch/arm/dts/armada-385.dtsi
@@ -0,0 +1,184 @@
+/*
+ * Device Tree Include file for Marvell Armada 385 SoC.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-38x.dtsi"
+
+/ {
+	model = "Marvell Armada 385 family SoC";
+	compatible = "marvell,armada385", "marvell,armada380";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "marvell,armada-380-smp";
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	soc {
+		internal-regs {
+			pinctrl@18000 {
+				compatible = "marvell,mv88f6820-pinctrl";
+			};
+		};
+
+		pcie-controller {
+			compatible = "marvell,armada-370-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+				0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 1 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 1 IO  */
+				0x82000000 0x3 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 2 MEM */
+				0x81000000 0x3 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 2 IO  */
+				0x82000000 0x4 0     MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 3 MEM */
+				0x81000000 0x4 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 3 IO  */>;
+
+			/*
+			 * This port can be either x4 or x1. When
+			 * configured in x4 by the bootloader, then
+			 * pcie@4,0 is not available.
+			 */
+			pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 8>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+
+			/* x1 port */
+			pcie@3,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				reg = <0x1800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+					  0x81000000 0 0 0x81000000 0x3 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <2>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 6>;
+				status = "disabled";
+			};
+
+			/*
+			 * x1 port only available when pcie@1,0 is
+			 * configured as a x1 port
+			 */
+			pcie@4,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				reg = <0x2000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
+					  0x81000000 0 0 0x81000000 0x4 0 1 0>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+				marvell,pcie-port = <3>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 7>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-388-clearfog-u-boot.dtsi b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
new file mode 100644
index 0000000..f31691e
--- /dev/null
+++ b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+&spi1 {
+	u-boot,dm-spl;
+
+	spi-flash@0 {
+		u-boot,dm-spl;
+	};
+};
diff --git a/arch/arm/dts/armada-388-clearfog.dts b/arch/arm/dts/armada-388-clearfog.dts
new file mode 100644
index 0000000..16a47d5
--- /dev/null
+++ b/arch/arm/dts/armada-388-clearfog.dts
@@ -0,0 +1,374 @@
+/*
+ * Device Tree file for SolidRun Clearfog revision A1 rev 2.0 (88F6828)
+ *
+ *  Copyright (C) 2015 Russell King
+ *
+ * This board is in development; the contents of this file work with
+ * the A1 rev 2.0 of the board, which does not represent final
+ * production board.  Things will change, don't expect this file to
+ * remain compatible info the future.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-388.dtsi"
+#include "armada-38x-solidrun-microsom.dtsi"
+
+/ {
+	model = "SolidRun Clearfog A1";
+	compatible = "solidrun,clearfog-a1", "marvell,armada388",
+		"marvell,armada385", "marvell,armada380";
+
+	aliases {
+		/* So that mvebu u-boot can update the MAC addresses */
+		ethernet1 = &eth0;
+		ethernet2 = &eth1;
+		ethernet3 = &eth2;
+		spi1 = &spi1;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	soc {
+		internal-regs {
+			rtc@a3800 {
+				/*
+				 * If the rtc doesn't work, run "date reset"
+				 * twice in u-boot.
+				 */
+				status = "okay";
+			};
+
+			sata@a8000 {
+				/* pinctrl? */
+				status = "okay";
+			};
+
+			sata@e0000 {
+				/* pinctrl? */
+				status = "okay";
+			};
+
+			sdhci@d8000 {
+				bus-width = <4>;
+				cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
+				no-1-8-v;
+				pinctrl-0 = <&microsom_sdhci_pins
+					     &clearfog_sdhci_cd_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				vmmc = <&reg_3p3v>;
+				wp-inverted;
+			};
+
+			serial@12100 {
+				/* mikrobus uart */
+				pinctrl-0 = <&mikro_uart_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+			};
+
+			spi1: spi@10680 {
+				/*
+				 * CS0: W25Q32
+				 * CS1:
+				 * CS2: mikrobus
+				 */
+				pinctrl-0 = <&spi1_pins &clearfog_spi1_cs_pins &mikro_spi_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+			};
+
+			usb0: usb3@f8000 {
+				/* CON7, USB-A port on back of device */
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * the mini-PCIe connectors on the board.
+			 */
+			pcie@2,0 {
+				/* Port 1, Lane 0. CONN3, nearest power. */
+				reset-gpios = <&expander0 1 GPIO_ACTIVE_LOW>;
+				status = "okay";
+			};
+			pcie@3,0 {
+				/* Port 2, Lane 0. CONN2, nearest CPU. */
+				reset-gpios = <&expander0 2 GPIO_ACTIVE_LOW>;
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&rear_button_pins>;
+		pinctrl-names = "default";
+
+		button_0 {
+			/* The rear SW3 button */
+			label = "Rear Button";
+			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+			linux,can-disable;
+			linux,code = <BTN_0>;
+		};
+	};
+};
+
+&w25q32 {
+	status = "okay";
+};
+
+&eth1 {
+	managed = "in-band-status";
+	phy-mode = "sgmii";
+	status = "okay";
+};
+
+&eth2 {
+	phy-mode = "sgmii";
+	status = "okay";
+};
+
+&i2c0 {
+	clock-frequency = <400000>;
+	pinctrl-0 = <&i2c0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	/*
+	 * PCA9655 GPIO expander, up to 1MHz clock.
+	 *  0-CON3 CLKREQ#
+	 *  1-CON3 PERST#
+	 *  2-CON2 PERST#
+	 *  3-CON3 W_DISABLE
+	 *  4-CON2 CLKREQ#
+	 *  5-USB3 overcurrent
+	 *  6-USB3 power
+	 *  7-CON2 W_DISABLE
+	 *  8-JP4 P1
+	 *  9-JP4 P4
+	 * 10-JP4 P5
+	 * 11-m.2 DEVSLP
+	 * 12-SFP_LOS
+	 * 13-SFP_TX_FAULT
+	 * 14-SFP_TX_DISABLE
+	 * 15-SFP_MOD_DEF0
+	 */
+	expander0: gpio-expander@20 {
+		/*
+		 * This is how it should be:
+		 * compatible = "onnn,pca9655",
+		 *	 "nxp,pca9555";
+		 * but you can't do this because of
+		 * the way I2C works.
+		 */
+		compatible = "nxp,pca9555";
+		gpio-controller;
+		#gpio-cells = <2>;
+		reg = <0x20>;
+
+		pcie1_0_clkreq {
+			gpio-hog;
+			gpios = <0 GPIO_ACTIVE_LOW>;
+			input;
+			line-name = "pcie1.0-clkreq";
+		};
+		pcie1_0_w_disable {
+			gpio-hog;
+			gpios = <3 GPIO_ACTIVE_LOW>;
+			output-low;
+			line-name = "pcie1.0-w-disable";
+		};
+		pcie2_0_clkreq {
+			gpio-hog;
+			gpios = <4 GPIO_ACTIVE_LOW>;
+			input;
+			line-name = "pcie2.0-clkreq";
+		};
+		pcie2_0_w_disable {
+			gpio-hog;
+			gpios = <7 GPIO_ACTIVE_LOW>;
+			output-low;
+			line-name = "pcie2.0-w-disable";
+		};
+		usb3_ilimit {
+			gpio-hog;
+			gpios = <5 GPIO_ACTIVE_LOW>;
+			input;
+			line-name = "usb3-current-limit";
+		};
+		usb3_power {
+			gpio-hog;
+			gpios = <6 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "usb3-power";
+		};
+		m2_devslp {
+			gpio-hog;
+			gpios = <11 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "m.2 devslp";
+		};
+	};
+
+	mikrobus_adc: mcp3021@4c {
+		compatible = "microchip,mcp3021";
+		reg = <0x4c>;
+	};
+};
+
+&i2c1 {
+	/*
+	 * Routed to SFP, mikrobus, and PCIe.
+	 * SFP limits this to 100kHz, and requires
+	 *  an AT24C01A/02/04 with address pins tied
+	 *  low, which takes addresses 0x50 and 0x51.
+	 * Mikrobus doesn't specify beyond an I2C
+	 *  bus being present.
+	 * PCIe uses ARP to assign addresses, or
+	 *  0x63-0x64.
+	 */
+	clock-frequency = <100000>;
+	pinctrl-0 = <&clearfog_i2c1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&pinctrl {
+	clearfog_i2c1_pins: i2c1-pins {
+		/* SFP, PCIe, mSATA, mikrobus */
+		marvell,pins = "mpp26", "mpp27";
+		marvell,function = "i2c1";
+	};
+	clearfog_sdhci_cd_pins: clearfog-sdhci-cd-pins {
+		marvell,pins = "mpp20";
+		marvell,function = "gpio";
+	};
+	clearfog_spi1_cs_pins: spi1-cs-pins {
+		marvell,pins = "mpp55";
+		marvell,function = "spi1";
+	};
+	mikro_pins: mikro-pins {
+		/* int: mpp22 rst: mpp29 */
+		marvell,pins = "mpp22", "mpp29";
+		marvell,function = "gpio";
+	};
+	mikro_spi_pins: mikro-spi-pins {
+		marvell,pins = "mpp43";
+		marvell,function = "spi1";
+	};
+	mikro_uart_pins: mikro-uart-pins {
+		marvell,pins = "mpp24", "mpp25";
+		marvell,function = "ua1";
+	};
+	rear_button_pins: rear-button-pins {
+		marvell,pins = "mpp34";
+		marvell,function = "gpio";
+	};
+};
+
+/*
++#define A38x_CUSTOMER_BOARD_1_MPP16_23         0x00400011
+MPP18: gpio		? (pca9655 int?)
+MPP19: gpio		? (clkreq?)
+MPP20: gpio		? (sd0 detect)
+MPP21: sd0:cmd		x sd0
+MPP22: gpio		x mikro int
+MPP23: gpio		x switch irq
++#define A38x_CUSTOMER_BOARD_1_MPP24_31         0x22043333
+MPP24: ua1:rxd		x mikro rx
+MPP25: ua1:txd		x mikro tx
+MPP26: i2c1:sck		x mikro sck
+MPP27: i2c1:sda		x mikro sda
+MPP28: sd0:clk		x sd0
+MPP29: gpio		x mikro rst
+MPP30: ge1:txd2		? (config)
+MPP31: ge1:txd3		? (config)
++#define A38x_CUSTOMER_BOARD_1_MPP32_39         0x44400002
+MPP32: ge1:txctl	? (unused)
+MPP33: gpio		? (pic_com0)
+MPP34: gpio		x rear button (pic_com1)
+MPP35: gpio		? (pic_com2)
+MPP36: gpio		? (unused)
+MPP37: sd0:d3		x sd0
+MPP38: sd0:d0		x sd0
+MPP39: sd0:d1		x sd0
++#define A38x_CUSTOMER_BOARD_1_MPP40_47         0x41144004
+MPP40: sd0:d2		x sd0
+MPP41: gpio		x switch reset
+MPP42: gpio		? sw1-1
+MPP43: spi1:cs2		x mikro cs
+MPP44: sata3:prsnt	? (unused)
+MPP45: ref:clk_out0	?
+MPP46: ref:clk_out1	x switch clk
+MPP47: 4		? (unused)
++#define A38x_CUSTOMER_BOARD_1_MPP48_55         0x40333333
+MPP48: tdm:pclk
+MPP49: tdm:fsync
+MPP50: tdm:drx
+MPP51: tdm:dtx
+MPP52: tdm:int
+MPP53: tdm:rst
+MPP54: gpio		? (pwm)
+MPP55: spi1:cs1		x slic
++#define A38x_CUSTOMER_BOARD_1_MPP56_63         0x00004444
+MPP56: spi1:mosi	x mikro mosi
+MPP57: spi1:sck		x mikro sck
+MPP58: spi1:miso	x mikro miso
+MPP59: spi1:cs0		x w25q32
+*/
diff --git a/arch/arm/dts/armada-388-gp.dts b/arch/arm/dts/armada-388-gp.dts
new file mode 100644
index 0000000..7bc878f
--- /dev/null
+++ b/arch/arm/dts/armada-388-gp.dts
@@ -0,0 +1,422 @@
+/*
+ * Device Tree file for Marvell Armada 385 development board
+ * (RD-88F6820-GP)
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "armada-388.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Marvell Armada 385 GP";
+	compatible = "marvell,a385-gp", "marvell,armada388", "marvell,armada380";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000>; /* 2 GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			spi@10600 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi0_pins>;
+				status = "okay";
+				u-boot,dm-pre-reloc;
+
+				spi-flash@0 {
+					u-boot,dm-pre-reloc;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "st,m25p128", "jedec,spi-nor";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <50000000>;
+					m25p,fast-read;
+				};
+			};
+
+			i2c@11000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c0_pins>;
+				status = "okay";
+				clock-frequency = <100000>;
+				/*
+				 * The EEPROM located at adresse 54 is needed
+				 * for the boot - DO NOT ERASE IT -
+				 */
+
+				expander0: pca9555@20 {
+					compatible = "nxp,pca9555";
+					pinctrl-names = "default";
+					pinctrl-0 = <&pca0_pins>;
+					interrupt-parent = <&gpio0>;
+					interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					reg = <0x20>;
+				};
+
+				expander1: pca9555@21 {
+					compatible = "nxp,pca9555";
+					pinctrl-names = "default";
+					interrupt-parent = <&gpio0>;
+					interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+					gpio-controller;
+					#gpio-cells = <2>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					reg = <0x21>;
+				};
+
+			};
+
+			serial@12000 {
+				/*
+				 * Exported on the micro USB connector CON16
+				 * through an FTDI
+				 */
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart0_pins>;
+				status = "okay";
+				u-boot,dm-pre-reloc;
+			};
+
+			/* GE1 CON15 */
+			ethernet@30000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&ge1_rgmii_pins>;
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "rgmii-id";
+			};
+
+			/* CON4 */
+			usb@58000 {
+				vcc-supply = <&reg_usb2_0_vbus>;
+				status = "okay";
+			};
+
+			/* GE0 CON1 */
+			ethernet@70000 {
+				pinctrl-names = "default";
+				/*
+				 * The Reference Clock 0 is used to provide a
+				 * clock to the PHY
+				 */
+				pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>;
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii-id";
+			};
+
+
+			mdio@72004 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&mdio_pins>;
+
+				phy0: ethernet-phy@1 {
+					reg = <1>;
+				};
+
+				phy1: ethernet-phy@0 {
+					reg = <0>;
+				};
+			};
+
+			sata@a8000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&sata0_pins>, <&sata1_pins>;
+				status = "okay";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sata0: sata-port@0 {
+					reg = <0>;
+					target-supply = <&reg_5v_sata0>;
+				};
+
+				sata1: sata-port@1 {
+					reg = <1>;
+					target-supply = <&reg_5v_sata1>;
+				};
+			};
+
+			sata@e0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&sata2_pins>, <&sata3_pins>;
+				status = "okay";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sata2: sata-port@0 {
+					reg = <0>;
+					target-supply = <&reg_5v_sata2>;
+				};
+
+				sata3: sata-port@1 {
+					reg = <1>;
+					target-supply = <&reg_5v_sata3>;
+				};
+			};
+
+			sdhci@d8000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&sdhci_pins>;
+				cd-gpios = <&expander0 5 GPIO_ACTIVE_LOW>;
+				no-1-8-v;
+				wp-inverted;
+				bus-width = <8>;
+				status = "okay";
+			};
+
+			/* CON5 */
+			usb3@f0000 {
+				vcc-supply = <&reg_usb2_1_vbus>;
+				status = "okay";
+			};
+
+			/* CON7 */
+			usb3@f8000 {
+				vcc-supply = <&reg_usb3_vbus>;
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * One PCIe units is accessible through
+			 * standard PCIe slot on the board.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			/*
+			 * The two other PCIe units are accessible
+			 * through mini PCIe slot on the board.
+			 */
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+			pcie@3,0 {
+				/* Port 2, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		gpio-fan {
+			compatible = "gpio-fan";
+			gpios = <&expander1 3 GPIO_ACTIVE_HIGH>;
+			gpio-fan,speed-map = <	 0 0
+					      3000 1>;
+		};
+	};
+
+	reg_usb3_vbus: usb3-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb3-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&expander1 15 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_usb2_0_vbus: v5-vbus0 {
+		compatible = "regulator-fixed";
+		regulator-name = "v5.0-vbus0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&expander1 14 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_usb2_1_vbus: v5-vbus1 {
+		compatible = "regulator-fixed";
+		regulator-name = "v5.0-vbus1";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&expander0 4 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_usb2_1_vbus: v5-vbus1 {
+		compatible = "regulator-fixed";
+		regulator-name = "v5.0-vbus1";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&expander0 4 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_sata0: pwr-sata0 {
+		compatible = "regulator-fixed";
+		regulator-name = "pwr_en_sata0";
+		enable-active-high;
+		regulator-always-on;
+
+	};
+
+	reg_5v_sata0: v5-sata0 {
+		compatible = "regulator-fixed";
+		regulator-name = "v5.0-sata0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata0>;
+	};
+
+	reg_12v_sata0: v12-sata0 {
+		compatible = "regulator-fixed";
+		regulator-name = "v12.0-sata0";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata0>;
+	};
+
+	reg_sata1: pwr-sata1 {
+		regulator-name = "pwr_en_sata1";
+		compatible = "regulator-fixed";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&expander0 3 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_5v_sata1: v5-sata1 {
+		compatible = "regulator-fixed";
+		regulator-name = "v5.0-sata1";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata1>;
+	};
+
+	reg_12v_sata1: v12-sata1 {
+		compatible = "regulator-fixed";
+		regulator-name = "v12.0-sata1";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata1>;
+	};
+
+	reg_sata2: pwr-sata2 {
+		compatible = "regulator-fixed";
+		regulator-name = "pwr_en_sata2";
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&expander0 11 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_5v_sata2: v5-sata2 {
+		compatible = "regulator-fixed";
+		regulator-name = "v5.0-sata2";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata2>;
+	};
+
+	reg_12v_sata2: v12-sata2 {
+		compatible = "regulator-fixed";
+		regulator-name = "v12.0-sata2";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata2>;
+	};
+
+	reg_sata3: pwr-sata3 {
+		compatible = "regulator-fixed";
+		regulator-name = "pwr_en_sata3";
+		enable-active-high;
+		regulator-always-on;
+		gpio = <&expander0 12 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_5v_sata3: v5-sata3 {
+		compatible = "regulator-fixed";
+		regulator-name = "v5.0-sata3";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata3>;
+	};
+
+	reg_12v_sata3: v12-sata3 {
+		compatible = "regulator-fixed";
+		regulator-name = "v12.0-sata3";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		vin-supply = <&reg_sata3>;
+	};
+};
+
+&pinctrl {
+	pca0_pins: pca0_pins {
+		marvell,pins = "mpp18";
+		marvell,function = "gpio";
+	};
+};
diff --git a/arch/arm/dts/armada-388-helios4-u-boot.dtsi b/arch/arm/dts/armada-388-helios4-u-boot.dtsi
new file mode 100644
index 0000000..4b20610
--- /dev/null
+++ b/arch/arm/dts/armada-388-helios4-u-boot.dtsi
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/ {
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		spi1 = &spi1;
+	};
+};
+
+&eth0 {
+	phy-reset-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>;
+};
+
+&spi1 {
+	u-boot,dm-spl;
+};
+
+&w25q32 {
+	status = "okay";
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/armada-388-helios4.dts b/arch/arm/dts/armada-388-helios4.dts
new file mode 100644
index 0000000..a154e0f
--- /dev/null
+++ b/arch/arm/dts/armada-388-helios4.dts
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device Tree file for Helios4
+ * based on SolidRun Clearfog revision A1 rev 2.0 (88F6828)
+ *
+ *  Copyright (C) 2017 Aditya Prayoga <aditya@kobol.io>
+ *
+ */
+
+/dts-v1/;
+#include "armada-388.dtsi"
+#include "armada-38x-solidrun-microsom.dtsi"
+
+/ {
+	model = "Helios4";
+	compatible = "kobol,helios4", "marvell,armada388",
+		"marvell,armada385", "marvell,armada380";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000>; /* 2 GB */
+	};
+
+	aliases {
+		/* So that mvebu u-boot can update the MAC addresses */
+		ethernet1 = &eth0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	reg_12v: regulator-12v {
+		compatible = "regulator-fixed";
+		regulator-name = "power_brick_12V";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		vin-supply = <&reg_12v>;
+	};
+
+	reg_5p0v_hdd: regulator-5v-hdd {
+		compatible = "regulator-fixed";
+		regulator-name = "5V_HDD";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&reg_12v>;
+	};
+
+	reg_5p0v_usb: regulator-5v-usb {
+		compatible = "regulator-fixed";
+		regulator-name = "USB-PWR";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+		regulator-always-on;
+		enable-active-high;
+		gpio = <&expander0 6 GPIO_ACTIVE_HIGH>;
+		vin-supply = <&reg_12v>;
+	};
+
+	system-leds {
+		compatible = "gpio-leds";
+		status-led {
+			label = "helios4:green:status";
+			gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+			default-state = "on";
+		};
+
+		fault-led {
+			label = "helios4:red:fault";
+			gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
+			default-state = "keep";
+		};
+	};
+
+	io-leds {
+		compatible = "gpio-leds";
+		sata1-led {
+			label = "helios4:green:ata1";
+			gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "ata1";
+			default-state = "off";
+		};
+		sata2-led {
+			label = "helios4:green:ata2";
+			gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "ata2";
+			default-state = "off";
+		};
+		sata3-led {
+			label = "helios4:green:ata3";
+			gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "ata3";
+			default-state = "off";
+		};
+		sata4-led {
+			label = "helios4:green:ata4";
+			gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "ata4";
+			default-state = "off";
+		};
+		usb-led {
+			label = "helios4:green:usb";
+			gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "usb-host";
+			default-state = "off";
+		};
+	};
+
+	fan1: j10-pwm {
+		compatible = "pwm-fan";
+		pwms = <&gpio1 9 40000>;	/* Target freq:25 kHz */
+	};
+
+	fan2: j17-pwm {
+		compatible = "pwm-fan";
+		pwms = <&gpio1 23 40000>;	/* Target freq:25 kHz */
+	};
+
+	usb2_phy: usb2-phy {
+		compatible = "usb-nop-xceiv";
+		vbus-regulator = <&reg_5p0v_usb>;
+	};
+
+	usb3_phy: usb3-phy {
+		compatible = "usb-nop-xceiv";
+	};
+
+	soc {
+		internal-regs {
+			i2c@11000 {
+				clock-frequency = <400000>;
+				pinctrl-0 = <&i2c0_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+
+				/*
+				 * PCA9655 GPIO expander, up to 1MHz clock.
+				 *  0-Board Revision bit 0 #
+				 *  1-Board Revision bit 1 #
+				 *  5-USB3 overcurrent
+				 *  6-USB3 power
+				 */
+				expander0: gpio-expander@20 {
+					/*
+					 * This is how it should be:
+					 * compatible = "onnn,pca9655",
+					 *	 "nxp,pca9555";
+					 * but you can't do this because of
+					 * the way I2C works.
+					 */
+					compatible = "nxp,pca9555";
+					gpio-controller;
+					#gpio-cells = <2>;
+					reg = <0x20>;
+					pinctrl-names = "default";
+					pinctrl-0 = <&pca0_pins>;
+					interrupt-parent = <&gpio0>;
+					interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+
+					board_rev_bit_0 {
+						gpio-hog;
+						gpios = <0 GPIO_ACTIVE_LOW>;
+						input;
+						line-name = "board-rev-0";
+					};
+					board_rev_bit_1 {
+						gpio-hog;
+						gpios = <1 GPIO_ACTIVE_LOW>;
+						input;
+						line-name = "board-rev-1";
+					};
+					usb3_ilimit {
+						gpio-hog;
+						gpios = <5 GPIO_ACTIVE_HIGH>;
+						input;
+						line-name =
+						"usb-overcurrent-status";
+					};
+				};
+
+				temp_sensor: temp@4c {
+					compatible = "ti,lm75";
+					reg = <0x4c>;
+					vcc-supply = <&reg_3p3v>;
+				};
+			};
+
+			i2c@11100 {
+				/*
+				 * External I2C Bus for user peripheral
+				 */
+				clock-frequency = <400000>;
+				pinctrl-0 = <&helios_i2c1_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+			};
+
+			sata@a8000 {
+				status = "okay";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sata0: sata-port@0 {
+					reg = <0>;
+				};
+
+				sata1: sata-port@1 {
+					reg = <1>;
+				};
+			};
+
+			sata@e0000 {
+				status = "okay";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sata2: sata-port@0 {
+					reg = <0>;
+				};
+
+				sata3: sata-port@1 {
+					reg = <1>;
+				};
+			};
+
+			spi@10680 {
+				pinctrl-0 = <&spi1_pins
+					     &microsom_spi1_cs_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+			};
+
+			sdhci@d8000 {
+				bus-width = <4>;
+				cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
+				no-1-8-v;
+				pinctrl-0 = <&microsom_sdhci_pins
+					     &helios_sdhci_cd_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				vmmc = <&reg_3p3v>;
+				wp-inverted;
+			};
+
+			usb@58000 {
+				usb-phy = <&usb2_phy>;
+				status = "okay";
+			};
+
+			usb3@f0000 {
+				status = "okay";
+			};
+
+			usb3@f8000 {
+				status = "okay";
+			};
+
+			pinctrl@18000 {
+				pca0_pins: pca0-pins {
+					marvell,pins = "mpp23";
+					marvell,function = "gpio";
+				};
+				microsom_phy0_int_pins: microsom-phy0-int-pins {
+					marvell,pins = "mpp18";
+					marvell,function = "gpio";
+				};
+				helios_i2c1_pins: i2c1-pins {
+					marvell,pins = "mpp26", "mpp27";
+					marvell,function = "i2c1";
+				};
+				helios_sdhci_cd_pins: helios-sdhci-cd-pins {
+					marvell,pins = "mpp20";
+					marvell,function = "gpio";
+				};
+				helios_led_pins: helios-led-pins {
+					marvell,pins = "mpp24", "mpp25",
+						       "mpp49", "mpp50",
+						       "mpp52", "mpp53",
+						       "mpp54";
+					marvell,function = "gpio";
+				};
+				helios_fan_pins: helios-fan-pins {
+					marvell,pins = "mpp41", "mpp43",
+						       "mpp48", "mpp55";
+					marvell,function = "gpio";
+				};
+				microsom_spi1_cs_pins: spi1-cs-pins {
+					marvell,pins = "mpp59";
+					marvell,function = "spi1";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-388.dtsi b/arch/arm/dts/armada-388.dtsi
new file mode 100644
index 0000000..564fa59
--- /dev/null
+++ b/arch/arm/dts/armada-388.dtsi
@@ -0,0 +1,70 @@
+/*
+ * Device Tree Include file for Marvell Armada 388 SoC.
+ *
+ * Copyright (C) 2015 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * The main difference with the Armada 385 is that the 388 can handle two more
+ * SATA ports. So we can reuse the dtsi of the Armada 385, override the pinctrl
+ * property and the name of the SoC, and add the second SATA host which control
+ * the 2 other ports.
+ */
+
+#include "armada-385.dtsi"
+
+/ {
+	model = "Marvell Armada 388 family SoC";
+	compatible = "marvell,armada388", "marvell,armada385",
+		"marvell,armada380";
+
+	soc {
+		internal-regs {
+			pinctrl@18000 {
+				compatible = "marvell,mv88f6828-pinctrl";
+			};
+
+			sata@e0000 {
+				compatible = "marvell,armada-380-ahci";
+				reg = <0xe0000 0x2000>;
+				interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 30>;
+				status = "disabled";
+			};
+
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-38x-controlcenterdc.dts b/arch/arm/dts/armada-38x-controlcenterdc.dts
new file mode 100644
index 0000000..2cc9968
--- /dev/null
+++ b/arch/arm/dts/armada-38x-controlcenterdc.dts
@@ -0,0 +1,588 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Device Tree file for the Guntermann & Drunck ControlCenter-Compact board
+ *
+ * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc>
+ *
+ * based on the Device Tree file for Marvell Armada 388 evaluation board
+ * (DB-88F6820), which is
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ */
+
+/dts-v1/;
+
+#include "armada-388.dtsi"
+
+&gpio0 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio1 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart1 {
+	u-boot,dm-pre-reloc;
+};
+
+/ {
+	model = "Controlcenter Digital Compact";
+	compatible = "marvell,a385-db", "marvell,armada388",
+		"marvell,armada385", "marvell,armada380";
+
+	chosen {
+		bootargs = "console=ttyS1,115200 earlyprintk";
+		stdout-path = "/soc/internal-regs/serial@12100";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet2 = &eth2;
+		mdio-gpio0 = &MDIO0;
+		mdio-gpio1 = &MDIO1;
+		mdio-gpio2 = &MDIO2;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		i2c0 = &I2C0;
+		i2c1 = &I2C1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	clocks {
+		sc16isclk: sc16isclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <11059200>;
+		};
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			spi0: spi@10600 {
+				status = "okay";
+				sc16is741: sc16is741@0 {
+					compatible = "nxp,sc16is741";
+					reg = <0>;
+					clocks = <&sc16isclk>;
+					spi-max-frequency = <4000000>;
+					interrupt-parent = <&gpio0>;
+					interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
+
+			spi1: spi@10680 {
+				status = "okay";
+				u-boot,dm-pre-reloc;
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q016a", "spi-flash";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+				spi-flash@1 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q128a11", "spi-flash";
+					reg = <1>; /* Chip select 1 */
+					spi-max-frequency = <108000000>;
+					u-boot,dm-pre-reloc;
+				};
+			};
+
+			I2C0: i2c@11000 {
+				status = "okay";
+				clock-frequency = <1000000>;
+				u-boot,dm-pre-reloc;
+				PCA21: pca9698@21 {
+					compatible = "nxp,pca9698";
+					reg = <0x21>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA22: pca9698@22 {
+					compatible = "nxp,pca9698";
+					u-boot,dm-pre-reloc;
+					reg = <0x22>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA23: pca9698@23 {
+					compatible = "nxp,pca9698";
+					reg = <0x23>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA24: pca9698@24 {
+					compatible = "nxp,pca9698";
+					reg = <0x24>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA25: pca9698@25 {
+					compatible = "nxp,pca9698";
+					reg = <0x25>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+				PCA26: pca9698@26 {
+					compatible = "nxp,pca9698";
+					reg = <0x26>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+			};
+
+			I2C1: i2c@11100 {
+				status = "okay";
+				clock-frequency = <400000>;
+				at97sc3205t@29 {
+					compatible = "atmel,at97sc3204t";
+					reg = <0x29>;
+					u-boot,i2c-offset-len = <0>;
+				};
+				emc2305@2d {
+					compatible = "smsc,emc2305";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x2d>;
+					fan@0 {
+						reg = <0>;
+					};
+					fan@1 {
+						reg = <1>;
+					};
+					fan@2 {
+						reg = <2>;
+					};
+					fan@3 {
+						reg = <3>;
+					};
+					fan@4 {
+						reg = <4>;
+					};
+				};
+				lm77@48 {
+					compatible = "national,lm77";
+					reg = <0x48>;
+				};
+				ads1015@49 {
+					compatible = "ti,ads1015";
+					reg = <0x49>;
+				};
+				lm77@4a {
+					compatible = "national,lm77";
+					reg = <0x4a>;
+				};
+				ads1015@4b {
+					compatible = "ti,ads1015";
+					reg = <0x4b>;
+				};
+				emc2305@4c {
+					compatible = "smsc,emc2305";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x4c>;
+					fan@0 {
+						reg = <0>;
+					};
+					fan@1 {
+						reg = <1>;
+					};
+					fan@2 {
+						reg = <2>;
+					};
+					fan@3 {
+						reg = <3>;
+					};
+					fan@4 {
+						reg = <4>;
+					};
+				};
+				at24c512@54 {
+					compatible = "atmel,24c512";
+					reg = <0x54>;
+					u-boot,i2c-offset-len = <2>;
+				};
+				ds1339@68 {
+					compatible = "dallas,ds1339";
+					reg = <0x68>;
+				};
+			};
+
+			serial@12000 {
+				status = "okay";
+			};
+
+			serial@12100 {
+				status = "okay";
+			};
+
+			ethernet@34000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "sgmii";
+			};
+
+			usb@58000 {
+				status = "ok";
+			};
+
+			ethernet@70000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "sgmii";
+			};
+
+			mdio@72004 {
+				phy0: ethernet-phy@0 {
+					reg = <1>;
+				};
+
+				phy1: ethernet-phy@1 {
+					reg = <0>;
+				};
+			};
+
+			sata@a8000 {
+				status = "okay";
+			};
+
+			sdhci@d8000 {
+				broken-cd;
+				wp-inverted;
+				bus-width = <4>;
+				status = "okay";
+				no-1-8-v;
+			};
+
+			usb3@f0000 {
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * standard PCIe slots on the board.
+			 */
+			pcie@3,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		MDIO0: mdio0 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio0 13 0
+				  /*MDIO*/ &gpio0 14 0>;
+			mv88e1240@0 {
+				reg = <0x0>;
+			};
+			mv88e1240@1 {
+				reg = <0x1>;
+			};
+			mv88e1240@2 {
+				reg = <0x2>;
+			};
+			mv88e1240@3 {
+				reg = <0x3>;
+			};
+			mv88e1240@4 {
+				reg = <0x4>;
+			};
+			mv88e1240@5 {
+				reg = <0x5>;
+			};
+			mv88e1240@6 {
+				reg = <0x6>;
+			};
+			mv88e1240@7 {
+				reg = <0x7>;
+			};
+			mv88e1240@8 {
+				reg = <0x8>;
+			};
+			mv88e1240@9 {
+				reg = <0x9>;
+			};
+			mv88e1240@a {
+				reg = <0xa>;
+			};
+			mv88e1240@b {
+				reg = <0xb>;
+			};
+			mv88e1240@c {
+				reg = <0xc>;
+			};
+			mv88e1240@d {
+				reg = <0xd>;
+			};
+			mv88e1240@e {
+				reg = <0xe>;
+			};
+			mv88e1240@f {
+				reg = <0xf>;
+			};
+			mv88e1240@10 {
+				reg = <0x10>;
+			};
+			mv88e1240@11 {
+				reg = <0x11>;
+			};
+			mv88e1240@12 {
+				reg = <0x12>;
+			};
+			mv88e1240@13 {
+				reg = <0x13>;
+			};
+			mv88e1240@14 {
+				reg = <0x14>;
+			};
+			mv88e1240@15 {
+				reg = <0x15>;
+			};
+			mv88e1240@16 {
+				reg = <0x16>;
+			};
+			mv88e1240@17 {
+				reg = <0x17>;
+			};
+			mv88e1240@18 {
+				reg = <0x18>;
+			};
+			mv88e1240@19 {
+				reg = <0x19>;
+			};
+			mv88e1240@1a {
+				reg = <0x1a>;
+			};
+			mv88e1240@1b {
+				reg = <0x1b>;
+			};
+			mv88e1240@1c {
+				reg = <0x1c>;
+			};
+			mv88e1240@1d {
+				reg = <0x1d>;
+			};
+			mv88e1240@1e {
+				reg = <0x1e>;
+			};
+			mv88e1240@1f {
+				reg = <0x1f>;
+			};
+		};
+
+		MDIO1: mdio1 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio0 25 0
+				  /*MDIO*/ &gpio1 13 0>;
+			mv88e1240@0 {
+				reg = <0x0>;
+			};
+			mv88e1240@1 {
+				reg = <0x1>;
+			};
+			mv88e1240@2 {
+				reg = <0x2>;
+			};
+			mv88e1240@3 {
+				reg = <0x3>;
+			};
+			mv88e1240@4 {
+				reg = <0x4>;
+			};
+			mv88e1240@5 {
+				reg = <0x5>;
+			};
+			mv88e1240@6 {
+				reg = <0x6>;
+			};
+			mv88e1240@7 {
+				reg = <0x7>;
+			};
+			mv88e1240@8 {
+				reg = <0x8>;
+			};
+			mv88e1240@9 {
+				reg = <0x9>;
+			};
+			mv88e1240@a {
+				reg = <0xa>;
+			};
+			mv88e1240@b {
+				reg = <0xb>;
+			};
+			mv88e1240@c {
+				reg = <0xc>;
+			};
+			mv88e1240@d {
+				reg = <0xd>;
+			};
+			mv88e1240@e {
+				reg = <0xe>;
+			};
+			mv88e1240@f {
+				reg = <0xf>;
+			};
+			mv88e1240@10 {
+				reg = <0x10>;
+			};
+			mv88e1240@11 {
+				reg = <0x11>;
+			};
+			mv88e1240@12 {
+				reg = <0x12>;
+			};
+			mv88e1240@13 {
+				reg = <0x13>;
+			};
+			mv88e1240@14 {
+				reg = <0x14>;
+			};
+			mv88e1240@15 {
+				reg = <0x15>;
+			};
+			mv88e1240@16 {
+				reg = <0x16>;
+			};
+			mv88e1240@17 {
+				reg = <0x17>;
+			};
+			mv88e1240@18 {
+				reg = <0x18>;
+			};
+			mv88e1240@19 {
+				reg = <0x19>;
+			};
+			mv88e1240@1a {
+				reg = <0x1a>;
+			};
+			mv88e1240@1b {
+				reg = <0x1b>;
+			};
+			mv88e1240@1c {
+				reg = <0x1c>;
+			};
+			mv88e1240@1d {
+				reg = <0x1d>;
+			};
+			mv88e1240@1e {
+				reg = <0x1e>;
+			};
+			mv88e1240@1f {
+				reg = <0x1f>;
+			};
+		};
+
+		MDIO2: mdio2 {
+			compatible = "virtual,mdio-gpio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			gpios = < /*MDC*/ &gpio1 14 0
+				  /*MDIO*/ &gpio0 24 0>;
+			mv88e1240@0 {
+				reg = <0x0>;
+			};
+			mv88e1240@1 {
+				reg = <0x1>;
+			};
+			mv88e1240@2 {
+				reg = <0x2>;
+			};
+			mv88e1240@3 {
+				reg = <0x3>;
+			};
+			mv88e1240@4 {
+				reg = <0x4>;
+			};
+			mv88e1240@5 {
+				reg = <0x5>;
+			};
+			mv88e1240@6 {
+				reg = <0x6>;
+			};
+			mv88e1240@7 {
+				reg = <0x7>;
+			};
+			mv88e1240@8 {
+				reg = <0x8>;
+			};
+			mv88e1240@9 {
+				reg = <0x9>;
+			};
+			mv88e1240@a {
+				reg = <0xa>;
+			};
+			mv88e1240@b {
+				reg = <0xb>;
+			};
+			mv88e1240@c {
+				reg = <0xc>;
+			};
+			mv88e1240@d {
+				reg = <0xd>;
+			};
+			mv88e1240@e {
+				reg = <0xe>;
+			};
+			mv88e1240@f {
+				reg = <0xf>;
+			};
+			mv88e1240@10 {
+				reg = <0x10>;
+			};
+			mv88e1240@11 {
+				reg = <0x11>;
+			};
+			mv88e1240@12 {
+				reg = <0x12>;
+			};
+			mv88e1240@13 {
+				reg = <0x13>;
+			};
+			mv88e1240@14 {
+				reg = <0x14>;
+			};
+			mv88e1240@15 {
+				reg = <0x15>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		finder_led {
+			label = "finder-led";
+			gpios = <&PCA22 25 0>;
+		};
+
+		status_led {
+			label = "status-led";
+			gpios = <&gpio0 29 0>;
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-38x-solidrun-microsom.dtsi b/arch/arm/dts/armada-38x-solidrun-microsom.dtsi
new file mode 100644
index 0000000..74f58de
--- /dev/null
+++ b/arch/arm/dts/armada-38x-solidrun-microsom.dtsi
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device Tree file for SolidRun Armada 38x Microsom
+ *
+ *  Copyright (C) 2015 Russell King
+ *
+ * This board is in development; the contents of this file work with
+ * the A1 rev 2.0 of the board, which does not represent final
+ * production board.  Things will change, don't expect this file to
+ * remain compatible info the future.
+ */
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000
+			  MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>;
+
+		internal-regs {
+			rtc@a3800 {
+				/*
+				 * If the rtc doesn't work, run "date reset"
+				 * twice in u-boot.
+				 */
+				status = "okay";
+			};
+		};
+	};
+};
+
+&eth0 {
+	/* ethernet@70000 */
+	mac-address = [00 50 43 02 02 01];
+	pinctrl-0 = <&ge0_rgmii_pins>;
+	pinctrl-names = "default";
+	phy = <&phy_dedicated>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+};
+
+&mdio {
+	/*
+	 * Add the phy clock here, so the phy can be accessed to read its
+	 * IDs prior to binding with the driver.
+	 */
+	pinctrl-0 = <&mdio_pins &microsom_phy_clk_pins>;
+	pinctrl-names = "default";
+
+	phy_dedicated: ethernet-phy@0 {
+		/*
+		 * Annoyingly, the marvell phy driver configures the LED
+		 * register, rather than preserving reset-loaded setting.
+		 * We undo that rubbish here.
+		 */
+		marvell,reg-init = <3 16 0 0x101e>;
+		reg = <0>;
+	};
+};
+
+&pinctrl {
+	microsom_phy_clk_pins: microsom-phy-clk-pins {
+		marvell,pins = "mpp45";
+		marvell,function = "ref";
+	};
+	/* Optional eMMC */
+	microsom_sdhci_pins: microsom-sdhci-pins {
+		marvell,pins = "mpp21", "mpp28", "mpp37",
+			       "mpp38", "mpp39", "mpp40";
+		marvell,function = "sd0";
+	};
+};
+
+&spi1 {
+	/* The microsom has an optional W25Q32 on board, connected to CS0 */
+	pinctrl-0 = <&spi1_pins>;
+
+	w25q32: spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "w25q32", "jedec,spi-nor", "spi-flash";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <3000000>;
+		status = "disabled";
+	};
+};
+
+&uart0 {
+	pinctrl-0 = <&uart0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi
new file mode 100644
index 0000000..5e5a158
--- /dev/null
+++ b/arch/arm/dts/armada-38x.dtsi
@@ -0,0 +1,615 @@
+/*
+ * Device Tree Include file for Marvell Armada 38x family of SoCs.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
+/ {
+	model = "Marvell Armada 38x family SoC";
+	compatible = "marvell,armada380";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts-extended = <&mpic 3>;
+	};
+
+	soc {
+		compatible = "marvell,armada380-mbus", "simple-bus";
+		u-boot,dm-pre-reloc;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		controller = <&mbusc>;
+		interrupt-parent = <&gic>;
+		pcie-mem-aperture = <0xe0000000 0x8000000>;
+		pcie-io-aperture  = <0xe8000000 0x100000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0x1d) 0 0x200000>;
+		};
+
+		devbus-bootcs {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs0 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs1 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs2 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		devbus-cs3 {
+			compatible = "marvell,mvebu-devbus";
+			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
+			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		internal-regs {
+			compatible = "simple-bus";
+			u-boot,dm-pre-reloc;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+			L2: cache-controller@8000 {
+				compatible = "arm,pl310-cache";
+				reg = <0x8000 0x1000>;
+				cache-unified;
+				cache-level = <2>;
+			};
+
+			scu@c000 {
+				compatible = "arm,cortex-a9-scu";
+				reg = <0xc000 0x58>;
+			};
+
+			timer@c600 {
+				compatible = "arm,cortex-a9-twd-timer";
+				reg = <0xc600 0x20>;
+				interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
+				clocks = <&coreclk 2>;
+			};
+
+			gic: interrupt-controller@d000 {
+				compatible = "arm,cortex-a9-gic";
+				#interrupt-cells = <3>;
+				#size-cells = <0>;
+				interrupt-controller;
+				reg = <0xd000 0x1000>,
+				      <0xc100 0x100>;
+			};
+
+			spi0: spi@10600 {
+				compatible = "marvell,armada-380-spi",
+						"marvell,orion-spi";
+				reg = <0x10600 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			spi1: spi@10680 {
+				compatible = "marvell,armada-380-spi",
+						"marvell,orion-spi";
+				reg = <0x10680 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <1>;
+				interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@11100 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11100 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+				timeout-ms = <1000>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			uart0: serial@12000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			uart1: serial@12100 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+				reg-io-width = <1>;
+				clocks = <&coreclk 0>;
+				status = "disabled";
+			};
+
+			pinctrl: pinctrl@18000 {
+				reg = <0x18000 0x20>;
+
+				ge0_rgmii_pins: ge-rgmii-pins-0 {
+					marvell,pins = "mpp6", "mpp7", "mpp8",
+						       "mpp9", "mpp10", "mpp11",
+						       "mpp12", "mpp13", "mpp14",
+						       "mpp15", "mpp16", "mpp17";
+					marvell,function = "ge0";
+				};
+
+				ge1_rgmii_pins: ge-rgmii-pins-1 {
+					marvell,pins = "mpp21", "mpp27", "mpp28",
+						       "mpp29", "mpp30", "mpp31",
+						       "mpp32", "mpp37", "mpp38",
+						       "mpp39", "mpp40", "mpp41";
+					marvell,function = "ge1";
+				};
+
+				i2c0_pins: i2c-pins-0 {
+					marvell,pins = "mpp2", "mpp3";
+					marvell,function = "i2c0";
+				};
+
+				nand_pins: nand-pins {
+					marvell,pins = "mpp22", "mpp34", "mpp23", "mpp33",
+						       "mpp38", "mpp28", "mpp40", "mpp42",
+						       "mpp35", "mpp36", "mpp25", "mpp30",
+						       "mpp32";
+					marvell,function = "dev";
+				};
+
+				nand_rb: nand-rb {
+					marvell,pins = "mpp41";
+					marvell,function = "nand";
+				};
+
+				mdio_pins: mdio-pins {
+					marvell,pins = "mpp4", "mpp5";
+					marvell,function = "ge";
+				};
+
+				ref_clk0_pins: ref-clk-pins-0 {
+					marvell,pins = "mpp45";
+					marvell,function = "ref";
+				};
+
+				ref_clk1_pins: ref-clk-pins-1 {
+					marvell,pins = "mpp46";
+					marvell,function = "ref";
+				};
+
+				spi0_pins: spi-pins-0 {
+					marvell,pins = "mpp22", "mpp23", "mpp24",
+						       "mpp25";
+					marvell,function = "spi0";
+				};
+
+				spi1_pins: spi-pins-1 {
+					marvell,pins = "mpp56", "mpp57", "mpp58",
+						       "mpp59";
+					marvell,function = "spi1";
+				};
+
+				uart0_pins: uart-pins-0 {
+					marvell,pins = "mpp0", "mpp1";
+					marvell,function = "ua0";
+				};
+
+				uart1_pins: uart-pins-1 {
+					marvell,pins = "mpp19", "mpp20";
+					marvell,function = "ua1";
+				};
+
+				sdhci_pins: sdhci-pins {
+					marvell,pins = "mpp48", "mpp49", "mpp50",
+						       "mpp52", "mpp53", "mpp54",
+						       "mpp55", "mpp57", "mpp58",
+						       "mpp59";
+					marvell,function = "sd0";
+				};
+
+				sata0_pins: sata-pins-0 {
+					marvell,pins = "mpp20";
+					marvell,function = "sata0";
+				};
+
+				sata1_pins: sata-pins-1 {
+					marvell,pins = "mpp19";
+					marvell,function = "sata1";
+				};
+
+				sata2_pins: sata-pins-2 {
+					marvell,pins = "mpp47";
+					marvell,function = "sata2";
+				};
+
+				sata3_pins: sata-pins-3 {
+					marvell,pins = "mpp44";
+					marvell,function = "sata3";
+				};
+			};
+
+			gpio0: gpio@18100 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18100 0x40>;
+				ngpios = <32>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			gpio1: gpio@18140 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18140 0x40>;
+				ngpios = <28>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			system-controller@18200 {
+				compatible = "marvell,armada-380-system-controller",
+					     "marvell,armada-370-xp-system-controller";
+				reg = <0x18200 0x100>;
+			};
+
+			gateclk: clock-gating-control@18220 {
+				compatible = "marvell,armada-380-gating-clock";
+				reg = <0x18220 0x4>;
+				clocks = <&coreclk 0>;
+				#clock-cells = <1>;
+			};
+
+			coreclk: mvebu-sar@18600 {
+				compatible = "marvell,armada-380-core-clock";
+				reg = <0x18600 0x04>;
+				#clock-cells = <1>;
+			};
+
+			mbusc: mbus-controller@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x100>, <0x20180 0x20>;
+			};
+
+			mpic: interrupt-controller@20a00 {
+				compatible = "marvell,mpic";
+				reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+				#interrupt-cells = <1>;
+				#size-cells = <1>;
+				interrupt-controller;
+				msi-controller;
+				interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			timer@20300 {
+				compatible = "marvell,armada-380-timer",
+					     "marvell,armada-xp-timer";
+				reg = <0x20300 0x30>, <0x21040 0x30>;
+				interrupts-extended = <&gic  GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+						      <&gic  GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+						      <&mpic 5>,
+						      <&mpic 6>;
+				clocks = <&coreclk 2>, <&refclk>;
+				clock-names = "nbclk", "fixed";
+			};
+
+			watchdog@20300 {
+				compatible = "marvell,armada-380-wdt";
+				reg = <0x20300 0x34>, <0x20704 0x4>, <0x18260 0x4>;
+				clocks = <&coreclk 2>, <&refclk>;
+				clock-names = "nbclk", "fixed";
+			};
+
+			cpurst@20800 {
+				compatible = "marvell,armada-370-cpu-reset";
+				reg = <0x20800 0x10>;
+			};
+
+			mpcore-soc-ctrl@20d20 {
+				compatible = "marvell,armada-380-mpcore-soc-ctrl";
+				reg = <0x20d20 0x6c>;
+			};
+
+			coherency-fabric@21010 {
+				compatible = "marvell,armada-380-coherency-fabric";
+				reg = <0x21010 0x1c>;
+			};
+
+			pmsu@22000 {
+				compatible = "marvell,armada-380-pmsu";
+				reg = <0x22000 0x1000>;
+			};
+
+			eth1: ethernet@30000 {
+				compatible = "marvell,armada-370-neta";
+				reg = <0x30000 0x4000>;
+				interrupts-extended = <&mpic 10>;
+				clocks = <&gateclk 3>;
+				status = "disabled";
+			};
+
+			eth2: ethernet@34000 {
+				compatible = "marvell,armada-370-neta";
+				reg = <0x34000 0x4000>;
+				interrupts-extended = <&mpic 12>;
+				clocks = <&gateclk 2>;
+				status = "disabled";
+			};
+
+			usb@58000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x58000 0x500>;
+				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 18>;
+				status = "disabled";
+			};
+
+			xor@60800 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60800 0x100
+				       0x60a00 0x100>;
+				clocks = <&gateclk 22>;
+				status = "okay";
+
+				xor00 {
+					interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor01 {
+					interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			xor@60900 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+				clocks = <&gateclk 28>;
+				status = "okay";
+
+				xor10 {
+					interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor11 {
+					interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			eth0: ethernet@70000 {
+				compatible = "marvell,armada-370-neta";
+				reg = <0x70000 0x4000>;
+				interrupts-extended = <&mpic 8>;
+				clocks = <&gateclk 4>;
+				status = "disabled";
+			};
+
+			mdio: mdio@72004 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "marvell,orion-mdio";
+				reg = <0x72004 0x4>;
+				clocks = <&gateclk 4>;
+			};
+
+			rtc@a3800 {
+				compatible = "marvell,armada-380-rtc";
+				reg = <0xa3800 0x20>, <0x184a0 0x0c>;
+				reg-names = "rtc", "rtc-soc";
+				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			sata@a8000 {
+				compatible = "marvell,armada-380-ahci";
+				reg = <0xa8000 0x2000>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 15>;
+				status = "disabled";
+			};
+
+			sata@e0000 {
+				compatible = "marvell,armada-380-ahci";
+				reg = <0xe0000 0x2000>;
+				interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 30>;
+				status = "disabled";
+			};
+
+			coredivclk: clock@e4250 {
+				compatible = "marvell,armada-380-corediv-clock";
+				reg = <0xe4250 0xc>;
+				#clock-cells = <1>;
+				clocks = <&mainpll>;
+				clock-output-names = "nand";
+			};
+
+			thermal@e8078 {
+				compatible = "marvell,armada380-thermal";
+				reg = <0xe4078 0x4>, <0xe4074 0x4>;
+				status = "okay";
+			};
+
+			flash@d0000 {
+				compatible = "marvell,armada370-nand","marvell,mvebu-pxa3xx-nand";
+				reg = <0xd0000 0x54>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&coredivclk 0>;
+				status = "disabled";
+			};
+
+			sdhci@d8000 {
+				compatible = "marvell,armada-380-sdhci";
+				reg-names = "sdhci", "mbus", "conf-sdio3";
+				reg = <0xd8000 0x1000>,
+					<0xdc000 0x100>,
+					<0x18454 0x4>;
+				interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 17>;
+				mrvl,clk-delay-cycles = <0x1F>;
+				status = "disabled";
+			};
+
+			usb3@f0000 {
+				compatible = "marvell,armada-380-xhci";
+				reg = <0xf0000 0x4000>,<0xf4000 0x4000>;
+				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 9>;
+				status = "disabled";
+			};
+
+			usb3@f8000 {
+				compatible = "marvell,armada-380-xhci";
+				reg = <0xf8000 0x4000>,<0xfc000 0x4000>;
+				interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gateclk 10>;
+				status = "disabled";
+			};
+		};
+	};
+
+	clocks {
+		/* 2 GHz fixed main PLL */
+		mainpll: mainpll {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1000000000>;
+		};
+
+		/* 25 MHz reference crystal */
+		refclk: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-7040-db-nand.dts b/arch/arm/dts/armada-7040-db-nand.dts
new file mode 100644
index 0000000..3a9df21
--- /dev/null
+++ b/arch/arm/dts/armada-7040-db-nand.dts
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2017 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada 7040 Development board platform
+ * Boot device: NAND, 0xE (SW3)
+ */
+
+#include "armada-7040.dtsi"
+
+/ {
+	model = "Marvell Armada 7040 DB board with NAND";
+	compatible = "marvell,armada7040-db-nand", "marvell,armada7040-db",
+		     "marvell,armada7040", "marvell,armada-ap806-quad",
+		     "marvell,armada-ap806";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		i2c0 = &cpm_i2c0;
+		spi0 = &cpm_spi1;
+	};
+
+	memory@00000000 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+&ap_pinctl {
+	   /* MPP Bus:
+	    * SDIO  [0-5]
+	    * UART0 [11,19]
+	    */
+		  /* 0   1   2   3   4   5   6   7   8   9 */
+	pin-func = < 0x1 0x1 0x1 0x1 0x1 0x1 0x0 0x0 0x0 0x0
+		     0x0 0x3 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x3 >;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+
+&cpm_pcie2 {
+	status = "okay";
+};
+
+&cpm_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c0_pins>;
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&cpm_pinctl {
+		/* MPP Bus:
+		 * AUDIO   [0-5]
+                 * GBE     [6-11]
+		 * SS_PWDN [12]
+		 * NF_RBn  [13]
+                 * GPIO    [14]
+		 * DEV_BUS [15-27]
+		 * SATA1   [28]
+		 * UART0   [29-30]
+		 * MSS_VTT_EN [31]
+		 * SMI	   [32,34]
+		 * XSMI    [35-36]
+		 * I2C	   [37-38]
+		 * RGMII1  [44-55]
+		 * SD	   [56-61]
+		 * GPIO    [62]
+		 */
+		 /*   0   1   2   3   4   5   6   7   8   9 */
+	 pin-func = < 0x2 0x2 0x2 0x2 0x2 0x2 0x3 0x3 0x3 0x3
+		      0x3 0x3 0x0 0x2 0x0 0x1 0x1 0x1 0x1 0x1
+		      0x1 0x1 0x1 0x1 0x1 0x1 0x1 0x1 0x9 0xa
+		      0xa 0x0 0x7 0x0 0x7 0x7 0x7 0x2 0x2 0x0
+		      0x0 0x0 0x0 0x0 0x1 0x1 0x1 0x1 0x1 0x1
+		      0x1 0x1 0x1 0x1 0x1 0x1 0xe 0xe 0xe 0xe
+		      0xe 0xe 0x0>;
+};
+
+&cpm_spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_spi0_pins>;
+	status = "disabled";
+
+	spi-flash@0 {
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-max-frequency = <20000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0x0 0x200000>;
+			};
+
+			partition@400000 {
+				label = "Filesystem";
+				reg = <0x200000 0xe00000>;
+			};
+		};
+	};
+};
+
+&cpm_sata0 {
+	status = "okay";
+};
+
+&cpm_usb3_0 {
+	status = "okay";
+};
+
+&cpm_usb3_1 {
+	status = "okay";
+};
+
+&cpm_comphy {
+	phy0 {
+		phy-type = <PHY_TYPE_SGMII2>;
+		phy-speed = <PHY_SPEED_3_125G>;
+	};
+
+	phy1 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+
+	phy2 {
+		phy-type = <PHY_TYPE_SGMII0>;
+		phy-speed = <PHY_SPEED_1_25G>;
+	};
+
+	phy3 {
+		phy-type = <PHY_TYPE_SATA1>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+
+	phy4 {
+		phy-type = <PHY_TYPE_USB3_HOST1>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+
+	phy5 {
+		phy-type = <PHY_TYPE_PEX2>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+};
+
+&cpm_nand {
+	status = "okay";
+};
+
+&cpm_utmi0 {
+	status = "okay";
+};
+
+&cpm_utmi1 {
+	status = "okay";
+};
+
+&ap_sdhci0 {
+	status = "okay";
+	bus-width = <4>;
+	no-1-8-v;
+	non-removable;
+};
+
+&cpm_sdhci0 {
+	status = "okay";
+	bus-width = <4>;
+	no-1-8-v;
+	non-removable;
+};
diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts
new file mode 100644
index 0000000..cfd2b4b
--- /dev/null
+++ b/arch/arm/dts/armada-7040-db.dts
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada 7040 Development board platform
+ * Boot device: SPI NOR, 0x32 (SW3)
+ */
+
+#include "armada-7040.dtsi"
+
+/ {
+	model = "Marvell Armada 7040 DB board";
+	compatible = "marvell,armada7040-db", "marvell,armada7040",
+		     "marvell,armada-ap806-quad", "marvell,armada-ap806";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		i2c0 = &cpm_i2c0;
+		spi0 = &cpm_spi1;
+	};
+
+	memory@00000000 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+&ap_pinctl {
+	   /* MPP Bus:
+	    * SDIO  [0-5]
+	    * UART0 [11,19]
+	    */
+		  /* 0 1 2 3 4 5 6 7 8 9 */
+	pin-func = < 1 1 1 1 1 1 0 0 0 0
+		     0 3 0 0 0 0 0 0 0 3 >;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+
+&cpm_pcie2 {
+	status = "okay";
+};
+
+&cpm_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c0_pins>;
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&cpm_pinctl {
+		/* MPP Bus:
+		 * TDM	 [0-11]
+		 * SPI   [13-16]
+		 * SATA1 [28]
+		 * UART0 [29-30]
+		 * SMI	 [32,34]
+		 * XSMI  [35-36]
+		 * I2C	 [37-38]
+		 * RGMII1[44-55]
+		 * SD	 [56-62]
+		 */
+		/*   0   1   2   3   4   5   6   7   8   9 */
+	pin-func = < 4   4   4   4   4   4   4   4   4   4
+		     4   4   0   3   3   3   3   0   0   0
+		     0   0   0   0   0   0   0   0   9   0xA
+		     0xA 0   7   0   7   7   7   2   2   0
+		     0   0   0   0   1   1   1   1   1   1
+		     1   1   1   1   1   1   0xE 0xE 0xE 0xE
+		     0xE 0xE 0xE >;
+};
+
+&cpm_spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_spi0_pins>;
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-max-frequency = <20000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0x0 0x200000>;
+			};
+
+			partition@400000 {
+				label = "Filesystem";
+				reg = <0x200000 0xe00000>;
+			};
+		};
+	};
+};
+
+&cpm_sata0 {
+	status = "okay";
+};
+
+&cpm_usb3_0 {
+	status = "okay";
+};
+
+&cpm_usb3_1 {
+	status = "okay";
+};
+
+&cpm_comphy {
+	phy0 {
+		phy-type = <PHY_TYPE_SGMII1>;
+		phy-speed = <PHY_SPEED_1_25G>;
+	};
+
+	phy1 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+
+	phy2 {
+		phy-type = <PHY_TYPE_SFI>;
+	};
+
+	phy3 {
+		phy-type = <PHY_TYPE_SATA1>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+
+	phy4 {
+		phy-type = <PHY_TYPE_USB3_HOST1>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+
+	phy5 {
+		phy-type = <PHY_TYPE_PEX2>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+};
+
+&cpm_utmi0 {
+	status = "okay";
+};
+
+&cpm_utmi1 {
+	status = "okay";
+};
+
+&ap_sdhci0 {
+	status = "okay";
+	bus-width = <4>;
+	no-1-8-v;
+	non-removable;
+};
+
+&cpm_sdhci0 {
+	status = "okay";
+	bus-width = <4>;
+	no-1-8-v;
+	non-removable;
+};
+
+&cpm_mdio {
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+&cpm_ethernet {
+	status = "okay";
+};
+
+&cpm_eth0 {
+	status = "okay";
+	phy-mode = "sfi"; /* lane-2 */
+};
+
+&cpm_eth1 {
+	status = "okay";
+	phy = <&phy0>;
+	phy-mode = "sgmii";
+};
+
+&cpm_eth2 {
+	status = "okay";
+	phy = <&phy1>;
+	phy-mode = "rgmii-id";
+};
diff --git a/arch/arm/dts/armada-7040.dtsi b/arch/arm/dts/armada-7040.dtsi
new file mode 100644
index 0000000..b5be0c4
--- /dev/null
+++ b/arch/arm/dts/armada-7040.dtsi
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for the Armada 7040 SoC, made of an AP806 Quad and
+ * one CP110.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-ap806-quad.dtsi"
+#include "armada-cp110-master.dtsi"
+
+/ {
+	model = "Marvell Armada 7040";
+	compatible = "marvell,armada7040", "marvell,armada-ap806-quad",
+		     "marvell,armada-ap806";
+};
diff --git a/arch/arm/dts/armada-8020.dtsi b/arch/arm/dts/armada-8020.dtsi
new file mode 100644
index 0000000..048e5cf
--- /dev/null
+++ b/arch/arm/dts/armada-8020.dtsi
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for the Armada 8020 SoC, made of an AP806 Dual and
+ * two CP110.
+ */
+
+#include "armada-ap806-dual.dtsi"
+#include "armada-cp110-master.dtsi"
+#include "armada-cp110-slave.dtsi"
+
+/ {
+	model = "Marvell Armada 8020";
+	compatible = "marvell,armada8020", "marvell,armada-ap806-dual",
+		     "marvell,armada-ap806";
+};
diff --git a/arch/arm/dts/armada-8040-clearfog-gt-8k.dts b/arch/arm/dts/armada-8040-clearfog-gt-8k.dts
new file mode 100644
index 0000000..498105f
--- /dev/null
+++ b/arch/arm/dts/armada-8040-clearfog-gt-8k.dts
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 SolidRun ltd
+ */
+
+#include "armada-8040.dtsi"
+
+/ {
+	model = "ClearFog-GT-8K";
+	compatible = "solidrun,clearfog-gt-8k",
+		     "marvell,armada8040";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		i2c0 = &cpm_i2c0;
+		i2c1 = &cpm_i2c1;
+		spi0 = &cps_spi1;
+	};
+
+	memory@00000000 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	simple-bus {
+		compatible = "simple-bus";
+
+		reg_usb3h0_vbus: usb3-vbus0 {
+			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&cpm_xhci_vbus_pins>;
+			regulator-name = "reg-usb3h0-vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			startup-delay-us = <300000>;
+			shutdown-delay-us = <500000>;
+			regulator-force-boot-off;
+			gpio = <&cpm_gpio1 15 GPIO_ACTIVE_LOW>; /* GPIO[47] */
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&ap_pinctl {
+	/*
+	 * MPP Bus:
+	 * eMMC [0-10]
+	 * UART0 [11,19]
+	 */
+		  /* 0 1 2 3 4 5 6 7 8 9 */
+	pin-func = < 1 1 1 1 1 1 1 1 1 1
+		     1 3 0 0 0 0 0 0 0 3 >;
+};
+
+/* on-board eMMC */
+&ap_sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ap_emmc_pins>;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&cpm_pinctl {
+	/*
+	 * MPP Bus:
+	 * [0-31] = 0xff: Keep default CP0_shared_pins:
+	 * [11] CLKOUT_MPP_11 (out)
+	 * [23] LINK_RD_IN_CP2CP (in)
+	 * [25] CLKOUT_MPP_25 (out)
+	 * [29] AVS_FB_IN_CP2CP (in)
+	 * [32, 33, 34] pci0/1/2 reset
+	 * [35-38] CP0 I2C1 and I2C0
+	 * [39] GPIO reset button
+	 * [40,41] LED0 and LED1
+	 * [43] 1512 phy reset
+	 * [47] USB VBUS EN (active low)
+	 * [48] FAN PWM
+	 * [49] SFP+ present signal
+	 * [50] TPM interrupt
+	 * [51] WLAN0 disable
+	 * [52] WLAN1 disable
+	 * [53] LTE disable
+	 * [54] NFC reset
+	 * [55] Micro SD card detect
+	 * [56-61] Micro SD
+	 */
+		/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0    0    0    0    2    2    2    2    0
+		     0    0    0    0    0    0    0    0    0    0
+		     0    0    0    0    0    0    0xe  0xe  0xe  0xe
+		     0xe  0xe  0 >;
+
+	cpm_xhci_vbus_pins: cpm-xhci-vbus-pins {
+		marvell,pins = < 47 >;
+		marvell,function = <0>;
+	};
+
+	cps_1g_phy_reset: cps-1g-phy-reset {
+		marvell,pins = < 43 >;
+		marvell,function = <0>;
+	};
+};
+
+/* uSD slot */
+&cpm_sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_sdhci_pins>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&cpm_pcie0 {
+	num-lanes = <1>;
+	status = "okay";
+};
+
+&cpm_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c0_pins>;
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&cpm_i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c1_pins>;
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&cpm_sata0 {
+	status = "okay";
+};
+
+&cpm_comphy {
+	/*
+	 * CP0 Serdes Configuration:
+	 * Lane 0: PCIe0 (x1)
+	 * Lane 1: Not connected
+	 * Lane 2: SFI (10G)
+	 * Lane 3: Not connected
+	 * Lane 4: USB 3.0 host port1 (can be PCIe)
+	 * Lane 5: Not connected
+	 */
+	phy0 {
+		phy-type = <PHY_TYPE_PEX0>;
+	};
+	phy1 {
+		phy-type = <PHY_TYPE_UNCONNECTED>;
+	};
+	phy2 {
+		phy-type = <PHY_TYPE_SFI>;
+	};
+	phy3 {
+		phy-type = <PHY_TYPE_UNCONNECTED>;
+	};
+	phy4 {
+		phy-type = <PHY_TYPE_USB3_HOST1>;
+	};
+	phy5 {
+		phy-type = <PHY_TYPE_UNCONNECTED>;
+	};
+};
+
+&cpm_ethernet {
+        pinctrl-names = "default";
+        status = "okay";
+};
+
+/* 10G SFI SFP */
+&cpm_eth0 {
+        status = "okay";
+        phy-mode = "sfi";
+};
+
+&cps_sata0 {
+	status = "okay";
+};
+
+&cps_usb3_0 {
+	vbus-supply = <&reg_usb3h0_vbus>;
+	status = "okay";
+};
+
+&cps_utmi0 {
+	status = "okay";
+};
+
+&cps_pinctl {
+	/*
+	 * MPP Bus:
+	 * [0-5] TDM
+	 * [6]   VHV Enable
+	 * [7]   CP1 SPI0 CSn1 (FXS)
+	 * [8]   CP1 SPI0 CSn0 (TPM)
+	 * [9.11]CP1 SPI0 MOSI/MISO/CLK
+	 * [13]  CP1 SPI1 MISO (TDM and SPI ROM shared)
+	 * [14]  CP1 SPI1 CS0n (64Mb SPI ROM)
+	 * [15]  CP1 SPI1 MOSI (TDM and SPI ROM shared)
+	 * [16]  CP1 SPI1 CLK (TDM and SPI ROM shared)
+	 * [24]  Topaz switch reset
+	 * [26]  Buzzer
+	 * [27]  CP1 SMI MDIO
+	 * [28]  CP1 SMI MDC
+	 * [29]  CP0 10G SFP TX Disable
+	 * [30]  WPS button
+	 * [31]  Front panel button
+	 * [32-62] = 0xff: Keep default CP1_shared_pins:
+	 */
+		/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0x4  0x4  0x4  0x4  0x4  0x4  0x0  0x4  0x4  0x4
+		     0x4  0x4  0x0  0x3  0x3  0x3  0x3  0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0x0  0xff 0x0  0x8  0x8  0x0
+		     0x0  0x0  0x0  0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff>;
+};
+
+&cps_spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cps_spi1_pins>;
+	status = "okay";
+
+	spi-flash@0 {
+		compatible = "jedec,spi-nor", "spi-flash";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0 0x200000>;
+			};
+			partition@200000 {
+				label = "Filesystem";
+				reg = <0x200000 0xce0000>;
+			};
+		};
+	};
+};
+
+&cps_comphy {
+	/*
+	 * CP1 Serdes Configuration:
+	 * Lane 0: SATA 1 (RX swapped). Can be PCIe0
+	 * Lane 1: Not used
+	 * Lane 2: USB HOST 0
+	 * Lane 3: SGMII1 - Connected to 1512 port
+	 * Lane 4: Not used
+	 * Lane 5: SGMII2 - Connected to Topaz switch
+	 */
+	phy0 {
+		phy-type = <PHY_TYPE_SATA1>;
+		phy-invert = <PHY_POLARITY_RXD_INVERT>;
+	};
+	phy1 {
+		phy-type = <PHY_TYPE_UNCONNECTED>;
+	};
+	phy2 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+	};
+	phy3 {
+		phy-type = <PHY_TYPE_SGMII1>;
+		phy-speed = <PHY_SPEED_1_25G>;
+	};
+	phy4 {
+		phy-type = <PHY_TYPE_UNCONNECTED>;
+	};
+	phy5 {
+		phy-type = <PHY_TYPE_SGMII2>;
+		phy-speed = <PHY_SPEED_3_125G>;
+	};
+};
+
+&cps_mdio {
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
+&cps_ethernet {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cps_1g_phy_reset>;
+	status = "okay";
+};
+
+/* 1G SGMII */
+&cps_eth1 {
+	status = "okay";
+	phy-mode = "sgmii";
+	phy = <&phy0>;
+	phy-reset-gpios = <&cpm_gpio1 11 GPIO_ACTIVE_LOW>;
+};
+
+/* 2.5G to Topaz switch */
+&cps_eth2 {
+	status = "okay";
+	phy-mode = "sgmii";
+	phy-speed = <2500>;
+	phy-reset-gpios = <&cps_gpio0 24 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm/dts/armada-8040-db.dts b/arch/arm/dts/armada-8040-db.dts
new file mode 100644
index 0000000..65b30bb
--- /dev/null
+++ b/arch/arm/dts/armada-8040-db.dts
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada 8040 Development board platform
+ */
+
+#include "armada-8040.dtsi"
+
+/ {
+	model = "Marvell Armada 8040 DB board";
+	compatible = "marvell,armada8040-db", "marvell,armada8040",
+		     "marvell,armada-ap806-quad", "marvell,armada-ap806";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		i2c0 = &cpm_i2c0;
+		spi0 = &cps_spi1;
+	};
+
+	memory@00000000 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+/* Accessible over the mini-USB CON9 connector on the main board */
+&uart0 {
+	status = "okay";
+};
+
+&ap_pinctl {
+	/* MPP Bus:
+	 * SDIO  [0-10]
+	 * UART0 [11,19]
+	 */
+		  /* 0 1 2 3 4 5 6 7 8 9 */
+	pin-func = < 1 1 1 1 1 1 1 1 1 1
+		     1 3 0 0 0 0 0 0 0 3 >;
+};
+
+&ap_sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ap_emmc_pins>;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&cpm_pinctl {
+	/* MPP Bus:
+	 *	[0-31]	= 0xff: Keep default CP0_shared_pins
+	 *	[11]	CLKOUT_MPP_11 (out)
+	 *	[23]	LINK_RD_IN_CP2CP (in)
+	 *	[25]	CLKOUT_MPP_25 (out)
+	 *	[29]	AVS_FB_IN_CP2CP (in)
+	 *	[32,34]	GE_MDIO/MDC
+	 *	[33]	GPIO: GE_INT#/push button/Wake
+	 *	[35]	MSS_GPIO[3]: MSS_PWDN
+	 *	[36]	MSS_GPIO[5]: MSS_VTT_EN
+	 *	[37-38]	I2C0
+	 *	[39]	PTP_CLK
+	 *	[40-41]	SATA[0/1]_PRESENT_ACTIVEn
+	 *	[42-43]	XG_MDC/XG_MDIO (XSMI)
+	 *	[44-55]	RGMII1
+	 *	[56-62]	SD
+	 */
+	/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0x7  0x0  0x7  0xa  0xa  0x2  0x2  0x5
+		     0x9  0x9  0x8  0x8  0x1  0x1  0x1  0x1  0x1  0x1
+		     0x1  0x1  0x1  0x1  0x1  0x1  0xe  0xe  0xe  0xe
+		     0xe  0xe  0xe>;
+};
+
+&cpm_comphy {
+	/* Serdes Configuration:
+	 *	Lane 0: PCIe0 (x1)
+	 *	Lane 1: SATA0
+	 *	Lane 2: SFI (10G)
+	 *	Lane 3: SATA1
+	 *	Lane 4: USB3_HOST1
+	 *	Lane 5: PCIe2 (x1)
+	 */
+	phy0 {
+		phy-type = <PHY_TYPE_PEX0>;
+	};
+	phy1 {
+		phy-type = <PHY_TYPE_SATA0>;
+	};
+	phy2 {
+		phy-type = <PHY_TYPE_SFI>;
+	};
+	phy3 {
+		phy-type = <PHY_TYPE_SATA1>;
+	};
+	phy4 {
+		phy-type = <PHY_TYPE_USB3_HOST1>;
+	};
+	phy5 {
+		phy-type = <PHY_TYPE_PEX2>;
+	};
+};
+
+/* CON6 on CP0 expansion */
+&cpm_pcie0 {
+	status = "okay";
+};
+
+&cpm_pcie1 {
+	status = "disabled";
+};
+
+/* CON5 on CP0 expansion */
+&cpm_pcie2 {
+	status = "okay";
+};
+
+&cpm_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c0_pins>;
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+/* CON4 on CP0 expansion */
+&cpm_sata0 {
+	status = "okay";
+};
+
+/* CON9 on CP0 expansion */
+&cpm_usb3_0 {
+	status = "okay";
+};
+
+/* CON10 on CP0 expansion */
+&cpm_usb3_1 {
+	status = "okay";
+};
+
+&cpm_utmi0 {
+	status = "okay";
+};
+
+&cpm_utmi1 {
+	status = "okay";
+};
+
+&cpm_sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_sdhci_pins>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&cps_pinctl {
+	/* MPP Bus:
+	 *	[0-11]	RGMII0
+	 *	[13-16]	SPI1
+	 *	[27,31]	GE_MDIO/MDC
+	 *	[28]	SATA1_PRESENT_ACTIVEn
+	 *	[29-30]	UART0
+	 *	[32-62]	= 0xff: Keep default CP1_shared_pins
+	 */
+	/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3
+		     0x3  0x3  0x3  0x3  0x3  0x3  0x3  0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x8  0x9  0xa
+		     0xA  0x8  0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff>;
+};
+
+&cps_comphy {
+	/* Serdes Configuration:
+	 *	Lane 0: PCIe0 (x1)
+	 *	Lane 1: SATA0
+	 *	Lane 2: SFI (10G)
+	 *	Lane 3: SATA1
+	 *	Lane 4: PCIe1 (x1)
+	 *	Lane 5: PCIe2 (x1)
+	 */
+	phy0 {
+		phy-type = <PHY_TYPE_PEX0>;
+	};
+	phy1 {
+		phy-type = <PHY_TYPE_SATA0>;
+	};
+	phy2 {
+		phy-type = <PHY_TYPE_SFI>;
+	};
+	phy3 {
+		phy-type = <PHY_TYPE_SATA1>;
+	};
+	phy4 {
+		phy-type = <PHY_TYPE_PEX1>;
+	};
+	phy5 {
+		phy-type = <PHY_TYPE_PEX2>;
+	};
+};
+
+/* CON6 on CP1 expansion */
+&cps_pcie0 {
+	status = "okay";
+};
+
+&cps_pcie1 {
+	status = "okay";
+};
+
+/* CON5 on CP1 expansion */
+&cps_pcie2 {
+	status = "okay";
+};
+
+&cps_spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cps_spi1_pins>;
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0 0x200000>;
+			};
+			partition@400000 {
+				label = "Filesystem";
+				reg = <0x200000 0xce0000>;
+			};
+		};
+	};
+};
+
+/* CON4 on CP1 expansion */
+&cps_sata0 {
+	status = "okay";
+};
+
+/* CON9 on CP1 expansion */
+&cps_usb3_0 {
+	status = "okay";
+};
+
+/* CON10 on CP1 expansion */
+&cps_usb3_1 {
+	status = "okay";
+};
+
+&cps_utmi0 {
+	status = "okay";
+};
+
+&cpm_mdio {
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+&cpm_ethernet {
+	status = "okay";
+};
+
+&cpm_eth2 {
+	status = "okay";
+	phy = <&phy1>;
+	phy-mode = "rgmii-id";
+};
diff --git a/arch/arm/dts/armada-8040-mcbin.dts b/arch/arm/dts/armada-8040-mcbin.dts
new file mode 100644
index 0000000..7e8e2f7
--- /dev/null
+++ b/arch/arm/dts/armada-8040-mcbin.dts
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ */
+
+#include "armada-8040.dtsi" /* include SoC device tree */
+
+/ {
+	model = "MACCHIATOBin-8040";
+	compatible = "marvell,armada8040-mcbin",
+		     "marvell,armada8040";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		i2c0 = &cpm_i2c0;
+		i2c1 = &cpm_i2c1;
+		spi0 = &cps_spi1;
+		gpio0 = &ap_gpio0;
+		gpio1 = &cpm_gpio0;
+		gpio2 = &cpm_gpio1;
+	};
+
+	memory@00000000 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	simple-bus {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb3h0_vbus: usb3-vbus0 {
+			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&cpm_xhci_vbus_pins>;
+			regulator-name = "reg-usb3h0-vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			startup-delay-us = <500000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&cpm_gpio1 15 GPIO_ACTIVE_HIGH>; /* GPIO[47] */
+		};
+	};
+};
+
+/* Accessible over the mini-USB CON9 connector on the main board */
+&uart0 {
+	status = "okay";
+};
+
+&ap_pinctl {
+	/*
+	 * MPP Bus:
+	 * eMMC [0-10]
+	 * UART0 [11,19]
+	 */
+		  /* 0 1 2 3 4 5 6 7 8 9 */
+	pin-func = < 1 1 1 1 1 1 1 1 1 1
+		     1 3 0 0 0 0 0 0 0 3 >;
+};
+
+/* on-board eMMC */
+&ap_sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ap_emmc_pins>;
+	bus-width= <8>;
+	status = "okay";
+};
+
+&cpm_pinctl {
+	/*
+	 * MPP Bus:
+	 * [0-31] = 0xff: Keep default CP0_shared_pins:
+	 * [11] CLKOUT_MPP_11 (out)
+	 * [23] LINK_RD_IN_CP2CP (in)
+	 * [25] CLKOUT_MPP_25 (out)
+	 * [29] AVS_FB_IN_CP2CP (in)
+	 * [32,34] SMI
+	 * [33]    MSS power down
+	 * [35-38] CP0 I2C1 and I2C0
+	 * [39] MSS CKE Enable
+	 * [40,41] CP0 UART1 TX/RX
+	 * [42,43] XSMI (controls two 10G phys)
+	 * [47] USB VBUS EN
+	 * [48] FAN PWM
+	 * [49] 10G port 1 interrupt
+	 * [50] 10G port 0 interrupt
+	 * [51] 2.5G SFP TX fault
+	 * [52] PCIe reset out
+	 * [53] 2.5G SFP mode
+	 * [54] 2.5G SFP LOS
+	 * [55] Micro SD card detect
+	 * [56-61] Micro SD
+	 * [62] CP1 SFI SFP FAULT
+	 */
+		/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0    7    0xa  7    2    2    2    2    0xa
+		     7    7    8    8    0    0    0    0    0    0
+		     0    0    0    0    0    0    0xe  0xe  0xe  0xe
+		     0xe  0xe  0 >;
+
+	cpm_xhci_vbus_pins: cpm-xhci-vbus-pins {
+		marvell,pins = < 47 >;
+		marvell,function = <0>;
+	};
+
+	cpm_pcie_reset_pins: cpm-pcie-reset-pins {
+		marvell,pins = < 52 >;
+		marvell,function = <0>;
+	};
+};
+
+/* uSD slot */
+&cpm_sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_sdhci_pins>;
+	bus-width= <4>;
+	status = "okay";
+};
+
+/* PCIe x4 */
+&cpm_pcie0 {
+	num-lanes = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_pcie_reset_pins>;
+	marvell,reset-gpio = <&cpm_gpio1 20 GPIO_ACTIVE_HIGH>; /* GPIO[52] */
+	status = "okay";
+};
+
+&cpm_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c0_pins>;
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&cpm_i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c1_pins>;
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&cpm_sata0 {
+	status = "okay";
+};
+
+&cpm_mdio {
+	ge_phy: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
+&cpm_comphy {
+	/*
+	 * CP0 Serdes Configuration:
+	 * Lane 0: PCIe0 (x4)
+	 * Lane 1: PCIe0 (x4)
+	 * Lane 2: PCIe0 (x4)
+	 * Lane 3: PCIe0 (x4)
+	 * Lane 4: SFI (10G)
+	 * Lane 5: SATA1
+	 */
+	phy0 {
+		phy-type = <PHY_TYPE_PEX0>;
+	};
+	phy1 {
+		phy-type = <PHY_TYPE_PEX0>;
+	};
+	phy2 {
+		phy-type = <PHY_TYPE_PEX0>;
+	};
+	phy3 {
+		phy-type = <PHY_TYPE_PEX0>;
+	};
+	phy4 {
+		phy-type = <PHY_TYPE_SFI>;
+	};
+	phy5 {
+		phy-type = <PHY_TYPE_SATA1>;
+	};
+};
+
+&cps_sata0 {
+	status = "okay";
+};
+
+&cps_usb3_0 {
+	vbus-supply = <&reg_usb3h0_vbus>;
+	status = "okay";
+};
+
+&cps_utmi0 {
+	status = "okay";
+};
+
+&cps_ethernet {
+	status = "okay";
+};
+
+&cps_eth1 {
+	status = "okay";
+	phy = <&ge_phy>;
+	phy-mode = "sgmii";
+};
+
+&cps_pinctl {
+	/*
+	 * MPP Bus:
+	 * [0-5] TDM
+	 * [6,7] CP1_UART 0
+	 * [8]   CP1 10G SFP LOS
+	 * [9]   CP1 10G PHY RESET
+	 * [10]  CP1 10G SFP TX Disable
+	 * [11]  CP1 10G SFP Mode
+	 * [12]  SPI1 CS1n
+	 * [13]  SPI1 MISO (TDM and SPI ROM shared)
+	 * [14]  SPI1 CS0n
+	 * [15]  SPI1 MOSI (TDM and SPI ROM shared)
+	 * [16]  SPI1 CLK (TDM and SPI ROM shared)
+	 * [24]  CP1 2.5G SFP TX Disable
+	 * [26]  CP0 10G SFP TX Fault
+	 * [27]  CP0 10G SFP Mode
+	 * [28]  CP0 10G SFP LOS
+	 * [29]  CP0 10G SFP TX Disable
+	 * [30]  USB Over current indication
+	 * [31]  10G Port 0 phy reset
+	 * [32-62] = 0xff: Keep default CP1_shared_pins:
+	 */
+		/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0x4  0x4  0x4  0x4  0x4  0x4  0x8  0x8  0x0  0x0
+		     0x0  0x0  0x3  0x3  0x3  0x3  0x3  0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0x0  0xff 0x0  0x0  0x0 0x0
+		     0x0  0x0  0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff>;
+};
+
+&cps_spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cps_spi1_pins>;
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0 0x200000>;
+			};
+			partition@400000 {
+				label = "Filesystem";
+				reg = <0x200000 0xce0000>;
+			};
+		};
+	};
+};
+
+&cps_comphy {
+	/*
+	 * CP1 Serdes Configuration:
+	 * Lane 0: SGMII1
+	 * Lane 1: SATA 0
+	 * Lane 2: USB HOST 0
+	 * Lane 3: SATA1
+	 * Lane 4: SFI (10G)
+	 * Lane 5: SGMII3
+	 */
+	phy0 {
+		phy-type = <PHY_TYPE_SGMII1>;
+		phy-speed = <PHY_SPEED_1_25G>;
+	};
+	phy1 {
+		phy-type = <PHY_TYPE_SATA0>;
+	};
+	phy2 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+	};
+	phy3 {
+		phy-type = <PHY_TYPE_SATA1>;
+	};
+	phy4 {
+		phy-type = <PHY_TYPE_SFI>;
+	};
+	phy5 {
+		phy-type = <PHY_TYPE_SGMII3>;
+	};
+};
diff --git a/arch/arm/dts/armada-8040.dtsi b/arch/arm/dts/armada-8040.dtsi
new file mode 100644
index 0000000..96cc112
--- /dev/null
+++ b/arch/arm/dts/armada-8040.dtsi
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for the Armada 8040 SoC, made of an AP806 Quad and
+ * two CP110.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-ap806-quad.dtsi"
+#include "armada-cp110-master.dtsi"
+#include "armada-cp110-slave.dtsi"
+
+/ {
+	model = "Marvell Armada 8040";
+	compatible = "marvell,armada8040", "marvell,armada-ap806-quad",
+		     "marvell,armada-ap806";
+};
diff --git a/arch/arm/dts/armada-ap806-quad.dtsi b/arch/arm/dts/armada-ap806-quad.dtsi
new file mode 100644
index 0000000..ba43a43
--- /dev/null
+++ b/arch/arm/dts/armada-ap806-quad.dtsi
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Publ