0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <linux/delay.h>
0032 #include <linux/firmware.h>
0033 #include <linux/io.h>
0034 #include <linux/module.h>
0035 #include <linux/of_address.h>
0036 #include <linux/of_device.h>
0037 #include <linux/platform_device.h>
0038
0039 #define DRVNAME "brcmstb-dpfe"
0040
0041
0042 #define REG_DCPU_RESET 0x0
0043 #define REG_TO_DCPU_MBOX 0x10
0044 #define REG_TO_HOST_MBOX 0x14
0045
0046
0047 #define DRAM_MSG_ADDR_OFFSET 0x0
0048 #define DRAM_MSG_TYPE_OFFSET 0x1c
0049 #define DRAM_MSG_ADDR_MASK ((1UL << DRAM_MSG_TYPE_OFFSET) - 1)
0050 #define DRAM_MSG_TYPE_MASK ((1UL << \
0051 (BITS_PER_LONG - DRAM_MSG_TYPE_OFFSET)) - 1)
0052
0053
0054 #define DCPU_MSG_RAM_START 0x100
0055 #define DCPU_MSG_RAM(x) (DCPU_MSG_RAM_START + (x) * sizeof(u32))
0056
0057
0058 #define DRAM_INFO_INTERVAL 0x0
0059 #define DRAM_INFO_MR4 0x4
0060 #define DRAM_INFO_ERROR 0x8
0061 #define DRAM_INFO_MR4_MASK 0xff
0062 #define DRAM_INFO_MR4_SHIFT 24
0063
0064
0065 #define DRAM_MR4_REFRESH 0x0
0066 #define DRAM_MR4_SR_ABORT 0x3
0067 #define DRAM_MR4_PPRE 0x4
0068 #define DRAM_MR4_TH_OFFS 0x5
0069 #define DRAM_MR4_TUF 0x7
0070
0071 #define DRAM_MR4_REFRESH_MASK 0x7
0072 #define DRAM_MR4_SR_ABORT_MASK 0x1
0073 #define DRAM_MR4_PPRE_MASK 0x1
0074 #define DRAM_MR4_TH_OFFS_MASK 0x3
0075 #define DRAM_MR4_TUF_MASK 0x1
0076
0077
0078 #define DRAM_VENDOR_MR5 0x0
0079 #define DRAM_VENDOR_MR6 0x4
0080 #define DRAM_VENDOR_MR7 0x8
0081 #define DRAM_VENDOR_MR8 0xc
0082 #define DRAM_VENDOR_ERROR 0x10
0083 #define DRAM_VENDOR_MASK 0xff
0084 #define DRAM_VENDOR_SHIFT 24
0085
0086
0087 #define DRAM_DDR_INFO_MR4 0x0
0088 #define DRAM_DDR_INFO_MR5 0x4
0089 #define DRAM_DDR_INFO_MR6 0x8
0090 #define DRAM_DDR_INFO_MR7 0xc
0091 #define DRAM_DDR_INFO_MR8 0x10
0092 #define DRAM_DDR_INFO_ERROR 0x14
0093 #define DRAM_DDR_INFO_MASK 0xff
0094
0095
0096 #define DCPU_RESET_SHIFT 0x0
0097 #define DCPU_RESET_MASK 0x1
0098 #define DCPU_CLK_DISABLE_SHIFT 0x2
0099
0100
0101 #define DCPU_RET_ERROR_BIT BIT(31)
0102 #define DCPU_RET_SUCCESS 0x1
0103 #define DCPU_RET_ERR_HEADER (DCPU_RET_ERROR_BIT | BIT(0))
0104 #define DCPU_RET_ERR_INVAL (DCPU_RET_ERROR_BIT | BIT(1))
0105 #define DCPU_RET_ERR_CHKSUM (DCPU_RET_ERROR_BIT | BIT(2))
0106 #define DCPU_RET_ERR_COMMAND (DCPU_RET_ERROR_BIT | BIT(3))
0107
0108 #define DCPU_RET_ERR_TIMEDOUT (DCPU_RET_ERROR_BIT | BIT(4))
0109
0110
0111 #define DPFE_BE_MAGIC 0xfe1010fe
0112 #define DPFE_LE_MAGIC 0xfe0101fe
0113
0114
0115 #define ERR_INVALID_MAGIC -1
0116 #define ERR_INVALID_SIZE -2
0117 #define ERR_INVALID_CHKSUM -3
0118
0119
0120 #define DPFE_MSG_TYPE_COMMAND 1
0121 #define DPFE_MSG_TYPE_RESPONSE 2
0122
0123 #define DELAY_LOOP_MAX 1000
0124
0125 enum dpfe_msg_fields {
0126 MSG_HEADER,
0127 MSG_COMMAND,
0128 MSG_ARG_COUNT,
0129 MSG_ARG0,
0130 MSG_FIELD_MAX = 16
0131 };
0132
0133 enum dpfe_commands {
0134 DPFE_CMD_GET_INFO,
0135 DPFE_CMD_GET_REFRESH,
0136 DPFE_CMD_GET_VENDOR,
0137 DPFE_CMD_MAX
0138 };
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 struct dpfe_firmware_header {
0158 u32 magic;
0159 u32 sequence;
0160 u32 version;
0161 u32 imem_size;
0162 u32 dmem_size;
0163 };
0164
0165
0166 struct init_data {
0167 unsigned int dmem_len;
0168 unsigned int imem_len;
0169 unsigned int chksum;
0170 bool is_big_endian;
0171 };
0172
0173
0174 struct dpfe_api {
0175 int version;
0176 const char *fw_name;
0177 const struct attribute_group **sysfs_attrs;
0178 u32 command[DPFE_CMD_MAX][MSG_FIELD_MAX];
0179 };
0180
0181
0182 struct brcmstb_dpfe_priv {
0183 void __iomem *regs;
0184 void __iomem *dmem;
0185 void __iomem *imem;
0186 struct device *dev;
0187 const struct dpfe_api *dpfe_api;
0188 struct mutex lock;
0189 };
0190
0191
0192
0193
0194
0195 static ssize_t show_info(struct device *, struct device_attribute *, char *);
0196 static ssize_t show_refresh(struct device *, struct device_attribute *, char *);
0197 static ssize_t store_refresh(struct device *, struct device_attribute *,
0198 const char *, size_t);
0199 static ssize_t show_vendor(struct device *, struct device_attribute *, char *);
0200 static ssize_t show_dram(struct device *, struct device_attribute *, char *);
0201
0202
0203
0204
0205
0206
0207 static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL);
0208 static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh);
0209 static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL);
0210 static DEVICE_ATTR(dpfe_dram, 0444, show_dram, NULL);
0211
0212
0213 static struct attribute *dpfe_v2_attrs[] = {
0214 &dev_attr_dpfe_info.attr,
0215 &dev_attr_dpfe_refresh.attr,
0216 &dev_attr_dpfe_vendor.attr,
0217 NULL
0218 };
0219 ATTRIBUTE_GROUPS(dpfe_v2);
0220
0221
0222 static struct attribute *dpfe_v3_attrs[] = {
0223 &dev_attr_dpfe_info.attr,
0224 &dev_attr_dpfe_dram.attr,
0225 NULL
0226 };
0227 ATTRIBUTE_GROUPS(dpfe_v3);
0228
0229
0230
0231
0232
0233
0234 static const struct dpfe_api dpfe_api_old_v2 = {
0235 .version = 1,
0236 .fw_name = "dpfe.bin",
0237 .sysfs_attrs = dpfe_v2_groups,
0238 .command = {
0239 [DPFE_CMD_GET_INFO] = {
0240 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0241 [MSG_COMMAND] = 1,
0242 [MSG_ARG_COUNT] = 1,
0243 [MSG_ARG0] = 1,
0244 },
0245 [DPFE_CMD_GET_REFRESH] = {
0246 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0247 [MSG_COMMAND] = 2,
0248 [MSG_ARG_COUNT] = 1,
0249 [MSG_ARG0] = 1,
0250 },
0251 [DPFE_CMD_GET_VENDOR] = {
0252 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0253 [MSG_COMMAND] = 2,
0254 [MSG_ARG_COUNT] = 1,
0255 [MSG_ARG0] = 2,
0256 },
0257 }
0258 };
0259
0260
0261
0262
0263
0264 static const struct dpfe_api dpfe_api_new_v2 = {
0265 .version = 2,
0266 .fw_name = NULL,
0267 .sysfs_attrs = dpfe_v2_groups,
0268 .command = {
0269 [DPFE_CMD_GET_INFO] = {
0270 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0271 [MSG_COMMAND] = 0x101,
0272 },
0273 [DPFE_CMD_GET_REFRESH] = {
0274 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0275 [MSG_COMMAND] = 0x201,
0276 },
0277 [DPFE_CMD_GET_VENDOR] = {
0278 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0279 [MSG_COMMAND] = 0x202,
0280 },
0281 }
0282 };
0283
0284
0285 static const struct dpfe_api dpfe_api_v3 = {
0286 .version = 3,
0287 .fw_name = NULL,
0288 .sysfs_attrs = dpfe_v3_groups,
0289 .command = {
0290 [DPFE_CMD_GET_INFO] = {
0291 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0292 [MSG_COMMAND] = 0x0101,
0293 [MSG_ARG_COUNT] = 1,
0294 [MSG_ARG0] = 1,
0295 },
0296 [DPFE_CMD_GET_REFRESH] = {
0297 [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0298 [MSG_COMMAND] = 0x0202,
0299 [MSG_ARG_COUNT] = 0,
0300 },
0301
0302 },
0303 };
0304
0305 static const char *get_error_text(unsigned int i)
0306 {
0307 static const char * const error_text[] = {
0308 "Success", "Header code incorrect",
0309 "Unknown command or argument", "Incorrect checksum",
0310 "Malformed command", "Timed out", "Unknown error",
0311 };
0312
0313 if (unlikely(i >= ARRAY_SIZE(error_text)))
0314 i = ARRAY_SIZE(error_text) - 1;
0315
0316 return error_text[i];
0317 }
0318
0319 static bool is_dcpu_enabled(struct brcmstb_dpfe_priv *priv)
0320 {
0321 u32 val;
0322
0323 mutex_lock(&priv->lock);
0324 val = readl_relaxed(priv->regs + REG_DCPU_RESET);
0325 mutex_unlock(&priv->lock);
0326
0327 return !(val & DCPU_RESET_MASK);
0328 }
0329
0330 static void __disable_dcpu(struct brcmstb_dpfe_priv *priv)
0331 {
0332 u32 val;
0333
0334 if (!is_dcpu_enabled(priv))
0335 return;
0336
0337 mutex_lock(&priv->lock);
0338
0339
0340 val = readl_relaxed(priv->regs + REG_DCPU_RESET);
0341 val |= (1 << DCPU_RESET_SHIFT);
0342 writel_relaxed(val, priv->regs + REG_DCPU_RESET);
0343
0344 mutex_unlock(&priv->lock);
0345 }
0346
0347 static void __enable_dcpu(struct brcmstb_dpfe_priv *priv)
0348 {
0349 void __iomem *regs = priv->regs;
0350 u32 val;
0351
0352 mutex_lock(&priv->lock);
0353
0354
0355 writel_relaxed(0, regs + REG_TO_DCPU_MBOX);
0356 writel_relaxed(0, regs + REG_TO_HOST_MBOX);
0357
0358
0359 val = readl_relaxed(regs + REG_DCPU_RESET);
0360 val &= ~(1 << DCPU_CLK_DISABLE_SHIFT);
0361 writel_relaxed(val, regs + REG_DCPU_RESET);
0362
0363
0364 val = readl_relaxed(regs + REG_DCPU_RESET);
0365 val &= ~(1 << DCPU_RESET_SHIFT);
0366 writel_relaxed(val, regs + REG_DCPU_RESET);
0367
0368 mutex_unlock(&priv->lock);
0369 }
0370
0371 static unsigned int get_msg_chksum(const u32 msg[], unsigned int max)
0372 {
0373 unsigned int sum = 0;
0374 unsigned int i;
0375
0376
0377 for (i = 0; i < max; i++)
0378 sum += msg[i];
0379
0380 return sum;
0381 }
0382
0383 static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
0384 char *buf, ssize_t *size)
0385 {
0386 unsigned int msg_type;
0387 unsigned int offset;
0388 void __iomem *ptr = NULL;
0389
0390
0391 if (unlikely(priv->dpfe_api->version >= 3))
0392 return NULL;
0393
0394 msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
0395 offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
0396
0397
0398
0399
0400
0401
0402
0403 switch (msg_type) {
0404 case 1:
0405 ptr = priv->regs + DCPU_MSG_RAM_START + offset;
0406 break;
0407 case 0:
0408 ptr = priv->dmem + offset;
0409 break;
0410 default:
0411 dev_emerg(priv->dev, "invalid message reply from DCPU: %#x\n",
0412 response);
0413 if (buf && size)
0414 *size = sprintf(buf,
0415 "FATAL: communication error with DCPU\n");
0416 }
0417
0418 return ptr;
0419 }
0420
0421 static void __finalize_command(struct brcmstb_dpfe_priv *priv)
0422 {
0423 unsigned int release_mbox;
0424
0425
0426
0427
0428
0429 release_mbox = (priv->dpfe_api->version < 2)
0430 ? REG_TO_HOST_MBOX : REG_TO_DCPU_MBOX;
0431 writel_relaxed(0, priv->regs + release_mbox);
0432 }
0433
0434 static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
0435 u32 result[])
0436 {
0437 const u32 *msg = priv->dpfe_api->command[cmd];
0438 void __iomem *regs = priv->regs;
0439 unsigned int i, chksum, chksum_idx;
0440 int ret = 0;
0441 u32 resp;
0442
0443 if (cmd >= DPFE_CMD_MAX)
0444 return -1;
0445
0446 mutex_lock(&priv->lock);
0447
0448
0449 for (i = 0; i < DELAY_LOOP_MAX; i++) {
0450 resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
0451 if (resp == 0)
0452 break;
0453 msleep(1);
0454 }
0455 if (resp != 0) {
0456 mutex_unlock(&priv->lock);
0457 return -ffs(DCPU_RET_ERR_TIMEDOUT);
0458 }
0459
0460
0461 chksum_idx = msg[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
0462 chksum = get_msg_chksum(msg, chksum_idx);
0463
0464
0465 for (i = 0; i < MSG_FIELD_MAX; i++) {
0466 if (i == chksum_idx)
0467 writel_relaxed(chksum, regs + DCPU_MSG_RAM(i));
0468 else
0469 writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i));
0470 }
0471
0472
0473 writel_relaxed(1, regs + REG_TO_DCPU_MBOX);
0474
0475
0476 for (i = 0; i < DELAY_LOOP_MAX; i++) {
0477
0478 resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
0479 if (resp > 0)
0480 break;
0481 msleep(1);
0482 }
0483
0484 if (i == DELAY_LOOP_MAX) {
0485 resp = (DCPU_RET_ERR_TIMEDOUT & ~DCPU_RET_ERROR_BIT);
0486 ret = -ffs(resp);
0487 } else {
0488
0489 for (i = 0; i < MSG_FIELD_MAX; i++)
0490 result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i));
0491 chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
0492 }
0493
0494
0495 __finalize_command(priv);
0496
0497 mutex_unlock(&priv->lock);
0498
0499 if (ret)
0500 return ret;
0501
0502
0503 chksum = get_msg_chksum(result, chksum_idx);
0504 if (chksum != result[chksum_idx])
0505 resp = DCPU_RET_ERR_CHKSUM;
0506
0507 if (resp != DCPU_RET_SUCCESS) {
0508 resp &= ~DCPU_RET_ERROR_BIT;
0509 ret = -ffs(resp);
0510 }
0511
0512 return ret;
0513 }
0514
0515
0516 static int __verify_firmware(struct init_data *init,
0517 const struct firmware *fw)
0518 {
0519 const struct dpfe_firmware_header *header = (void *)fw->data;
0520 unsigned int dmem_size, imem_size, total_size;
0521 bool is_big_endian = false;
0522 const u32 *chksum_ptr;
0523
0524 if (header->magic == DPFE_BE_MAGIC)
0525 is_big_endian = true;
0526 else if (header->magic != DPFE_LE_MAGIC)
0527 return ERR_INVALID_MAGIC;
0528
0529 if (is_big_endian) {
0530 dmem_size = be32_to_cpu(header->dmem_size);
0531 imem_size = be32_to_cpu(header->imem_size);
0532 } else {
0533 dmem_size = le32_to_cpu(header->dmem_size);
0534 imem_size = le32_to_cpu(header->imem_size);
0535 }
0536
0537
0538 if ((dmem_size % sizeof(u32)) != 0 || (imem_size % sizeof(u32)) != 0)
0539 return ERR_INVALID_SIZE;
0540
0541
0542
0543
0544
0545 total_size = dmem_size + imem_size + sizeof(*header) +
0546 sizeof(*chksum_ptr);
0547 if (total_size != fw->size)
0548 return ERR_INVALID_SIZE;
0549
0550
0551 chksum_ptr = (void *)fw->data + sizeof(*header) + dmem_size + imem_size;
0552
0553 init->is_big_endian = is_big_endian;
0554 init->dmem_len = dmem_size;
0555 init->imem_len = imem_size;
0556 init->chksum = (is_big_endian)
0557 ? be32_to_cpu(*chksum_ptr) : le32_to_cpu(*chksum_ptr);
0558
0559 return 0;
0560 }
0561
0562
0563 static int __verify_fw_checksum(struct init_data *init,
0564 struct brcmstb_dpfe_priv *priv,
0565 const struct dpfe_firmware_header *header,
0566 u32 checksum)
0567 {
0568 u32 magic, sequence, version, sum;
0569 u32 __iomem *dmem = priv->dmem;
0570 u32 __iomem *imem = priv->imem;
0571 unsigned int i;
0572
0573 if (init->is_big_endian) {
0574 magic = be32_to_cpu(header->magic);
0575 sequence = be32_to_cpu(header->sequence);
0576 version = be32_to_cpu(header->version);
0577 } else {
0578 magic = le32_to_cpu(header->magic);
0579 sequence = le32_to_cpu(header->sequence);
0580 version = le32_to_cpu(header->version);
0581 }
0582
0583 sum = magic + sequence + version + init->dmem_len + init->imem_len;
0584
0585 for (i = 0; i < init->dmem_len / sizeof(u32); i++)
0586 sum += readl_relaxed(dmem + i);
0587
0588 for (i = 0; i < init->imem_len / sizeof(u32); i++)
0589 sum += readl_relaxed(imem + i);
0590
0591 return (sum == checksum) ? 0 : -1;
0592 }
0593
0594 static int __write_firmware(u32 __iomem *mem, const u32 *fw,
0595 unsigned int size, bool is_big_endian)
0596 {
0597 unsigned int i;
0598
0599
0600 size /= sizeof(u32);
0601
0602
0603 for (i = 0; i < size; i++)
0604 writel_relaxed(0, mem + i);
0605
0606
0607 if (is_big_endian) {
0608 for (i = 0; i < size; i++)
0609 writel_relaxed(be32_to_cpu(fw[i]), mem + i);
0610 } else {
0611 for (i = 0; i < size; i++)
0612 writel_relaxed(le32_to_cpu(fw[i]), mem + i);
0613 }
0614
0615 return 0;
0616 }
0617
0618 static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv)
0619 {
0620 const struct dpfe_firmware_header *header;
0621 unsigned int dmem_size, imem_size;
0622 struct device *dev = priv->dev;
0623 bool is_big_endian = false;
0624 const struct firmware *fw;
0625 const u32 *dmem, *imem;
0626 struct init_data init;
0627 const void *fw_blob;
0628 int ret;
0629
0630
0631
0632
0633
0634 if (is_dcpu_enabled(priv)) {
0635 u32 response[MSG_FIELD_MAX];
0636
0637 ret = __send_command(priv, DPFE_CMD_GET_INFO, response);
0638 if (!ret)
0639 return 0;
0640 }
0641
0642
0643
0644
0645
0646
0647 if (!priv->dpfe_api->fw_name)
0648 return -ENODEV;
0649
0650 ret = firmware_request_nowarn(&fw, priv->dpfe_api->fw_name, dev);
0651
0652
0653
0654
0655 if (ret)
0656 return (ret == -ENOENT) ? -EPROBE_DEFER : ret;
0657
0658 ret = __verify_firmware(&init, fw);
0659 if (ret) {
0660 ret = -EFAULT;
0661 goto release_fw;
0662 }
0663
0664 __disable_dcpu(priv);
0665
0666 is_big_endian = init.is_big_endian;
0667 dmem_size = init.dmem_len;
0668 imem_size = init.imem_len;
0669
0670
0671 header = (struct dpfe_firmware_header *)fw->data;
0672
0673 fw_blob = fw->data + sizeof(*header);
0674
0675 imem = fw_blob;
0676
0677 dmem = fw_blob + imem_size;
0678
0679 ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian);
0680 if (ret)
0681 goto release_fw;
0682 ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian);
0683 if (ret)
0684 goto release_fw;
0685
0686 ret = __verify_fw_checksum(&init, priv, header, init.chksum);
0687 if (ret)
0688 goto release_fw;
0689
0690 __enable_dcpu(priv);
0691
0692 release_fw:
0693 release_firmware(fw);
0694 return ret;
0695 }
0696
0697 static ssize_t generic_show(unsigned int command, u32 response[],
0698 struct brcmstb_dpfe_priv *priv, char *buf)
0699 {
0700 int ret;
0701
0702 if (!priv)
0703 return sprintf(buf, "ERROR: driver private data not set\n");
0704
0705 ret = __send_command(priv, command, response);
0706 if (ret < 0)
0707 return sprintf(buf, "ERROR: %s\n", get_error_text(-ret));
0708
0709 return 0;
0710 }
0711
0712 static ssize_t show_info(struct device *dev, struct device_attribute *devattr,
0713 char *buf)
0714 {
0715 u32 response[MSG_FIELD_MAX];
0716 struct brcmstb_dpfe_priv *priv;
0717 unsigned int info;
0718 ssize_t ret;
0719
0720 priv = dev_get_drvdata(dev);
0721 ret = generic_show(DPFE_CMD_GET_INFO, response, priv, buf);
0722 if (ret)
0723 return ret;
0724
0725 info = response[MSG_ARG0];
0726
0727 return sprintf(buf, "%u.%u.%u.%u\n",
0728 (info >> 24) & 0xff,
0729 (info >> 16) & 0xff,
0730 (info >> 8) & 0xff,
0731 info & 0xff);
0732 }
0733
0734 static ssize_t show_refresh(struct device *dev,
0735 struct device_attribute *devattr, char *buf)
0736 {
0737 u32 response[MSG_FIELD_MAX];
0738 void __iomem *info;
0739 struct brcmstb_dpfe_priv *priv;
0740 u8 refresh, sr_abort, ppre, thermal_offs, tuf;
0741 u32 mr4;
0742 ssize_t ret;
0743
0744 priv = dev_get_drvdata(dev);
0745 ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
0746 if (ret)
0747 return ret;
0748
0749 info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
0750 if (!info)
0751 return ret;
0752
0753 mr4 = (readl_relaxed(info + DRAM_INFO_MR4) >> DRAM_INFO_MR4_SHIFT) &
0754 DRAM_INFO_MR4_MASK;
0755
0756 refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK;
0757 sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK;
0758 ppre = (mr4 >> DRAM_MR4_PPRE) & DRAM_MR4_PPRE_MASK;
0759 thermal_offs = (mr4 >> DRAM_MR4_TH_OFFS) & DRAM_MR4_TH_OFFS_MASK;
0760 tuf = (mr4 >> DRAM_MR4_TUF) & DRAM_MR4_TUF_MASK;
0761
0762 return sprintf(buf, "%#x %#x %#x %#x %#x %#x %#x\n",
0763 readl_relaxed(info + DRAM_INFO_INTERVAL),
0764 refresh, sr_abort, ppre, thermal_offs, tuf,
0765 readl_relaxed(info + DRAM_INFO_ERROR));
0766 }
0767
0768 static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
0769 const char *buf, size_t count)
0770 {
0771 u32 response[MSG_FIELD_MAX];
0772 struct brcmstb_dpfe_priv *priv;
0773 void __iomem *info;
0774 unsigned long val;
0775 int ret;
0776
0777 if (kstrtoul(buf, 0, &val) < 0)
0778 return -EINVAL;
0779
0780 priv = dev_get_drvdata(dev);
0781 ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response);
0782 if (ret)
0783 return ret;
0784
0785 info = get_msg_ptr(priv, response[MSG_ARG0], NULL, NULL);
0786 if (!info)
0787 return -EIO;
0788
0789 writel_relaxed(val, info + DRAM_INFO_INTERVAL);
0790
0791 return count;
0792 }
0793
0794 static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr,
0795 char *buf)
0796 {
0797 u32 response[MSG_FIELD_MAX];
0798 struct brcmstb_dpfe_priv *priv;
0799 void __iomem *info;
0800 ssize_t ret;
0801 u32 mr5, mr6, mr7, mr8, err;
0802
0803 priv = dev_get_drvdata(dev);
0804 ret = generic_show(DPFE_CMD_GET_VENDOR, response, priv, buf);
0805 if (ret)
0806 return ret;
0807
0808 info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
0809 if (!info)
0810 return ret;
0811
0812 mr5 = (readl_relaxed(info + DRAM_VENDOR_MR5) >> DRAM_VENDOR_SHIFT) &
0813 DRAM_VENDOR_MASK;
0814 mr6 = (readl_relaxed(info + DRAM_VENDOR_MR6) >> DRAM_VENDOR_SHIFT) &
0815 DRAM_VENDOR_MASK;
0816 mr7 = (readl_relaxed(info + DRAM_VENDOR_MR7) >> DRAM_VENDOR_SHIFT) &
0817 DRAM_VENDOR_MASK;
0818 mr8 = (readl_relaxed(info + DRAM_VENDOR_MR8) >> DRAM_VENDOR_SHIFT) &
0819 DRAM_VENDOR_MASK;
0820 err = readl_relaxed(info + DRAM_VENDOR_ERROR) & DRAM_VENDOR_MASK;
0821
0822 return sprintf(buf, "%#x %#x %#x %#x %#x\n", mr5, mr6, mr7, mr8, err);
0823 }
0824
0825 static ssize_t show_dram(struct device *dev, struct device_attribute *devattr,
0826 char *buf)
0827 {
0828 u32 response[MSG_FIELD_MAX];
0829 struct brcmstb_dpfe_priv *priv;
0830 ssize_t ret;
0831 u32 mr4, mr5, mr6, mr7, mr8, err;
0832
0833 priv = dev_get_drvdata(dev);
0834 ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
0835 if (ret)
0836 return ret;
0837
0838 mr4 = response[MSG_ARG0 + 0] & DRAM_INFO_MR4_MASK;
0839 mr5 = response[MSG_ARG0 + 1] & DRAM_DDR_INFO_MASK;
0840 mr6 = response[MSG_ARG0 + 2] & DRAM_DDR_INFO_MASK;
0841 mr7 = response[MSG_ARG0 + 3] & DRAM_DDR_INFO_MASK;
0842 mr8 = response[MSG_ARG0 + 4] & DRAM_DDR_INFO_MASK;
0843 err = response[MSG_ARG0 + 5] & DRAM_DDR_INFO_MASK;
0844
0845 return sprintf(buf, "%#x %#x %#x %#x %#x %#x\n", mr4, mr5, mr6, mr7,
0846 mr8, err);
0847 }
0848
0849 static int brcmstb_dpfe_resume(struct platform_device *pdev)
0850 {
0851 struct brcmstb_dpfe_priv *priv = platform_get_drvdata(pdev);
0852
0853 return brcmstb_dpfe_download_firmware(priv);
0854 }
0855
0856 static int brcmstb_dpfe_probe(struct platform_device *pdev)
0857 {
0858 struct device *dev = &pdev->dev;
0859 struct brcmstb_dpfe_priv *priv;
0860 int ret;
0861
0862 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0863 if (!priv)
0864 return -ENOMEM;
0865
0866 priv->dev = dev;
0867
0868 mutex_init(&priv->lock);
0869 platform_set_drvdata(pdev, priv);
0870
0871 priv->regs = devm_platform_ioremap_resource_byname(pdev, "dpfe-cpu");
0872 if (IS_ERR(priv->regs)) {
0873 dev_err(dev, "couldn't map DCPU registers\n");
0874 return -ENODEV;
0875 }
0876
0877 priv->dmem = devm_platform_ioremap_resource_byname(pdev, "dpfe-dmem");
0878 if (IS_ERR(priv->dmem)) {
0879 dev_err(dev, "Couldn't map DCPU data memory\n");
0880 return -ENOENT;
0881 }
0882
0883 priv->imem = devm_platform_ioremap_resource_byname(pdev, "dpfe-imem");
0884 if (IS_ERR(priv->imem)) {
0885 dev_err(dev, "Couldn't map DCPU instruction memory\n");
0886 return -ENOENT;
0887 }
0888
0889 priv->dpfe_api = of_device_get_match_data(dev);
0890 if (unlikely(!priv->dpfe_api)) {
0891
0892
0893
0894
0895 dev_err(dev, "Couldn't determine API\n");
0896 return -ENOENT;
0897 }
0898
0899 ret = brcmstb_dpfe_download_firmware(priv);
0900 if (ret)
0901 return dev_err_probe(dev, ret, "Couldn't download firmware\n");
0902
0903 ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
0904 if (!ret)
0905 dev_info(dev, "registered with API v%d.\n",
0906 priv->dpfe_api->version);
0907
0908 return ret;
0909 }
0910
0911 static int brcmstb_dpfe_remove(struct platform_device *pdev)
0912 {
0913 struct brcmstb_dpfe_priv *priv = dev_get_drvdata(&pdev->dev);
0914
0915 sysfs_remove_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
0916
0917 return 0;
0918 }
0919
0920 static const struct of_device_id brcmstb_dpfe_of_match[] = {
0921
0922 { .compatible = "brcm,bcm7268-dpfe-cpu", .data = &dpfe_api_old_v2 },
0923 { .compatible = "brcm,bcm7271-dpfe-cpu", .data = &dpfe_api_old_v2 },
0924 { .compatible = "brcm,bcm7278-dpfe-cpu", .data = &dpfe_api_old_v2 },
0925 { .compatible = "brcm,bcm7211-dpfe-cpu", .data = &dpfe_api_new_v2 },
0926
0927 { .compatible = "brcm,dpfe-cpu", .data = &dpfe_api_v3 },
0928 {}
0929 };
0930 MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match);
0931
0932 static struct platform_driver brcmstb_dpfe_driver = {
0933 .driver = {
0934 .name = DRVNAME,
0935 .of_match_table = brcmstb_dpfe_of_match,
0936 },
0937 .probe = brcmstb_dpfe_probe,
0938 .remove = brcmstb_dpfe_remove,
0939 .resume = brcmstb_dpfe_resume,
0940 };
0941
0942 module_platform_driver(brcmstb_dpfe_driver);
0943
0944 MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
0945 MODULE_DESCRIPTION("BRCMSTB DDR PHY Front End Driver");
0946 MODULE_LICENSE("GPL");