mirror of https://github.com/OpenIPC/firmware.git
182 lines
3.9 KiB
Diff
182 lines
3.9 KiB
Diff
--- linux-4.9.37/drivers/goke/cma/cma.c 1970-01-01 03:00:00.000000000 +0300
|
|
+++ linux-4.9.y/drivers/goke/cma/cma.c 2021-06-07 13:01:33.000000000 +0300
|
|
@@ -0,0 +1,178 @@
|
|
+/*
|
|
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
|
|
+ */
|
|
+#include <linux/goke_cma.h>
|
|
+
|
|
+static u32 num_zones;
|
|
+static struct cma_zone zone[ZONE_MAX];
|
|
+static int use_bootargs;
|
|
+
|
|
+unsigned int get_cma_size(void)
|
|
+{
|
|
+ int i;
|
|
+ u64 total = 0;
|
|
+
|
|
+ for (i = 0; i < num_zones; i++) {
|
|
+ total += zone[i].nbytes;
|
|
+ }
|
|
+
|
|
+ /* unit is M */
|
|
+ return (unsigned int)(total >> 20);
|
|
+}
|
|
+
|
|
+int is_cma_address(phys_addr_t phys, unsigned long size)
|
|
+{
|
|
+ phys_addr_t start, end;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < num_zones; i++) {
|
|
+ start = zone[i].phys_start;
|
|
+ end = zone[i].phys_start + zone[i].nbytes;
|
|
+
|
|
+ if ((phys >= start) && ((phys + size) <= end)) {
|
|
+ /*
|
|
+ * Yes, found!
|
|
+ */
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(is_cma_address);
|
|
+
|
|
+static int __init mmz_parse_cmdline(char *s)
|
|
+{
|
|
+ char *line = NULL;
|
|
+ char *tmp = NULL;
|
|
+ char tmpline[256];
|
|
+
|
|
+ if (s == NULL) {
|
|
+ pr_info("There is no cma zone!\n");
|
|
+ return 0;
|
|
+ }
|
|
+ strncpy(tmpline, s, sizeof(tmpline));
|
|
+ tmpline[sizeof(tmpline) - 1] = '\0';
|
|
+ tmp = tmpline;
|
|
+
|
|
+ while ((line = strsep(&tmp, ":")) != NULL) {
|
|
+ int i;
|
|
+ char *argv[6];
|
|
+
|
|
+ for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;)
|
|
+ if (++i == ARRAY_SIZE(argv)) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ zone[num_zones].pdev.coherent_dma_mask = DMA_BIT_MASK(64);
|
|
+ if (i == 4) {
|
|
+ strlcpy(zone[num_zones].name, argv[0], NAME_LEN_MAX);
|
|
+ zone[num_zones].gfp = memparse(argv[1], NULL);
|
|
+ zone[num_zones].phys_start = memparse(argv[2], NULL);
|
|
+ zone[num_zones].nbytes = memparse(argv[3], NULL);
|
|
+ }
|
|
+
|
|
+ else if (i == 6) {
|
|
+ strlcpy(zone[num_zones].name, argv[0], NAME_LEN_MAX);
|
|
+ zone[num_zones].gfp = memparse(argv[1], NULL);
|
|
+ zone[num_zones].phys_start = memparse(argv[2], NULL);
|
|
+ zone[num_zones].nbytes = memparse(argv[3], NULL);
|
|
+ zone[num_zones].alloc_type = memparse(argv[4], NULL);
|
|
+ zone[num_zones].block_align = memparse(argv[5], NULL);
|
|
+ } else {
|
|
+ pr_err("ion parameter is not correct\n");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ num_zones++;
|
|
+ }
|
|
+ if (num_zones != 0) {
|
|
+ use_bootargs = 1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+early_param("mmz", mmz_parse_cmdline);
|
|
+
|
|
+phys_addr_t goke_get_zones_start(void)
|
|
+{
|
|
+ int i;
|
|
+ phys_addr_t lowest_zone_base = memblock_end_of_DRAM();
|
|
+
|
|
+ for (i = 0; i < num_zones; i++) {
|
|
+ if (lowest_zone_base > zone[i].phys_start) {
|
|
+ lowest_zone_base = zone[i].phys_start;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return lowest_zone_base;
|
|
+}
|
|
+EXPORT_SYMBOL(goke_get_zones_start);
|
|
+
|
|
+struct cma_zone *goke_get_cma_zone(const char *name)
|
|
+{
|
|
+ int i = 0;
|
|
+
|
|
+ for (i = 0; i < num_zones; i++)
|
|
+ if (strcmp(zone[i].name, name) == 0) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (i == num_zones) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return &zone[i];
|
|
+}
|
|
+EXPORT_SYMBOL(goke_get_cma_zone);
|
|
+
|
|
+struct device *goke_get_cma_device(const char *name)
|
|
+{
|
|
+ int i = 0;
|
|
+
|
|
+ for (i = 0; i < num_zones; i++)
|
|
+ if (strcmp(zone[i].name, name) == 0) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (i == num_zones) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return &zone[i].pdev;
|
|
+}
|
|
+EXPORT_SYMBOL(goke_get_cma_device);
|
|
+
|
|
+int __init goke_declare_heap_memory(void)
|
|
+{
|
|
+ int i;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (use_bootargs == 0) {
|
|
+ pr_info("cma zone is not set!\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < num_zones; i++) {
|
|
+ ret = dma_declare_contiguous(&zone[i].pdev,
|
|
+ zone[i].nbytes, zone[i].phys_start, 0);
|
|
+ if (ret) {
|
|
+ panic("declare cma zone %s base: %lux size:%lux MB failed. ret:%d",
|
|
+ zone[i].name, (unsigned long)zone[i].phys_start,
|
|
+ (unsigned long)zone[i].nbytes >> 20, ret);
|
|
+ }
|
|
+ zone[i].phys_start = cma_get_base(zone[i].pdev.cma_area);
|
|
+ zone[i].nbytes = cma_get_size(zone[i].pdev.cma_area);
|
|
+
|
|
+ /* FIXME need to fix dma_declare_contiguous return value &&value type */
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL(goke_declare_heap_memory);
|
|
+
|
|
+static int mmz_setup(struct reserved_mem *rmem)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+RESERVEDMEM_OF_DECLARE(cma, "mmz", mmz_setup);
|