0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/io.h>
0015 #include <linux/regmap.h>
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #define DA8XX_MSTPRI0_OFFSET 0
0030 #define DA8XX_MSTPRI1_OFFSET 4
0031 #define DA8XX_MSTPRI2_OFFSET 8
0032
0033 enum {
0034 DA8XX_MSTPRI_ARM_I = 0,
0035 DA8XX_MSTPRI_ARM_D,
0036 DA8XX_MSTPRI_UPP,
0037 DA8XX_MSTPRI_SATA,
0038 DA8XX_MSTPRI_PRU0,
0039 DA8XX_MSTPRI_PRU1,
0040 DA8XX_MSTPRI_EDMA30TC0,
0041 DA8XX_MSTPRI_EDMA30TC1,
0042 DA8XX_MSTPRI_EDMA31TC0,
0043 DA8XX_MSTPRI_VPIF_DMA_0,
0044 DA8XX_MSTPRI_VPIF_DMA_1,
0045 DA8XX_MSTPRI_EMAC,
0046 DA8XX_MSTPRI_USB0CFG,
0047 DA8XX_MSTPRI_USB0CDMA,
0048 DA8XX_MSTPRI_UHPI,
0049 DA8XX_MSTPRI_USB1,
0050 DA8XX_MSTPRI_LCDC,
0051 };
0052
0053 struct da8xx_mstpri_descr {
0054 int reg;
0055 int shift;
0056 int mask;
0057 };
0058
0059 static const struct da8xx_mstpri_descr da8xx_mstpri_priority_list[] = {
0060 [DA8XX_MSTPRI_ARM_I] = {
0061 .reg = DA8XX_MSTPRI0_OFFSET,
0062 .shift = 0,
0063 .mask = 0x0000000f,
0064 },
0065 [DA8XX_MSTPRI_ARM_D] = {
0066 .reg = DA8XX_MSTPRI0_OFFSET,
0067 .shift = 4,
0068 .mask = 0x000000f0,
0069 },
0070 [DA8XX_MSTPRI_UPP] = {
0071 .reg = DA8XX_MSTPRI0_OFFSET,
0072 .shift = 16,
0073 .mask = 0x000f0000,
0074 },
0075 [DA8XX_MSTPRI_SATA] = {
0076 .reg = DA8XX_MSTPRI0_OFFSET,
0077 .shift = 20,
0078 .mask = 0x00f00000,
0079 },
0080 [DA8XX_MSTPRI_PRU0] = {
0081 .reg = DA8XX_MSTPRI1_OFFSET,
0082 .shift = 0,
0083 .mask = 0x0000000f,
0084 },
0085 [DA8XX_MSTPRI_PRU1] = {
0086 .reg = DA8XX_MSTPRI1_OFFSET,
0087 .shift = 4,
0088 .mask = 0x000000f0,
0089 },
0090 [DA8XX_MSTPRI_EDMA30TC0] = {
0091 .reg = DA8XX_MSTPRI1_OFFSET,
0092 .shift = 8,
0093 .mask = 0x00000f00,
0094 },
0095 [DA8XX_MSTPRI_EDMA30TC1] = {
0096 .reg = DA8XX_MSTPRI1_OFFSET,
0097 .shift = 12,
0098 .mask = 0x0000f000,
0099 },
0100 [DA8XX_MSTPRI_EDMA31TC0] = {
0101 .reg = DA8XX_MSTPRI1_OFFSET,
0102 .shift = 16,
0103 .mask = 0x000f0000,
0104 },
0105 [DA8XX_MSTPRI_VPIF_DMA_0] = {
0106 .reg = DA8XX_MSTPRI1_OFFSET,
0107 .shift = 24,
0108 .mask = 0x0f000000,
0109 },
0110 [DA8XX_MSTPRI_VPIF_DMA_1] = {
0111 .reg = DA8XX_MSTPRI1_OFFSET,
0112 .shift = 28,
0113 .mask = 0xf0000000,
0114 },
0115 [DA8XX_MSTPRI_EMAC] = {
0116 .reg = DA8XX_MSTPRI2_OFFSET,
0117 .shift = 0,
0118 .mask = 0x0000000f,
0119 },
0120 [DA8XX_MSTPRI_USB0CFG] = {
0121 .reg = DA8XX_MSTPRI2_OFFSET,
0122 .shift = 8,
0123 .mask = 0x00000f00,
0124 },
0125 [DA8XX_MSTPRI_USB0CDMA] = {
0126 .reg = DA8XX_MSTPRI2_OFFSET,
0127 .shift = 12,
0128 .mask = 0x0000f000,
0129 },
0130 [DA8XX_MSTPRI_UHPI] = {
0131 .reg = DA8XX_MSTPRI2_OFFSET,
0132 .shift = 20,
0133 .mask = 0x00f00000,
0134 },
0135 [DA8XX_MSTPRI_USB1] = {
0136 .reg = DA8XX_MSTPRI2_OFFSET,
0137 .shift = 24,
0138 .mask = 0x0f000000,
0139 },
0140 [DA8XX_MSTPRI_LCDC] = {
0141 .reg = DA8XX_MSTPRI2_OFFSET,
0142 .shift = 28,
0143 .mask = 0xf0000000,
0144 },
0145 };
0146
0147 struct da8xx_mstpri_priority {
0148 int which;
0149 u32 val;
0150 };
0151
0152 struct da8xx_mstpri_board_priorities {
0153 const char *board;
0154 const struct da8xx_mstpri_priority *priorities;
0155 size_t numprio;
0156 };
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 static const struct da8xx_mstpri_priority da850_lcdk_priorities[] = {
0167 {
0168 .which = DA8XX_MSTPRI_LCDC,
0169 .val = 0,
0170 },
0171 {
0172 .which = DA8XX_MSTPRI_EDMA30TC1,
0173 .val = 0,
0174 },
0175 {
0176 .which = DA8XX_MSTPRI_EDMA30TC0,
0177 .val = 1,
0178 },
0179 };
0180
0181 static const struct da8xx_mstpri_board_priorities da8xx_mstpri_board_confs[] = {
0182 {
0183 .board = "ti,da850-lcdk",
0184 .priorities = da850_lcdk_priorities,
0185 .numprio = ARRAY_SIZE(da850_lcdk_priorities),
0186 },
0187 };
0188
0189 static const struct da8xx_mstpri_board_priorities *
0190 da8xx_mstpri_get_board_prio(void)
0191 {
0192 const struct da8xx_mstpri_board_priorities *board_prio;
0193 int i;
0194
0195 for (i = 0; i < ARRAY_SIZE(da8xx_mstpri_board_confs); i++) {
0196 board_prio = &da8xx_mstpri_board_confs[i];
0197
0198 if (of_machine_is_compatible(board_prio->board))
0199 return board_prio;
0200 }
0201
0202 return NULL;
0203 }
0204
0205 static int da8xx_mstpri_probe(struct platform_device *pdev)
0206 {
0207 const struct da8xx_mstpri_board_priorities *prio_list;
0208 const struct da8xx_mstpri_descr *prio_descr;
0209 const struct da8xx_mstpri_priority *prio;
0210 struct device *dev = &pdev->dev;
0211 struct resource *res;
0212 void __iomem *mstpri;
0213 u32 reg;
0214 int i;
0215
0216 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0217 mstpri = devm_ioremap_resource(dev, res);
0218 if (IS_ERR(mstpri)) {
0219 dev_err(dev, "unable to map MSTPRI registers\n");
0220 return PTR_ERR(mstpri);
0221 }
0222
0223 prio_list = da8xx_mstpri_get_board_prio();
0224 if (!prio_list) {
0225 dev_err(dev, "no master priorities defined for this board\n");
0226 return -EINVAL;
0227 }
0228
0229 for (i = 0; i < prio_list->numprio; i++) {
0230 prio = &prio_list->priorities[i];
0231 prio_descr = &da8xx_mstpri_priority_list[prio->which];
0232
0233 if (prio_descr->reg + sizeof(u32) > resource_size(res)) {
0234 dev_warn(dev, "register offset out of range\n");
0235 continue;
0236 }
0237
0238 reg = readl(mstpri + prio_descr->reg);
0239 reg &= ~prio_descr->mask;
0240 reg |= prio->val << prio_descr->shift;
0241
0242 writel(reg, mstpri + prio_descr->reg);
0243 }
0244
0245 return 0;
0246 }
0247
0248 static const struct of_device_id da8xx_mstpri_of_match[] = {
0249 { .compatible = "ti,da850-mstpri", },
0250 { },
0251 };
0252
0253 static struct platform_driver da8xx_mstpri_driver = {
0254 .probe = da8xx_mstpri_probe,
0255 .driver = {
0256 .name = "da8xx-mstpri",
0257 .of_match_table = da8xx_mstpri_of_match,
0258 },
0259 };
0260 module_platform_driver(da8xx_mstpri_driver);
0261
0262 MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
0263 MODULE_DESCRIPTION("TI da8xx master peripheral priority driver");
0264 MODULE_LICENSE("GPL v2");