16db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai/* 26db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * Copyright 2009-2010 Freescale Semiconductor, Inc. 36db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * 46db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM 56db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * 66db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * Author: Vivek Mahajan <vivek.mahajan@freescale.com> 76db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * 86db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * This file is derived from the original work done 96db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * by Sylvain Munaut for the Bestcomm SRAM allocator. 106db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * 116db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * This program is free software; you can redistribute it and/or modify it 126db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * under the terms of the GNU General Public License as published by the 136db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * Free Software Foundation; either version 2 of the License, or (at your 146db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * option) any later version. 156db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * 166db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * This program is distributed in the hope that it will be useful, 176db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * but WITHOUT ANY WARRANTY; without even the implied warranty of 186db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 196db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * GNU General Public License for more details. 206db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * 216db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * You should have received a copy of the GNU General Public License 226db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * along with this program; if not, write to the Free Software 236db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 246db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai */ 256db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 266db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai#include <linux/kernel.h> 27e4399461bdf4d230129c99f785ebe6814269427bClaudiu Manoil#include <linux/export.h> 286db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai#include <linux/slab.h> 296db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai#include <linux/err.h> 306db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai#include <linux/of_platform.h> 316db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai#include <asm/pgtable.h> 326db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai#include <asm/fsl_85xx_cache_sram.h> 336db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 346db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai#include "fsl_85xx_cache_ctlr.h" 356db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 366db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raistruct mpc85xx_cache_sram *cache_sram; 376db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 386db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raivoid *mpc85xx_cache_sram_alloc(unsigned int size, 396db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai phys_addr_t *phys, unsigned int align) 406db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai{ 416db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai unsigned long offset; 426db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai unsigned long flags; 436db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 446db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (unlikely(cache_sram == NULL)) 456db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return NULL; 466db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 476db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (!size || (size > cache_sram->size) || (align > cache_sram->size)) { 486db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai pr_err("%s(): size(=%x) or align(=%x) zero or too big\n", 496db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai __func__, size, align); 506db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return NULL; 516db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai } 526db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 536db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if ((align & (align - 1)) || align <= 1) { 546db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai pr_err("%s(): align(=%x) must be power of two and >1\n", 556db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai __func__, align); 566db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return NULL; 576db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai } 586db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 596db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai spin_lock_irqsave(&cache_sram->lock, flags); 606db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai offset = rh_alloc_align(cache_sram->rh, size, align, NULL); 616db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai spin_unlock_irqrestore(&cache_sram->lock, flags); 626db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 636db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (IS_ERR_VALUE(offset)) 646db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return NULL; 656db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 666db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai *phys = cache_sram->base_phys + offset; 676db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 686db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return (unsigned char *)cache_sram->base_virt + offset; 696db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai} 706db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder RaiEXPORT_SYMBOL(mpc85xx_cache_sram_alloc); 716db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 726db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raivoid mpc85xx_cache_sram_free(void *ptr) 736db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai{ 746db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai unsigned long flags; 756db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai BUG_ON(!ptr); 766db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 776db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai spin_lock_irqsave(&cache_sram->lock, flags); 786db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai rh_free(cache_sram->rh, ptr - cache_sram->base_virt); 796db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai spin_unlock_irqrestore(&cache_sram->lock, flags); 806db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai} 816db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder RaiEXPORT_SYMBOL(mpc85xx_cache_sram_free); 826db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 836db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raiint __init instantiate_cache_sram(struct platform_device *dev, 846db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai struct sram_parameters sram_params) 856db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai{ 866db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai int ret = 0; 876db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 886db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (cache_sram) { 896db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev_err(&dev->dev, "Already initialized cache-sram\n"); 906db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return -EBUSY; 916db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai } 926db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 936db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL); 946db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (!cache_sram) { 956db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev_err(&dev->dev, "Out of memory for cache_sram structure\n"); 966db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return -ENOMEM; 976db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai } 986db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 996db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai cache_sram->base_phys = sram_params.sram_offset; 1006db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai cache_sram->size = sram_params.sram_size; 1016db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1026db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (!request_mem_region(cache_sram->base_phys, cache_sram->size, 1036db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai "fsl_85xx_cache_sram")) { 1046db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev_err(&dev->dev, "%s: request memory failed\n", 1056db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev->dev.of_node->full_name); 1066db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai ret = -ENXIO; 1076db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai goto out_free; 1086db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai } 1096db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 11040f1ce7fb7e8b5d4d0821c0f3dc866cb1d47d99cAnton Blanchard cache_sram->base_virt = ioremap_prot(cache_sram->base_phys, 1116db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL); 1126db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (!cache_sram->base_virt) { 11340f1ce7fb7e8b5d4d0821c0f3dc866cb1d47d99cAnton Blanchard dev_err(&dev->dev, "%s: ioremap_prot failed\n", 1146db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev->dev.of_node->full_name); 1156db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai ret = -ENOMEM; 1166db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai goto out_release; 1176db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai } 1186db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1196db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai cache_sram->rh = rh_create(sizeof(unsigned int)); 1206db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai if (IS_ERR(cache_sram->rh)) { 1216db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev_err(&dev->dev, "%s: Unable to create remote heap\n", 1226db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev->dev.of_node->full_name); 1236db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai ret = PTR_ERR(cache_sram->rh); 1246db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai goto out_unmap; 1256db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai } 1266db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1276db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai rh_attach_region(cache_sram->rh, 0, cache_sram->size); 1286db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai spin_lock_init(&cache_sram->lock); 1296db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1306db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n", 1316db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai (unsigned long long)cache_sram->base_phys, cache_sram->size); 1326db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1336db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return 0; 1346db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1356db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raiout_unmap: 1366db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai iounmap(cache_sram->base_virt); 1376db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1386db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raiout_release: 1396db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai release_mem_region(cache_sram->base_phys, cache_sram->size); 1406db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1416db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raiout_free: 1426db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai kfree(cache_sram); 1436db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai return ret; 1446db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai} 1456db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1466db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Raivoid remove_cache_sram(struct platform_device *dev) 1476db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai{ 1486db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai BUG_ON(!cache_sram); 1496db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1506db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai rh_detach_region(cache_sram->rh, 0, cache_sram->size); 1516db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai rh_destroy(cache_sram->rh); 1526db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1536db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai iounmap(cache_sram->base_virt); 1546db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai release_mem_region(cache_sram->base_phys, cache_sram->size); 1556db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1566db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai kfree(cache_sram); 1576db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai cache_sram = NULL; 1586db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai 1596db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n"); 1606db92cc9d07db9f713da8554b4bcdfc8e54ad386Harninder Rai} 161