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

arcpgu.c (11767B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ARC PGU DRM driver.
      4 *
      5 * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
      6 */
      7
      8#include <linux/clk.h>
      9#include <drm/drm_atomic_helper.h>
     10#include <drm/drm_debugfs.h>
     11#include <drm/drm_device.h>
     12#include <drm/drm_drv.h>
     13#include <drm/drm_fb_cma_helper.h>
     14#include <drm/drm_fb_helper.h>
     15#include <drm/drm_fourcc.h>
     16#include <drm/drm_gem_cma_helper.h>
     17#include <drm/drm_gem_framebuffer_helper.h>
     18#include <drm/drm_module.h>
     19#include <drm/drm_of.h>
     20#include <drm/drm_probe_helper.h>
     21#include <drm/drm_simple_kms_helper.h>
     22#include <linux/dma-mapping.h>
     23#include <linux/module.h>
     24#include <linux/of_reserved_mem.h>
     25#include <linux/platform_device.h>
     26
     27#define ARCPGU_REG_CTRL		0x00
     28#define ARCPGU_REG_STAT		0x04
     29#define ARCPGU_REG_FMT		0x10
     30#define ARCPGU_REG_HSYNC	0x14
     31#define ARCPGU_REG_VSYNC	0x18
     32#define ARCPGU_REG_ACTIVE	0x1c
     33#define ARCPGU_REG_BUF0_ADDR	0x40
     34#define ARCPGU_REG_STRIDE	0x50
     35#define ARCPGU_REG_START_SET	0x84
     36
     37#define ARCPGU_REG_ID		0x3FC
     38
     39#define ARCPGU_CTRL_ENABLE_MASK	0x02
     40#define ARCPGU_CTRL_VS_POL_MASK	0x1
     41#define ARCPGU_CTRL_VS_POL_OFST	0x3
     42#define ARCPGU_CTRL_HS_POL_MASK	0x1
     43#define ARCPGU_CTRL_HS_POL_OFST	0x4
     44#define ARCPGU_MODE_XRGB8888	BIT(2)
     45#define ARCPGU_STAT_BUSY_MASK	0x02
     46
     47struct arcpgu_drm_private {
     48	struct drm_device	drm;
     49	void __iomem		*regs;
     50	struct clk		*clk;
     51	struct drm_simple_display_pipe pipe;
     52	struct drm_connector	sim_conn;
     53};
     54
     55#define dev_to_arcpgu(x) container_of(x, struct arcpgu_drm_private, drm)
     56
     57#define pipe_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, pipe)
     58
     59static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu,
     60				 unsigned int reg, u32 value)
     61{
     62	iowrite32(value, arcpgu->regs + reg);
     63}
     64
     65static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu,
     66			       unsigned int reg)
     67{
     68	return ioread32(arcpgu->regs + reg);
     69}
     70
     71#define XRES_DEF	640
     72#define YRES_DEF	480
     73
     74#define XRES_MAX	8192
     75#define YRES_MAX	8192
     76
     77static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
     78{
     79	int count;
     80
     81	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
     82	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
     83	return count;
     84}
     85
     86static const struct drm_connector_helper_funcs
     87arcpgu_drm_connector_helper_funcs = {
     88	.get_modes = arcpgu_drm_connector_get_modes,
     89};
     90
     91static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
     92	.reset = drm_atomic_helper_connector_reset,
     93	.fill_modes = drm_helper_probe_single_connector_modes,
     94	.destroy = drm_connector_cleanup,
     95	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
     96	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
     97};
     98
     99static int arcpgu_drm_sim_init(struct drm_device *drm, struct drm_connector *connector)
    100{
    101	drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
    102	return drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
    103				  DRM_MODE_CONNECTOR_VIRTUAL);
    104}
    105
    106#define ENCODE_PGU_XY(x, y)	((((x) - 1) << 16) | ((y) - 1))
    107
    108static const u32 arc_pgu_supported_formats[] = {
    109	DRM_FORMAT_RGB565,
    110	DRM_FORMAT_XRGB8888,
    111	DRM_FORMAT_ARGB8888,
    112};
    113
    114static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu)
    115{
    116	const struct drm_framebuffer *fb = arcpgu->pipe.plane.state->fb;
    117	uint32_t pixel_format = fb->format->format;
    118	u32 format = DRM_FORMAT_INVALID;
    119	int i;
    120	u32 reg_ctrl;
    121
    122	for (i = 0; i < ARRAY_SIZE(arc_pgu_supported_formats); i++) {
    123		if (arc_pgu_supported_formats[i] == pixel_format)
    124			format = arc_pgu_supported_formats[i];
    125	}
    126
    127	if (WARN_ON(format == DRM_FORMAT_INVALID))
    128		return;
    129
    130	reg_ctrl = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL);
    131	if (format == DRM_FORMAT_RGB565)
    132		reg_ctrl &= ~ARCPGU_MODE_XRGB8888;
    133	else
    134		reg_ctrl |= ARCPGU_MODE_XRGB8888;
    135	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, reg_ctrl);
    136}
    137
    138static enum drm_mode_status arc_pgu_mode_valid(struct drm_simple_display_pipe *pipe,
    139					       const struct drm_display_mode *mode)
    140{
    141	struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe);
    142	long rate, clk_rate = mode->clock * 1000;
    143	long diff = clk_rate / 200; /* +-0.5% allowed by HDMI spec */
    144
    145	rate = clk_round_rate(arcpgu->clk, clk_rate);
    146	if ((max(rate, clk_rate) - min(rate, clk_rate) < diff) && (rate > 0))
    147		return MODE_OK;
    148
    149	return MODE_NOCLOCK;
    150}
    151
    152static void arc_pgu_mode_set(struct arcpgu_drm_private *arcpgu)
    153{
    154	struct drm_display_mode *m = &arcpgu->pipe.crtc.state->adjusted_mode;
    155	u32 val;
    156
    157	arc_pgu_write(arcpgu, ARCPGU_REG_FMT,
    158		      ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal));
    159
    160	arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC,
    161		      ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay,
    162				    m->crtc_hsync_end - m->crtc_hdisplay));
    163
    164	arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC,
    165		      ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay,
    166				    m->crtc_vsync_end - m->crtc_vdisplay));
    167
    168	arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE,
    169		      ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start,
    170				    m->crtc_vblank_end - m->crtc_vblank_start));
    171
    172	val = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL);
    173
    174	if (m->flags & DRM_MODE_FLAG_PVSYNC)
    175		val |= ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST;
    176	else
    177		val &= ~(ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST);
    178
    179	if (m->flags & DRM_MODE_FLAG_PHSYNC)
    180		val |= ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST;
    181	else
    182		val &= ~(ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST);
    183
    184	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, val);
    185	arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0);
    186	arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
    187
    188	arc_pgu_set_pxl_fmt(arcpgu);
    189
    190	clk_set_rate(arcpgu->clk, m->crtc_clock * 1000);
    191}
    192
    193static void arc_pgu_enable(struct drm_simple_display_pipe *pipe,
    194			   struct drm_crtc_state *crtc_state,
    195			   struct drm_plane_state *plane_state)
    196{
    197	struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe);
    198
    199	arc_pgu_mode_set(arcpgu);
    200
    201	clk_prepare_enable(arcpgu->clk);
    202	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
    203		      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
    204		      ARCPGU_CTRL_ENABLE_MASK);
    205}
    206
    207static void arc_pgu_disable(struct drm_simple_display_pipe *pipe)
    208{
    209	struct arcpgu_drm_private *arcpgu = pipe_to_arcpgu_priv(pipe);
    210
    211	clk_disable_unprepare(arcpgu->clk);
    212	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
    213			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
    214			      ~ARCPGU_CTRL_ENABLE_MASK);
    215}
    216
    217static void arc_pgu_update(struct drm_simple_display_pipe *pipe,
    218			   struct drm_plane_state *state)
    219{
    220	struct arcpgu_drm_private *arcpgu;
    221	struct drm_gem_cma_object *gem;
    222
    223	if (!pipe->plane.state->fb)
    224		return;
    225
    226	arcpgu = pipe_to_arcpgu_priv(pipe);
    227	gem = drm_fb_cma_get_gem_obj(pipe->plane.state->fb, 0);
    228	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
    229}
    230
    231static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = {
    232	.update = arc_pgu_update,
    233	.mode_valid = arc_pgu_mode_valid,
    234	.enable	= arc_pgu_enable,
    235	.disable = arc_pgu_disable,
    236};
    237
    238static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
    239	.fb_create  = drm_gem_fb_create,
    240	.atomic_check = drm_atomic_helper_check,
    241	.atomic_commit = drm_atomic_helper_commit,
    242};
    243
    244DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops);
    245
    246static int arcpgu_load(struct arcpgu_drm_private *arcpgu)
    247{
    248	struct platform_device *pdev = to_platform_device(arcpgu->drm.dev);
    249	struct device_node *encoder_node = NULL, *endpoint_node = NULL;
    250	struct drm_connector *connector = NULL;
    251	struct drm_device *drm = &arcpgu->drm;
    252	struct resource *res;
    253	int ret;
    254
    255	arcpgu->clk = devm_clk_get(drm->dev, "pxlclk");
    256	if (IS_ERR(arcpgu->clk))
    257		return PTR_ERR(arcpgu->clk);
    258
    259	ret = drmm_mode_config_init(drm);
    260	if (ret)
    261		return ret;
    262
    263	drm->mode_config.min_width = 0;
    264	drm->mode_config.min_height = 0;
    265	drm->mode_config.max_width = 1920;
    266	drm->mode_config.max_height = 1080;
    267	drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
    268
    269	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    270	arcpgu->regs = devm_ioremap_resource(&pdev->dev, res);
    271	if (IS_ERR(arcpgu->regs))
    272		return PTR_ERR(arcpgu->regs);
    273
    274	dev_info(drm->dev, "arc_pgu ID: 0x%x\n",
    275		 arc_pgu_read(arcpgu, ARCPGU_REG_ID));
    276
    277	/* Get the optional framebuffer memory resource */
    278	ret = of_reserved_mem_device_init(drm->dev);
    279	if (ret && ret != -ENODEV)
    280		return ret;
    281
    282	if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)))
    283		return -ENODEV;
    284
    285	/*
    286	 * There is only one output port inside each device. It is linked with
    287	 * encoder endpoint.
    288	 */
    289	endpoint_node = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
    290	if (endpoint_node) {
    291		encoder_node = of_graph_get_remote_port_parent(endpoint_node);
    292		of_node_put(endpoint_node);
    293	} else {
    294		connector = &arcpgu->sim_conn;
    295		dev_info(drm->dev, "no encoder found. Assumed virtual LCD on simulation platform\n");
    296		ret = arcpgu_drm_sim_init(drm, connector);
    297		if (ret < 0)
    298			return ret;
    299	}
    300
    301	ret = drm_simple_display_pipe_init(drm, &arcpgu->pipe, &arc_pgu_pipe_funcs,
    302					   arc_pgu_supported_formats,
    303					   ARRAY_SIZE(arc_pgu_supported_formats),
    304					   NULL, connector);
    305	if (ret)
    306		return ret;
    307
    308	if (encoder_node) {
    309		struct drm_bridge *bridge;
    310
    311		/* Locate drm bridge from the hdmi encoder DT node */
    312		bridge = of_drm_find_bridge(encoder_node);
    313		if (!bridge)
    314			return -EPROBE_DEFER;
    315
    316		ret = drm_simple_display_pipe_attach_bridge(&arcpgu->pipe, bridge);
    317		if (ret)
    318			return ret;
    319	}
    320
    321	drm_mode_config_reset(drm);
    322	drm_kms_helper_poll_init(drm);
    323
    324	platform_set_drvdata(pdev, drm);
    325	return 0;
    326}
    327
    328static int arcpgu_unload(struct drm_device *drm)
    329{
    330	drm_kms_helper_poll_fini(drm);
    331	drm_atomic_helper_shutdown(drm);
    332
    333	return 0;
    334}
    335
    336#ifdef CONFIG_DEBUG_FS
    337static int arcpgu_show_pxlclock(struct seq_file *m, void *arg)
    338{
    339	struct drm_info_node *node = (struct drm_info_node *)m->private;
    340	struct drm_device *drm = node->minor->dev;
    341	struct arcpgu_drm_private *arcpgu = dev_to_arcpgu(drm);
    342	unsigned long clkrate = clk_get_rate(arcpgu->clk);
    343	unsigned long mode_clock = arcpgu->pipe.crtc.mode.crtc_clock * 1000;
    344
    345	seq_printf(m, "hw  : %lu\n", clkrate);
    346	seq_printf(m, "mode: %lu\n", mode_clock);
    347	return 0;
    348}
    349
    350static struct drm_info_list arcpgu_debugfs_list[] = {
    351	{ "clocks", arcpgu_show_pxlclock, 0 },
    352};
    353
    354static void arcpgu_debugfs_init(struct drm_minor *minor)
    355{
    356	drm_debugfs_create_files(arcpgu_debugfs_list,
    357				 ARRAY_SIZE(arcpgu_debugfs_list),
    358				 minor->debugfs_root, minor);
    359}
    360#endif
    361
    362static const struct drm_driver arcpgu_drm_driver = {
    363	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
    364	.name = "arcpgu",
    365	.desc = "ARC PGU Controller",
    366	.date = "20160219",
    367	.major = 1,
    368	.minor = 0,
    369	.patchlevel = 0,
    370	.fops = &arcpgu_drm_ops,
    371	DRM_GEM_CMA_DRIVER_OPS,
    372#ifdef CONFIG_DEBUG_FS
    373	.debugfs_init = arcpgu_debugfs_init,
    374#endif
    375};
    376
    377static int arcpgu_probe(struct platform_device *pdev)
    378{
    379	struct arcpgu_drm_private *arcpgu;
    380	int ret;
    381
    382	arcpgu = devm_drm_dev_alloc(&pdev->dev, &arcpgu_drm_driver,
    383				    struct arcpgu_drm_private, drm);
    384	if (IS_ERR(arcpgu))
    385		return PTR_ERR(arcpgu);
    386
    387	ret = arcpgu_load(arcpgu);
    388	if (ret)
    389		return ret;
    390
    391	ret = drm_dev_register(&arcpgu->drm, 0);
    392	if (ret)
    393		goto err_unload;
    394
    395	drm_fbdev_generic_setup(&arcpgu->drm, 16);
    396
    397	return 0;
    398
    399err_unload:
    400	arcpgu_unload(&arcpgu->drm);
    401
    402	return ret;
    403}
    404
    405static int arcpgu_remove(struct platform_device *pdev)
    406{
    407	struct drm_device *drm = platform_get_drvdata(pdev);
    408
    409	drm_dev_unregister(drm);
    410	arcpgu_unload(drm);
    411
    412	return 0;
    413}
    414
    415static const struct of_device_id arcpgu_of_table[] = {
    416	{.compatible = "snps,arcpgu"},
    417	{}
    418};
    419
    420MODULE_DEVICE_TABLE(of, arcpgu_of_table);
    421
    422static struct platform_driver arcpgu_platform_driver = {
    423	.probe = arcpgu_probe,
    424	.remove = arcpgu_remove,
    425	.driver = {
    426		   .name = "arcpgu",
    427		   .of_match_table = arcpgu_of_table,
    428		   },
    429};
    430
    431drm_module_platform_driver(arcpgu_platform_driver);
    432
    433MODULE_AUTHOR("Carlos Palminha <palminha@synopsys.com>");
    434MODULE_DESCRIPTION("ARC PGU DRM driver");
    435MODULE_LICENSE("GPL");