162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Keystone2 based boards and SOC related code. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2013 Texas Instruments, Inc. 662306a36Sopenharmony_ci * Cyril Chemparathy <cyril@ti.com> 762306a36Sopenharmony_ci * Santosh Shilimkar <santosh.shillimkar@ti.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/io.h> 1162306a36Sopenharmony_ci#include <linux/dma-map-ops.h> 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1462306a36Sopenharmony_ci#include <linux/pm_clock.h> 1562306a36Sopenharmony_ci#include <linux/memblock.h> 1662306a36Sopenharmony_ci#include <linux/of.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <asm/setup.h> 2062306a36Sopenharmony_ci#include <asm/mach/map.h> 2162306a36Sopenharmony_ci#include <asm/mach/arch.h> 2262306a36Sopenharmony_ci#include <asm/mach/time.h> 2362306a36Sopenharmony_ci#include <asm/page.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define KEYSTONE_LOW_PHYS_START 0x80000000ULL 2662306a36Sopenharmony_ci#define KEYSTONE_LOW_PHYS_SIZE 0x80000000ULL /* 2G */ 2762306a36Sopenharmony_ci#define KEYSTONE_LOW_PHYS_END (KEYSTONE_LOW_PHYS_START + \ 2862306a36Sopenharmony_ci KEYSTONE_LOW_PHYS_SIZE - 1) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define KEYSTONE_HIGH_PHYS_START 0x800000000ULL 3162306a36Sopenharmony_ci#define KEYSTONE_HIGH_PHYS_SIZE 0x400000000ULL /* 16G */ 3262306a36Sopenharmony_ci#define KEYSTONE_HIGH_PHYS_END (KEYSTONE_HIGH_PHYS_START + \ 3362306a36Sopenharmony_ci KEYSTONE_HIGH_PHYS_SIZE - 1) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic struct dev_pm_domain keystone_pm_domain = { 3662306a36Sopenharmony_ci .ops = { 3762306a36Sopenharmony_ci USE_PM_CLK_RUNTIME_OPS 3862306a36Sopenharmony_ci USE_PLATFORM_PM_SLEEP_OPS 3962306a36Sopenharmony_ci }, 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic struct pm_clk_notifier_block platform_domain_notifier = { 4362306a36Sopenharmony_ci .pm_domain = &keystone_pm_domain, 4462306a36Sopenharmony_ci .con_ids = { NULL }, 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic const struct of_device_id of_keystone_table[] = { 4862306a36Sopenharmony_ci {.compatible = "ti,k2hk"}, 4962306a36Sopenharmony_ci {.compatible = "ti,k2e"}, 5062306a36Sopenharmony_ci {.compatible = "ti,k2l"}, 5162306a36Sopenharmony_ci { /* end of list */ }, 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic int __init keystone_pm_runtime_init(void) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci struct device_node *np; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci np = of_find_matching_node(NULL, of_keystone_table); 5962306a36Sopenharmony_ci if (!np) 6062306a36Sopenharmony_ci return 0; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci pm_clk_add_notifier(&platform_bus_type, &platform_domain_notifier); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci return 0; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 6862306a36Sopenharmony_cistatic int keystone_platform_notifier(struct notifier_block *nb, 6962306a36Sopenharmony_ci unsigned long event, void *data) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct device *dev = data; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (event != BUS_NOTIFY_ADD_DEVICE) 7462306a36Sopenharmony_ci return NOTIFY_DONE; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (!dev) 7762306a36Sopenharmony_ci return NOTIFY_BAD; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (!dev->of_node) { 8062306a36Sopenharmony_ci int ret = dma_direct_set_offset(dev, KEYSTONE_HIGH_PHYS_START, 8162306a36Sopenharmony_ci KEYSTONE_LOW_PHYS_START, 8262306a36Sopenharmony_ci KEYSTONE_HIGH_PHYS_SIZE); 8362306a36Sopenharmony_ci dev_err(dev, "set dma_offset%08llx%s\n", 8462306a36Sopenharmony_ci KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START, 8562306a36Sopenharmony_ci ret ? " failed" : ""); 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci return NOTIFY_OK; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic struct notifier_block platform_nb = { 9162306a36Sopenharmony_ci .notifier_call = keystone_platform_notifier, 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci#endif /* CONFIG_ARM_LPAE */ 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic void __init keystone_init(void) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci#ifdef CONFIG_ARM_LPAE 9862306a36Sopenharmony_ci if (PHYS_OFFSET >= KEYSTONE_HIGH_PHYS_START) 9962306a36Sopenharmony_ci bus_register_notifier(&platform_bus_type, &platform_nb); 10062306a36Sopenharmony_ci#endif 10162306a36Sopenharmony_ci keystone_pm_runtime_init(); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic long long __init keystone_pv_fixup(void) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci long long offset; 10762306a36Sopenharmony_ci u64 mem_start, mem_end; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci mem_start = memblock_start_of_DRAM(); 11062306a36Sopenharmony_ci mem_end = memblock_end_of_DRAM(); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* nothing to do if we are running out of the <32-bit space */ 11362306a36Sopenharmony_ci if (mem_start >= KEYSTONE_LOW_PHYS_START && 11462306a36Sopenharmony_ci mem_end <= KEYSTONE_LOW_PHYS_END) 11562306a36Sopenharmony_ci return 0; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (mem_start < KEYSTONE_HIGH_PHYS_START || 11862306a36Sopenharmony_ci mem_end > KEYSTONE_HIGH_PHYS_END) { 11962306a36Sopenharmony_ci pr_crit("Invalid address space for memory (%08llx-%08llx)\n", 12062306a36Sopenharmony_ci mem_start, mem_end); 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* Populate the arch idmap hook */ 12762306a36Sopenharmony_ci arch_phys_to_idmap_offset = -offset; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci return offset; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic const char *const keystone_match[] __initconst = { 13362306a36Sopenharmony_ci "ti,k2hk", 13462306a36Sopenharmony_ci "ti,k2e", 13562306a36Sopenharmony_ci "ti,k2l", 13662306a36Sopenharmony_ci "ti,k2g", 13762306a36Sopenharmony_ci "ti,keystone", 13862306a36Sopenharmony_ci NULL, 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciDT_MACHINE_START(KEYSTONE, "Keystone") 14262306a36Sopenharmony_ci#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE) 14362306a36Sopenharmony_ci .dma_zone_size = SZ_2G, 14462306a36Sopenharmony_ci#endif 14562306a36Sopenharmony_ci .init_machine = keystone_init, 14662306a36Sopenharmony_ci .dt_compat = keystone_match, 14762306a36Sopenharmony_ci .pv_fixup = keystone_pv_fixup, 14862306a36Sopenharmony_ciMACHINE_END 149