18428e5adSDave Gerlach /* 28428e5adSDave Gerlach * TI AM33XX SRAM EMIF Driver 38428e5adSDave Gerlach * 48428e5adSDave Gerlach * Copyright (C) 2016-2017 Texas Instruments Inc. 58428e5adSDave Gerlach * Dave Gerlach 68428e5adSDave Gerlach * 78428e5adSDave Gerlach * This program is free software; you can redistribute it and/or 88428e5adSDave Gerlach * modify it under the terms of the GNU General Public License 98428e5adSDave Gerlach * version 2 as published by the Free Software Foundation. 108428e5adSDave Gerlach * 118428e5adSDave Gerlach * This program is distributed in the hope that it will be useful, 128428e5adSDave Gerlach * but WITHOUT ANY WARRANTY; without even the implied warranty of 138428e5adSDave Gerlach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 148428e5adSDave Gerlach * GNU General Public License for more details. 158428e5adSDave Gerlach */ 168428e5adSDave Gerlach 178428e5adSDave Gerlach #include <linux/err.h> 188428e5adSDave Gerlach #include <linux/genalloc.h> 198428e5adSDave Gerlach #include <linux/io.h> 208428e5adSDave Gerlach #include <linux/kernel.h> 218428e5adSDave Gerlach #include <linux/module.h> 228428e5adSDave Gerlach #include <linux/of.h> 238428e5adSDave Gerlach #include <linux/of_platform.h> 248428e5adSDave Gerlach #include <linux/platform_device.h> 258428e5adSDave Gerlach #include <linux/sram.h> 268428e5adSDave Gerlach #include <linux/ti-emif-sram.h> 278428e5adSDave Gerlach 288428e5adSDave Gerlach #include "emif.h" 298428e5adSDave Gerlach 308428e5adSDave Gerlach #define TI_EMIF_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \ 318428e5adSDave Gerlach (unsigned long)&ti_emif_sram) 328428e5adSDave Gerlach 338428e5adSDave Gerlach #define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 348428e5adSDave Gerlach 358428e5adSDave Gerlach struct ti_emif_data { 368428e5adSDave Gerlach phys_addr_t ti_emif_sram_phys; 378428e5adSDave Gerlach phys_addr_t ti_emif_sram_data_phys; 388428e5adSDave Gerlach unsigned long ti_emif_sram_virt; 398428e5adSDave Gerlach unsigned long ti_emif_sram_data_virt; 408428e5adSDave Gerlach struct gen_pool *sram_pool_code; 418428e5adSDave Gerlach struct gen_pool *sram_pool_data; 428428e5adSDave Gerlach struct ti_emif_pm_data pm_data; 438428e5adSDave Gerlach struct ti_emif_pm_functions pm_functions; 448428e5adSDave Gerlach }; 458428e5adSDave Gerlach 468428e5adSDave Gerlach static struct ti_emif_data *emif_instance; 478428e5adSDave Gerlach 488428e5adSDave Gerlach static u32 sram_suspend_address(struct ti_emif_data *emif_data, 498428e5adSDave Gerlach unsigned long addr) 508428e5adSDave Gerlach { 518428e5adSDave Gerlach return (emif_data->ti_emif_sram_virt + 528428e5adSDave Gerlach TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); 538428e5adSDave Gerlach } 548428e5adSDave Gerlach 558428e5adSDave Gerlach static phys_addr_t sram_resume_address(struct ti_emif_data *emif_data, 568428e5adSDave Gerlach unsigned long addr) 578428e5adSDave Gerlach { 588428e5adSDave Gerlach return ((unsigned long)emif_data->ti_emif_sram_phys + 598428e5adSDave Gerlach TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); 608428e5adSDave Gerlach } 618428e5adSDave Gerlach 628428e5adSDave Gerlach static void ti_emif_free_sram(struct ti_emif_data *emif_data) 638428e5adSDave Gerlach { 648428e5adSDave Gerlach gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, 658428e5adSDave Gerlach ti_emif_sram_sz); 668428e5adSDave Gerlach gen_pool_free(emif_data->sram_pool_data, 678428e5adSDave Gerlach emif_data->ti_emif_sram_data_virt, 688428e5adSDave Gerlach sizeof(struct emif_regs_amx3)); 698428e5adSDave Gerlach } 708428e5adSDave Gerlach 718428e5adSDave Gerlach static int ti_emif_alloc_sram(struct device *dev, 728428e5adSDave Gerlach struct ti_emif_data *emif_data) 738428e5adSDave Gerlach { 748428e5adSDave Gerlach struct device_node *np = dev->of_node; 758428e5adSDave Gerlach int ret; 768428e5adSDave Gerlach 778428e5adSDave Gerlach emif_data->sram_pool_code = of_gen_pool_get(np, "sram", 0); 788428e5adSDave Gerlach if (!emif_data->sram_pool_code) { 798428e5adSDave Gerlach dev_err(dev, "Unable to get sram pool for ocmcram code\n"); 808428e5adSDave Gerlach return -ENODEV; 818428e5adSDave Gerlach } 828428e5adSDave Gerlach 838428e5adSDave Gerlach emif_data->ti_emif_sram_virt = 848428e5adSDave Gerlach gen_pool_alloc(emif_data->sram_pool_code, 858428e5adSDave Gerlach ti_emif_sram_sz); 868428e5adSDave Gerlach if (!emif_data->ti_emif_sram_virt) { 878428e5adSDave Gerlach dev_err(dev, "Unable to allocate code memory from ocmcram\n"); 888428e5adSDave Gerlach return -ENOMEM; 898428e5adSDave Gerlach } 908428e5adSDave Gerlach 918428e5adSDave Gerlach /* Save physical address to calculate resume offset during pm init */ 928428e5adSDave Gerlach emif_data->ti_emif_sram_phys = 938428e5adSDave Gerlach gen_pool_virt_to_phys(emif_data->sram_pool_code, 948428e5adSDave Gerlach emif_data->ti_emif_sram_virt); 958428e5adSDave Gerlach 968428e5adSDave Gerlach /* Get sram pool for data section and allocate space */ 978428e5adSDave Gerlach emif_data->sram_pool_data = of_gen_pool_get(np, "sram", 1); 988428e5adSDave Gerlach if (!emif_data->sram_pool_data) { 998428e5adSDave Gerlach dev_err(dev, "Unable to get sram pool for ocmcram data\n"); 1008428e5adSDave Gerlach ret = -ENODEV; 1018428e5adSDave Gerlach goto err_free_sram_code; 1028428e5adSDave Gerlach } 1038428e5adSDave Gerlach 1048428e5adSDave Gerlach emif_data->ti_emif_sram_data_virt = 1058428e5adSDave Gerlach gen_pool_alloc(emif_data->sram_pool_data, 1068428e5adSDave Gerlach sizeof(struct emif_regs_amx3)); 1078428e5adSDave Gerlach if (!emif_data->ti_emif_sram_data_virt) { 1088428e5adSDave Gerlach dev_err(dev, "Unable to allocate data memory from ocmcram\n"); 1098428e5adSDave Gerlach ret = -ENOMEM; 1108428e5adSDave Gerlach goto err_free_sram_code; 1118428e5adSDave Gerlach } 1128428e5adSDave Gerlach 1138428e5adSDave Gerlach /* Save physical address to calculate resume offset during pm init */ 1148428e5adSDave Gerlach emif_data->ti_emif_sram_data_phys = 1158428e5adSDave Gerlach gen_pool_virt_to_phys(emif_data->sram_pool_data, 1168428e5adSDave Gerlach emif_data->ti_emif_sram_data_virt); 1178428e5adSDave Gerlach /* 1188428e5adSDave Gerlach * These functions are called during suspend path while MMU is 1198428e5adSDave Gerlach * still on so add virtual base to offset for absolute address 1208428e5adSDave Gerlach */ 1218428e5adSDave Gerlach emif_data->pm_functions.save_context = 1228428e5adSDave Gerlach sram_suspend_address(emif_data, 1238428e5adSDave Gerlach (unsigned long)ti_emif_save_context); 1248428e5adSDave Gerlach emif_data->pm_functions.enter_sr = 1258428e5adSDave Gerlach sram_suspend_address(emif_data, 1268428e5adSDave Gerlach (unsigned long)ti_emif_enter_sr); 1278428e5adSDave Gerlach emif_data->pm_functions.abort_sr = 1288428e5adSDave Gerlach sram_suspend_address(emif_data, 1298428e5adSDave Gerlach (unsigned long)ti_emif_abort_sr); 1308428e5adSDave Gerlach 1318428e5adSDave Gerlach /* 1328428e5adSDave Gerlach * These are called during resume path when MMU is not enabled 1338428e5adSDave Gerlach * so physical address is used instead 1348428e5adSDave Gerlach */ 1358428e5adSDave Gerlach emif_data->pm_functions.restore_context = 1368428e5adSDave Gerlach sram_resume_address(emif_data, 1378428e5adSDave Gerlach (unsigned long)ti_emif_restore_context); 1388428e5adSDave Gerlach emif_data->pm_functions.exit_sr = 1398428e5adSDave Gerlach sram_resume_address(emif_data, 1408428e5adSDave Gerlach (unsigned long)ti_emif_exit_sr); 1418428e5adSDave Gerlach 1428428e5adSDave Gerlach emif_data->pm_data.regs_virt = 1438428e5adSDave Gerlach (struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt; 1448428e5adSDave Gerlach emif_data->pm_data.regs_phys = emif_data->ti_emif_sram_data_phys; 1458428e5adSDave Gerlach 1468428e5adSDave Gerlach return 0; 1478428e5adSDave Gerlach 1488428e5adSDave Gerlach err_free_sram_code: 1498428e5adSDave Gerlach gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, 1508428e5adSDave Gerlach ti_emif_sram_sz); 1518428e5adSDave Gerlach return ret; 1528428e5adSDave Gerlach } 1538428e5adSDave Gerlach 1548428e5adSDave Gerlach static int ti_emif_push_sram(struct device *dev, struct ti_emif_data *emif_data) 1558428e5adSDave Gerlach { 1568428e5adSDave Gerlach void *copy_addr; 1578428e5adSDave Gerlach u32 data_addr; 1588428e5adSDave Gerlach 1598428e5adSDave Gerlach copy_addr = sram_exec_copy(emif_data->sram_pool_code, 1608428e5adSDave Gerlach (void *)emif_data->ti_emif_sram_virt, 1618428e5adSDave Gerlach &ti_emif_sram, ti_emif_sram_sz); 1628428e5adSDave Gerlach if (!copy_addr) { 1638428e5adSDave Gerlach dev_err(dev, "Cannot copy emif code to sram\n"); 1648428e5adSDave Gerlach return -ENODEV; 1658428e5adSDave Gerlach } 1668428e5adSDave Gerlach 1678428e5adSDave Gerlach data_addr = sram_suspend_address(emif_data, 1688428e5adSDave Gerlach (unsigned long)&ti_emif_pm_sram_data); 1698428e5adSDave Gerlach copy_addr = sram_exec_copy(emif_data->sram_pool_code, 1708428e5adSDave Gerlach (void *)data_addr, 1718428e5adSDave Gerlach &emif_data->pm_data, 1728428e5adSDave Gerlach sizeof(emif_data->pm_data)); 1738428e5adSDave Gerlach if (!copy_addr) { 1748428e5adSDave Gerlach dev_err(dev, "Cannot copy emif data to code sram\n"); 1758428e5adSDave Gerlach return -ENODEV; 1768428e5adSDave Gerlach } 1778428e5adSDave Gerlach 1788428e5adSDave Gerlach return 0; 1798428e5adSDave Gerlach } 1808428e5adSDave Gerlach 1818428e5adSDave Gerlach /* 1828428e5adSDave Gerlach * Due to Usage Note 3.1.2 "DDR3: JEDEC Compliance for Maximum 1838428e5adSDave Gerlach * Self-Refresh Command Limit" found in AM335x Silicon Errata 1848428e5adSDave Gerlach * (Document SPRZ360F Revised November 2013) we must configure 1858428e5adSDave Gerlach * the self refresh delay timer to 0xA (8192 cycles) to avoid 1868428e5adSDave Gerlach * generating too many refresh command from the EMIF. 1878428e5adSDave Gerlach */ 1888428e5adSDave Gerlach static void ti_emif_configure_sr_delay(struct ti_emif_data *emif_data) 1898428e5adSDave Gerlach { 1908428e5adSDave Gerlach writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, 1918428e5adSDave Gerlach (emif_data->pm_data.ti_emif_base_addr_virt + 1928428e5adSDave Gerlach EMIF_POWER_MANAGEMENT_CONTROL)); 1938428e5adSDave Gerlach 1948428e5adSDave Gerlach writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, 1958428e5adSDave Gerlach (emif_data->pm_data.ti_emif_base_addr_virt + 1968428e5adSDave Gerlach EMIF_POWER_MANAGEMENT_CTRL_SHDW)); 1978428e5adSDave Gerlach } 1988428e5adSDave Gerlach 1998428e5adSDave Gerlach /** 2008428e5adSDave Gerlach * ti_emif_copy_pm_function_table - copy mapping of pm funcs in sram 2018428e5adSDave Gerlach * @sram_pool: pointer to struct gen_pool where dst resides 2028428e5adSDave Gerlach * @dst: void * to address that table should be copied 2038428e5adSDave Gerlach * 2048428e5adSDave Gerlach * Returns 0 if success other error code if table is not available 2058428e5adSDave Gerlach */ 2068428e5adSDave Gerlach int ti_emif_copy_pm_function_table(struct gen_pool *sram_pool, void *dst) 2078428e5adSDave Gerlach { 2088428e5adSDave Gerlach void *copy_addr; 2098428e5adSDave Gerlach 2108428e5adSDave Gerlach if (!emif_instance) 2118428e5adSDave Gerlach return -ENODEV; 2128428e5adSDave Gerlach 2138428e5adSDave Gerlach copy_addr = sram_exec_copy(sram_pool, dst, 2148428e5adSDave Gerlach &emif_instance->pm_functions, 2158428e5adSDave Gerlach sizeof(emif_instance->pm_functions)); 2168428e5adSDave Gerlach if (!copy_addr) 2178428e5adSDave Gerlach return -ENODEV; 2188428e5adSDave Gerlach 2198428e5adSDave Gerlach return 0; 2208428e5adSDave Gerlach } 2218428e5adSDave Gerlach EXPORT_SYMBOL_GPL(ti_emif_copy_pm_function_table); 2228428e5adSDave Gerlach 2238428e5adSDave Gerlach /** 2248428e5adSDave Gerlach * ti_emif_get_mem_type - return type for memory type in use 2258428e5adSDave Gerlach * 2268428e5adSDave Gerlach * Returns memory type value read from EMIF or error code if fails 2278428e5adSDave Gerlach */ 2288428e5adSDave Gerlach int ti_emif_get_mem_type(void) 2298428e5adSDave Gerlach { 2308428e5adSDave Gerlach unsigned long temp; 2318428e5adSDave Gerlach 2328428e5adSDave Gerlach if (!emif_instance) 2338428e5adSDave Gerlach return -ENODEV; 2348428e5adSDave Gerlach 2358428e5adSDave Gerlach temp = readl(emif_instance->pm_data.ti_emif_base_addr_virt + 2368428e5adSDave Gerlach EMIF_SDRAM_CONFIG); 2378428e5adSDave Gerlach 2388428e5adSDave Gerlach temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT; 2398428e5adSDave Gerlach return temp; 2408428e5adSDave Gerlach } 2418428e5adSDave Gerlach EXPORT_SYMBOL_GPL(ti_emif_get_mem_type); 2428428e5adSDave Gerlach 2438428e5adSDave Gerlach static const struct of_device_id ti_emif_of_match[] = { 2448428e5adSDave Gerlach { .compatible = "ti,emif-am3352", .data = 2458428e5adSDave Gerlach (void *)EMIF_SRAM_AM33_REG_LAYOUT, }, 2468428e5adSDave Gerlach { .compatible = "ti,emif-am4372", .data = 2478428e5adSDave Gerlach (void *)EMIF_SRAM_AM43_REG_LAYOUT, }, 2488428e5adSDave Gerlach {}, 2498428e5adSDave Gerlach }; 2508428e5adSDave Gerlach MODULE_DEVICE_TABLE(of, ti_emif_of_match); 2518428e5adSDave Gerlach 2528428e5adSDave Gerlach static int ti_emif_probe(struct platform_device *pdev) 2538428e5adSDave Gerlach { 2548428e5adSDave Gerlach int ret; 2558428e5adSDave Gerlach struct resource *res; 2568428e5adSDave Gerlach struct device *dev = &pdev->dev; 2578428e5adSDave Gerlach const struct of_device_id *match; 2588428e5adSDave Gerlach struct ti_emif_data *emif_data; 2598428e5adSDave Gerlach 2608428e5adSDave Gerlach emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL); 2618428e5adSDave Gerlach if (!emif_data) 2628428e5adSDave Gerlach return -ENOMEM; 2638428e5adSDave Gerlach 2648428e5adSDave Gerlach match = of_match_device(ti_emif_of_match, &pdev->dev); 2658428e5adSDave Gerlach if (!match) 2668428e5adSDave Gerlach return -ENODEV; 2678428e5adSDave Gerlach 2688428e5adSDave Gerlach emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data; 2698428e5adSDave Gerlach 2708428e5adSDave Gerlach res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2718428e5adSDave Gerlach emif_data->pm_data.ti_emif_base_addr_virt = devm_ioremap_resource(dev, 2728428e5adSDave Gerlach res); 2738428e5adSDave Gerlach if (IS_ERR(emif_data->pm_data.ti_emif_base_addr_virt)) { 2748428e5adSDave Gerlach dev_err(dev, "could not ioremap emif mem\n"); 2758428e5adSDave Gerlach ret = PTR_ERR(emif_data->pm_data.ti_emif_base_addr_virt); 2768428e5adSDave Gerlach return ret; 2778428e5adSDave Gerlach } 2788428e5adSDave Gerlach 2798428e5adSDave Gerlach emif_data->pm_data.ti_emif_base_addr_phys = res->start; 2808428e5adSDave Gerlach 2818428e5adSDave Gerlach ti_emif_configure_sr_delay(emif_data); 2828428e5adSDave Gerlach 2838428e5adSDave Gerlach ret = ti_emif_alloc_sram(dev, emif_data); 2848428e5adSDave Gerlach if (ret) 2858428e5adSDave Gerlach return ret; 2868428e5adSDave Gerlach 2878428e5adSDave Gerlach ret = ti_emif_push_sram(dev, emif_data); 2888428e5adSDave Gerlach if (ret) 2898428e5adSDave Gerlach goto fail_free_sram; 2908428e5adSDave Gerlach 2918428e5adSDave Gerlach emif_instance = emif_data; 2928428e5adSDave Gerlach 2938428e5adSDave Gerlach return 0; 2948428e5adSDave Gerlach 2958428e5adSDave Gerlach fail_free_sram: 2968428e5adSDave Gerlach ti_emif_free_sram(emif_data); 2978428e5adSDave Gerlach 2988428e5adSDave Gerlach return ret; 2998428e5adSDave Gerlach } 3008428e5adSDave Gerlach 3018428e5adSDave Gerlach static int ti_emif_remove(struct platform_device *pdev) 3028428e5adSDave Gerlach { 3038428e5adSDave Gerlach struct device *dev = &pdev->dev; 3048428e5adSDave Gerlach struct ti_emif_data *emif_data = emif_instance; 3058428e5adSDave Gerlach 3068428e5adSDave Gerlach emif_instance = NULL; 3078428e5adSDave Gerlach 3088428e5adSDave Gerlach ti_emif_free_sram(emif_data); 3098428e5adSDave Gerlach 3108428e5adSDave Gerlach return 0; 3118428e5adSDave Gerlach } 3128428e5adSDave Gerlach 3138428e5adSDave Gerlach static struct platform_driver ti_emif_driver = { 3148428e5adSDave Gerlach .probe = ti_emif_probe, 3158428e5adSDave Gerlach .remove = ti_emif_remove, 3168428e5adSDave Gerlach .driver = { 3178428e5adSDave Gerlach .name = KBUILD_MODNAME, 3188428e5adSDave Gerlach .of_match_table = of_match_ptr(ti_emif_of_match), 3198428e5adSDave Gerlach }, 3208428e5adSDave Gerlach }; 3218428e5adSDave Gerlach module_platform_driver(ti_emif_driver); 3228428e5adSDave Gerlach 3238428e5adSDave Gerlach MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>"); 3248428e5adSDave Gerlach MODULE_DESCRIPTION("Texas Instruments SRAM EMIF driver"); 3258428e5adSDave Gerlach MODULE_LICENSE("GPL v2"); 326