From patchwork Wed Jun 26 13:40:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 18134 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f200.google.com (mail-ve0-f200.google.com [209.85.128.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id F264725E0D for ; Wed, 26 Jun 2013 13:41:05 +0000 (UTC) Received: by mail-ve0-f200.google.com with SMTP id m1sf19549424ves.7 for ; Wed, 26 Jun 2013 06:41:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-beenthere:x-forwarded-to:x-forwarded-for:delivered-to:x-auditid :from:to:date:message-id:x-mailer:in-reply-to:references :x-brightmail-tracker:cc:subject:x-beenthere:x-mailman-version :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:errors-to:sender :x-gm-message-state:x-original-sender :x-original-authentication-results:mailing-list:x-google-group-id :content-type:content-transfer-encoding; bh=1wOIZOmWkMRbVEMaWZCfxmi3eAoNVnPzS1Ch4ESEviA=; b=Ut42Kbc9X8NaXCpb9p1x5tYoVUDsDBwaNMuMgLvf6aTcax8tFwZJjX+txgNZnqaSvj pgtG7ruDARURjcm0pqwzOqHwnUObAzfxFcyDRkx4was1bEICAnHilulwXLWe5b6kXTCz tRv8xyUBXjORGaj6NeVKd+VSZ5/LyvqtiETctJkDfebFfie5rrnG2BVwlD+9SSO0vFoF 5PyyCrKdO22LWTFLkJasj+qHyaA4mZDqV6CX/SJhfC4OFpnDlRtCo6Z+oB7gOxVgeFWn 3mCZ+y4nA+qa8NJq4lL5dQPejRG4Bj7raYTSgPe59Hz2hVZbWCN1M2T7Q+ALf05fzcoz 0DvA== X-Received: by 10.224.59.205 with SMTP id m13mr3901636qah.7.1372254065647; Wed, 26 Jun 2013 06:41:05 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.39.3 with SMTP id l3ls403081qek.62.gmail; Wed, 26 Jun 2013 06:41:05 -0700 (PDT) X-Received: by 10.52.163.46 with SMTP id yf14mr1404213vdb.58.1372254065554; Wed, 26 Jun 2013 06:41:05 -0700 (PDT) Received: from mail-vb0-x232.google.com (mail-vb0-x232.google.com [2607:f8b0:400c:c02::232]) by mx.google.com with ESMTPS id ef7si7689999vdc.72.2013.06.26.06.41.05 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 26 Jun 2013 06:41:05 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:400c:c02::232 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c02::232; Received: by mail-vb0-f50.google.com with SMTP id w16so10818491vbb.9 for ; Wed, 26 Jun 2013 06:41:05 -0700 (PDT) X-Received: by 10.58.45.70 with SMTP id k6mr1788314vem.9.1372254065440; Wed, 26 Jun 2013 06:41:05 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.165.8 with SMTP id yu8csp109488veb; Wed, 26 Jun 2013 06:41:04 -0700 (PDT) X-Received: by 10.180.211.171 with SMTP id nd11mr2723852wic.17.1372254064303; Wed, 26 Jun 2013 06:41:04 -0700 (PDT) Received: from ip-10-141-164-156.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id bl7si9845865wjc.121.2013.06.26.06.41.02 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 26 Jun 2013 06:41:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-141-164-156.ec2.internal) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1Urpxl-0000fo-Cs; Wed, 26 Jun 2013 13:40:45 +0000 Received: from mailout1.samsung.com ([203.254.224.24]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1Urpxk-0000fE-08 for linaro-mm-sig@lists.linaro.org; Wed, 26 Jun 2013 13:40:44 +0000 Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MP000H935ZSX130@mailout1.samsung.com> for linaro-mm-sig@lists.linaro.org; Wed, 26 Jun 2013 22:40:53 +0900 (KST) X-AuditID: cbfee61b-b7f8e6d00000524c-23-51caef647247 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 1A.F8.21068.46FEAC15; Wed, 26 Jun 2013 22:40:53 +0900 (KST) Received: from localhost.localdomain ([106.116.147.30]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MP000FD85ZDHR90@mmp2.samsung.com>; Wed, 26 Jun 2013 22:40:52 +0900 (KST) From: Marek Szyprowski To: linux-arm-kernel@lists.infradead.org, linaro-mm-sig@lists.linaro.org, devicetree-discuss@lists.ozlabs.org Date: Wed, 26 Jun 2013 15:40:09 +0200 Message-id: <1372254009-25307-3-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1372254009-25307-1-git-send-email-m.szyprowski@samsung.com> References: <1372254009-25307-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrBLMWRmVeSWpSXmKPExsVy+t9jQd3U96cCDeZfZLb4O+kYu8WB2Q9Z LV6d2chmcbbpDbvF9s4Z7BZfrjxkstj0+Bqrxdojd9ktNrw8yGSx4HgLq8Wf6XIWp65/ZrP4 /u0bm8Xf7ZtYLA6/aWe1WD/jNYuDgMfvX5MYPS739TJ57Jx1l91j85J6j9v/HjN7nJ+xkNHj yokmVo91f14xefT/NfDo27KK0ePnS50A7igum5TUnMyy1CJ9uwSujGvH3jAWdLhXvL1wm6mB scmyi5GTQ0LAROLs8WYmCFtM4sK99WxdjFwcQgLTGSUOXF/ACuG0M0l8PtvMDlLFJmAo0fW2 C6iKg0NEIF9i9SxekDCzQBuLxIsNLCBhYYEwiYULwkHCLAKqEvM6/7ODhHkFPCS2zuECMSUE FCTmTLIBqeAU8JSY2HUU7AIhoIrt97+wTWDkXcDIsIpRNLUguaA4KT3XSK84Mbe4NC9dLzk/ dxMjOLyfSe9gXNVgcYhRgINRiYdXYevJQCHWxLLiytxDjBIczEoivG/mnwoU4k1JrKxKLcqP LyrNSS0+xCjNwaIkznuw1TpQSCA9sSQ1OzW1ILUIJsvEwSnVwBhwulwzSUYjYdrn1YFrJ9lW SlT77lz+2nFtiUg361T9/1uf9Es0fXyzyyjt5NkY5defPnBxvVdxuv4oSkx3jaXx/Jv6SzoK Up8vWPfpThGHwJPSdbO2LvIvbRQqmOWg0LggLCLl0t7DZoVWmle6YqZ+4u1S3rA7QCRFdfln zZkKKpee+257d0aJpTgj0VCLuag4EQCIlsGTawIAAA== Cc: Arnd Bergmann , Tomasz Figa , Michal Nazarewicz , Grant Likely , Kyungmin Park , Rob Herring , Sylwester Nawrocki , Olof Johansson , Sascha Hauer Subject: [Linaro-mm-sig] [PATCH v3 2/2] drivers: dma-contiguous: add initialization from device tree X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-mm-sig-bounces@lists.linaro.org Sender: linaro-mm-sig-bounces@lists.linaro.org X-Gm-Message-State: ALoCoQm3qRJCYRmpdTgaod7EyVjbLGMwRXQ/i8sDneCIneOGsDRXG3HdMNDHeWsYtRHT/hPibGuW X-Original-Sender: m.szyprowski@samsung.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c02::232 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Add device tree support for contiguous memory regions defined in device tree. Initialization is done in 2 steps. First, the contiguous memory is reserved, what happens very early when only flattened device tree is available. Then on device initialization the corresponding cma regions are assigned to each device structure. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park --- .../devicetree/bindings/contiguous-memory.txt | 94 ++++++++++++++ arch/arm/boot/dts/skeleton.dtsi | 7 +- drivers/base/dma-contiguous.c | 132 ++++++++++++++++++++ 3 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/contiguous-memory.txt diff --git a/Documentation/devicetree/bindings/contiguous-memory.txt b/Documentation/devicetree/bindings/contiguous-memory.txt new file mode 100644 index 0000000..a733df2 --- /dev/null +++ b/Documentation/devicetree/bindings/contiguous-memory.txt @@ -0,0 +1,94 @@ +*** Contiguous Memory binding *** + +The /chosen/contiguous-memory node provides runtime configuration of +contiguous memory regions for Linux kernel. Such regions can be created +for special usage by various device drivers. A good example are +contiguous memory allocations or memory sharing with other operating +system(s) on the same hardware board. Those special memory regions might +depend on the selected board configuration and devices used on the target +system. + +Parameters for each memory region can be encoded into the device tree +with the following convention: + +contiguous-memory { + + (name): region@(base-address) { + reg = <(baseaddr) (size)>; + (linux,default-contiguous-region); + device = <&device_0 &device_1 ...> + }; +}; + +name: an name given to the defined region; +base-address: the base address of the defined region; +size: the size of the memory region (bytes); +linux,default-contiguous-region: property indicating that the region + is the default region for all contiguous memory + allocations, Linux specific (optional); +device: array of phandles to the client device nodes, which + will use the defined contiguous region. + +Each defined region must use unique name. It is optional to specify the +base address, so if one wants to use autoconfiguration of the base +address, he must specify the '0' as base address in the 'reg' property +and assign ann uniqe name to such regions, following the convention: +'region@0', 'region@1', 'region@2', ... + + +*** Example *** + +This example defines a memory configuration containing 2 contiguous +regions for Linux kernel, one default of all device drivers (named +contig_mem, autoconfigured at boot time, 64MiB) and one dedicated to the +framebuffer device (named display_mem, placed at 0x78000000, 64MiB). The +display_mem region is then assigned to fb@12300000, scaller@12500000 and +codec@12600000 devices for contiguous memory allocation with Linux +kernel drivers. + +The reason for creating a separate region for framebuffer device is to +match the framebuffer base address to the one configured by bootloader, +so once Linux kernel drivers starts no glitches on the displayed boot +logo appears. Scaller and codec drivers should share the memory +allocations with framebuffer driver. + +/ { + /* ... */ + + chosen { + bootargs = /* ... */ + + contiguous-memory { + + /* + * global autoconfigured region + * for contiguous allocations + */ + contig_mem: region@0 { + reg = <0x0 0x4000000>; + linux,default-contiguous-region; + }; + + /* + * special region for framebuffer and + * multimedia processing devices + */ + display_mem: region@78000000 { + reg = <0x78000000 0x4000000>; + device = <&fb0 &scaller &codec>; + }; + }; + }; + + /* ... */ + + fb0: fb@12300000 { + status = "okay"; + }; + scaller: scaller@12500000 { + status = "okay"; + }; + codec: codec@12600000 { + status = "okay"; + }; +}; diff --git a/arch/arm/boot/dts/skeleton.dtsi b/arch/arm/boot/dts/skeleton.dtsi index b41d241..cadc3b9 100644 --- a/arch/arm/boot/dts/skeleton.dtsi +++ b/arch/arm/boot/dts/skeleton.dtsi @@ -7,7 +7,12 @@ / { #address-cells = <1>; #size-cells = <1>; - chosen { }; + chosen { + contiguous-memory { + #address-cells = <1>; + #size-cells = <1>; + }; + }; aliases { }; memory { device_type = "memory"; reg = <0 0>; }; }; diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 01fe743..ce5f5d1 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -24,6 +24,9 @@ #include #include +#include +#include +#include #include #include #include @@ -37,6 +40,7 @@ struct cma { unsigned long base_pfn; unsigned long count; unsigned long *bitmap; + char full_name[32]; }; static DEFINE_MUTEX(cma_mutex); @@ -133,6 +137,52 @@ static __init int cma_activate_area(struct cma *cma) return 0; } +/*****************************************************************************/ + +#ifdef CONFIG_OF +int __init cma_fdt_scan(unsigned long node, const char *uname, + int depth, void *data) +{ + static int level; + phys_addr_t base, size; + unsigned long len; + struct cma *cma; + __be32 *prop; + int ret; + + if (depth == 1 && strcmp(uname, "chosen") == 0) { + level = depth; + return 0; + } + + if (depth == 2 && strcmp(uname, "contiguous-memory") == 0) { + level = depth; + return 0; + } + + if (level != 2 || depth != 3 || strncmp(uname, "region@", 7) != 0) + return 0; + + prop = of_get_flat_dt_prop(node, "reg", &len); + if (!prop || (len != 2 * sizeof(unsigned long))) + return 0; + + base = be32_to_cpu(prop[0]); + size = be32_to_cpu(prop[1]); + + pr_info("Found %s, memory base %lx, size %ld MiB\n", uname, + (unsigned long)base, (unsigned long)size / SZ_1M); + + ret = dma_contiguous_reserve_area(size, base, 0, &cma); + if (ret == 0) { + strcpy(cma->full_name, uname); + if (of_get_flat_dt_prop(node, "linux,default-contiguous-region", NULL)) + dma_contiguous_default_area = cma; + } + return 0; +} +#endif + /** * dma_contiguous_reserve() - reserve area(s) for contiguous memory handling * @limit: End address of the reserved memory (optional, 0 for any). @@ -149,6 +199,10 @@ void __init dma_contiguous_reserve(phys_addr_t limit) pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit); +#ifdef CONFIG_OF + of_scan_flat_dt(cma_fdt_scan, NULL); +#endif + if (size_cmdline != -1) { sel_size = size_cmdline; } else { @@ -265,6 +319,80 @@ int __init dma_contiguous_add_device(struct device *dev, struct cma *cma) return 0; } +#ifdef CONFIG_OF + +#define MAX_CMA_MAPS 64 + +static struct cma_map { + struct cma *cma; + struct device_node *node; +} cma_maps[MAX_CMA_MAPS]; +static unsigned cma_map_count; + +static void cma_assign_device_from_dt(struct device *dev) +{ + int i; + for (i = 0; i < cma_map_count; i++) { + if (cma_maps[i].node == dev->of_node) { + dev_set_cma_area(dev, cma_maps[i].cma); + pr_info("Assigned CMA %s to %s device\n", + cma_maps[i].cma->full_name, + dev_name(dev)); + } + } +} + +static int cma_device_init_notifier_call(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct device *dev = data; + if (event == BUS_NOTIFY_ADD_DEVICE && dev->of_node) + cma_assign_device_from_dt(dev); + return NOTIFY_DONE; +} + +static struct notifier_block cma_dev_init_nb = { + .notifier_call = cma_device_init_notifier_call, +}; + +void scan_cma_nodes(void) +{ + struct device_node *parent = of_find_node_by_path("/chosen/contiguous-memory"); + struct device_node *child; + + if (!parent) + return; + + for_each_child_of_node(parent, child) { + struct cma *cma = NULL; + int i; + + for (i = 0; i < cma_area_count; i++) { + char *p = strrchr(child->full_name, '/') + 1; + if (strcmp(p, cma_areas[i].full_name) == 0) + cma = &cma_areas[i]; + } + if (!cma) + continue; + + for (i = 0;; i++) { + struct device_node *node; + node = of_parse_phandle(child, "device", i); + if (!node) + break; + + if (cma_map_count < MAX_CMA_MAPS) { + cma_maps[cma_map_count].cma = cma; + cma_maps[cma_map_count].node = node; + cma_map_count++; + } else { + pr_err("CMA error: too many devices defined\n"); + } + } + } +} +#endif + static int __init cma_init_reserved_areas(void) { int i; @@ -275,6 +403,10 @@ static int __init cma_init_reserved_areas(void) return ret; } +#ifdef CONFIG_OF + scan_cma_nodes(); + bus_register_notifier(&platform_bus_type, &cma_dev_init_nb); +#endif return 0; } core_initcall(cma_init_reserved_areas);