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

tidss_drv.c (5640B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
      4 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
      5 */
      6
      7#include <linux/console.h>
      8#include <linux/of_device.h>
      9#include <linux/module.h>
     10#include <linux/pm_runtime.h>
     11
     12#include <drm/drm_atomic.h>
     13#include <drm/drm_atomic_helper.h>
     14#include <drm/drm_crtc.h>
     15#include <drm/drm_crtc_helper.h>
     16#include <drm/drm_drv.h>
     17#include <drm/drm_fb_helper.h>
     18#include <drm/drm_gem_cma_helper.h>
     19#include <drm/drm_managed.h>
     20#include <drm/drm_module.h>
     21#include <drm/drm_probe_helper.h>
     22
     23#include "tidss_dispc.h"
     24#include "tidss_drv.h"
     25#include "tidss_kms.h"
     26#include "tidss_irq.h"
     27
     28/* Power management */
     29
     30int tidss_runtime_get(struct tidss_device *tidss)
     31{
     32	int r;
     33
     34	dev_dbg(tidss->dev, "%s\n", __func__);
     35
     36	r = pm_runtime_get_sync(tidss->dev);
     37	WARN_ON(r < 0);
     38	return r < 0 ? r : 0;
     39}
     40
     41void tidss_runtime_put(struct tidss_device *tidss)
     42{
     43	int r;
     44
     45	dev_dbg(tidss->dev, "%s\n", __func__);
     46
     47	r = pm_runtime_put_sync(tidss->dev);
     48	WARN_ON(r < 0);
     49}
     50
     51static int __maybe_unused tidss_pm_runtime_suspend(struct device *dev)
     52{
     53	struct tidss_device *tidss = dev_get_drvdata(dev);
     54
     55	dev_dbg(dev, "%s\n", __func__);
     56
     57	return dispc_runtime_suspend(tidss->dispc);
     58}
     59
     60static int __maybe_unused tidss_pm_runtime_resume(struct device *dev)
     61{
     62	struct tidss_device *tidss = dev_get_drvdata(dev);
     63	int r;
     64
     65	dev_dbg(dev, "%s\n", __func__);
     66
     67	r = dispc_runtime_resume(tidss->dispc);
     68	if (r)
     69		return r;
     70
     71	return 0;
     72}
     73
     74static int __maybe_unused tidss_suspend(struct device *dev)
     75{
     76	struct tidss_device *tidss = dev_get_drvdata(dev);
     77
     78	dev_dbg(dev, "%s\n", __func__);
     79
     80	return drm_mode_config_helper_suspend(&tidss->ddev);
     81}
     82
     83static int __maybe_unused tidss_resume(struct device *dev)
     84{
     85	struct tidss_device *tidss = dev_get_drvdata(dev);
     86
     87	dev_dbg(dev, "%s\n", __func__);
     88
     89	return drm_mode_config_helper_resume(&tidss->ddev);
     90}
     91
     92static __maybe_unused const struct dev_pm_ops tidss_pm_ops = {
     93	SET_SYSTEM_SLEEP_PM_OPS(tidss_suspend, tidss_resume)
     94	SET_RUNTIME_PM_OPS(tidss_pm_runtime_suspend, tidss_pm_runtime_resume, NULL)
     95};
     96
     97/* DRM device Information */
     98
     99static void tidss_release(struct drm_device *ddev)
    100{
    101	drm_kms_helper_poll_fini(ddev);
    102}
    103
    104DEFINE_DRM_GEM_CMA_FOPS(tidss_fops);
    105
    106static const struct drm_driver tidss_driver = {
    107	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
    108	.fops			= &tidss_fops,
    109	.release		= tidss_release,
    110	DRM_GEM_CMA_DRIVER_OPS_VMAP,
    111	.name			= "tidss",
    112	.desc			= "TI Keystone DSS",
    113	.date			= "20180215",
    114	.major			= 1,
    115	.minor			= 0,
    116};
    117
    118static int tidss_probe(struct platform_device *pdev)
    119{
    120	struct device *dev = &pdev->dev;
    121	struct tidss_device *tidss;
    122	struct drm_device *ddev;
    123	int ret;
    124	int irq;
    125
    126	dev_dbg(dev, "%s\n", __func__);
    127
    128	tidss = devm_drm_dev_alloc(&pdev->dev, &tidss_driver,
    129				   struct tidss_device, ddev);
    130	if (IS_ERR(tidss))
    131		return PTR_ERR(tidss);
    132
    133	ddev = &tidss->ddev;
    134
    135	tidss->dev = dev;
    136	tidss->feat = of_device_get_match_data(dev);
    137
    138	platform_set_drvdata(pdev, tidss);
    139
    140	ret = dispc_init(tidss);
    141	if (ret) {
    142		dev_err(dev, "failed to initialize dispc: %d\n", ret);
    143		return ret;
    144	}
    145
    146	pm_runtime_enable(dev);
    147
    148#ifndef CONFIG_PM
    149	/* If we don't have PM, we need to call resume manually */
    150	dispc_runtime_resume(tidss->dispc);
    151#endif
    152
    153	ret = tidss_modeset_init(tidss);
    154	if (ret < 0) {
    155		if (ret != -EPROBE_DEFER)
    156			dev_err(dev, "failed to init DRM/KMS (%d)\n", ret);
    157		goto err_runtime_suspend;
    158	}
    159
    160	irq = platform_get_irq(pdev, 0);
    161	if (irq < 0) {
    162		ret = irq;
    163		goto err_runtime_suspend;
    164	}
    165	tidss->irq = irq;
    166
    167	ret = tidss_irq_install(ddev, irq);
    168	if (ret) {
    169		dev_err(dev, "tidss_irq_install failed: %d\n", ret);
    170		goto err_runtime_suspend;
    171	}
    172
    173	drm_kms_helper_poll_init(ddev);
    174
    175	drm_mode_config_reset(ddev);
    176
    177	ret = drm_dev_register(ddev, 0);
    178	if (ret) {
    179		dev_err(dev, "failed to register DRM device\n");
    180		goto err_irq_uninstall;
    181	}
    182
    183	drm_fbdev_generic_setup(ddev, 32);
    184
    185	dev_dbg(dev, "%s done\n", __func__);
    186
    187	return 0;
    188
    189err_irq_uninstall:
    190	tidss_irq_uninstall(ddev);
    191
    192err_runtime_suspend:
    193#ifndef CONFIG_PM
    194	dispc_runtime_suspend(tidss->dispc);
    195#endif
    196	pm_runtime_disable(dev);
    197
    198	return ret;
    199}
    200
    201static int tidss_remove(struct platform_device *pdev)
    202{
    203	struct device *dev = &pdev->dev;
    204	struct tidss_device *tidss = platform_get_drvdata(pdev);
    205	struct drm_device *ddev = &tidss->ddev;
    206
    207	dev_dbg(dev, "%s\n", __func__);
    208
    209	drm_dev_unregister(ddev);
    210
    211	drm_atomic_helper_shutdown(ddev);
    212
    213	tidss_irq_uninstall(ddev);
    214
    215#ifndef CONFIG_PM
    216	/* If we don't have PM, we need to call suspend manually */
    217	dispc_runtime_suspend(tidss->dispc);
    218#endif
    219	pm_runtime_disable(dev);
    220
    221	/* devm allocated dispc goes away with the dev so mark it NULL */
    222	dispc_remove(tidss);
    223
    224	dev_dbg(dev, "%s done\n", __func__);
    225
    226	return 0;
    227}
    228
    229static void tidss_shutdown(struct platform_device *pdev)
    230{
    231	drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
    232}
    233
    234static const struct of_device_id tidss_of_table[] = {
    235	{ .compatible = "ti,k2g-dss", .data = &dispc_k2g_feats, },
    236	{ .compatible = "ti,am65x-dss", .data = &dispc_am65x_feats, },
    237	{ .compatible = "ti,j721e-dss", .data = &dispc_j721e_feats, },
    238	{ }
    239};
    240
    241MODULE_DEVICE_TABLE(of, tidss_of_table);
    242
    243static struct platform_driver tidss_platform_driver = {
    244	.probe		= tidss_probe,
    245	.remove		= tidss_remove,
    246	.shutdown	= tidss_shutdown,
    247	.driver		= {
    248		.name	= "tidss",
    249		.pm	= pm_ptr(&tidss_pm_ops),
    250		.of_match_table = tidss_of_table,
    251		.suppress_bind_attrs = true,
    252	},
    253};
    254
    255drm_module_platform_driver(tidss_platform_driver);
    256
    257MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
    258MODULE_DESCRIPTION("TI Keystone DSS Driver");
    259MODULE_LICENSE("GPL v2");