18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008-2015 Freescale Semiconductor Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 58c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met: 68c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 78c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 88c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 98c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 108c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 118c2ecf20Sopenharmony_ci * * Neither the name of Freescale Semiconductor nor the 128c2ecf20Sopenharmony_ci * names of its contributors may be used to endorse or promote products 138c2ecf20Sopenharmony_ci * derived from this software without specific prior written permission. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the 178c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software 188c2ecf20Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any 198c2ecf20Sopenharmony_ci * later version. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 228c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 238c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 248c2ecf20Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 258c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 268c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 278c2ecf20Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 288c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 298c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 308c2ecf20Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include "fman_muram.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/io.h> 368c2ecf20Sopenharmony_ci#include <linux/slab.h> 378c2ecf20Sopenharmony_ci#include <linux/genalloc.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct muram_info { 408c2ecf20Sopenharmony_ci struct gen_pool *pool; 418c2ecf20Sopenharmony_ci void __iomem *vbase; 428c2ecf20Sopenharmony_ci size_t size; 438c2ecf20Sopenharmony_ci phys_addr_t pbase; 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic unsigned long fman_muram_vbase_to_offset(struct muram_info *muram, 478c2ecf20Sopenharmony_ci unsigned long vaddr) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci return vaddr - (unsigned long)muram->vbase; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/** 538c2ecf20Sopenharmony_ci * fman_muram_init 548c2ecf20Sopenharmony_ci * @base: Pointer to base of memory mapped FM-MURAM. 558c2ecf20Sopenharmony_ci * @size: Size of the FM-MURAM partition. 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * Creates partition in the MURAM. 588c2ecf20Sopenharmony_ci * The routine returns a pointer to the MURAM partition. 598c2ecf20Sopenharmony_ci * This pointer must be passed as to all other FM-MURAM function calls. 608c2ecf20Sopenharmony_ci * No actual initialization or configuration of FM_MURAM hardware is done by 618c2ecf20Sopenharmony_ci * this routine. 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * Return: pointer to FM-MURAM object, or NULL for Failure. 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_cistruct muram_info *fman_muram_init(phys_addr_t base, size_t size) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci struct muram_info *muram; 688c2ecf20Sopenharmony_ci void __iomem *vaddr; 698c2ecf20Sopenharmony_ci int ret; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci muram = kzalloc(sizeof(*muram), GFP_KERNEL); 728c2ecf20Sopenharmony_ci if (!muram) 738c2ecf20Sopenharmony_ci return NULL; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci muram->pool = gen_pool_create(ilog2(64), -1); 768c2ecf20Sopenharmony_ci if (!muram->pool) { 778c2ecf20Sopenharmony_ci pr_err("%s(): MURAM pool create failed\n", __func__); 788c2ecf20Sopenharmony_ci goto muram_free; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci vaddr = ioremap(base, size); 828c2ecf20Sopenharmony_ci if (!vaddr) { 838c2ecf20Sopenharmony_ci pr_err("%s(): MURAM ioremap failed\n", __func__); 848c2ecf20Sopenharmony_ci goto pool_destroy; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci ret = gen_pool_add_virt(muram->pool, (unsigned long)vaddr, 888c2ecf20Sopenharmony_ci base, size, -1); 898c2ecf20Sopenharmony_ci if (ret < 0) { 908c2ecf20Sopenharmony_ci pr_err("%s(): MURAM pool add failed\n", __func__); 918c2ecf20Sopenharmony_ci iounmap(vaddr); 928c2ecf20Sopenharmony_ci goto pool_destroy; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci memset_io(vaddr, 0, (int)size); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci muram->vbase = vaddr; 988c2ecf20Sopenharmony_ci muram->pbase = base; 998c2ecf20Sopenharmony_ci return muram; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cipool_destroy: 1028c2ecf20Sopenharmony_ci gen_pool_destroy(muram->pool); 1038c2ecf20Sopenharmony_cimuram_free: 1048c2ecf20Sopenharmony_ci kfree(muram); 1058c2ecf20Sopenharmony_ci return NULL; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/** 1098c2ecf20Sopenharmony_ci * fman_muram_offset_to_vbase 1108c2ecf20Sopenharmony_ci * @muram: FM-MURAM module pointer. 1118c2ecf20Sopenharmony_ci * @offset: the offset of the memory block 1128c2ecf20Sopenharmony_ci * 1138c2ecf20Sopenharmony_ci * Gives the address of the memory region from specific offset 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * Return: The address of the memory block 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ciunsigned long fman_muram_offset_to_vbase(struct muram_info *muram, 1188c2ecf20Sopenharmony_ci unsigned long offset) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return offset + (unsigned long)muram->vbase; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/** 1248c2ecf20Sopenharmony_ci * fman_muram_alloc 1258c2ecf20Sopenharmony_ci * @muram: FM-MURAM module pointer. 1268c2ecf20Sopenharmony_ci * @size: Size of the memory to be allocated. 1278c2ecf20Sopenharmony_ci * 1288c2ecf20Sopenharmony_ci * Allocate some memory from FM-MURAM partition. 1298c2ecf20Sopenharmony_ci * 1308c2ecf20Sopenharmony_ci * Return: address of the allocated memory; NULL otherwise. 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ciunsigned long fman_muram_alloc(struct muram_info *muram, size_t size) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci unsigned long vaddr; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci vaddr = gen_pool_alloc(muram->pool, size); 1378c2ecf20Sopenharmony_ci if (!vaddr) 1388c2ecf20Sopenharmony_ci return -ENOMEM; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci memset_io((void __iomem *)vaddr, 0, size); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci return fman_muram_vbase_to_offset(muram, vaddr); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/** 1468c2ecf20Sopenharmony_ci * fman_muram_free_mem 1478c2ecf20Sopenharmony_ci * @muram: FM-MURAM module pointer. 1488c2ecf20Sopenharmony_ci * @offset: offset of the memory region to be freed. 1498c2ecf20Sopenharmony_ci * @size: size of the memory to be freed. 1508c2ecf20Sopenharmony_ci * 1518c2ecf20Sopenharmony_ci * Free an allocated memory from FM-MURAM partition. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_civoid fman_muram_free_mem(struct muram_info *muram, unsigned long offset, 1548c2ecf20Sopenharmony_ci size_t size) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci unsigned long addr = fman_muram_offset_to_vbase(muram, offset); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci gen_pool_free(muram->pool, addr, size); 1598c2ecf20Sopenharmony_ci} 160