brintos

brintos / linux-shallow public Read only

0
0
Text · 7.4 KiB · c0e8b76 Raw
289 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.4 * Copyright (C) 2011 Google, Inc.5 *6 * Author:7 *	Jay Cheng <jacheng@nvidia.com>8 *	James Wylder <james.wylder@motorola.com>9 *	Benoit Goby <benoit@android.com>10 *	Colin Cross <ccross@android.com>11 *	Hiroshi DOYU <hdoyu@nvidia.com>12 */13 14#include <linux/err.h>15#include <linux/kernel.h>16#include <linux/module.h>17#include <linux/platform_device.h>18#include <linux/io.h>19#include <linux/of.h>20 21#include <soc/tegra/ahb.h>22 23#define DRV_NAME "tegra-ahb"24 25#define AHB_ARBITRATION_DISABLE		0x0426#define AHB_ARBITRATION_PRIORITY_CTRL	0x0827#define   AHB_PRIORITY_WEIGHT(x)	(((x) & 0x7) << 29)28#define   PRIORITY_SELECT_USB BIT(6)29#define   PRIORITY_SELECT_USB2 BIT(18)30#define   PRIORITY_SELECT_USB3 BIT(17)31 32#define AHB_GIZMO_AHB_MEM		0x1033#define   ENB_FAST_REARBITRATE BIT(2)34#define   DONT_SPLIT_AHB_WR     BIT(7)35 36#define AHB_GIZMO_APB_DMA		0x1437#define AHB_GIZMO_IDE			0x1c38#define AHB_GIZMO_USB			0x2039#define AHB_GIZMO_AHB_XBAR_BRIDGE	0x2440#define AHB_GIZMO_CPU_AHB_BRIDGE	0x2841#define AHB_GIZMO_COP_AHB_BRIDGE	0x2c42#define AHB_GIZMO_XBAR_APB_CTLR		0x3043#define AHB_GIZMO_VCP_AHB_BRIDGE	0x3444#define AHB_GIZMO_NAND			0x4045#define AHB_GIZMO_SDMMC4		0x4846#define AHB_GIZMO_XIO			0x4c47#define AHB_GIZMO_BSEV			0x6448#define AHB_GIZMO_BSEA			0x7449#define AHB_GIZMO_NOR			0x7850#define AHB_GIZMO_USB2			0x7c51#define AHB_GIZMO_USB3			0x8052#define   IMMEDIATE	BIT(18)53 54#define AHB_GIZMO_SDMMC1		0x8455#define AHB_GIZMO_SDMMC2		0x8856#define AHB_GIZMO_SDMMC3		0x8c57#define AHB_MEM_PREFETCH_CFG_X		0xdc58#define AHB_ARBITRATION_XBAR_CTRL	0xe059#define AHB_MEM_PREFETCH_CFG3		0xe460#define AHB_MEM_PREFETCH_CFG4		0xe861#define AHB_MEM_PREFETCH_CFG1		0xf062#define AHB_MEM_PREFETCH_CFG2		0xf463#define   PREFETCH_ENB	BIT(31)64#define   MST_ID(x)	(((x) & 0x1f) << 26)65#define   AHBDMA_MST_ID	MST_ID(5)66#define   USB_MST_ID	MST_ID(6)67#define   USB2_MST_ID	MST_ID(18)68#define   USB3_MST_ID	MST_ID(17)69#define   ADDR_BNDRY(x)	(((x) & 0xf) << 21)70#define   INACTIVITY_TIMEOUT(x)	(((x) & 0xffff) << 0)71 72#define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID	0xfc73 74#define AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE BIT(17)75 76/*77 * INCORRECT_BASE_ADDR_LOW_BYTE: Legacy kernel DT files for Tegra SoCs78 * prior to Tegra124 generally use a physical base address ending in79 * 0x4 for the AHB IP block.  According to the TRM, the low byte80 * should be 0x0.  During device probing, this macro is used to detect81 * whether the passed-in physical address is incorrect, and if so, to82 * correct it.83 */84#define INCORRECT_BASE_ADDR_LOW_BYTE		0x485 86static struct platform_driver tegra_ahb_driver;87 88static const u32 tegra_ahb_gizmo[] = {89	AHB_ARBITRATION_DISABLE,90	AHB_ARBITRATION_PRIORITY_CTRL,91	AHB_GIZMO_AHB_MEM,92	AHB_GIZMO_APB_DMA,93	AHB_GIZMO_IDE,94	AHB_GIZMO_USB,95	AHB_GIZMO_AHB_XBAR_BRIDGE,96	AHB_GIZMO_CPU_AHB_BRIDGE,97	AHB_GIZMO_COP_AHB_BRIDGE,98	AHB_GIZMO_XBAR_APB_CTLR,99	AHB_GIZMO_VCP_AHB_BRIDGE,100	AHB_GIZMO_NAND,101	AHB_GIZMO_SDMMC4,102	AHB_GIZMO_XIO,103	AHB_GIZMO_BSEV,104	AHB_GIZMO_BSEA,105	AHB_GIZMO_NOR,106	AHB_GIZMO_USB2,107	AHB_GIZMO_USB3,108	AHB_GIZMO_SDMMC1,109	AHB_GIZMO_SDMMC2,110	AHB_GIZMO_SDMMC3,111	AHB_MEM_PREFETCH_CFG_X,112	AHB_ARBITRATION_XBAR_CTRL,113	AHB_MEM_PREFETCH_CFG3,114	AHB_MEM_PREFETCH_CFG4,115	AHB_MEM_PREFETCH_CFG1,116	AHB_MEM_PREFETCH_CFG2,117	AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID,118};119 120struct tegra_ahb {121	void __iomem	*regs;122	struct device	*dev;123	u32		ctx[];124};125 126static inline u32 gizmo_readl(struct tegra_ahb *ahb, u32 offset)127{128	return readl(ahb->regs + offset);129}130 131static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)132{133	writel(value, ahb->regs + offset);134}135 136#ifdef CONFIG_TEGRA_IOMMU_SMMU137int tegra_ahb_enable_smmu(struct device_node *dn)138{139	struct device *dev;140	u32 val;141	struct tegra_ahb *ahb;142 143	dev = driver_find_device_by_of_node(&tegra_ahb_driver.driver, dn);144	if (!dev)145		return -EPROBE_DEFER;146	ahb = dev_get_drvdata(dev);147	val = gizmo_readl(ahb, AHB_ARBITRATION_XBAR_CTRL);148	val |= AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE;149	gizmo_writel(ahb, val, AHB_ARBITRATION_XBAR_CTRL);150	return 0;151}152EXPORT_SYMBOL(tegra_ahb_enable_smmu);153#endif154 155static int __maybe_unused tegra_ahb_suspend(struct device *dev)156{157	int i;158	struct tegra_ahb *ahb = dev_get_drvdata(dev);159 160	for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++)161		ahb->ctx[i] = gizmo_readl(ahb, tegra_ahb_gizmo[i]);162	return 0;163}164 165static int __maybe_unused tegra_ahb_resume(struct device *dev)166{167	int i;168	struct tegra_ahb *ahb = dev_get_drvdata(dev);169 170	for (i = 0; i < ARRAY_SIZE(tegra_ahb_gizmo); i++)171		gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]);172	return 0;173}174 175static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm,176			    tegra_ahb_suspend,177			    tegra_ahb_resume, NULL);178 179static void tegra_ahb_gizmo_init(struct tegra_ahb *ahb)180{181	u32 val;182 183	val = gizmo_readl(ahb, AHB_GIZMO_AHB_MEM);184	val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR;185	gizmo_writel(ahb, val, AHB_GIZMO_AHB_MEM);186 187	val = gizmo_readl(ahb, AHB_GIZMO_USB);188	val |= IMMEDIATE;189	gizmo_writel(ahb, val, AHB_GIZMO_USB);190 191	val = gizmo_readl(ahb, AHB_GIZMO_USB2);192	val |= IMMEDIATE;193	gizmo_writel(ahb, val, AHB_GIZMO_USB2);194 195	val = gizmo_readl(ahb, AHB_GIZMO_USB3);196	val |= IMMEDIATE;197	gizmo_writel(ahb, val, AHB_GIZMO_USB3);198 199	val = gizmo_readl(ahb, AHB_ARBITRATION_PRIORITY_CTRL);200	val |= PRIORITY_SELECT_USB |201		PRIORITY_SELECT_USB2 |202		PRIORITY_SELECT_USB3 |203		AHB_PRIORITY_WEIGHT(7);204	gizmo_writel(ahb, val, AHB_ARBITRATION_PRIORITY_CTRL);205 206	val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG1);207	val &= ~MST_ID(~0);208	val |= PREFETCH_ENB |209		AHBDMA_MST_ID |210		ADDR_BNDRY(0xc) |211		INACTIVITY_TIMEOUT(0x1000);212	gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG1);213 214	val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG2);215	val &= ~MST_ID(~0);216	val |= PREFETCH_ENB |217		USB_MST_ID |218		ADDR_BNDRY(0xc) |219		INACTIVITY_TIMEOUT(0x1000);220	gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG2);221 222	val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG3);223	val &= ~MST_ID(~0);224	val |= PREFETCH_ENB |225		USB3_MST_ID |226		ADDR_BNDRY(0xc) |227		INACTIVITY_TIMEOUT(0x1000);228	gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG3);229 230	val = gizmo_readl(ahb, AHB_MEM_PREFETCH_CFG4);231	val &= ~MST_ID(~0);232	val |= PREFETCH_ENB |233		USB2_MST_ID |234		ADDR_BNDRY(0xc) |235		INACTIVITY_TIMEOUT(0x1000);236	gizmo_writel(ahb, val, AHB_MEM_PREFETCH_CFG4);237}238 239static int tegra_ahb_probe(struct platform_device *pdev)240{241	struct resource *res;242	struct tegra_ahb *ahb;243	size_t bytes;244 245	bytes = sizeof(*ahb) + sizeof(u32) * ARRAY_SIZE(tegra_ahb_gizmo);246	ahb = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL);247	if (!ahb)248		return -ENOMEM;249 250	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);251 252	/* Correct the IP block base address if necessary */253	if (res &&254	    (res->start & INCORRECT_BASE_ADDR_LOW_BYTE) ==255	    INCORRECT_BASE_ADDR_LOW_BYTE) {256		dev_warn(&pdev->dev, "incorrect AHB base address in DT data - enabling workaround\n");257		res->start -= INCORRECT_BASE_ADDR_LOW_BYTE;258	}259 260	ahb->regs = devm_ioremap_resource(&pdev->dev, res);261	if (IS_ERR(ahb->regs))262		return PTR_ERR(ahb->regs);263 264	ahb->dev = &pdev->dev;265	platform_set_drvdata(pdev, ahb);266	tegra_ahb_gizmo_init(ahb);267	return 0;268}269 270static const struct of_device_id tegra_ahb_of_match[] = {271	{ .compatible = "nvidia,tegra30-ahb", },272	{ .compatible = "nvidia,tegra20-ahb", },273	{},274};275 276static struct platform_driver tegra_ahb_driver = {277	.probe = tegra_ahb_probe,278	.driver = {279		.name = DRV_NAME,280		.of_match_table = tegra_ahb_of_match,281		.pm = &tegra_ahb_pm,282	},283};284module_platform_driver(tegra_ahb_driver);285 286MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");287MODULE_DESCRIPTION("Tegra AHB driver");288MODULE_ALIAS("platform:" DRV_NAME);289