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

Configure Feed

Select the types of activity you want to include in your feed.

at v4.13-rc2 188 lines 4.4 kB view raw
1/* 2 * rcar-fcp.c -- R-Car Frame Compression Processor Driver 3 * 4 * Copyright (C) 2016 Renesas Electronics Corporation 5 * 6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.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 as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14#include <linux/device.h> 15#include <linux/list.h> 16#include <linux/module.h> 17#include <linux/mutex.h> 18#include <linux/platform_device.h> 19#include <linux/pm_runtime.h> 20#include <linux/slab.h> 21 22#include <media/rcar-fcp.h> 23 24struct rcar_fcp_device { 25 struct list_head list; 26 struct device *dev; 27}; 28 29static LIST_HEAD(fcp_devices); 30static DEFINE_MUTEX(fcp_lock); 31 32/* ----------------------------------------------------------------------------- 33 * Public API 34 */ 35 36/** 37 * rcar_fcp_get - Find and acquire a reference to an FCP instance 38 * @np: Device node of the FCP instance 39 * 40 * Search the list of registered FCP instances for the instance corresponding to 41 * the given device node. 42 * 43 * Return a pointer to the FCP instance, or an ERR_PTR if the instance can't be 44 * found. 45 */ 46struct rcar_fcp_device *rcar_fcp_get(const struct device_node *np) 47{ 48 struct rcar_fcp_device *fcp; 49 50 mutex_lock(&fcp_lock); 51 52 list_for_each_entry(fcp, &fcp_devices, list) { 53 if (fcp->dev->of_node != np) 54 continue; 55 56 get_device(fcp->dev); 57 goto done; 58 } 59 60 fcp = ERR_PTR(-EPROBE_DEFER); 61 62done: 63 mutex_unlock(&fcp_lock); 64 return fcp; 65} 66EXPORT_SYMBOL_GPL(rcar_fcp_get); 67 68/** 69 * rcar_fcp_put - Release a reference to an FCP instance 70 * @fcp: The FCP instance 71 * 72 * Release the FCP instance acquired by a call to rcar_fcp_get(). 73 */ 74void rcar_fcp_put(struct rcar_fcp_device *fcp) 75{ 76 if (fcp) 77 put_device(fcp->dev); 78} 79EXPORT_SYMBOL_GPL(rcar_fcp_put); 80 81struct device *rcar_fcp_get_device(struct rcar_fcp_device *fcp) 82{ 83 return fcp->dev; 84} 85EXPORT_SYMBOL_GPL(rcar_fcp_get_device); 86 87/** 88 * rcar_fcp_enable - Enable an FCP 89 * @fcp: The FCP instance 90 * 91 * Before any memory access through an FCP is performed by a module, the FCP 92 * must be enabled by a call to this function. The enable calls are reference 93 * counted, each successful call must be followed by one rcar_fcp_disable() 94 * call when no more memory transfer can occur through the FCP. 95 * 96 * Return 0 on success or a negative error code if an error occurs. The enable 97 * reference count isn't increased when this function returns an error. 98 */ 99int rcar_fcp_enable(struct rcar_fcp_device *fcp) 100{ 101 int ret; 102 103 if (!fcp) 104 return 0; 105 106 ret = pm_runtime_get_sync(fcp->dev); 107 if (ret < 0) 108 return ret; 109 110 return 0; 111} 112EXPORT_SYMBOL_GPL(rcar_fcp_enable); 113 114/** 115 * rcar_fcp_disable - Disable an FCP 116 * @fcp: The FCP instance 117 * 118 * This function is the counterpart of rcar_fcp_enable(). As enable calls are 119 * reference counted a disable call may not disable the FCP synchronously. 120 */ 121void rcar_fcp_disable(struct rcar_fcp_device *fcp) 122{ 123 if (fcp) 124 pm_runtime_put(fcp->dev); 125} 126EXPORT_SYMBOL_GPL(rcar_fcp_disable); 127 128/* ----------------------------------------------------------------------------- 129 * Platform Driver 130 */ 131 132static int rcar_fcp_probe(struct platform_device *pdev) 133{ 134 struct rcar_fcp_device *fcp; 135 136 fcp = devm_kzalloc(&pdev->dev, sizeof(*fcp), GFP_KERNEL); 137 if (fcp == NULL) 138 return -ENOMEM; 139 140 fcp->dev = &pdev->dev; 141 142 pm_runtime_enable(&pdev->dev); 143 144 mutex_lock(&fcp_lock); 145 list_add_tail(&fcp->list, &fcp_devices); 146 mutex_unlock(&fcp_lock); 147 148 platform_set_drvdata(pdev, fcp); 149 150 return 0; 151} 152 153static int rcar_fcp_remove(struct platform_device *pdev) 154{ 155 struct rcar_fcp_device *fcp = platform_get_drvdata(pdev); 156 157 mutex_lock(&fcp_lock); 158 list_del(&fcp->list); 159 mutex_unlock(&fcp_lock); 160 161 pm_runtime_disable(&pdev->dev); 162 163 return 0; 164} 165 166static const struct of_device_id rcar_fcp_of_match[] = { 167 { .compatible = "renesas,fcpf" }, 168 { .compatible = "renesas,fcpv" }, 169 { }, 170}; 171MODULE_DEVICE_TABLE(of, rcar_fcp_of_match); 172 173static struct platform_driver rcar_fcp_platform_driver = { 174 .probe = rcar_fcp_probe, 175 .remove = rcar_fcp_remove, 176 .driver = { 177 .name = "rcar-fcp", 178 .of_match_table = rcar_fcp_of_match, 179 .suppress_bind_attrs = true, 180 }, 181}; 182 183module_platform_driver(rcar_fcp_platform_driver); 184 185MODULE_ALIAS("rcar-fcp"); 186MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 187MODULE_DESCRIPTION("Renesas FCP Driver"); 188MODULE_LICENSE("GPL");