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