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