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

da8xx-mstpri.c (6066B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * TI da8xx master peripheral priority driver
      4 *
      5 * Copyright (C) 2016 BayLibre SAS
      6 *
      7 * Author:
      8 *   Bartosz Golaszewski <bgolaszewski@baylibre.com>
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/of.h>
     13#include <linux/platform_device.h>
     14#include <linux/io.h>
     15#include <linux/regmap.h>
     16
     17/*
     18 * REVISIT: Linux doesn't have a good framework for the kind of performance
     19 * knobs this driver controls. We can't use device tree properties as it deals
     20 * with hardware configuration rather than description. We also don't want to
     21 * commit to maintaining some random sysfs attributes.
     22 *
     23 * For now we just hardcode the register values for the boards that need
     24 * some changes (as is the case for the LCD controller on da850-lcdk - the
     25 * first board we support here). When linux gets an appropriate framework,
     26 * we'll easily convert the driver to it.
     27 */
     28
     29#define DA8XX_MSTPRI0_OFFSET		0
     30#define DA8XX_MSTPRI1_OFFSET		4
     31#define DA8XX_MSTPRI2_OFFSET		8
     32
     33enum {
     34	DA8XX_MSTPRI_ARM_I = 0,
     35	DA8XX_MSTPRI_ARM_D,
     36	DA8XX_MSTPRI_UPP,
     37	DA8XX_MSTPRI_SATA,
     38	DA8XX_MSTPRI_PRU0,
     39	DA8XX_MSTPRI_PRU1,
     40	DA8XX_MSTPRI_EDMA30TC0,
     41	DA8XX_MSTPRI_EDMA30TC1,
     42	DA8XX_MSTPRI_EDMA31TC0,
     43	DA8XX_MSTPRI_VPIF_DMA_0,
     44	DA8XX_MSTPRI_VPIF_DMA_1,
     45	DA8XX_MSTPRI_EMAC,
     46	DA8XX_MSTPRI_USB0CFG,
     47	DA8XX_MSTPRI_USB0CDMA,
     48	DA8XX_MSTPRI_UHPI,
     49	DA8XX_MSTPRI_USB1,
     50	DA8XX_MSTPRI_LCDC,
     51};
     52
     53struct da8xx_mstpri_descr {
     54	int reg;
     55	int shift;
     56	int mask;
     57};
     58
     59static const struct da8xx_mstpri_descr da8xx_mstpri_priority_list[] = {
     60	[DA8XX_MSTPRI_ARM_I] = {
     61		.reg = DA8XX_MSTPRI0_OFFSET,
     62		.shift = 0,
     63		.mask = 0x0000000f,
     64	},
     65	[DA8XX_MSTPRI_ARM_D] = {
     66		.reg = DA8XX_MSTPRI0_OFFSET,
     67		.shift = 4,
     68		.mask = 0x000000f0,
     69	},
     70	[DA8XX_MSTPRI_UPP] = {
     71		.reg = DA8XX_MSTPRI0_OFFSET,
     72		.shift = 16,
     73		.mask = 0x000f0000,
     74	},
     75	[DA8XX_MSTPRI_SATA] = {
     76		.reg = DA8XX_MSTPRI0_OFFSET,
     77		.shift = 20,
     78		.mask = 0x00f00000,
     79	},
     80	[DA8XX_MSTPRI_PRU0] = {
     81		.reg = DA8XX_MSTPRI1_OFFSET,
     82		.shift = 0,
     83		.mask = 0x0000000f,
     84	},
     85	[DA8XX_MSTPRI_PRU1] = {
     86		.reg = DA8XX_MSTPRI1_OFFSET,
     87		.shift = 4,
     88		.mask = 0x000000f0,
     89	},
     90	[DA8XX_MSTPRI_EDMA30TC0] = {
     91		.reg = DA8XX_MSTPRI1_OFFSET,
     92		.shift = 8,
     93		.mask = 0x00000f00,
     94	},
     95	[DA8XX_MSTPRI_EDMA30TC1] = {
     96		.reg = DA8XX_MSTPRI1_OFFSET,
     97		.shift = 12,
     98		.mask = 0x0000f000,
     99	},
    100	[DA8XX_MSTPRI_EDMA31TC0] = {
    101		.reg = DA8XX_MSTPRI1_OFFSET,
    102		.shift = 16,
    103		.mask = 0x000f0000,
    104	},
    105	[DA8XX_MSTPRI_VPIF_DMA_0] = {
    106		.reg = DA8XX_MSTPRI1_OFFSET,
    107		.shift = 24,
    108		.mask = 0x0f000000,
    109	},
    110	[DA8XX_MSTPRI_VPIF_DMA_1] = {
    111		.reg = DA8XX_MSTPRI1_OFFSET,
    112		.shift = 28,
    113		.mask = 0xf0000000,
    114	},
    115	[DA8XX_MSTPRI_EMAC] = {
    116		.reg = DA8XX_MSTPRI2_OFFSET,
    117		.shift = 0,
    118		.mask = 0x0000000f,
    119	},
    120	[DA8XX_MSTPRI_USB0CFG] = {
    121		.reg = DA8XX_MSTPRI2_OFFSET,
    122		.shift = 8,
    123		.mask = 0x00000f00,
    124	},
    125	[DA8XX_MSTPRI_USB0CDMA] = {
    126		.reg = DA8XX_MSTPRI2_OFFSET,
    127		.shift = 12,
    128		.mask = 0x0000f000,
    129	},
    130	[DA8XX_MSTPRI_UHPI] = {
    131		.reg = DA8XX_MSTPRI2_OFFSET,
    132		.shift = 20,
    133		.mask = 0x00f00000,
    134	},
    135	[DA8XX_MSTPRI_USB1] = {
    136		.reg = DA8XX_MSTPRI2_OFFSET,
    137		.shift = 24,
    138		.mask = 0x0f000000,
    139	},
    140	[DA8XX_MSTPRI_LCDC] = {
    141		.reg = DA8XX_MSTPRI2_OFFSET,
    142		.shift = 28,
    143		.mask = 0xf0000000,
    144	},
    145};
    146
    147struct da8xx_mstpri_priority {
    148	int which;
    149	u32 val;
    150};
    151
    152struct da8xx_mstpri_board_priorities {
    153	const char *board;
    154	const struct da8xx_mstpri_priority *priorities;
    155	size_t numprio;
    156};
    157
    158/*
    159 * Default memory settings of da850 do not meet the throughput/latency
    160 * requirements of tilcdc. This results in the image displayed being
    161 * incorrect and the following warning being displayed by the LCDC
    162 * drm driver:
    163 *
    164 *   tilcdc da8xx_lcdc.0: tilcdc_crtc_irq(0x00000020): FIFO underfow
    165 */
    166static const struct da8xx_mstpri_priority da850_lcdk_priorities[] = {
    167	{
    168		.which = DA8XX_MSTPRI_LCDC,
    169		.val = 0,
    170	},
    171	{
    172		.which = DA8XX_MSTPRI_EDMA30TC1,
    173		.val = 0,
    174	},
    175	{
    176		.which = DA8XX_MSTPRI_EDMA30TC0,
    177		.val = 1,
    178	},
    179};
    180
    181static const struct da8xx_mstpri_board_priorities da8xx_mstpri_board_confs[] = {
    182	{
    183		.board = "ti,da850-lcdk",
    184		.priorities = da850_lcdk_priorities,
    185		.numprio = ARRAY_SIZE(da850_lcdk_priorities),
    186	},
    187};
    188
    189static const struct da8xx_mstpri_board_priorities *
    190da8xx_mstpri_get_board_prio(void)
    191{
    192	const struct da8xx_mstpri_board_priorities *board_prio;
    193	int i;
    194
    195	for (i = 0; i < ARRAY_SIZE(da8xx_mstpri_board_confs); i++) {
    196		board_prio = &da8xx_mstpri_board_confs[i];
    197
    198		if (of_machine_is_compatible(board_prio->board))
    199			return board_prio;
    200	}
    201
    202	return NULL;
    203}
    204
    205static int da8xx_mstpri_probe(struct platform_device *pdev)
    206{
    207	const struct da8xx_mstpri_board_priorities *prio_list;
    208	const struct da8xx_mstpri_descr *prio_descr;
    209	const struct da8xx_mstpri_priority *prio;
    210	struct device *dev = &pdev->dev;
    211	struct resource *res;
    212	void __iomem *mstpri;
    213	u32 reg;
    214	int i;
    215
    216	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    217	mstpri = devm_ioremap_resource(dev, res);
    218	if (IS_ERR(mstpri)) {
    219		dev_err(dev, "unable to map MSTPRI registers\n");
    220		return PTR_ERR(mstpri);
    221	}
    222
    223	prio_list = da8xx_mstpri_get_board_prio();
    224	if (!prio_list) {
    225		dev_err(dev, "no master priorities defined for this board\n");
    226		return -EINVAL;
    227	}
    228
    229	for (i = 0; i < prio_list->numprio; i++) {
    230		prio = &prio_list->priorities[i];
    231		prio_descr = &da8xx_mstpri_priority_list[prio->which];
    232
    233		if (prio_descr->reg + sizeof(u32) > resource_size(res)) {
    234			dev_warn(dev, "register offset out of range\n");
    235			continue;
    236		}
    237
    238		reg = readl(mstpri + prio_descr->reg);
    239		reg &= ~prio_descr->mask;
    240		reg |= prio->val << prio_descr->shift;
    241
    242		writel(reg, mstpri + prio_descr->reg);
    243	}
    244
    245	return 0;
    246}
    247
    248static const struct of_device_id da8xx_mstpri_of_match[] = {
    249	{ .compatible = "ti,da850-mstpri", },
    250	{ },
    251};
    252
    253static struct platform_driver da8xx_mstpri_driver = {
    254	.probe = da8xx_mstpri_probe,
    255	.driver = {
    256		.name = "da8xx-mstpri",
    257		.of_match_table = da8xx_mstpri_of_match,
    258	},
    259};
    260module_platform_driver(da8xx_mstpri_driver);
    261
    262MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
    263MODULE_DESCRIPTION("TI da8xx master peripheral priority driver");
    264MODULE_LICENSE("GPL v2");