1af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU/* 2af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * Tegra30 Memory Controller 3af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * 4af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 5af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * 6af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * This program is free software; you can redistribute it and/or modify it 7af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * under the terms and conditions of the GNU General Public License, 8af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * version 2, as published by the Free Software Foundation. 9af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * 10af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * This program is distributed in the hope it will be useful, but WITHOUT 11af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * more details. 14af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * 15af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * You should have received a copy of the GNU General Public License along with 16af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * this program; if not, write to the Free Software Foundation, Inc., 17af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU */ 19af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 2006303c2e00701724acb95069ca46f87c998c4be1Thierry Reding#include <linux/err.h> 21af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#include <linux/kernel.h> 22af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#include <linux/module.h> 23af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#include <linux/ratelimit.h> 24af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#include <linux/platform_device.h> 25af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#include <linux/interrupt.h> 26af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#include <linux/io.h> 27af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 28af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define DRV_NAME "tegra30-mc" 29af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 30af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INTSTATUS 0x0 31af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INTMASK 0x4 32af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 33af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INT_ERR_SHIFT 6 34af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT) 35af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT) 36af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2) 37af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3) 38af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_INT_INVALID_SMMU_PAGE BIT(MC_INT_ERR_SHIFT + 4) 39af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 40af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_STATUS 0x8 41af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_ADR 0xc 42af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 43af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_TYPE_SHIFT 28 44af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_TYPE_MASK (7 << MC_ERR_TYPE_SHIFT) 45af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_TYPE_DECERR_EMEM 2 46af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_TYPE_SECURITY_TRUSTZONE 3 47af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_TYPE_SECURITY_CARVEOUT 4 48af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_TYPE_INVALID_SMMU_PAGE 6 49af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 50af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_INVALID_SMMU_PAGE_SHIFT 25 51af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_INVALID_SMMU_PAGE_MASK (7 << MC_ERR_INVALID_SMMU_PAGE_SHIFT) 52af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_RW_SHIFT 16 53af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_RW BIT(MC_ERR_RW_SHIFT) 54af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_ERR_SECURITY BIT(MC_ERR_RW_SHIFT + 1) 55af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 56af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */ 57af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 58af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_CFG 0x90 59af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 60af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_RCD 0x98 61af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_RP 0x9c 62af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_RC 0xa0 63af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_RAS 0xa4 64af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_FAW 0xa8 65af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_RRD 0xac 66af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 67af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 68af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_R2R 0xb8 69af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_W2W 0xbc 70af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_R2W 0xc0 71af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_TIMING_W2R 0xc4 72af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 73af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_DA_TURNS 0xd0 74af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_DA_COVERS 0xd4 75af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_MISC0 0xd8 76af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_MISC1 0xdc 77af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 78af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_RING3_THROTTLE 0xe4 79af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_EMEM_ARB_OVERRIDE 0xe8 80af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 81af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_TIMING_CONTROL 0xfc 82af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 83af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define MC_CLIENT_ID_MASK 0x7f 84af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 85af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU#define NUM_MC_REG_BANKS 4 86af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 87af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstruct tegra30_mc { 88af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU void __iomem *regs[NUM_MC_REG_BANKS]; 89af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU struct device *dev; 90af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU u32 ctx[0]; 91af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU}; 92af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 93af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic inline u32 mc_readl(struct tegra30_mc *mc, u32 offs) 94af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU{ 95b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU u32 val = 0; 96b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU 97af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if (offs < 0x10) 98b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU val = readl(mc->regs[0] + offs); 99e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2Axel Lin else if (offs < 0x1f0) 100b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU val = readl(mc->regs[1] + offs - 0x3c); 101e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2Axel Lin else if (offs < 0x228) 102b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU val = readl(mc->regs[2] + offs - 0x200); 103e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2Axel Lin else if (offs < 0x400) 104b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU val = readl(mc->regs[3] + offs - 0x284); 105b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU 106b37fd4154e758c7226fda663e2ea3a97c6e8c732Hiroshi DOYU return val; 107af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU} 108af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 109af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs) 110af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU{ 111e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2Axel Lin if (offs < 0x10) 112af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU writel(val, mc->regs[0] + offs); 113e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2Axel Lin else if (offs < 0x1f0) 114af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU writel(val, mc->regs[1] + offs - 0x3c); 115e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2Axel Lin else if (offs < 0x228) 116af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU writel(val, mc->regs[2] + offs - 0x200); 117e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2Axel Lin else if (offs < 0x400) 118af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU writel(val, mc->regs[3] + offs - 0x284); 119af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU} 120af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 121af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic const char * const tegra30_mc_client[] = { 122af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_ptcr", 123af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display0a", 124af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display0ab", 125af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display0b", 126af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display0bb", 127af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display0c", 128af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display0cb", 129af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display1b", 130af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_display1bb", 131af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_eppup", 132af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_g2pr", 133af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_g2sr", 134af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_mpeunifbr", 135af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbr_viruv", 136af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_afir", 137af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_avpcarm7r", 138af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_displayhc", 139af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_displayhcb", 140af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_fdcdrd", 141af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_fdcdrd2", 142af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_g2dr", 143af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_hdar", 144af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_host1xdmar", 145af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_host1xr", 146af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_idxsrd", 147af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_idxsrd2", 148af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_mpe_ipred", 149af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_mpeamemrd", 150af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_mpecsrd", 151af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_ppcsahbdmar", 152af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_ppcsahbslvr", 153af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_satar", 154af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_texsrd", 155af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_texsrd2", 156af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_vdebsevr", 157af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_vdember", 158af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_vdemcer", 159af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_vdetper", 160af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_mpcorelpr", 161af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csr_mpcorer", 162af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_eppu", 163af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_eppv", 164af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_eppy", 165af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_mpeunifbw", 166af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_viwsb", 167af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_viwu", 168af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_viwv", 169af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "cbw_viwy", 170af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "ccw_g2dw", 171af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_afiw", 172af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_avpcarm7w", 173af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_fdcdwr", 174af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_fdcdwr2", 175af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_hdaw", 176af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_host1xw", 177af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_ispw", 178af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_mpcorelpw", 179af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_mpcorew", 180af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_mpecswr", 181af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_ppcsahbdmaw", 182af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_ppcsahbslvw", 183af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_sataw", 184af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_vdebsevw", 185af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_vdedbgw", 186af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_vdembew", 187af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "csw_vdetpmw", 188af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU}; 189af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 190af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic void tegra30_mc_decode(struct tegra30_mc *mc, int n) 191af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU{ 192af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU u32 err, addr; 193af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU const char * const mc_int_err[] = { 194af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "MC_DECERR", 195af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "Unknown", 196af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "MC_SECURITY_ERR", 197af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "MC_ARBITRATION_EMEM", 198af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "MC_SMMU_ERR", 199af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU }; 200af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU const char * const err_type[] = { 201af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "Unknown", 202af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "Unknown", 203af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "DECERR_EMEM", 204af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "SECURITY_TRUSTZONE", 205af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "SECURITY_CARVEOUT", 206af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "Unknown", 207af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "INVALID_SMMU_PAGE", 208af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU "Unknown", 209af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU }; 210af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU char attr[6]; 211af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU int cid, perm, type, idx; 212af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU const char *client = "Unknown"; 213af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 214af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU idx = n - MC_INT_ERR_SHIFT; 215af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if ((idx < 0) || (idx >= ARRAY_SIZE(mc_int_err)) || (idx == 1)) { 21690394482b807cb0a474fb387ed020603df14cfd0Hiroshi DOYU dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n", 21790394482b807cb0a474fb387ed020603df14cfd0Hiroshi DOYU BIT(n)); 218af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return; 219af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU } 220af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 22136dd68319c7b56a76ed450b0e470067b5d74b9b2Tuomas Tynkkynen err = mc_readl(mc, MC_ERR_STATUS); 222af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 223af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; 224af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> 225af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_ERR_INVALID_SMMU_PAGE_SHIFT; 226af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if (type == MC_ERR_TYPE_INVALID_SMMU_PAGE) 227af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU sprintf(attr, "%c-%c-%c", 228af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU (perm & BIT(2)) ? 'R' : '-', 229af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU (perm & BIT(1)) ? 'W' : '-', 230af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU (perm & BIT(0)) ? 'S' : '-'); 231af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU else 232af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU attr[0] = '\0'; 233af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 234af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU cid = err & MC_CLIENT_ID_MASK; 235af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if (cid < ARRAY_SIZE(tegra30_mc_client)) 236af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU client = tegra30_mc_client[cid]; 237af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 23836dd68319c7b56a76ed450b0e470067b5d74b9b2Tuomas Tynkkynen addr = mc_readl(mc, MC_ERR_ADR); 239af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 24090394482b807cb0a474fb387ed020603df14cfd0Hiroshi DOYU dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", 241af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc_int_err[idx], err, addr, client, 242af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU (err & MC_ERR_SECURITY) ? "secure" : "non-secure", 243af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU (err & MC_ERR_RW) ? "write" : "read", 244af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU err_type[type], attr); 245af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU} 246af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 247af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic const u32 tegra30_mc_ctx[] = { 248af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_CFG, 249af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_OUTSTANDING_REQ, 250af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_RCD, 251af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_RP, 252af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_RC, 253af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_RAS, 254af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_FAW, 255af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_RRD, 256af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_RAP2PRE, 257af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_WAP2PRE, 258af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_R2R, 259af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_W2W, 260af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_R2W, 261af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_TIMING_W2R, 262af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_DA_TURNS, 263af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_DA_COVERS, 264af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_MISC0, 265af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_MISC1, 266af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_RING3_THROTTLE, 267af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_EMEM_ARB_OVERRIDE, 268af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_INTMASK, 269af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU}; 270af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 2719f7345b7a7cbf4c78a8161cba21de1772d5ad56eHiroshi Doyu#ifdef CONFIG_PM 272af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic int tegra30_mc_suspend(struct device *dev) 273af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU{ 274af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU int i; 275af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU struct tegra30_mc *mc = dev_get_drvdata(dev); 276af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 277af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++) 278af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc->ctx[i] = mc_readl(mc, tegra30_mc_ctx[i]); 279af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return 0; 280af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU} 281af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 282af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic int tegra30_mc_resume(struct device *dev) 283af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU{ 284af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU int i; 285af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU struct tegra30_mc *mc = dev_get_drvdata(dev); 286af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 287af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++) 288af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc_writel(mc, mc->ctx[i], tegra30_mc_ctx[i]); 289af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 290af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc_writel(mc, 1, MC_TIMING_CONTROL); 291af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU /* Read-back to ensure that write reached */ 292af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc_readl(mc, MC_TIMING_CONTROL); 293af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return 0; 294af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU} 2959f7345b7a7cbf4c78a8161cba21de1772d5ad56eHiroshi Doyu#endif 296af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 297af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm, 298af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU tegra30_mc_suspend, 299af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU tegra30_mc_resume, NULL); 300af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 30127796aa0dce01661fedb5f3fa6b11db13f02a77fGreg Kroah-Hartmanstatic const struct of_device_id tegra30_mc_of_match[] = { 302af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU { .compatible = "nvidia,tegra30-mc", }, 303af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU {}, 304af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU}; 305af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 306af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic irqreturn_t tegra30_mc_isr(int irq, void *data) 307af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU{ 308af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU u32 stat, mask, bit; 309af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU struct tegra30_mc *mc = data; 310af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 311af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU stat = mc_readl(mc, MC_INTSTATUS); 312af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mask = mc_readl(mc, MC_INTMASK); 313af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mask &= stat; 314af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if (!mask) 315af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return IRQ_NONE; 31636dd68319c7b56a76ed450b0e470067b5d74b9b2Tuomas Tynkkynen while ((bit = ffs(mask)) != 0) { 317af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU tegra30_mc_decode(mc, bit - 1); 31836dd68319c7b56a76ed450b0e470067b5d74b9b2Tuomas Tynkkynen mask &= ~BIT(bit - 1); 31936dd68319c7b56a76ed450b0e470067b5d74b9b2Tuomas Tynkkynen } 32036dd68319c7b56a76ed450b0e470067b5d74b9b2Tuomas Tynkkynen 321af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc_writel(mc, stat, MC_INTSTATUS); 322af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return IRQ_HANDLED; 323af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU} 324af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 32527796aa0dce01661fedb5f3fa6b11db13f02a77fGreg Kroah-Hartmanstatic int tegra30_mc_probe(struct platform_device *pdev) 326af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU{ 327af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU struct resource *irq; 328af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU struct tegra30_mc *mc; 329af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU size_t bytes; 330af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU int err, i; 331af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU u32 intmask; 332af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 333af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU bytes = sizeof(*mc) + sizeof(u32) * ARRAY_SIZE(tegra30_mc_ctx); 334af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL); 335af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if (!mc) 336af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return -ENOMEM; 337af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc->dev = &pdev->dev; 338af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 339af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU for (i = 0; i < ARRAY_SIZE(mc->regs); i++) { 340af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU struct resource *res; 341af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 342af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU res = platform_get_resource(pdev, IORESOURCE_MEM, i); 34306303c2e00701724acb95069ca46f87c998c4be1Thierry Reding mc->regs[i] = devm_ioremap_resource(&pdev->dev, res); 34406303c2e00701724acb95069ca46f87c998c4be1Thierry Reding if (IS_ERR(mc->regs[i])) 34506303c2e00701724acb95069ca46f87c998c4be1Thierry Reding return PTR_ERR(mc->regs[i]); 346af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU } 347af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 348af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 349af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if (!irq) 350af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return -ENODEV; 351af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU err = devm_request_irq(&pdev->dev, irq->start, tegra30_mc_isr, 352af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU IRQF_SHARED, dev_name(&pdev->dev), mc); 353af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU if (err) 354af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return -ENODEV; 355af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 356af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU platform_set_drvdata(pdev, mc); 357af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 358af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU intmask = MC_INT_INVALID_SMMU_PAGE | 359af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION; 360af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU mc_writel(mc, intmask, MC_INTMASK); 361af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU return 0; 362af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU} 363af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 364af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUstatic struct platform_driver tegra30_mc_driver = { 365af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU .probe = tegra30_mc_probe, 366af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU .driver = { 367af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU .name = DRV_NAME, 368af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU .owner = THIS_MODULE, 369af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU .of_match_table = tegra30_mc_of_match, 370af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU .pm = &tegra30_mc_pm, 371af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU }, 372af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU}; 373af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUmodule_platform_driver(tegra30_mc_driver); 374af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYU 375af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUMODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); 376af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUMODULE_DESCRIPTION("Tegra30 MC driver"); 377af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUMODULE_LICENSE("GPL v2"); 378af4681097b23fe9c63a03d774de7c742fa3a920eHiroshi DOYUMODULE_ALIAS("platform:" DRV_NAME); 379