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