1/* 2 * linux/arch/arm/mach-mmp/sram.c 3 * 4 * based on mach-davinci/sram.c - DaVinci simple SRAM allocator 5 * 6 * Copyright (c) 2011 Marvell Semiconductors Inc. 7 * All Rights Reserved 8 * 9 * Add for mmp sram support - Leo Yan <leoy@marvell.com> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 * 15 */ 16 17#include <linux/module.h> 18#include <linux/init.h> 19#include <linux/platform_device.h> 20#include <linux/io.h> 21#include <linux/err.h> 22#include <linux/slab.h> 23#include <linux/genalloc.h> 24 25#include <linux/platform_data/dma-mmp_tdma.h> 26 27struct sram_bank_info { 28 char *pool_name; 29 struct gen_pool *gpool; 30 int granularity; 31 32 phys_addr_t sram_phys; 33 void __iomem *sram_virt; 34 u32 sram_size; 35 36 struct list_head node; 37}; 38 39static DEFINE_MUTEX(sram_lock); 40static LIST_HEAD(sram_bank_list); 41 42struct gen_pool *sram_get_gpool(char *pool_name) 43{ 44 struct sram_bank_info *info = NULL; 45 46 if (!pool_name) 47 return NULL; 48 49 mutex_lock(&sram_lock); 50 51 list_for_each_entry(info, &sram_bank_list, node) 52 if (!strcmp(pool_name, info->pool_name)) 53 break; 54 55 mutex_unlock(&sram_lock); 56 57 if (&info->node == &sram_bank_list) 58 return NULL; 59 60 return info->gpool; 61} 62EXPORT_SYMBOL(sram_get_gpool); 63 64static int sram_probe(struct platform_device *pdev) 65{ 66 struct sram_platdata *pdata = pdev->dev.platform_data; 67 struct sram_bank_info *info; 68 struct resource *res; 69 int ret = 0; 70 71 if (!pdata || !pdata->pool_name) 72 return -ENODEV; 73 74 info = kzalloc(sizeof(*info), GFP_KERNEL); 75 if (!info) 76 return -ENOMEM; 77 78 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 79 if (res == NULL) { 80 dev_err(&pdev->dev, "no memory resource defined\n"); 81 ret = -ENODEV; 82 goto out; 83 } 84 85 if (!resource_size(res)) 86 return 0; 87 88 info->sram_phys = (phys_addr_t)res->start; 89 info->sram_size = resource_size(res); 90 info->sram_virt = ioremap(info->sram_phys, info->sram_size); 91 info->pool_name = kstrdup(pdata->pool_name, GFP_KERNEL); 92 info->granularity = pdata->granularity; 93 94 info->gpool = gen_pool_create(ilog2(info->granularity), -1); 95 if (!info->gpool) { 96 dev_err(&pdev->dev, "create pool failed\n"); 97 ret = -ENOMEM; 98 goto create_pool_err; 99 } 100 101 ret = gen_pool_add_virt(info->gpool, (unsigned long)info->sram_virt, 102 info->sram_phys, info->sram_size, -1); 103 if (ret < 0) { 104 dev_err(&pdev->dev, "add new chunk failed\n"); 105 ret = -ENOMEM; 106 goto add_chunk_err; 107 } 108 109 mutex_lock(&sram_lock); 110 list_add(&info->node, &sram_bank_list); 111 mutex_unlock(&sram_lock); 112 113 platform_set_drvdata(pdev, info); 114 115 dev_info(&pdev->dev, "initialized\n"); 116 return 0; 117 118add_chunk_err: 119 gen_pool_destroy(info->gpool); 120create_pool_err: 121 iounmap(info->sram_virt); 122 kfree(info->pool_name); 123out: 124 kfree(info); 125 return ret; 126} 127 128static int sram_remove(struct platform_device *pdev) 129{ 130 struct sram_bank_info *info; 131 132 info = platform_get_drvdata(pdev); 133 if (info == NULL) 134 return -ENODEV; 135 136 mutex_lock(&sram_lock); 137 list_del(&info->node); 138 mutex_unlock(&sram_lock); 139 140 gen_pool_destroy(info->gpool); 141 iounmap(info->sram_virt); 142 kfree(info->pool_name); 143 kfree(info); 144 return 0; 145} 146 147static const struct platform_device_id sram_id_table[] = { 148 { "asram", MMP_ASRAM }, 149 { "isram", MMP_ISRAM }, 150 { } 151}; 152 153static struct platform_driver sram_driver = { 154 .probe = sram_probe, 155 .remove = sram_remove, 156 .driver = { 157 .name = "mmp-sram", 158 }, 159 .id_table = sram_id_table, 160}; 161 162static int __init sram_init(void) 163{ 164 return platform_driver_register(&sram_driver); 165} 166core_initcall(sram_init); 167 168MODULE_LICENSE("GPL"); 169