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