cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

base.c (6314B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * OMAP Display Subsystem Base
      4 *
      5 * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com/
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/list.h>
     10#include <linux/module.h>
     11#include <linux/mutex.h>
     12#include <linux/of.h>
     13#include <linux/of_graph.h>
     14#include <linux/platform_device.h>
     15
     16#include "dss.h"
     17#include "omapdss.h"
     18
     19struct dispc_device *dispc_get_dispc(struct dss_device *dss)
     20{
     21	return dss->dispc;
     22}
     23
     24/* -----------------------------------------------------------------------------
     25 * OMAP DSS Devices Handling
     26 */
     27
     28static LIST_HEAD(omapdss_devices_list);
     29static DEFINE_MUTEX(omapdss_devices_lock);
     30
     31void omapdss_device_register(struct omap_dss_device *dssdev)
     32{
     33	mutex_lock(&omapdss_devices_lock);
     34	list_add_tail(&dssdev->list, &omapdss_devices_list);
     35	mutex_unlock(&omapdss_devices_lock);
     36}
     37
     38void omapdss_device_unregister(struct omap_dss_device *dssdev)
     39{
     40	mutex_lock(&omapdss_devices_lock);
     41	list_del(&dssdev->list);
     42	mutex_unlock(&omapdss_devices_lock);
     43}
     44
     45static bool omapdss_device_is_registered(struct device_node *node)
     46{
     47	struct omap_dss_device *dssdev;
     48	bool found = false;
     49
     50	mutex_lock(&omapdss_devices_lock);
     51
     52	list_for_each_entry(dssdev, &omapdss_devices_list, list) {
     53		if (dssdev->dev->of_node == node) {
     54			found = true;
     55			break;
     56		}
     57	}
     58
     59	mutex_unlock(&omapdss_devices_lock);
     60	return found;
     61}
     62
     63struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev)
     64{
     65	if (get_device(dssdev->dev) == NULL)
     66		return NULL;
     67
     68	return dssdev;
     69}
     70
     71void omapdss_device_put(struct omap_dss_device *dssdev)
     72{
     73	put_device(dssdev->dev);
     74}
     75
     76struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node)
     77{
     78	struct omap_dss_device *dssdev;
     79
     80	list_for_each_entry(dssdev, &omapdss_devices_list, list) {
     81		if (dssdev->dev->of_node == node)
     82			return omapdss_device_get(dssdev);
     83	}
     84
     85	return NULL;
     86}
     87
     88/*
     89 * Search for the next output device starting at @from. Release the reference to
     90 * the @from device, and acquire a reference to the returned device if found.
     91 */
     92struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from)
     93{
     94	struct omap_dss_device *dssdev;
     95	struct list_head *list;
     96
     97	mutex_lock(&omapdss_devices_lock);
     98
     99	if (list_empty(&omapdss_devices_list)) {
    100		dssdev = NULL;
    101		goto done;
    102	}
    103
    104	/*
    105	 * Start from the from entry if given or from omapdss_devices_list
    106	 * otherwise.
    107	 */
    108	list = from ? &from->list : &omapdss_devices_list;
    109
    110	list_for_each_entry(dssdev, list, list) {
    111		/*
    112		 * Stop if we reach the omapdss_devices_list, that's the end of
    113		 * the list.
    114		 */
    115		if (&dssdev->list == &omapdss_devices_list) {
    116			dssdev = NULL;
    117			goto done;
    118		}
    119
    120		if (dssdev->id && dssdev->bridge)
    121			goto done;
    122	}
    123
    124	dssdev = NULL;
    125
    126done:
    127	if (from)
    128		omapdss_device_put(from);
    129	if (dssdev)
    130		omapdss_device_get(dssdev);
    131
    132	mutex_unlock(&omapdss_devices_lock);
    133	return dssdev;
    134}
    135
    136static bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
    137{
    138	return dssdev->dss;
    139}
    140
    141int omapdss_device_connect(struct dss_device *dss,
    142			   struct omap_dss_device *src,
    143			   struct omap_dss_device *dst)
    144{
    145	dev_dbg(&dss->pdev->dev, "connect(%s, %s)\n",
    146		src ? dev_name(src->dev) : "NULL",
    147		dst ? dev_name(dst->dev) : "NULL");
    148
    149	if (!dst) {
    150		/*
    151		 * The destination is NULL when the source is connected to a
    152		 * bridge instead of a DSS device. Stop here, we will attach
    153		 * the bridge later when we will have a DRM encoder.
    154		 */
    155		return src && src->bridge ? 0 : -EINVAL;
    156	}
    157
    158	if (omapdss_device_is_connected(dst))
    159		return -EBUSY;
    160
    161	dst->dss = dss;
    162
    163	return 0;
    164}
    165
    166void omapdss_device_disconnect(struct omap_dss_device *src,
    167			       struct omap_dss_device *dst)
    168{
    169	struct dss_device *dss = src ? src->dss : dst->dss;
    170
    171	dev_dbg(&dss->pdev->dev, "disconnect(%s, %s)\n",
    172		src ? dev_name(src->dev) : "NULL",
    173		dst ? dev_name(dst->dev) : "NULL");
    174
    175	if (!dst) {
    176		WARN_ON(!src->bridge);
    177		return;
    178	}
    179
    180	if (!dst->id && !omapdss_device_is_connected(dst)) {
    181		WARN_ON(1);
    182		return;
    183	}
    184
    185	dst->dss = NULL;
    186}
    187
    188/* -----------------------------------------------------------------------------
    189 * Components Handling
    190 */
    191
    192static struct list_head omapdss_comp_list;
    193
    194struct omapdss_comp_node {
    195	struct list_head list;
    196	struct device_node *node;
    197	bool dss_core_component;
    198	const char *compat;
    199};
    200
    201static bool omapdss_list_contains(const struct device_node *node)
    202{
    203	struct omapdss_comp_node *comp;
    204
    205	list_for_each_entry(comp, &omapdss_comp_list, list) {
    206		if (comp->node == node)
    207			return true;
    208	}
    209
    210	return false;
    211}
    212
    213static void omapdss_walk_device(struct device *dev, struct device_node *node,
    214				bool dss_core)
    215{
    216	struct omapdss_comp_node *comp;
    217	struct device_node *n;
    218	const char *compat;
    219	int ret;
    220
    221	ret = of_property_read_string(node, "compatible", &compat);
    222	if (ret < 0)
    223		return;
    224
    225	comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
    226	if (comp) {
    227		comp->node = node;
    228		comp->dss_core_component = dss_core;
    229		comp->compat = compat;
    230		list_add(&comp->list, &omapdss_comp_list);
    231	}
    232
    233	/*
    234	 * of_graph_get_remote_port_parent() prints an error if there is no
    235	 * port/ports node. To avoid that, check first that there's the node.
    236	 */
    237	n = of_get_child_by_name(node, "ports");
    238	if (!n)
    239		n = of_get_child_by_name(node, "port");
    240	if (!n)
    241		return;
    242
    243	of_node_put(n);
    244
    245	n = NULL;
    246	while ((n = of_graph_get_next_endpoint(node, n)) != NULL) {
    247		struct device_node *pn = of_graph_get_remote_port_parent(n);
    248
    249		if (!pn)
    250			continue;
    251
    252		if (!of_device_is_available(pn) || omapdss_list_contains(pn)) {
    253			of_node_put(pn);
    254			continue;
    255		}
    256
    257		omapdss_walk_device(dev, pn, false);
    258	}
    259}
    260
    261void omapdss_gather_components(struct device *dev)
    262{
    263	struct device_node *child;
    264
    265	INIT_LIST_HEAD(&omapdss_comp_list);
    266
    267	omapdss_walk_device(dev, dev->of_node, true);
    268
    269	for_each_available_child_of_node(dev->of_node, child)
    270		omapdss_walk_device(dev, child, true);
    271}
    272
    273static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp)
    274{
    275	if (comp->dss_core_component)
    276		return true;
    277	if (!strstarts(comp->compat, "omapdss,"))
    278		return true;
    279	if (omapdss_device_is_registered(comp->node))
    280		return true;
    281
    282	return false;
    283}
    284
    285bool omapdss_stack_is_ready(void)
    286{
    287	struct omapdss_comp_node *comp;
    288
    289	list_for_each_entry(comp, &omapdss_comp_list, list) {
    290		if (!omapdss_component_is_loaded(comp))
    291			return false;
    292	}
    293
    294	return true;
    295}