1 /* 2 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #include <dt-bindings/memory/tegra20-mc.h> 10 11 #include "mc.h" 12 13 static const struct tegra_mc_client tegra20_mc_clients[] = { 14 { 15 .id = 0x00, 16 .name = "display0a", 17 }, { 18 .id = 0x01, 19 .name = "display0ab", 20 }, { 21 .id = 0x02, 22 .name = "display0b", 23 }, { 24 .id = 0x03, 25 .name = "display0bb", 26 }, { 27 .id = 0x04, 28 .name = "display0c", 29 }, { 30 .id = 0x05, 31 .name = "display0cb", 32 }, { 33 .id = 0x06, 34 .name = "display1b", 35 }, { 36 .id = 0x07, 37 .name = "display1bb", 38 }, { 39 .id = 0x08, 40 .name = "eppup", 41 }, { 42 .id = 0x09, 43 .name = "g2pr", 44 }, { 45 .id = 0x0a, 46 .name = "g2sr", 47 }, { 48 .id = 0x0b, 49 .name = "mpeunifbr", 50 }, { 51 .id = 0x0c, 52 .name = "viruv", 53 }, { 54 .id = 0x0d, 55 .name = "avpcarm7r", 56 }, { 57 .id = 0x0e, 58 .name = "displayhc", 59 }, { 60 .id = 0x0f, 61 .name = "displayhcb", 62 }, { 63 .id = 0x10, 64 .name = "fdcdrd", 65 }, { 66 .id = 0x11, 67 .name = "g2dr", 68 }, { 69 .id = 0x12, 70 .name = "host1xdmar", 71 }, { 72 .id = 0x13, 73 .name = "host1xr", 74 }, { 75 .id = 0x14, 76 .name = "idxsrd", 77 }, { 78 .id = 0x15, 79 .name = "mpcorer", 80 }, { 81 .id = 0x16, 82 .name = "mpe_ipred", 83 }, { 84 .id = 0x17, 85 .name = "mpeamemrd", 86 }, { 87 .id = 0x18, 88 .name = "mpecsrd", 89 }, { 90 .id = 0x19, 91 .name = "ppcsahbdmar", 92 }, { 93 .id = 0x1a, 94 .name = "ppcsahbslvr", 95 }, { 96 .id = 0x1b, 97 .name = "texsrd", 98 }, { 99 .id = 0x1c, 100 .name = "vdebsevr", 101 }, { 102 .id = 0x1d, 103 .name = "vdember", 104 }, { 105 .id = 0x1e, 106 .name = "vdemcer", 107 }, { 108 .id = 0x1f, 109 .name = "vdetper", 110 }, { 111 .id = 0x20, 112 .name = "eppu", 113 }, { 114 .id = 0x21, 115 .name = "eppv", 116 }, { 117 .id = 0x22, 118 .name = "eppy", 119 }, { 120 .id = 0x23, 121 .name = "mpeunifbw", 122 }, { 123 .id = 0x24, 124 .name = "viwsb", 125 }, { 126 .id = 0x25, 127 .name = "viwu", 128 }, { 129 .id = 0x26, 130 .name = "viwv", 131 }, { 132 .id = 0x27, 133 .name = "viwy", 134 }, { 135 .id = 0x28, 136 .name = "g2dw", 137 }, { 138 .id = 0x29, 139 .name = "avpcarm7w", 140 }, { 141 .id = 0x2a, 142 .name = "fdcdwr", 143 }, { 144 .id = 0x2b, 145 .name = "host1xw", 146 }, { 147 .id = 0x2c, 148 .name = "ispw", 149 }, { 150 .id = 0x2d, 151 .name = "mpcorew", 152 }, { 153 .id = 0x2e, 154 .name = "mpecswr", 155 }, { 156 .id = 0x2f, 157 .name = "ppcsahbdmaw", 158 }, { 159 .id = 0x30, 160 .name = "ppcsahbslvw", 161 }, { 162 .id = 0x31, 163 .name = "vdebsevw", 164 }, { 165 .id = 0x32, 166 .name = "vdembew", 167 }, { 168 .id = 0x33, 169 .name = "vdetpmw", 170 }, 171 }; 172 173 #define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit) \ 174 { \ 175 .name = #_name, \ 176 .id = TEGRA20_MC_RESET_##_name, \ 177 .control = _control, \ 178 .status = _status, \ 179 .reset = _reset, \ 180 .bit = _bit, \ 181 } 182 183 static const struct tegra_mc_reset tegra20_mc_resets[] = { 184 TEGRA20_MC_RESET(AVPC, 0x100, 0x140, 0x104, 0), 185 TEGRA20_MC_RESET(DC, 0x100, 0x144, 0x104, 1), 186 TEGRA20_MC_RESET(DCB, 0x100, 0x148, 0x104, 2), 187 TEGRA20_MC_RESET(EPP, 0x100, 0x14c, 0x104, 3), 188 TEGRA20_MC_RESET(2D, 0x100, 0x150, 0x104, 4), 189 TEGRA20_MC_RESET(HC, 0x100, 0x154, 0x104, 5), 190 TEGRA20_MC_RESET(ISP, 0x100, 0x158, 0x104, 6), 191 TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104, 7), 192 TEGRA20_MC_RESET(MPEA, 0x100, 0x160, 0x104, 8), 193 TEGRA20_MC_RESET(MPEB, 0x100, 0x164, 0x104, 9), 194 TEGRA20_MC_RESET(MPEC, 0x100, 0x168, 0x104, 10), 195 TEGRA20_MC_RESET(3D, 0x100, 0x16c, 0x104, 11), 196 TEGRA20_MC_RESET(PPCS, 0x100, 0x170, 0x104, 12), 197 TEGRA20_MC_RESET(VDE, 0x100, 0x174, 0x104, 13), 198 TEGRA20_MC_RESET(VI, 0x100, 0x178, 0x104, 14), 199 }; 200 201 static int tegra20_mc_hotreset_assert(struct tegra_mc *mc, 202 const struct tegra_mc_reset *rst) 203 { 204 unsigned long flags; 205 u32 value; 206 207 spin_lock_irqsave(&mc->lock, flags); 208 209 value = mc_readl(mc, rst->reset); 210 mc_writel(mc, value & ~BIT(rst->bit), rst->reset); 211 212 spin_unlock_irqrestore(&mc->lock, flags); 213 214 return 0; 215 } 216 217 static int tegra20_mc_hotreset_deassert(struct tegra_mc *mc, 218 const struct tegra_mc_reset *rst) 219 { 220 unsigned long flags; 221 u32 value; 222 223 spin_lock_irqsave(&mc->lock, flags); 224 225 value = mc_readl(mc, rst->reset); 226 mc_writel(mc, value | BIT(rst->bit), rst->reset); 227 228 spin_unlock_irqrestore(&mc->lock, flags); 229 230 return 0; 231 } 232 233 static int tegra20_mc_block_dma(struct tegra_mc *mc, 234 const struct tegra_mc_reset *rst) 235 { 236 unsigned long flags; 237 u32 value; 238 239 spin_lock_irqsave(&mc->lock, flags); 240 241 value = mc_readl(mc, rst->control) & ~BIT(rst->bit); 242 mc_writel(mc, value, rst->control); 243 244 spin_unlock_irqrestore(&mc->lock, flags); 245 246 return 0; 247 } 248 249 static bool tegra20_mc_dma_idling(struct tegra_mc *mc, 250 const struct tegra_mc_reset *rst) 251 { 252 return mc_readl(mc, rst->status) == 0; 253 } 254 255 static int tegra20_mc_reset_status(struct tegra_mc *mc, 256 const struct tegra_mc_reset *rst) 257 { 258 return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0; 259 } 260 261 static int tegra20_mc_unblock_dma(struct tegra_mc *mc, 262 const struct tegra_mc_reset *rst) 263 { 264 unsigned long flags; 265 u32 value; 266 267 spin_lock_irqsave(&mc->lock, flags); 268 269 value = mc_readl(mc, rst->control) | BIT(rst->bit); 270 mc_writel(mc, value, rst->control); 271 272 spin_unlock_irqrestore(&mc->lock, flags); 273 274 return 0; 275 } 276 277 static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = { 278 .hotreset_assert = tegra20_mc_hotreset_assert, 279 .hotreset_deassert = tegra20_mc_hotreset_deassert, 280 .block_dma = tegra20_mc_block_dma, 281 .dma_idling = tegra20_mc_dma_idling, 282 .unblock_dma = tegra20_mc_unblock_dma, 283 .reset_status = tegra20_mc_reset_status, 284 }; 285 286 const struct tegra_mc_soc tegra20_mc_soc = { 287 .clients = tegra20_mc_clients, 288 .num_clients = ARRAY_SIZE(tegra20_mc_clients), 289 .num_address_bits = 32, 290 .client_id_mask = 0x3f, 291 .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | 292 MC_INT_DECERR_EMEM, 293 .reset_ops = &tegra20_mc_reset_ops, 294 .resets = tegra20_mc_resets, 295 .num_resets = ARRAY_SIZE(tegra20_mc_resets), 296 }; 297