Skip to content

Commit f7a2757

Browse files
kishonbjorn-helgaas
authored andcommitted
PCI: dwc: dra7xx: Workaround for errata id i870
According to errata i870, access to the PCIe slave port that are not 32-bit aligned will result in incorrect mapping to TLP Address and Byte enable fields. Accessing non 32-bit aligned data causes incorrect data in the target buffer if memcpy is used. Implement the workaround for this errata here. Signed-off-by: Kishon Vijay Abraham I <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent 40cc72e commit f7a2757

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

drivers/pci/dwc/pci-dra7xx.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include <linux/pm_runtime.h>
2727
#include <linux/resource.h>
2828
#include <linux/types.h>
29+
#include <linux/mfd/syscon.h>
30+
#include <linux/regmap.h>
2931

3032
#include "pcie-designware.h"
3133

@@ -528,6 +530,48 @@ static const struct of_device_id of_dra7xx_pcie_match[] = {
528530
{},
529531
};
530532

533+
/*
534+
* dra7xx_pcie_ep_unaligned_memaccess: workaround for AM572x/AM571x Errata i870
535+
* @dra7xx: the dra7xx device where the workaround should be applied
536+
*
537+
* Access to the PCIe slave port that are not 32-bit aligned will result
538+
* in incorrect mapping to TLP Address and Byte enable fields. Therefore,
539+
* byte and half-word accesses are not possible to byte offset 0x1, 0x2, or
540+
* 0x3.
541+
*
542+
* To avoid this issue set PCIE_SS1_AXI2OCP_LEGACY_MODE_ENABLE to 1.
543+
*/
544+
static int dra7xx_pcie_ep_unaligned_memaccess(struct device *dev)
545+
{
546+
int ret;
547+
struct device_node *np = dev->of_node;
548+
struct of_phandle_args args;
549+
struct regmap *regmap;
550+
551+
regmap = syscon_regmap_lookup_by_phandle(np,
552+
"ti,syscon-unaligned-access");
553+
if (IS_ERR(regmap)) {
554+
dev_dbg(dev, "can't get ti,syscon-unaligned-access\n");
555+
return -EINVAL;
556+
}
557+
558+
ret = of_parse_phandle_with_fixed_args(np, "ti,syscon-unaligned-access",
559+
2, 0, &args);
560+
if (ret) {
561+
dev_err(dev, "failed to parse ti,syscon-unaligned-access\n");
562+
return ret;
563+
}
564+
565+
ret = regmap_update_bits(regmap, args.args[0], args.args[1],
566+
args.args[1]);
567+
if (ret)
568+
dev_err(dev, "failed to enable unaligned access\n");
569+
570+
of_node_put(args.np);
571+
572+
return ret;
573+
}
574+
531575
static int __init dra7xx_pcie_probe(struct platform_device *pdev)
532576
{
533577
u32 reg;
@@ -644,6 +688,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
644688
case DW_PCIE_EP_TYPE:
645689
dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE,
646690
DEVICE_TYPE_EP);
691+
692+
ret = dra7xx_pcie_ep_unaligned_memaccess(dev);
693+
if (ret)
694+
goto err_gpio;
695+
647696
ret = dra7xx_add_pcie_ep(dra7xx, pdev);
648697
if (ret < 0)
649698
goto err_gpio;

0 commit comments

Comments
 (0)