1 /* 2 * DDR PHY Front End (DPFE) driver for Broadcom set top box SoCs 3 * 4 * Copyright (c) 2017 Broadcom 5 * 6 * Released under the GPLv2 only. 7 * SPDX-License-Identifier: GPL-2.0 8 */ 9 10 /* 11 * This driver provides access to the DPFE interface of Broadcom STB SoCs. 12 * The firmware running on the DCPU inside the DDR PHY can provide current 13 * information about the system's RAM, for instance the DRAM refresh rate. 14 * This can be used as an indirect indicator for the DRAM's temperature. 15 * Slower refresh rate means cooler RAM, higher refresh rate means hotter 16 * RAM. 17 * 18 * Throughout the driver, we use readl_relaxed() and writel_relaxed(), which 19 * already contain the appropriate le32_to_cpu()/cpu_to_le32() calls. 20 * 21 * Note regarding the loading of the firmware image: we use be32_to_cpu() 22 * and le_32_to_cpu(), so we can support the following four cases: 23 * - LE kernel + LE firmware image (the most common case) 24 * - LE kernel + BE firmware image 25 * - BE kernel + LE firmware image 26 * - BE kernel + BE firmware image 27 * 28 * The DPCU always runs in big endian mode. The firwmare image, however, can 29 * be in either format. Also, communication between host CPU and DCPU is 30 * always in little endian. 31 */ 32 33 #include <linux/delay.h> 34 #include <linux/firmware.h> 35 #include <linux/io.h> 36 #include <linux/module.h> 37 #include <linux/of_address.h> 38 #include <linux/platform_device.h> 39 40 #define DRVNAME "brcmstb-dpfe" 41 #define FIRMWARE_NAME "dpfe.bin" 42 43 /* DCPU register offsets */ 44 #define REG_DCPU_RESET 0x0 45 #define REG_TO_DCPU_MBOX 0x10 46 #define REG_TO_HOST_MBOX 0x14 47 48 /* Message RAM */ 49 #define DCPU_MSG_RAM(x) (0x100 + (x) * sizeof(u32)) 50 51 /* DRAM Info Offsets & Masks */ 52 #define DRAM_INFO_INTERVAL 0x0 53 #define DRAM_INFO_MR4 0x4 54 #define DRAM_INFO_ERROR 0x8 55 #define DRAM_INFO_MR4_MASK 0xff 56 57 /* DRAM MR4 Offsets & Masks */ 58 #define DRAM_MR4_REFRESH 0x0 /* Refresh rate */ 59 #define DRAM_MR4_SR_ABORT 0x3 /* Self Refresh Abort */ 60 #define DRAM_MR4_PPRE 0x4 /* Post-package repair entry/exit */ 61 #define DRAM_MR4_TH_OFFS 0x5 /* Thermal Offset; vendor specific */ 62 #define DRAM_MR4_TUF 0x7 /* Temperature Update Flag */ 63 64 #define DRAM_MR4_REFRESH_MASK 0x7 65 #define DRAM_MR4_SR_ABORT_MASK 0x1 66 #define DRAM_MR4_PPRE_MASK 0x1 67 #define DRAM_MR4_TH_OFFS_MASK 0x3 68 #define DRAM_MR4_TUF_MASK 0x1 69 70 /* DRAM Vendor Offsets & Masks */ 71 #define DRAM_VENDOR_MR5 0x0 72 #define DRAM_VENDOR_MR6 0x4 73 #define DRAM_VENDOR_MR7 0x8 74 #define DRAM_VENDOR_MR8 0xc 75 #define DRAM_VENDOR_ERROR 0x10 76 #define DRAM_VENDOR_MASK 0xff 77 78 /* Reset register bits & masks */ 79 #define DCPU_RESET_SHIFT 0x0 80 #define DCPU_RESET_MASK 0x1 81 #define DCPU_CLK_DISABLE_SHIFT 0x2 82 83 /* DCPU return codes */ 84 #define DCPU_RET_ERROR_BIT BIT(31) 85 #define DCPU_RET_SUCCESS 0x1 86 #define DCPU_RET_ERR_HEADER (DCPU_RET_ERROR_BIT | BIT(0)) 87 #define DCPU_RET_ERR_INVAL (DCPU_RET_ERROR_BIT | BIT(1)) 88 #define DCPU_RET_ERR_CHKSUM (DCPU_RET_ERROR_BIT | BIT(2)) 89 #define DCPU_RET_ERR_COMMAND (DCPU_RET_ERROR_BIT | BIT(3)) 90 /* This error code is not firmware defined and only used in the driver. */ 91 #define DCPU_RET_ERR_TIMEDOUT (DCPU_RET_ERROR_BIT | BIT(4)) 92 93 /* Firmware magic */ 94 #define DPFE_BE_MAGIC 0xfe1010fe 95 #define DPFE_LE_MAGIC 0xfe0101fe 96 97 /* Error codes */ 98 #define ERR_INVALID_MAGIC -1 99 #define ERR_INVALID_SIZE -2 100 #define ERR_INVALID_CHKSUM -3 101 102 /* Message types */ 103 #define DPFE_MSG_TYPE_COMMAND 1 104 #define DPFE_MSG_TYPE_RESPONSE 2 105 106 #define DELAY_LOOP_MAX 200000 107 108 enum dpfe_msg_fields { 109 MSG_HEADER, 110 MSG_COMMAND, 111 MSG_ARG_COUNT, 112 MSG_ARG0, 113 MSG_CHKSUM, 114 MSG_FIELD_MAX /* Last entry */ 115 }; 116 117 enum dpfe_commands { 118 DPFE_CMD_GET_INFO, 119 DPFE_CMD_GET_REFRESH, 120 DPFE_CMD_GET_VENDOR, 121 DPFE_CMD_MAX /* Last entry */ 122 }; 123 124 struct dpfe_msg { 125 u32 header; 126 u32 command; 127 u32 arg_count; 128 u32 arg0; 129 u32 chksum; /* This is the sum of all other entries. */ 130 }; 131 132 /* 133 * Format of the binary firmware file: 134 * 135 * entry 136 * 0 header 137 * value: 0xfe0101fe <== little endian 138 * 0xfe1010fe <== big endian 139 * 1 sequence: 140 * [31:16] total segments on this build 141 * [15:0] this segment sequence. 142 * 2 FW version 143 * 3 IMEM byte size 144 * 4 DMEM byte size 145 * IMEM 146 * DMEM 147 * last checksum ==> sum of everything 148 */ 149 struct dpfe_firmware_header { 150 u32 magic; 151 u32 sequence; 152 u32 version; 153 u32 imem_size; 154 u32 dmem_size; 155 }; 156 157 /* Things we only need during initialization. */ 158 struct init_data { 159 unsigned int dmem_len; 160 unsigned int imem_len; 161 unsigned int chksum; 162 bool is_big_endian; 163 }; 164 165 /* Things we need for as long as we are active. */ 166 struct private_data { 167 void __iomem *regs; 168 void __iomem *dmem; 169 void __iomem *imem; 170 struct device *dev; 171 unsigned int index; 172 struct mutex lock; 173 }; 174 175 static const char *error_text[] = { 176 "Success", "Header code incorrect", "Unknown command or argument", 177 "Incorrect checksum", "Malformed command", "Timed out", 178 }; 179 180 /* List of supported firmware commands */ 181 static const u32 dpfe_commands[DPFE_CMD_MAX][MSG_FIELD_MAX] = { 182 [DPFE_CMD_GET_INFO] = { 183 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, 184 [MSG_COMMAND] = 1, 185 [MSG_ARG_COUNT] = 1, 186 [MSG_ARG0] = 1, 187 [MSG_CHKSUM] = 4, 188 }, 189 [DPFE_CMD_GET_REFRESH] = { 190 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, 191 [MSG_COMMAND] = 2, 192 [MSG_ARG_COUNT] = 1, 193 [MSG_ARG0] = 1, 194 [MSG_CHKSUM] = 5, 195 }, 196 [DPFE_CMD_GET_VENDOR] = { 197 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, 198 [MSG_COMMAND] = 2, 199 [MSG_ARG_COUNT] = 1, 200 [MSG_ARG0] = 2, 201 [MSG_CHKSUM] = 6, 202 }, 203 }; 204 205 static bool is_dcpu_enabled(void __iomem *regs) 206 { 207 u32 val; 208 209 val = readl_relaxed(regs + REG_DCPU_RESET); 210 211 return !(val & DCPU_RESET_MASK); 212 } 213 214 static void __disable_dcpu(void __iomem *regs) 215 { 216 u32 val; 217 218 if (!is_dcpu_enabled(regs)) 219 return; 220 221 /* Put DCPU in reset if it's running. */ 222 val = readl_relaxed(regs + REG_DCPU_RESET); 223 val |= (1 << DCPU_RESET_SHIFT); 224 writel_relaxed(val, regs + REG_DCPU_RESET); 225 } 226 227 static void __enable_dcpu(void __iomem *regs) 228 { 229 u32 val; 230 231 /* Clear mailbox registers. */ 232 writel_relaxed(0, regs + REG_TO_DCPU_MBOX); 233 writel_relaxed(0, regs + REG_TO_HOST_MBOX); 234 235 /* Disable DCPU clock gating */ 236 val = readl_relaxed(regs + REG_DCPU_RESET); 237 val &= ~(1 << DCPU_CLK_DISABLE_SHIFT); 238 writel_relaxed(val, regs + REG_DCPU_RESET); 239 240 /* Take DCPU out of reset */ 241 val = readl_relaxed(regs + REG_DCPU_RESET); 242 val &= ~(1 << DCPU_RESET_SHIFT); 243 writel_relaxed(val, regs + REG_DCPU_RESET); 244 } 245 246 static unsigned int get_msg_chksum(const u32 msg[]) 247 { 248 unsigned int sum = 0; 249 unsigned int i; 250 251 /* Don't include the last field in the checksum. */ 252 for (i = 0; i < MSG_FIELD_MAX - 1; i++) 253 sum += msg[i]; 254 255 return sum; 256 } 257 258 static int __send_command(struct private_data *priv, unsigned int cmd, 259 u32 result[]) 260 { 261 const u32 *msg = dpfe_commands[cmd]; 262 void __iomem *regs = priv->regs; 263 unsigned int i, chksum; 264 int ret = 0; 265 u32 resp; 266 267 if (cmd >= DPFE_CMD_MAX) 268 return -1; 269 270 mutex_lock(&priv->lock); 271 272 /* Write command and arguments to message area */ 273 for (i = 0; i < MSG_FIELD_MAX; i++) 274 writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i)); 275 276 /* Tell DCPU there is a command waiting */ 277 writel_relaxed(1, regs + REG_TO_DCPU_MBOX); 278 279 /* Wait for DCPU to process the command */ 280 for (i = 0; i < DELAY_LOOP_MAX; i++) { 281 /* Read response code */ 282 resp = readl_relaxed(regs + REG_TO_HOST_MBOX); 283 if (resp > 0) 284 break; 285 udelay(5); 286 } 287 288 if (i == DELAY_LOOP_MAX) { 289 resp = (DCPU_RET_ERR_TIMEDOUT & ~DCPU_RET_ERROR_BIT); 290 ret = -ffs(resp); 291 } else { 292 /* Read response data */ 293 for (i = 0; i < MSG_FIELD_MAX; i++) 294 result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i)); 295 } 296 297 /* Tell DCPU we are done */ 298 writel_relaxed(0, regs + REG_TO_HOST_MBOX); 299 300 mutex_unlock(&priv->lock); 301 302 if (ret) 303 return ret; 304 305 /* Verify response */ 306 chksum = get_msg_chksum(result); 307 if (chksum != result[MSG_CHKSUM]) 308 resp = DCPU_RET_ERR_CHKSUM; 309 310 if (resp != DCPU_RET_SUCCESS) { 311 resp &= ~DCPU_RET_ERROR_BIT; 312 ret = -ffs(resp); 313 } 314 315 return ret; 316 } 317 318 /* Ensure that the firmware file loaded meets all the requirements. */ 319 static int __verify_firmware(struct init_data *init, 320 const struct firmware *fw) 321 { 322 const struct dpfe_firmware_header *header = (void *)fw->data; 323 unsigned int dmem_size, imem_size, total_size; 324 bool is_big_endian = false; 325 const u32 *chksum_ptr; 326 327 if (header->magic == DPFE_BE_MAGIC) 328 is_big_endian = true; 329 else if (header->magic != DPFE_LE_MAGIC) 330 return ERR_INVALID_MAGIC; 331 332 if (is_big_endian) { 333 dmem_size = be32_to_cpu(header->dmem_size); 334 imem_size = be32_to_cpu(header->imem_size); 335 } else { 336 dmem_size = le32_to_cpu(header->dmem_size); 337 imem_size = le32_to_cpu(header->imem_size); 338 } 339 340 /* Data and instruction sections are 32 bit words. */ 341 if ((dmem_size % sizeof(u32)) != 0 || (imem_size % sizeof(u32)) != 0) 342 return ERR_INVALID_SIZE; 343 344 /* 345 * The header + the data section + the instruction section + the 346 * checksum must be equal to the total firmware size. 347 */ 348 total_size = dmem_size + imem_size + sizeof(*header) + 349 sizeof(*chksum_ptr); 350 if (total_size != fw->size) 351 return ERR_INVALID_SIZE; 352 353 /* The checksum comes at the very end. */ 354 chksum_ptr = (void *)fw->data + sizeof(*header) + dmem_size + imem_size; 355 356 init->is_big_endian = is_big_endian; 357 init->dmem_len = dmem_size; 358 init->imem_len = imem_size; 359 init->chksum = (is_big_endian) 360 ? be32_to_cpu(*chksum_ptr) : le32_to_cpu(*chksum_ptr); 361 362 return 0; 363 } 364 365 /* Verify checksum by reading back the firmware from co-processor RAM. */ 366 static int __verify_fw_checksum(struct init_data *init, 367 struct private_data *priv, 368 const struct dpfe_firmware_header *header, 369 u32 checksum) 370 { 371 u32 magic, sequence, version, sum; 372 u32 __iomem *dmem = priv->dmem; 373 u32 __iomem *imem = priv->imem; 374 unsigned int i; 375 376 if (init->is_big_endian) { 377 magic = be32_to_cpu(header->magic); 378 sequence = be32_to_cpu(header->sequence); 379 version = be32_to_cpu(header->version); 380 } else { 381 magic = le32_to_cpu(header->magic); 382 sequence = le32_to_cpu(header->sequence); 383 version = le32_to_cpu(header->version); 384 } 385 386 sum = magic + sequence + version + init->dmem_len + init->imem_len; 387 388 for (i = 0; i < init->dmem_len / sizeof(u32); i++) 389 sum += readl_relaxed(dmem + i); 390 391 for (i = 0; i < init->imem_len / sizeof(u32); i++) 392 sum += readl_relaxed(imem + i); 393 394 return (sum == checksum) ? 0 : -1; 395 } 396 397 static int __write_firmware(u32 __iomem *mem, const u32 *fw, 398 unsigned int size, bool is_big_endian) 399 { 400 unsigned int i; 401 402 /* Convert size to 32-bit words. */ 403 size /= sizeof(u32); 404 405 /* It is recommended to clear the firmware area first. */ 406 for (i = 0; i < size; i++) 407 writel_relaxed(0, mem + i); 408 409 /* Now copy it. */ 410 if (is_big_endian) { 411 for (i = 0; i < size; i++) 412 writel_relaxed(be32_to_cpu(fw[i]), mem + i); 413 } else { 414 for (i = 0; i < size; i++) 415 writel_relaxed(le32_to_cpu(fw[i]), mem + i); 416 } 417 418 return 0; 419 } 420 421 static int brcmstb_dpfe_download_firmware(struct platform_device *pdev, 422 struct init_data *init) 423 { 424 const struct dpfe_firmware_header *header; 425 unsigned int dmem_size, imem_size; 426 struct device *dev = &pdev->dev; 427 bool is_big_endian = false; 428 struct private_data *priv; 429 const struct firmware *fw; 430 const u32 *dmem, *imem; 431 const void *fw_blob; 432 int ret; 433 434 priv = platform_get_drvdata(pdev); 435 436 /* 437 * Skip downloading the firmware if the DCPU is already running and 438 * responding to commands. 439 */ 440 if (is_dcpu_enabled(priv->regs)) { 441 u32 response[MSG_FIELD_MAX]; 442 443 ret = __send_command(priv, DPFE_CMD_GET_INFO, response); 444 if (!ret) 445 return 0; 446 } 447 448 ret = request_firmware(&fw, FIRMWARE_NAME, dev); 449 /* request_firmware() prints its own error messages. */ 450 if (ret) 451 return ret; 452 453 ret = __verify_firmware(init, fw); 454 if (ret) 455 return -EFAULT; 456 457 __disable_dcpu(priv->regs); 458 459 is_big_endian = init->is_big_endian; 460 dmem_size = init->dmem_len; 461 imem_size = init->imem_len; 462 463 /* At the beginning of the firmware blob is a header. */ 464 header = (struct dpfe_firmware_header *)fw->data; 465 /* Void pointer to the beginning of the actual firmware. */ 466 fw_blob = fw->data + sizeof(*header); 467 /* IMEM comes right after the header. */ 468 imem = fw_blob; 469 /* DMEM follows after IMEM. */ 470 dmem = fw_blob + imem_size; 471 472 ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian); 473 if (ret) 474 return ret; 475 ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian); 476 if (ret) 477 return ret; 478 479 ret = __verify_fw_checksum(init, priv, header, init->chksum); 480 if (ret) 481 return ret; 482 483 __enable_dcpu(priv->regs); 484 485 return 0; 486 } 487 488 static ssize_t generic_show(unsigned int command, u32 response[], 489 struct device *dev, char *buf) 490 { 491 struct private_data *priv; 492 int ret; 493 494 priv = dev_get_drvdata(dev); 495 if (!priv) 496 return sprintf(buf, "ERROR: driver private data not set\n"); 497 498 ret = __send_command(priv, command, response); 499 if (ret < 0) 500 return sprintf(buf, "ERROR: %s\n", error_text[-ret]); 501 502 return 0; 503 } 504 505 static ssize_t show_info(struct device *dev, struct device_attribute *devattr, 506 char *buf) 507 { 508 u32 response[MSG_FIELD_MAX]; 509 unsigned int info; 510 int ret; 511 512 ret = generic_show(DPFE_CMD_GET_INFO, response, dev, buf); 513 if (ret) 514 return ret; 515 516 info = response[MSG_ARG0]; 517 518 return sprintf(buf, "%u.%u.%u.%u\n", 519 (info >> 24) & 0xff, 520 (info >> 16) & 0xff, 521 (info >> 8) & 0xff, 522 info & 0xff); 523 } 524 525 static ssize_t show_refresh(struct device *dev, 526 struct device_attribute *devattr, char *buf) 527 { 528 u32 response[MSG_FIELD_MAX]; 529 void __iomem *info; 530 struct private_data *priv; 531 unsigned int offset; 532 u8 refresh, sr_abort, ppre, thermal_offs, tuf; 533 u32 mr4; 534 int ret; 535 536 ret = generic_show(DPFE_CMD_GET_REFRESH, response, dev, buf); 537 if (ret) 538 return ret; 539 540 priv = dev_get_drvdata(dev); 541 offset = response[MSG_ARG0]; 542 info = priv->dmem + offset; 543 544 mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK; 545 546 refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK; 547 sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK; 548 ppre = (mr4 >> DRAM_MR4_PPRE) & DRAM_MR4_PPRE_MASK; 549 thermal_offs = (mr4 >> DRAM_MR4_TH_OFFS) & DRAM_MR4_TH_OFFS_MASK; 550 tuf = (mr4 >> DRAM_MR4_TUF) & DRAM_MR4_TUF_MASK; 551 552 return sprintf(buf, "%#x %#x %#x %#x %#x %#x %#x\n", 553 readl_relaxed(info + DRAM_INFO_INTERVAL), 554 refresh, sr_abort, ppre, thermal_offs, tuf, 555 readl_relaxed(info + DRAM_INFO_ERROR)); 556 } 557 558 static ssize_t store_refresh(struct device *dev, struct device_attribute *attr, 559 const char *buf, size_t count) 560 { 561 u32 response[MSG_FIELD_MAX]; 562 struct private_data *priv; 563 void __iomem *info; 564 unsigned int offset; 565 unsigned long val; 566 int ret; 567 568 if (kstrtoul(buf, 0, &val) < 0) 569 return -EINVAL; 570 571 priv = dev_get_drvdata(dev); 572 573 ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response); 574 if (ret) 575 return ret; 576 577 offset = response[MSG_ARG0]; 578 info = priv->dmem + offset; 579 writel_relaxed(val, info + DRAM_INFO_INTERVAL); 580 581 return count; 582 } 583 584 static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr, 585 char *buf) 586 { 587 u32 response[MSG_FIELD_MAX]; 588 struct private_data *priv; 589 void __iomem *info; 590 unsigned int offset; 591 int ret; 592 593 ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf); 594 if (ret) 595 return ret; 596 597 offset = response[MSG_ARG0]; 598 priv = dev_get_drvdata(dev); 599 info = priv->dmem + offset; 600 601 return sprintf(buf, "%#x %#x %#x %#x %#x\n", 602 readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK, 603 readl_relaxed(info + DRAM_VENDOR_MR6) & DRAM_VENDOR_MASK, 604 readl_relaxed(info + DRAM_VENDOR_MR7) & DRAM_VENDOR_MASK, 605 readl_relaxed(info + DRAM_VENDOR_MR8) & DRAM_VENDOR_MASK, 606 readl_relaxed(info + DRAM_VENDOR_ERROR)); 607 } 608 609 static int brcmstb_dpfe_resume(struct platform_device *pdev) 610 { 611 struct init_data init; 612 613 return brcmstb_dpfe_download_firmware(pdev, &init); 614 } 615 616 static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL); 617 static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh); 618 static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL); 619 static struct attribute *dpfe_attrs[] = { 620 &dev_attr_dpfe_info.attr, 621 &dev_attr_dpfe_refresh.attr, 622 &dev_attr_dpfe_vendor.attr, 623 NULL 624 }; 625 ATTRIBUTE_GROUPS(dpfe); 626 627 static int brcmstb_dpfe_probe(struct platform_device *pdev) 628 { 629 struct device *dev = &pdev->dev; 630 struct private_data *priv; 631 struct device *dpfe_dev; 632 struct init_data init; 633 struct resource *res; 634 u32 index; 635 int ret; 636 637 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 638 if (!priv) 639 return -ENOMEM; 640 641 mutex_init(&priv->lock); 642 platform_set_drvdata(pdev, priv); 643 644 /* Cell index is optional; default to 0 if not present. */ 645 ret = of_property_read_u32(dev->of_node, "cell-index", &index); 646 if (ret) 647 index = 0; 648 649 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-cpu"); 650 priv->regs = devm_ioremap_resource(dev, res); 651 if (IS_ERR(priv->regs)) { 652 dev_err(dev, "couldn't map DCPU registers\n"); 653 return -ENODEV; 654 } 655 656 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-dmem"); 657 priv->dmem = devm_ioremap_resource(dev, res); 658 if (IS_ERR(priv->dmem)) { 659 dev_err(dev, "Couldn't map DCPU data memory\n"); 660 return -ENOENT; 661 } 662 663 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-imem"); 664 priv->imem = devm_ioremap_resource(dev, res); 665 if (IS_ERR(priv->imem)) { 666 dev_err(dev, "Couldn't map DCPU instruction memory\n"); 667 return -ENOENT; 668 } 669 670 ret = brcmstb_dpfe_download_firmware(pdev, &init); 671 if (ret) 672 goto err; 673 674 dpfe_dev = devm_kzalloc(dev, sizeof(*dpfe_dev), GFP_KERNEL); 675 if (!dpfe_dev) { 676 ret = -ENOMEM; 677 goto err; 678 } 679 680 priv->dev = dpfe_dev; 681 priv->index = index; 682 683 dpfe_dev->parent = dev; 684 dpfe_dev->groups = dpfe_groups; 685 dpfe_dev->of_node = dev->of_node; 686 dev_set_drvdata(dpfe_dev, priv); 687 dev_set_name(dpfe_dev, "dpfe%u", index); 688 689 ret = device_register(dpfe_dev); 690 if (ret) 691 goto err; 692 693 dev_info(dev, "registered.\n"); 694 695 return 0; 696 697 err: 698 dev_err(dev, "failed to initialize -- error %d\n", ret); 699 700 return ret; 701 } 702 703 static const struct of_device_id brcmstb_dpfe_of_match[] = { 704 { .compatible = "brcm,dpfe-cpu", }, 705 {} 706 }; 707 MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match); 708 709 static struct platform_driver brcmstb_dpfe_driver = { 710 .driver = { 711 .name = DRVNAME, 712 .of_match_table = brcmstb_dpfe_of_match, 713 }, 714 .probe = brcmstb_dpfe_probe, 715 .resume = brcmstb_dpfe_resume, 716 }; 717 718 module_platform_driver(brcmstb_dpfe_driver); 719 720 MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>"); 721 MODULE_DESCRIPTION("BRCMSTB DDR PHY Front End Driver"); 722 MODULE_LICENSE("GPL"); 723