diff options
| author | Markus Mayer <mmayer@broadcom.com> | 2018-02-13 15:40:40 -0500 |
|---|---|---|
| committer | Florian Fainelli <f.fainelli@gmail.com> | 2018-02-23 13:56:59 -0500 |
| commit | fee5f1ef6cf76f87d9799596d06979c9e6589f2b (patch) | |
| tree | 74cc6257c8db33ad6a60ee68c9a9ab251d6ed6ec /drivers/memory | |
| parent | 9f2c4d95e088a44b2b68fedbd4593070b53754a7 (diff) | |
memory: brcmstb: dpfe: support new way of passing data from the DCPU
The DCPU can now send message data in two ways:
- via the data RAM, as before (this is now message type 0)
- via the message RAM (this is message type 1)
In order to support both methods, we check the message type of the
response (bits 31:28) and then treat the offset (bits 27:0)
accordingly.
Signed-off-by: Markus Mayer <mmayer@broadcom.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Diffstat (limited to 'drivers/memory')
| -rw-r--r-- | drivers/memory/brcmstb_dpfe.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index 2013a91217a9..e9c1485c32b9 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c | |||
| @@ -45,8 +45,16 @@ | |||
| 45 | #define REG_TO_DCPU_MBOX 0x10 | 45 | #define REG_TO_DCPU_MBOX 0x10 |
| 46 | #define REG_TO_HOST_MBOX 0x14 | 46 | #define REG_TO_HOST_MBOX 0x14 |
| 47 | 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 | |||
| 48 | /* Message RAM */ | 55 | /* Message RAM */ |
| 49 | #define DCPU_MSG_RAM(x) (0x100 + (x) * sizeof(u32)) | 56 | #define DCPU_MSG_RAM_START 0x100 |
| 57 | #define DCPU_MSG_RAM(x) (DCPU_MSG_RAM_START + (x) * sizeof(u32)) | ||
| 50 | 58 | ||
| 51 | /* DRAM Info Offsets & Masks */ | 59 | /* DRAM Info Offsets & Masks */ |
| 52 | #define DRAM_INFO_INTERVAL 0x0 | 60 | #define DRAM_INFO_INTERVAL 0x0 |
| @@ -255,6 +263,40 @@ static unsigned int get_msg_chksum(const u32 msg[]) | |||
| 255 | return sum; | 263 | return sum; |
| 256 | } | 264 | } |
| 257 | 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 | |||
| 258 | static int __send_command(struct private_data *priv, unsigned int cmd, | 300 | static int __send_command(struct private_data *priv, unsigned int cmd, |
| 259 | u32 result[]) | 301 | u32 result[]) |
| 260 | { | 302 | { |
| @@ -528,7 +570,6 @@ static ssize_t show_refresh(struct device *dev, | |||
| 528 | u32 response[MSG_FIELD_MAX]; | 570 | u32 response[MSG_FIELD_MAX]; |
| 529 | void __iomem *info; | 571 | void __iomem *info; |
| 530 | struct private_data *priv; | 572 | struct private_data *priv; |
| 531 | unsigned int offset; | ||
| 532 | u8 refresh, sr_abort, ppre, thermal_offs, tuf; | 573 | u8 refresh, sr_abort, ppre, thermal_offs, tuf; |
| 533 | u32 mr4; | 574 | u32 mr4; |
| 534 | ssize_t ret; | 575 | ssize_t ret; |
| @@ -538,8 +579,10 @@ static ssize_t show_refresh(struct device *dev, | |||
| 538 | return ret; | 579 | return ret; |
| 539 | 580 | ||
| 540 | priv = dev_get_drvdata(dev); | 581 | priv = dev_get_drvdata(dev); |
| 541 | offset = response[MSG_ARG0]; | 582 | |
| 542 | info = priv->dmem + offset; | 583 | info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret); |
| 584 | if (!info) | ||
| 585 | return ret; | ||
| 543 | 586 | ||
| 544 | mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK; | 587 | mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK; |
| 545 | 588 | ||
| @@ -561,7 +604,6 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr, | |||
| 561 | u32 response[MSG_FIELD_MAX]; | 604 | u32 response[MSG_FIELD_MAX]; |
| 562 | struct private_data *priv; | 605 | struct private_data *priv; |
| 563 | void __iomem *info; | 606 | void __iomem *info; |
| 564 | unsigned int offset; | ||
| 565 | unsigned long val; | 607 | unsigned long val; |
| 566 | int ret; | 608 | int ret; |
| 567 | 609 | ||
| @@ -574,8 +616,10 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr, | |||
| 574 | if (ret) | 616 | if (ret) |
| 575 | return ret; | 617 | return ret; |
| 576 | 618 | ||
| 577 | offset = response[MSG_ARG0]; | 619 | info = get_msg_ptr(priv, response[MSG_ARG0], NULL, NULL); |
| 578 | info = priv->dmem + offset; | 620 | if (!info) |
| 621 | return -EIO; | ||
| 622 | |||
| 579 | writel_relaxed(val, info + DRAM_INFO_INTERVAL); | 623 | writel_relaxed(val, info + DRAM_INFO_INTERVAL); |
| 580 | 624 | ||
| 581 | return count; | 625 | return count; |
| @@ -587,16 +631,17 @@ static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr, | |||
| 587 | u32 response[MSG_FIELD_MAX]; | 631 | u32 response[MSG_FIELD_MAX]; |
| 588 | struct private_data *priv; | 632 | struct private_data *priv; |
| 589 | void __iomem *info; | 633 | void __iomem *info; |
| 590 | unsigned int offset; | ||
| 591 | ssize_t ret; | 634 | ssize_t ret; |
| 592 | 635 | ||
| 593 | ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf); | 636 | ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf); |
| 594 | if (ret) | 637 | if (ret) |
| 595 | return ret; | 638 | return ret; |
| 596 | 639 | ||
| 597 | offset = response[MSG_ARG0]; | ||
| 598 | priv = dev_get_drvdata(dev); | 640 | priv = dev_get_drvdata(dev); |
| 599 | info = priv->dmem + offset; | 641 | |
| 642 | info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret); | ||
| 643 | if (!info) | ||
| 644 | return ret; | ||
| 600 | 645 | ||
| 601 | return sprintf(buf, "%#x %#x %#x %#x %#x\n", | 646 | return sprintf(buf, "%#x %#x %#x %#x %#x\n", |
| 602 | readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK, | 647 | readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK, |
