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

dp_parser.c (8589B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/of_gpio.h>
      7#include <linux/phy/phy.h>
      8
      9#include <drm/drm_of.h>
     10#include <drm/drm_print.h>
     11#include <drm/drm_bridge.h>
     12
     13#include "dp_parser.h"
     14#include "dp_reg.h"
     15
     16#define DP_DEFAULT_AHB_OFFSET	0x0000
     17#define DP_DEFAULT_AHB_SIZE	0x0200
     18#define DP_DEFAULT_AUX_OFFSET	0x0200
     19#define DP_DEFAULT_AUX_SIZE	0x0200
     20#define DP_DEFAULT_LINK_OFFSET	0x0400
     21#define DP_DEFAULT_LINK_SIZE	0x0C00
     22#define DP_DEFAULT_P0_OFFSET	0x1000
     23#define DP_DEFAULT_P0_SIZE	0x0400
     24
     25static const struct dp_regulator_cfg sdm845_dp_reg_cfg = {
     26	.num = 2,
     27	.regs = {
     28		{"vdda-1p2", 21800, 4 },	/* 1.2 V */
     29		{"vdda-0p9", 36000, 32 },	/* 0.9 V */
     30	},
     31};
     32
     33static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
     34{
     35	struct resource *res;
     36	void __iomem *base;
     37
     38	base = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
     39	if (!IS_ERR(base))
     40		*len = resource_size(res);
     41
     42	return base;
     43}
     44
     45static int dp_parser_ctrl_res(struct dp_parser *parser)
     46{
     47	struct platform_device *pdev = parser->pdev;
     48	struct dp_io *io = &parser->io;
     49	struct dss_io_data *dss = &io->dp_controller;
     50
     51	dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
     52	if (IS_ERR(dss->ahb.base))
     53		return PTR_ERR(dss->ahb.base);
     54
     55	dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
     56	if (IS_ERR(dss->aux.base)) {
     57		/*
     58		 * The initial binding had a single reg, but in order to
     59		 * support variation in the sub-region sizes this was split.
     60		 * dp_ioremap() will fail with -EINVAL here if only a single
     61		 * reg is specified, so fill in the sub-region offsets and
     62		 * lengths based on this single region.
     63		 */
     64		if (PTR_ERR(dss->aux.base) == -EINVAL) {
     65			if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) {
     66				DRM_ERROR("legacy memory region not large enough\n");
     67				return -EINVAL;
     68			}
     69
     70			dss->ahb.len = DP_DEFAULT_AHB_SIZE;
     71			dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET;
     72			dss->aux.len = DP_DEFAULT_AUX_SIZE;
     73			dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET;
     74			dss->link.len = DP_DEFAULT_LINK_SIZE;
     75			dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET;
     76			dss->p0.len = DP_DEFAULT_P0_SIZE;
     77		} else {
     78			DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base);
     79			return PTR_ERR(dss->aux.base);
     80		}
     81	} else {
     82		dss->link.base = dp_ioremap(pdev, 2, &dss->link.len);
     83		if (IS_ERR(dss->link.base)) {
     84			DRM_ERROR("unable to remap link region: %pe\n", dss->link.base);
     85			return PTR_ERR(dss->link.base);
     86		}
     87
     88		dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len);
     89		if (IS_ERR(dss->p0.base)) {
     90			DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base);
     91			return PTR_ERR(dss->p0.base);
     92		}
     93	}
     94
     95	io->phy = devm_phy_get(&pdev->dev, "dp");
     96	if (IS_ERR(io->phy))
     97		return PTR_ERR(io->phy);
     98
     99	return 0;
    100}
    101
    102static int dp_parser_misc(struct dp_parser *parser)
    103{
    104	struct device_node *of_node = parser->pdev->dev.of_node;
    105	int len = 0;
    106	const char *data_lane_property = "data-lanes";
    107
    108	len = of_property_count_elems_of_size(of_node,
    109			 data_lane_property, sizeof(u32));
    110	if (len < 0) {
    111		DRM_WARN("Invalid property %s, default max DP lanes = %d\n",
    112				data_lane_property, DP_MAX_NUM_DP_LANES);
    113		len = DP_MAX_NUM_DP_LANES;
    114	}
    115
    116	parser->max_dp_lanes = len;
    117	return 0;
    118}
    119
    120static inline bool dp_parser_check_prefix(const char *clk_prefix,
    121						const char *clk_name)
    122{
    123	return !strncmp(clk_prefix, clk_name, strlen(clk_prefix));
    124}
    125
    126static int dp_parser_init_clk_data(struct dp_parser *parser)
    127{
    128	int num_clk, i, rc;
    129	int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
    130	const char *clk_name;
    131	struct device *dev = &parser->pdev->dev;
    132	struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
    133	struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
    134	struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
    135
    136	num_clk = of_property_count_strings(dev->of_node, "clock-names");
    137	if (num_clk <= 0) {
    138		DRM_ERROR("no clocks are defined\n");
    139		return -EINVAL;
    140	}
    141
    142	for (i = 0; i < num_clk; i++) {
    143		rc = of_property_read_string_index(dev->of_node,
    144				"clock-names", i, &clk_name);
    145		if (rc < 0)
    146			return rc;
    147
    148		if (dp_parser_check_prefix("core", clk_name))
    149			core_clk_count++;
    150
    151		if (dp_parser_check_prefix("ctrl", clk_name))
    152			ctrl_clk_count++;
    153
    154		if (dp_parser_check_prefix("stream", clk_name))
    155			stream_clk_count++;
    156	}
    157
    158	/* Initialize the CORE power module */
    159	if (core_clk_count == 0) {
    160		DRM_ERROR("no core clocks are defined\n");
    161		return -EINVAL;
    162	}
    163
    164	core_power->num_clk = core_clk_count;
    165	core_power->clk_config = devm_kzalloc(dev,
    166			sizeof(struct dss_clk) * core_power->num_clk,
    167			GFP_KERNEL);
    168	if (!core_power->clk_config)
    169		return -EINVAL;
    170
    171	/* Initialize the CTRL power module */
    172	if (ctrl_clk_count == 0) {
    173		DRM_ERROR("no ctrl clocks are defined\n");
    174		return -EINVAL;
    175	}
    176
    177	ctrl_power->num_clk = ctrl_clk_count;
    178	ctrl_power->clk_config = devm_kzalloc(dev,
    179			sizeof(struct dss_clk) * ctrl_power->num_clk,
    180			GFP_KERNEL);
    181	if (!ctrl_power->clk_config) {
    182		ctrl_power->num_clk = 0;
    183		return -EINVAL;
    184	}
    185
    186	/* Initialize the STREAM power module */
    187	if (stream_clk_count == 0) {
    188		DRM_ERROR("no stream (pixel) clocks are defined\n");
    189		return -EINVAL;
    190	}
    191
    192	stream_power->num_clk = stream_clk_count;
    193	stream_power->clk_config = devm_kzalloc(dev,
    194			sizeof(struct dss_clk) * stream_power->num_clk,
    195			GFP_KERNEL);
    196	if (!stream_power->clk_config) {
    197		stream_power->num_clk = 0;
    198		return -EINVAL;
    199	}
    200
    201	return 0;
    202}
    203
    204static int dp_parser_clock(struct dp_parser *parser)
    205{
    206	int rc = 0, i = 0;
    207	int num_clk = 0;
    208	int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0;
    209	int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
    210	const char *clk_name;
    211	struct device *dev = &parser->pdev->dev;
    212	struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
    213	struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
    214	struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
    215
    216	rc =  dp_parser_init_clk_data(parser);
    217	if (rc) {
    218		DRM_ERROR("failed to initialize power data %d\n", rc);
    219		return -EINVAL;
    220	}
    221
    222	core_clk_count = core_power->num_clk;
    223	ctrl_clk_count = ctrl_power->num_clk;
    224	stream_clk_count = stream_power->num_clk;
    225
    226	num_clk = core_clk_count + ctrl_clk_count + stream_clk_count;
    227
    228	for (i = 0; i < num_clk; i++) {
    229		rc = of_property_read_string_index(dev->of_node, "clock-names",
    230				i, &clk_name);
    231		if (rc) {
    232			DRM_ERROR("error reading clock-names %d\n", rc);
    233			return rc;
    234		}
    235		if (dp_parser_check_prefix("core", clk_name) &&
    236				core_clk_index < core_clk_count) {
    237			struct dss_clk *clk =
    238				&core_power->clk_config[core_clk_index];
    239			strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
    240			clk->type = DSS_CLK_AHB;
    241			core_clk_index++;
    242		} else if (dp_parser_check_prefix("stream", clk_name) &&
    243				stream_clk_index < stream_clk_count) {
    244			struct dss_clk *clk =
    245				&stream_power->clk_config[stream_clk_index];
    246			strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
    247			clk->type = DSS_CLK_PCLK;
    248			stream_clk_index++;
    249		} else if (dp_parser_check_prefix("ctrl", clk_name) &&
    250			   ctrl_clk_index < ctrl_clk_count) {
    251			struct dss_clk *clk =
    252				&ctrl_power->clk_config[ctrl_clk_index];
    253			strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
    254			ctrl_clk_index++;
    255			if (dp_parser_check_prefix("ctrl_link", clk_name) ||
    256			    dp_parser_check_prefix("stream_pixel", clk_name))
    257				clk->type = DSS_CLK_PCLK;
    258			else
    259				clk->type = DSS_CLK_AHB;
    260		}
    261	}
    262
    263	return 0;
    264}
    265
    266int dp_parser_find_next_bridge(struct dp_parser *parser)
    267{
    268	struct device *dev = &parser->pdev->dev;
    269	struct drm_bridge *bridge;
    270
    271	bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
    272	if (IS_ERR(bridge))
    273		return PTR_ERR(bridge);
    274
    275	parser->next_bridge = bridge;
    276
    277	return 0;
    278}
    279
    280static int dp_parser_parse(struct dp_parser *parser)
    281{
    282	int rc = 0;
    283
    284	if (!parser) {
    285		DRM_ERROR("invalid input\n");
    286		return -EINVAL;
    287	}
    288
    289	rc = dp_parser_ctrl_res(parser);
    290	if (rc)
    291		return rc;
    292
    293	rc = dp_parser_misc(parser);
    294	if (rc)
    295		return rc;
    296
    297	rc = dp_parser_clock(parser);
    298	if (rc)
    299		return rc;
    300
    301	/* Map the corresponding regulator information according to
    302	 * version. Currently, since we only have one supported platform,
    303	 * mapping the regulator directly.
    304	 */
    305	parser->regulator_cfg = &sdm845_dp_reg_cfg;
    306
    307	return 0;
    308}
    309
    310struct dp_parser *dp_parser_get(struct platform_device *pdev)
    311{
    312	struct dp_parser *parser;
    313
    314	parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
    315	if (!parser)
    316		return ERR_PTR(-ENOMEM);
    317
    318	parser->parse = dp_parser_parse;
    319	parser->pdev = pdev;
    320
    321	return parser;
    322}