xref: /openbmc/linux/drivers/bus/da8xx-mstpri.c (revision d2912cb1)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28e7223fcSBartosz Golaszewski /*
38e7223fcSBartosz Golaszewski  * TI da8xx master peripheral priority driver
48e7223fcSBartosz Golaszewski  *
58e7223fcSBartosz Golaszewski  * Copyright (C) 2016 BayLibre SAS
68e7223fcSBartosz Golaszewski  *
78e7223fcSBartosz Golaszewski  * Author:
8430d7dd4SBartosz Golaszewski  *   Bartosz Golaszewski <bgolaszewski@baylibre.com>
98e7223fcSBartosz Golaszewski  */
108e7223fcSBartosz Golaszewski 
118e7223fcSBartosz Golaszewski #include <linux/module.h>
128e7223fcSBartosz Golaszewski #include <linux/of.h>
138e7223fcSBartosz Golaszewski #include <linux/platform_device.h>
148e7223fcSBartosz Golaszewski #include <linux/io.h>
158e7223fcSBartosz Golaszewski #include <linux/regmap.h>
168e7223fcSBartosz Golaszewski 
178e7223fcSBartosz Golaszewski /*
188e7223fcSBartosz Golaszewski  * REVISIT: Linux doesn't have a good framework for the kind of performance
198e7223fcSBartosz Golaszewski  * knobs this driver controls. We can't use device tree properties as it deals
208e7223fcSBartosz Golaszewski  * with hardware configuration rather than description. We also don't want to
218e7223fcSBartosz Golaszewski  * commit to maintaining some random sysfs attributes.
228e7223fcSBartosz Golaszewski  *
238e7223fcSBartosz Golaszewski  * For now we just hardcode the register values for the boards that need
248e7223fcSBartosz Golaszewski  * some changes (as is the case for the LCD controller on da850-lcdk - the
258e7223fcSBartosz Golaszewski  * first board we support here). When linux gets an appropriate framework,
268e7223fcSBartosz Golaszewski  * we'll easily convert the driver to it.
278e7223fcSBartosz Golaszewski  */
288e7223fcSBartosz Golaszewski 
298e7223fcSBartosz Golaszewski #define DA8XX_MSTPRI0_OFFSET		0
308e7223fcSBartosz Golaszewski #define DA8XX_MSTPRI1_OFFSET		4
318e7223fcSBartosz Golaszewski #define DA8XX_MSTPRI2_OFFSET		8
328e7223fcSBartosz Golaszewski 
338e7223fcSBartosz Golaszewski enum {
348e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_ARM_I = 0,
358e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_ARM_D,
368e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_UPP,
378e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_SATA,
388e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_PRU0,
398e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_PRU1,
408e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_EDMA30TC0,
418e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_EDMA30TC1,
428e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_EDMA31TC0,
438e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_VPIF_DMA_0,
448e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_VPIF_DMA_1,
458e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_EMAC,
468e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_USB0CFG,
478e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_USB0CDMA,
488e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_UHPI,
498e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_USB1,
508e7223fcSBartosz Golaszewski 	DA8XX_MSTPRI_LCDC,
518e7223fcSBartosz Golaszewski };
528e7223fcSBartosz Golaszewski 
538e7223fcSBartosz Golaszewski struct da8xx_mstpri_descr {
548e7223fcSBartosz Golaszewski 	int reg;
558e7223fcSBartosz Golaszewski 	int shift;
568e7223fcSBartosz Golaszewski 	int mask;
578e7223fcSBartosz Golaszewski };
588e7223fcSBartosz Golaszewski 
598e7223fcSBartosz Golaszewski static const struct da8xx_mstpri_descr da8xx_mstpri_priority_list[] = {
608e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_ARM_I] = {
618e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI0_OFFSET,
628e7223fcSBartosz Golaszewski 		.shift = 0,
638e7223fcSBartosz Golaszewski 		.mask = 0x0000000f,
648e7223fcSBartosz Golaszewski 	},
658e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_ARM_D] = {
668e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI0_OFFSET,
678e7223fcSBartosz Golaszewski 		.shift = 4,
688e7223fcSBartosz Golaszewski 		.mask = 0x000000f0,
698e7223fcSBartosz Golaszewski 	},
708e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_UPP] = {
718e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI0_OFFSET,
728e7223fcSBartosz Golaszewski 		.shift = 16,
738e7223fcSBartosz Golaszewski 		.mask = 0x000f0000,
748e7223fcSBartosz Golaszewski 	},
758e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_SATA] = {
768e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI0_OFFSET,
778e7223fcSBartosz Golaszewski 		.shift = 20,
788e7223fcSBartosz Golaszewski 		.mask = 0x00f00000,
798e7223fcSBartosz Golaszewski 	},
808e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_PRU0] = {
818e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI1_OFFSET,
828e7223fcSBartosz Golaszewski 		.shift = 0,
838e7223fcSBartosz Golaszewski 		.mask = 0x0000000f,
848e7223fcSBartosz Golaszewski 	},
858e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_PRU1] = {
868e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI1_OFFSET,
878e7223fcSBartosz Golaszewski 		.shift = 4,
888e7223fcSBartosz Golaszewski 		.mask = 0x000000f0,
898e7223fcSBartosz Golaszewski 	},
908e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_EDMA30TC0] = {
918e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI1_OFFSET,
928e7223fcSBartosz Golaszewski 		.shift = 8,
938e7223fcSBartosz Golaszewski 		.mask = 0x00000f00,
948e7223fcSBartosz Golaszewski 	},
958e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_EDMA30TC1] = {
968e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI1_OFFSET,
978e7223fcSBartosz Golaszewski 		.shift = 12,
988e7223fcSBartosz Golaszewski 		.mask = 0x0000f000,
998e7223fcSBartosz Golaszewski 	},
1008e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_EDMA31TC0] = {
1018e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI1_OFFSET,
1028e7223fcSBartosz Golaszewski 		.shift = 16,
1038e7223fcSBartosz Golaszewski 		.mask = 0x000f0000,
1048e7223fcSBartosz Golaszewski 	},
1058e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_VPIF_DMA_0] = {
1068e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI1_OFFSET,
1078e7223fcSBartosz Golaszewski 		.shift = 24,
1088e7223fcSBartosz Golaszewski 		.mask = 0x0f000000,
1098e7223fcSBartosz Golaszewski 	},
1108e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_VPIF_DMA_1] = {
1118e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI1_OFFSET,
1128e7223fcSBartosz Golaszewski 		.shift = 28,
1138e7223fcSBartosz Golaszewski 		.mask = 0xf0000000,
1148e7223fcSBartosz Golaszewski 	},
1158e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_EMAC] = {
1168e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI2_OFFSET,
1178e7223fcSBartosz Golaszewski 		.shift = 0,
1188e7223fcSBartosz Golaszewski 		.mask = 0x0000000f,
1198e7223fcSBartosz Golaszewski 	},
1208e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_USB0CFG] = {
1218e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI2_OFFSET,
1228e7223fcSBartosz Golaszewski 		.shift = 8,
1238e7223fcSBartosz Golaszewski 		.mask = 0x00000f00,
1248e7223fcSBartosz Golaszewski 	},
1258e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_USB0CDMA] = {
1268e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI2_OFFSET,
1278e7223fcSBartosz Golaszewski 		.shift = 12,
1288e7223fcSBartosz Golaszewski 		.mask = 0x0000f000,
1298e7223fcSBartosz Golaszewski 	},
1308e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_UHPI] = {
1318e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI2_OFFSET,
1328e7223fcSBartosz Golaszewski 		.shift = 20,
1338e7223fcSBartosz Golaszewski 		.mask = 0x00f00000,
1348e7223fcSBartosz Golaszewski 	},
1358e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_USB1] = {
1368e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI2_OFFSET,
1378e7223fcSBartosz Golaszewski 		.shift = 24,
1388e7223fcSBartosz Golaszewski 		.mask = 0x0f000000,
1398e7223fcSBartosz Golaszewski 	},
1408e7223fcSBartosz Golaszewski 	[DA8XX_MSTPRI_LCDC] = {
1418e7223fcSBartosz Golaszewski 		.reg = DA8XX_MSTPRI2_OFFSET,
1428e7223fcSBartosz Golaszewski 		.shift = 28,
1438e7223fcSBartosz Golaszewski 		.mask = 0xf0000000,
1448e7223fcSBartosz Golaszewski 	},
1458e7223fcSBartosz Golaszewski };
1468e7223fcSBartosz Golaszewski 
1478e7223fcSBartosz Golaszewski struct da8xx_mstpri_priority {
1488e7223fcSBartosz Golaszewski 	int which;
1498e7223fcSBartosz Golaszewski 	u32 val;
1508e7223fcSBartosz Golaszewski };
1518e7223fcSBartosz Golaszewski 
1528e7223fcSBartosz Golaszewski struct da8xx_mstpri_board_priorities {
1538e7223fcSBartosz Golaszewski 	const char *board;
1548e7223fcSBartosz Golaszewski 	const struct da8xx_mstpri_priority *priorities;
1558e7223fcSBartosz Golaszewski 	size_t numprio;
1568e7223fcSBartosz Golaszewski };
1578e7223fcSBartosz Golaszewski 
1588e7223fcSBartosz Golaszewski /*
1598e7223fcSBartosz Golaszewski  * Default memory settings of da850 do not meet the throughput/latency
1608e7223fcSBartosz Golaszewski  * requirements of tilcdc. This results in the image displayed being
1618e7223fcSBartosz Golaszewski  * incorrect and the following warning being displayed by the LCDC
1628e7223fcSBartosz Golaszewski  * drm driver:
1638e7223fcSBartosz Golaszewski  *
1648e7223fcSBartosz Golaszewski  *   tilcdc da8xx_lcdc.0: tilcdc_crtc_irq(0x00000020): FIFO underfow
1658e7223fcSBartosz Golaszewski  */
1668e7223fcSBartosz Golaszewski static const struct da8xx_mstpri_priority da850_lcdk_priorities[] = {
1678e7223fcSBartosz Golaszewski 	{
1688e7223fcSBartosz Golaszewski 		.which = DA8XX_MSTPRI_LCDC,
1698e7223fcSBartosz Golaszewski 		.val = 0,
1708e7223fcSBartosz Golaszewski 	},
1718e7223fcSBartosz Golaszewski 	{
1728e7223fcSBartosz Golaszewski 		.which = DA8XX_MSTPRI_EDMA30TC1,
1738e7223fcSBartosz Golaszewski 		.val = 0,
1748e7223fcSBartosz Golaszewski 	},
1758e7223fcSBartosz Golaszewski 	{
1768e7223fcSBartosz Golaszewski 		.which = DA8XX_MSTPRI_EDMA30TC0,
1778e7223fcSBartosz Golaszewski 		.val = 1,
1788e7223fcSBartosz Golaszewski 	},
1798e7223fcSBartosz Golaszewski };
1808e7223fcSBartosz Golaszewski 
1818e7223fcSBartosz Golaszewski static const struct da8xx_mstpri_board_priorities da8xx_mstpri_board_confs[] = {
1828e7223fcSBartosz Golaszewski 	{
1838e7223fcSBartosz Golaszewski 		.board = "ti,da850-lcdk",
1848e7223fcSBartosz Golaszewski 		.priorities = da850_lcdk_priorities,
1858e7223fcSBartosz Golaszewski 		.numprio = ARRAY_SIZE(da850_lcdk_priorities),
1868e7223fcSBartosz Golaszewski 	},
1878e7223fcSBartosz Golaszewski };
1888e7223fcSBartosz Golaszewski 
1898e7223fcSBartosz Golaszewski static const struct da8xx_mstpri_board_priorities *
da8xx_mstpri_get_board_prio(void)1908e7223fcSBartosz Golaszewski da8xx_mstpri_get_board_prio(void)
1918e7223fcSBartosz Golaszewski {
1928e7223fcSBartosz Golaszewski 	const struct da8xx_mstpri_board_priorities *board_prio;
1938e7223fcSBartosz Golaszewski 	int i;
1948e7223fcSBartosz Golaszewski 
1958e7223fcSBartosz Golaszewski 	for (i = 0; i < ARRAY_SIZE(da8xx_mstpri_board_confs); i++) {
1968e7223fcSBartosz Golaszewski 		board_prio = &da8xx_mstpri_board_confs[i];
1978e7223fcSBartosz Golaszewski 
1988e7223fcSBartosz Golaszewski 		if (of_machine_is_compatible(board_prio->board))
1998e7223fcSBartosz Golaszewski 			return board_prio;
2008e7223fcSBartosz Golaszewski 	}
2018e7223fcSBartosz Golaszewski 
2028e7223fcSBartosz Golaszewski 	return NULL;
2038e7223fcSBartosz Golaszewski }
2048e7223fcSBartosz Golaszewski 
da8xx_mstpri_probe(struct platform_device * pdev)2058e7223fcSBartosz Golaszewski static int da8xx_mstpri_probe(struct platform_device *pdev)
2068e7223fcSBartosz Golaszewski {
2078e7223fcSBartosz Golaszewski 	const struct da8xx_mstpri_board_priorities *prio_list;
2088e7223fcSBartosz Golaszewski 	const struct da8xx_mstpri_descr *prio_descr;
2098e7223fcSBartosz Golaszewski 	const struct da8xx_mstpri_priority *prio;
2108e7223fcSBartosz Golaszewski 	struct device *dev = &pdev->dev;
2118e7223fcSBartosz Golaszewski 	struct resource *res;
2128e7223fcSBartosz Golaszewski 	void __iomem *mstpri;
2138e7223fcSBartosz Golaszewski 	u32 reg;
2148e7223fcSBartosz Golaszewski 	int i;
2158e7223fcSBartosz Golaszewski 
2168e7223fcSBartosz Golaszewski 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2178e7223fcSBartosz Golaszewski 	mstpri = devm_ioremap_resource(dev, res);
2188e7223fcSBartosz Golaszewski 	if (IS_ERR(mstpri)) {
2198e7223fcSBartosz Golaszewski 		dev_err(dev, "unable to map MSTPRI registers\n");
2208e7223fcSBartosz Golaszewski 		return PTR_ERR(mstpri);
2218e7223fcSBartosz Golaszewski 	}
2228e7223fcSBartosz Golaszewski 
2238e7223fcSBartosz Golaszewski 	prio_list = da8xx_mstpri_get_board_prio();
2248e7223fcSBartosz Golaszewski 	if (!prio_list) {
22548c28337SBartosz Golaszewski 		dev_err(dev, "no master priorities defined for this board\n");
2268e7223fcSBartosz Golaszewski 		return -EINVAL;
2278e7223fcSBartosz Golaszewski 	}
2288e7223fcSBartosz Golaszewski 
2298e7223fcSBartosz Golaszewski 	for (i = 0; i < prio_list->numprio; i++) {
2308e7223fcSBartosz Golaszewski 		prio = &prio_list->priorities[i];
2318e7223fcSBartosz Golaszewski 		prio_descr = &da8xx_mstpri_priority_list[prio->which];
2328e7223fcSBartosz Golaszewski 
2338e7223fcSBartosz Golaszewski 		if (prio_descr->reg + sizeof(u32) > resource_size(res)) {
2348e7223fcSBartosz Golaszewski 			dev_warn(dev, "register offset out of range\n");
2358e7223fcSBartosz Golaszewski 			continue;
2368e7223fcSBartosz Golaszewski 		}
2378e7223fcSBartosz Golaszewski 
2388e7223fcSBartosz Golaszewski 		reg = readl(mstpri + prio_descr->reg);
2398e7223fcSBartosz Golaszewski 		reg &= ~prio_descr->mask;
2408e7223fcSBartosz Golaszewski 		reg |= prio->val << prio_descr->shift;
2418e7223fcSBartosz Golaszewski 
2428e7223fcSBartosz Golaszewski 		writel(reg, mstpri + prio_descr->reg);
2438e7223fcSBartosz Golaszewski 	}
2448e7223fcSBartosz Golaszewski 
2458e7223fcSBartosz Golaszewski 	return 0;
2468e7223fcSBartosz Golaszewski }
2478e7223fcSBartosz Golaszewski 
2488e7223fcSBartosz Golaszewski static const struct of_device_id da8xx_mstpri_of_match[] = {
2498e7223fcSBartosz Golaszewski 	{ .compatible = "ti,da850-mstpri", },
2508e7223fcSBartosz Golaszewski 	{ },
2518e7223fcSBartosz Golaszewski };
2528e7223fcSBartosz Golaszewski 
2538e7223fcSBartosz Golaszewski static struct platform_driver da8xx_mstpri_driver = {
2548e7223fcSBartosz Golaszewski 	.probe = da8xx_mstpri_probe,
2558e7223fcSBartosz Golaszewski 	.driver = {
2568e7223fcSBartosz Golaszewski 		.name = "da8xx-mstpri",
2578e7223fcSBartosz Golaszewski 		.of_match_table = da8xx_mstpri_of_match,
2588e7223fcSBartosz Golaszewski 	},
2598e7223fcSBartosz Golaszewski };
2608e7223fcSBartosz Golaszewski module_platform_driver(da8xx_mstpri_driver);
2618e7223fcSBartosz Golaszewski 
2628e7223fcSBartosz Golaszewski MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
2638e7223fcSBartosz Golaszewski MODULE_DESCRIPTION("TI da8xx master peripheral priority driver");
2648e7223fcSBartosz Golaszewski MODULE_LICENSE("GPL v2");
265