aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Mayer <mmayer@broadcom.com>2018-02-13 15:40:40 -0500
committerFlorian Fainelli <f.fainelli@gmail.com>2018-02-23 13:56:59 -0500
commitfee5f1ef6cf76f87d9799596d06979c9e6589f2b (patch)
tree74cc6257c8db33ad6a60ee68c9a9ab251d6ed6ec
parent9f2c4d95e088a44b2b68fedbd4593070b53754a7 (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>
-rw-r--r--drivers/memory/brcmstb_dpfe.c65
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
266static 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
258static int __send_command(struct private_data *priv, unsigned int cmd, 300static 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,