Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: android: ion: Add ion driver for Hi6220 SoC platform

Add ion support for hi6220 SoC platform.

Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
Signed-off-by: Yu Dongbin <yudongbin@hisilicon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Chen Feng and committed by
Greg Kroah-Hartman
2b40182a d9c0e6c1

+237
+7
drivers/staging/android/ion/Kconfig
··· 33 33 help 34 34 Choose this option if you wish to use ion on an nVidia Tegra. 35 35 36 + config ION_HISI 37 + tristate "Ion for Hisilicon" 38 + depends on ARCH_HISI && ION 39 + help 40 + Choose this option if you wish to use ion on Hisilicon Platform. 41 + 42 + source "drivers/staging/android/ion/hisilicon/Kconfig"
+1
drivers/staging/android/ion/Makefile
··· 7 7 8 8 obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o 9 9 obj-$(CONFIG_ION_TEGRA) += tegra/ 10 + obj-$(CONFIG_ION_HISI) += hisilicon/ 10 11
+5
drivers/staging/android/ion/hisilicon/Kconfig
··· 1 + config HI6220_ION 2 + bool "Hi6220 ION Driver" 3 + depends on ARCH_HISI && ION 4 + help 5 + Build the Hisilicon Hi6220 ion driver.
+1
drivers/staging/android/ion/hisilicon/Makefile
··· 1 + obj-$(CONFIG_HI6220_ION) += hi6220_ion.o
+223
drivers/staging/android/ion/hisilicon/hi6220_ion.c
··· 1 + /* 2 + * Hisilicon Hi6220 ION Driver 3 + * 4 + * Copyright (c) 2015 Hisilicon Limited. 5 + * 6 + * Author: Chen Feng <puck.chen@hisilicon.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #define pr_fmt(fmt) "Ion: " fmt 14 + 15 + #include <linux/err.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/slab.h> 18 + #include <linux/of.h> 19 + #include <linux/mm.h> 20 + #include "../ion_priv.h" 21 + #include "../ion.h" 22 + 23 + struct hi6220_ion_type_table { 24 + const char *name; 25 + enum ion_heap_type type; 26 + }; 27 + 28 + static struct hi6220_ion_type_table ion_type_table[] = { 29 + {"ion_system", ION_HEAP_TYPE_SYSTEM}, 30 + {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG}, 31 + {"ion_carveout", ION_HEAP_TYPE_CARVEOUT}, 32 + {"ion_chunk", ION_HEAP_TYPE_CHUNK}, 33 + {"ion_dma", ION_HEAP_TYPE_DMA}, 34 + {"ion_custom", ION_HEAP_TYPE_CUSTOM}, 35 + }; 36 + 37 + static struct ion_device *idev; 38 + static int num_heaps; 39 + static struct ion_heap **heaps; 40 + static struct ion_platform_heap **heaps_data; 41 + 42 + static int get_type_by_name(const char *name, enum ion_heap_type *type) 43 + { 44 + int i; 45 + 46 + for (i = 0; i < ARRAY_SIZE(ion_type_table); i++) { 47 + if (strncmp(name, ion_type_table[i].name, strlen(name))) 48 + continue; 49 + 50 + *type = ion_type_table[i].type; 51 + return 0; 52 + } 53 + 54 + return -EINVAL; 55 + } 56 + 57 + static int hi6220_set_platform_data(struct platform_device *pdev) 58 + { 59 + unsigned int base; 60 + unsigned int size; 61 + unsigned int id; 62 + const char *heap_name; 63 + const char *type_name; 64 + enum ion_heap_type type; 65 + int ret; 66 + struct device_node *np; 67 + struct ion_platform_heap *p_data; 68 + const struct device_node *dt_node = pdev->dev.of_node; 69 + int index = 0; 70 + 71 + for_each_child_of_node(dt_node, np) 72 + num_heaps++; 73 + 74 + heaps_data = devm_kzalloc(&pdev->dev, 75 + sizeof(struct ion_platform_heap *) * 76 + num_heaps, 77 + GFP_KERNEL); 78 + if (!heaps_data) 79 + return -ENOMEM; 80 + 81 + for_each_child_of_node(dt_node, np) { 82 + ret = of_property_read_string(np, "heap-name", &heap_name); 83 + if (ret < 0) { 84 + pr_err("check the name of node %s\n", np->name); 85 + continue; 86 + } 87 + 88 + ret = of_property_read_u32(np, "heap-id", &id); 89 + if (ret < 0) { 90 + pr_err("check the id %s\n", np->name); 91 + continue; 92 + } 93 + 94 + ret = of_property_read_u32(np, "heap-base", &base); 95 + if (ret < 0) { 96 + pr_err("check the base of node %s\n", np->name); 97 + continue; 98 + } 99 + 100 + ret = of_property_read_u32(np, "heap-size", &size); 101 + if (ret < 0) { 102 + pr_err("check the size of node %s\n", np->name); 103 + continue; 104 + } 105 + 106 + ret = of_property_read_string(np, "heap-type", &type_name); 107 + if (ret < 0) { 108 + pr_err("check the type of node %s\n", np->name); 109 + continue; 110 + } 111 + 112 + ret = get_type_by_name(type_name, &type); 113 + if (ret < 0) { 114 + pr_err("type name error %s!\n", type_name); 115 + continue; 116 + } 117 + pr_info("heap index %d : name %s base 0x%x size 0x%x id %d type %d\n", 118 + index, heap_name, base, size, id, type); 119 + 120 + p_data = devm_kzalloc(&pdev->dev, 121 + sizeof(struct ion_platform_heap), 122 + GFP_KERNEL); 123 + if (!p_data) 124 + return -ENOMEM; 125 + 126 + p_data->name = heap_name; 127 + p_data->base = base; 128 + p_data->size = size; 129 + p_data->id = id; 130 + p_data->type = type; 131 + 132 + heaps_data[index] = p_data; 133 + index++; 134 + } 135 + return 0; 136 + } 137 + 138 + static int hi6220_ion_probe(struct platform_device *pdev) 139 + { 140 + int i; 141 + int err; 142 + static struct ion_platform_heap *p_heap; 143 + 144 + idev = ion_device_create(NULL); 145 + err = hi6220_set_platform_data(pdev); 146 + if (err) { 147 + pr_err("ion set platform data error!\n"); 148 + goto err_free_idev; 149 + } 150 + heaps = devm_kzalloc(&pdev->dev, 151 + sizeof(struct ion_heap *) * num_heaps, 152 + GFP_KERNEL); 153 + if (!heaps) { 154 + err = -ENOMEM; 155 + goto err_free_idev; 156 + } 157 + 158 + /* 159 + * create the heaps as specified in the dts file 160 + */ 161 + for (i = 0; i < num_heaps; i++) { 162 + p_heap = heaps_data[i]; 163 + heaps[i] = ion_heap_create(p_heap); 164 + if (IS_ERR_OR_NULL(heaps[i])) { 165 + err = PTR_ERR(heaps[i]); 166 + goto err_free_heaps; 167 + } 168 + 169 + ion_device_add_heap(idev, heaps[i]); 170 + 171 + pr_info("%s: adding heap %s of type %d with %lx@%lx\n", 172 + __func__, p_heap->name, p_heap->type, 173 + p_heap->base, (unsigned long)p_heap->size); 174 + } 175 + return err; 176 + 177 + err_free_heaps: 178 + for (i = 0; i < num_heaps; ++i) { 179 + ion_heap_destroy(heaps[i]); 180 + heaps[i] = NULL; 181 + } 182 + err_free_idev: 183 + ion_device_destroy(idev); 184 + 185 + return err; 186 + } 187 + 188 + static int hi6220_ion_remove(struct platform_device *pdev) 189 + { 190 + int i; 191 + 192 + for (i = 0; i < num_heaps; i++) { 193 + ion_heap_destroy(heaps[i]); 194 + heaps[i] = NULL; 195 + } 196 + ion_device_destroy(idev); 197 + 198 + return 0; 199 + } 200 + 201 + static const struct of_device_id hi6220_ion_match_table[] = { 202 + {.compatible = "hisilicon,hi6220-ion"}, 203 + {}, 204 + }; 205 + 206 + static struct platform_driver hi6220_ion_driver = { 207 + .probe = hi6220_ion_probe, 208 + .remove = hi6220_ion_remove, 209 + .driver = { 210 + .name = "ion-hi6220", 211 + .of_match_table = hi6220_ion_match_table, 212 + }, 213 + }; 214 + 215 + static int __init hi6220_ion_init(void) 216 + { 217 + int ret; 218 + 219 + ret = platform_driver_register(&hi6220_ion_driver); 220 + return ret; 221 + } 222 + 223 + subsys_initcall(hi6220_ion_init);