brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · ee4c023 Raw
265 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * TI da8xx master peripheral priority driver4 *5 * Copyright (C) 2016 BayLibre SAS6 *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 performance19 * knobs this driver controls. We can't use device tree properties as it deals20 * with hardware configuration rather than description. We also don't want to21 * commit to maintaining some random sysfs attributes.22 *23 * For now we just hardcode the register values for the boards that need24 * some changes (as is the case for the LCD controller on da850-lcdk - the25 * 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		030#define DA8XX_MSTPRI1_OFFSET		431#define DA8XX_MSTPRI2_OFFSET		832 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/latency160 * requirements of tilcdc. This results in the image displayed being161 * incorrect and the following warning being displayed by the LCDC162 * drm driver:163 *164 *   tilcdc da8xx_lcdc.0: tilcdc_crtc_irq(0x00000020): FIFO underfow165 */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");265