cregit-Linux how code gets into the kernel

Release 4.14 drivers/memory/tegra20-mc.c

Directory: drivers/memory
/*
 * Tegra20 Memory Controller
 *
 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ratelimit.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/io.h>


#define DRV_NAME "tegra20-mc"


#define MC_INTSTATUS			0x0

#define MC_INTMASK			0x4


#define MC_INT_ERR_SHIFT		6

#define MC_INT_ERR_MASK			(0x1f << MC_INT_ERR_SHIFT)

#define MC_INT_DECERR_EMEM		BIT(MC_INT_ERR_SHIFT)

#define MC_INT_INVALID_GART_PAGE	BIT(MC_INT_ERR_SHIFT + 1)

#define MC_INT_SECURITY_VIOLATION	BIT(MC_INT_ERR_SHIFT + 2)

#define MC_INT_ARBITRATION_EMEM		BIT(MC_INT_ERR_SHIFT + 3)


#define MC_GART_ERROR_REQ		0x30

#define MC_DECERR_EMEM_OTHERS_STATUS	0x58

#define MC_SECURITY_VIOLATION_STATUS	0x74


#define SECURITY_VIOLATION_TYPE		BIT(30)	
/* 0=TRUSTZONE, 1=CARVEOUT */


#define MC_CLIENT_ID_MASK		0x3f


#define NUM_MC_REG_BANKS		2


struct tegra20_mc {
	
void __iomem *regs[NUM_MC_REG_BANKS];
	
struct device *dev;
};


static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs) { u32 val = 0; if (offs < 0x24) val = readl(mc->regs[0] + offs); else if (offs < 0x400) val = readl(mc->regs[1] + offs - 0x3c); return val; }

Contributors

PersonTokensPropCommitsCommitProp
Hiroshi Doyu6598.48%266.67%
Axel Lin11.52%133.33%
Total66100.00%3100.00%


static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs) { if (offs < 0x24) writel(val, mc->regs[0] + offs); else if (offs < 0x400) writel(val, mc->regs[1] + offs - 0x3c); }

Contributors

PersonTokensPropCommitsCommitProp
Hiroshi Doyu6098.36%150.00%
Axel Lin11.64%150.00%
Total61100.00%2100.00%

static const char * const tegra20_mc_client[] = { "cbr_display0a", "cbr_display0ab", "cbr_display0b", "cbr_display0bb", "cbr_display0c", "cbr_display0cb", "cbr_display1b", "cbr_display1bb", "cbr_eppup", "cbr_g2pr", "cbr_g2sr", "cbr_mpeunifbr", "cbr_viruv", "csr_avpcarm7r", "csr_displayhc", "csr_displayhcb", "csr_fdcdrd", "csr_g2dr", "csr_host1xdmar", "csr_host1xr", "csr_idxsrd", "csr_mpcorer", "csr_mpe_ipred", "csr_mpeamemrd", "csr_mpecsrd", "csr_ppcsahbdmar", "csr_ppcsahbslvr", "csr_texsrd", "csr_vdebsevr", "csr_vdember", "csr_vdemcer", "csr_vdetper", "cbw_eppu", "cbw_eppv", "cbw_eppy", "cbw_mpeunifbw", "cbw_viwsb", "cbw_viwu", "cbw_viwv", "cbw_viwy", "ccw_g2dw", "csw_avpcarm7w", "csw_fdcdwr", "csw_host1xw", "csw_ispw", "csw_mpcorew", "csw_mpecswr", "csw_ppcsahbdmaw", "csw_ppcsahbslvw", "csw_vdebsevw", "csw_vdembew", "csw_vdetpmw", };
static void tegra20_mc_decode(struct tegra20_mc *mc, int n) { u32 addr, req; const char *client = "Unknown"; int idx, cid; const struct reg_info { u32 offset; u32 write_bit; /* 0=READ, 1=WRITE */ int cid_shift; char *message; } reg[] = { { .offset = MC_DECERR_EMEM_OTHERS_STATUS, .write_bit = 31, .message = "MC_DECERR", }, { .offset = MC_GART_ERROR_REQ, .cid_shift = 1, .message = "MC_GART_ERR", }, { .offset = MC_SECURITY_VIOLATION_STATUS, .write_bit = 31, .message = "MC_SECURITY_ERR", }, }; idx = n - MC_INT_ERR_SHIFT; if ((idx < 0) || (idx >= ARRAY_SIZE(reg))) { dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n", BIT(n)); return; } req = mc_readl(mc, reg[idx].offset); cid = (req >> reg[idx].cid_shift) & MC_CLIENT_ID_MASK; if (cid < ARRAY_SIZE(tegra20_mc_client)) client = tegra20_mc_client[cid]; addr = mc_readl(mc, reg[idx].offset + sizeof(u32)); dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s)\n", reg[idx].message, req, addr, client, (req & BIT(reg[idx].write_bit)) ? "write" : "read", (reg[idx].offset == MC_SECURITY_VIOLATION_STATUS) ? ((req & SECURITY_VIOLATION_TYPE) ? "carveout" : "trustzone") : ""); }

Contributors

PersonTokensPropCommitsCommitProp
Hiroshi Doyu275100.00%2100.00%
Total275100.00%2100.00%

static const struct of_device_id tegra20_mc_of_match[] = { { .compatible = "nvidia,tegra20-mc", }, {}, };
static irqreturn_t tegra20_mc_isr(int irq, void *data) { u32 stat, mask, bit; struct tegra20_mc *mc = data; stat = mc_readl(mc, MC_INTSTATUS); mask = mc_readl(mc, MC_INTMASK); mask &= stat; if (!mask) return IRQ_NONE; while ((bit = ffs(mask)) != 0) { tegra20_mc_decode(mc, bit - 1); mask &= ~BIT(bit - 1); } mc_writel(mc, stat, MC_INTSTATUS); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Hiroshi Doyu9188.35%150.00%
Tuomas Tynkkynen1211.65%150.00%
Total103100.00%2100.00%


static int tegra20_mc_probe(struct platform_device *pdev) { struct resource *irq; struct tegra20_mc *mc; int i, err; u32 intmask; mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); if (!mc) return -ENOMEM; mc->dev = &pdev->dev; for (i = 0; i < ARRAY_SIZE(mc->regs); i++) { struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, i); mc->regs[i] = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(mc->regs[i])) return PTR_ERR(mc->regs[i]); } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq) return -ENODEV; err = devm_request_irq(&pdev->dev, irq->start, tegra20_mc_isr, IRQF_SHARED, dev_name(&pdev->dev), mc); if (err) return -ENODEV; platform_set_drvdata(pdev, mc); intmask = MC_INT_INVALID_GART_PAGE | MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION; mc_writel(mc, intmask, MC_INTMASK); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Hiroshi Doyu21194.20%150.00%
Thierry Reding135.80%150.00%
Total224100.00%2100.00%

static struct platform_driver tegra20_mc_driver = { .probe = tegra20_mc_probe, .driver = { .name = DRV_NAME, .of_match_table = tegra20_mc_of_match, }, }; module_platform_driver(tegra20_mc_driver); MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); MODULE_DESCRIPTION("Tegra20 MC driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME);

Overall Contributors

PersonTokensPropCommitsCommitProp
Hiroshi Doyu98597.04%350.00%
Thierry Reding161.58%116.67%
Tuomas Tynkkynen121.18%116.67%
Axel Lin20.20%116.67%
Greg Kroah-Hartman0.00%00.00%
Total1015100.00%6100.00%
Directory: drivers/memory
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.