1183840Sraj/*- 2239277Sgonzo * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD. 3183840Sraj * All rights reserved. 4183840Sraj * 5183840Sraj * Developed by Semihalf. 6183840Sraj * 7183840Sraj * Redistribution and use in source and binary forms, with or without 8183840Sraj * modification, are permitted provided that the following conditions 9183840Sraj * are met: 10183840Sraj * 1. Redistributions of source code must retain the above copyright 11183840Sraj * notice, this list of conditions and the following disclaimer. 12183840Sraj * 2. Redistributions in binary form must reproduce the above copyright 13183840Sraj * notice, this list of conditions and the following disclaimer in the 14183840Sraj * documentation and/or other materials provided with the distribution. 15183840Sraj * 3. Neither the name of MARVELL nor the names of contributors 16183840Sraj * may be used to endorse or promote products derived from this software 17183840Sraj * without specific prior written permission. 18183840Sraj * 19183840Sraj * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20183840Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21183840Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22183840Sraj * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 23183840Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24183840Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25183840Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26183840Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27183840Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28183840Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29183840Sraj * SUCH DAMAGE. 30183840Sraj */ 31183840Sraj 32239277Sgonzo#include "opt_global.h" 33239277Sgonzo 34183840Sraj#include <sys/cdefs.h> 35183840Sraj__FBSDID("$FreeBSD$"); 36183840Sraj 37196532Sraj#include <sys/param.h> 38183840Sraj#include <sys/systm.h> 39183840Sraj#include <sys/bus.h> 40196532Sraj#include <sys/kernel.h> 41239277Sgonzo#include <sys/malloc.h> 42239277Sgonzo#include <sys/kdb.h> 43239277Sgonzo#include <sys/reboot.h> 44183840Sraj 45209131Sraj#include <dev/fdt/fdt_common.h> 46209131Sraj#include <dev/ofw/openfirm.h> 47209131Sraj 48183840Sraj#include <machine/bus.h> 49209131Sraj#include <machine/fdt.h> 50239277Sgonzo#include <machine/vmparam.h> 51183840Sraj 52183840Sraj#include <arm/mv/mvreg.h> 53183840Sraj#include <arm/mv/mvvar.h> 54194072Smarcel#include <arm/mv/mvwin.h> 55183840Sraj 56239277Sgonzo 57239277SgonzoMALLOC_DEFINE(M_IDMA, "idma", "idma dma test memory"); 58239277Sgonzo 59239277Sgonzo#define IDMA_DEBUG 60239277Sgonzo#undef IDMA_DEBUG 61239277Sgonzo 62209131Sraj#define MAX_CPU_WIN 5 63209131Sraj 64209131Sraj#ifdef DEBUG 65209131Sraj#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ 66209131Sraj printf(fmt,##args); } while (0) 67209131Sraj#else 68209131Sraj#define debugf(fmt, args...) 69209131Sraj#endif 70209131Sraj 71209131Sraj#ifdef DEBUG 72209131Sraj#define MV_DUMP_WIN 1 73209131Sraj#else 74209131Sraj#define MV_DUMP_WIN 0 75209131Sraj#endif 76209131Sraj 77183840Srajstatic int win_eth_can_remap(int i); 78183840Sraj 79239277Sgonzo#ifndef SOC_MV_FREY 80183840Srajstatic int decode_win_cpu_valid(void); 81239277Sgonzo#endif 82183840Srajstatic int decode_win_usb_valid(void); 83183840Srajstatic int decode_win_eth_valid(void); 84183840Srajstatic int decode_win_pcie_valid(void); 85186909Srajstatic int decode_win_sata_valid(void); 86250291Sgber 87209131Srajstatic int decode_win_idma_valid(void); 88209131Srajstatic int decode_win_xor_valid(void); 89183840Sraj 90239277Sgonzo#ifndef SOC_MV_FREY 91183840Srajstatic void decode_win_cpu_setup(void); 92250324Sgber#endif 93250324Sgber#ifdef SOC_MV_ARMADAXP 94250295Sgberstatic int decode_win_sdram_fixup(void); 95239277Sgonzo#endif 96209131Srajstatic void decode_win_usb_setup(u_long); 97209131Srajstatic void decode_win_eth_setup(u_long); 98209131Srajstatic void decode_win_sata_setup(u_long); 99250291Sgber 100209131Srajstatic void decode_win_idma_setup(u_long); 101209131Srajstatic void decode_win_xor_setup(u_long); 102183840Sraj 103209131Srajstatic void decode_win_usb_dump(u_long); 104209131Srajstatic void decode_win_eth_dump(u_long base); 105209131Srajstatic void decode_win_idma_dump(u_long base); 106209131Srajstatic void decode_win_xor_dump(u_long base); 107186909Sraj 108209131Srajstatic int fdt_get_ranges(const char *, void *, int, int *, int *); 109209131Sraj 110209131Srajstatic int win_cpu_from_dt(void); 111209131Srajstatic int fdt_win_setup(void); 112209131Sraj 113209131Srajstatic uint32_t dev_mask = 0; 114209131Srajstatic int cpu_wins_no = 0; 115209131Srajstatic int eth_port = 0; 116209131Srajstatic int usb_port = 0; 117183840Sraj 118209131Srajstatic struct decode_win cpu_win_tbl[MAX_CPU_WIN]; 119209131Sraj 120239277Sgonzoconst struct decode_win *cpu_wins = cpu_win_tbl; 121209131Sraj 122209131Srajtypedef void (*decode_win_setup_t)(u_long); 123209131Srajtypedef void (*dump_win_t)(u_long); 124209131Sraj 125209131Srajstruct soc_node_spec { 126209131Sraj const char *compat; 127209131Sraj decode_win_setup_t decode_handler; 128209131Sraj dump_win_t dump_handler; 129209131Sraj}; 130209131Sraj 131209131Srajstatic struct soc_node_spec soc_nodes[] = { 132209131Sraj { "mrvl,ge", &decode_win_eth_setup, &decode_win_eth_dump }, 133209131Sraj { "mrvl,usb-ehci", &decode_win_usb_setup, &decode_win_usb_dump }, 134209131Sraj { "mrvl,sata", &decode_win_sata_setup, NULL }, 135209131Sraj { "mrvl,xor", &decode_win_xor_setup, &decode_win_xor_dump }, 136209131Sraj { "mrvl,idma", &decode_win_idma_setup, &decode_win_idma_dump }, 137223665Skevlo { "mrvl,pcie", &decode_win_pcie_setup, NULL }, 138209131Sraj { NULL, NULL, NULL }, 139209131Sraj}; 140209131Sraj 141209131Srajstruct fdt_pm_mask_entry fdt_pm_mask_table[] = { 142209131Sraj { "mrvl,ge", CPU_PM_CTRL_GE(0) }, 143209131Sraj { "mrvl,ge", CPU_PM_CTRL_GE(1) }, 144209131Sraj { "mrvl,usb-ehci", CPU_PM_CTRL_USB(0) }, 145209131Sraj { "mrvl,usb-ehci", CPU_PM_CTRL_USB(1) }, 146209131Sraj { "mrvl,usb-ehci", CPU_PM_CTRL_USB(2) }, 147209131Sraj { "mrvl,xor", CPU_PM_CTRL_XOR }, 148209131Sraj { "mrvl,sata", CPU_PM_CTRL_SATA }, 149209131Sraj 150209131Sraj { NULL, 0 } 151209131Sraj}; 152209131Sraj 153196532Srajstatic __inline int 154196532Srajpm_is_disabled(uint32_t mask) 155196532Sraj{ 156256760Srrs#if defined(SOC_MV_KIRKWOOD) 157256760Srrs return (soc_power_ctrl_get(mask) == mask); 158256760Srrs#else 159196532Sraj return (soc_power_ctrl_get(mask) == mask ? 0 : 1); 160256760Srrs#endif 161196532Sraj} 162196532Sraj 163196532Sraj/* 164196532Sraj * Disable device using power management register. 165196532Sraj * 1 - Device Power On 166196532Sraj * 0 - Device Power Off 167196532Sraj * Mask can be set in loader. 168196532Sraj * EXAMPLE: 169196532Sraj * loader> set hw.pm-disable-mask=0x2 170196532Sraj * 171196532Sraj * Common mask: 172196532Sraj * |-------------------------------| 173196532Sraj * | Device | Kirkwood | Discovery | 174196532Sraj * |-------------------------------| 175196532Sraj * | USB0 | 0x00008 | 0x020000 | 176196532Sraj * |-------------------------------| 177196532Sraj * | USB1 | - | 0x040000 | 178196532Sraj * |-------------------------------| 179196532Sraj * | USB2 | - | 0x080000 | 180196532Sraj * |-------------------------------| 181196532Sraj * | GE0 | 0x00001 | 0x000002 | 182196532Sraj * |-------------------------------| 183196532Sraj * | GE1 | - | 0x000004 | 184196532Sraj * |-------------------------------| 185196532Sraj * | IDMA | - | 0x100000 | 186196532Sraj * |-------------------------------| 187196532Sraj * | XOR | 0x10000 | 0x200000 | 188196532Sraj * |-------------------------------| 189196532Sraj * | CESA | 0x20000 | 0x400000 | 190196532Sraj * |-------------------------------| 191196532Sraj * | SATA | 0x04000 | 0x004000 | 192196532Sraj * --------------------------------| 193196532Sraj * This feature can be used only on Kirkwood and Discovery 194196532Sraj * machines. 195196532Sraj */ 196196532Srajstatic __inline void 197196532Srajpm_disable_device(int mask) 198196532Sraj{ 199196532Sraj#ifdef DIAGNOSTIC 200196532Sraj uint32_t reg; 201196532Sraj 202196532Sraj reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL); 203196532Sraj printf("Power Management Register: 0%x\n", reg); 204196532Sraj 205196532Sraj reg &= ~mask; 206196532Sraj soc_power_ctrl_set(reg); 207196532Sraj printf("Device %x is disabled\n", mask); 208196532Sraj 209196532Sraj reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL); 210196532Sraj printf("Power Management Register: 0%x\n", reg); 211196532Sraj#endif 212196532Sraj} 213196532Sraj 214209131Srajint 215209131Srajfdt_pm(phandle_t node) 216209131Sraj{ 217209131Sraj uint32_t cpu_pm_ctrl; 218209131Sraj int i, ena, compat; 219209131Sraj 220209131Sraj ena = 1; 221209131Sraj cpu_pm_ctrl = read_cpu_ctrl(CPU_PM_CTRL); 222209131Sraj for (i = 0; fdt_pm_mask_table[i].compat != NULL; i++) { 223209131Sraj if (dev_mask & (1 << i)) 224209131Sraj continue; 225209131Sraj 226209131Sraj compat = fdt_is_compatible(node, fdt_pm_mask_table[i].compat); 227256760Srrs#if defined(SOC_MV_KIRKWOOD) 228256760Srrs if (compat && (cpu_pm_ctrl & fdt_pm_mask_table[i].mask)) { 229256760Srrs dev_mask |= (1 << i); 230256760Srrs ena = 0; 231256760Srrs break; 232256760Srrs } else if (compat) { 233256760Srrs dev_mask |= (1 << i); 234256760Srrs break; 235256760Srrs } 236256760Srrs#else 237209131Sraj if (compat && (~cpu_pm_ctrl & fdt_pm_mask_table[i].mask)) { 238209131Sraj dev_mask |= (1 << i); 239209131Sraj ena = 0; 240209131Sraj break; 241209131Sraj } else if (compat) { 242209131Sraj dev_mask |= (1 << i); 243209131Sraj break; 244209131Sraj } 245256760Srrs#endif 246209131Sraj } 247209131Sraj 248209131Sraj return (ena); 249209131Sraj} 250209131Sraj 251183840Srajuint32_t 252183840Srajread_cpu_ctrl(uint32_t reg) 253183840Sraj{ 254183840Sraj 255209131Sraj return (bus_space_read_4(fdtbus_bs_tag, MV_CPU_CONTROL_BASE, reg)); 256183840Sraj} 257183840Sraj 258183840Srajvoid 259183840Srajwrite_cpu_ctrl(uint32_t reg, uint32_t val) 260183840Sraj{ 261183840Sraj 262209131Sraj bus_space_write_4(fdtbus_bs_tag, MV_CPU_CONTROL_BASE, reg, val); 263183840Sraj} 264183840Sraj 265240488Sgber#if defined(SOC_MV_ARMADAXP) 266240488Sgberuint32_t 267240488Sgberread_cpu_mp_clocks(uint32_t reg) 268240488Sgber{ 269240488Sgber 270240488Sgber return (bus_space_read_4(fdtbus_bs_tag, MV_MP_CLOCKS_BASE, reg)); 271240488Sgber} 272240488Sgber 273183840Srajvoid 274240488Sgberwrite_cpu_mp_clocks(uint32_t reg, uint32_t val) 275240488Sgber{ 276240488Sgber 277240488Sgber bus_space_write_4(fdtbus_bs_tag, MV_MP_CLOCKS_BASE, reg, val); 278240488Sgber} 279240488Sgber 280240488Sgberuint32_t 281240488Sgberread_cpu_misc(uint32_t reg) 282240488Sgber{ 283240488Sgber 284240488Sgber return (bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE, reg)); 285240488Sgber} 286240488Sgber 287240488Sgbervoid 288240488Sgberwrite_cpu_misc(uint32_t reg, uint32_t val) 289240488Sgber{ 290240488Sgber 291240488Sgber bus_space_write_4(fdtbus_bs_tag, MV_MISC_BASE, reg, val); 292240488Sgber} 293240488Sgber#endif 294240488Sgber 295240488Sgbervoid 296183840Srajcpu_reset(void) 297183840Sraj{ 298183840Sraj 299240488Sgber#if defined(SOC_MV_ARMADAXP) 300240488Sgber write_cpu_misc(RSTOUTn_MASK, SOFT_RST_OUT_EN); 301240488Sgber write_cpu_misc(SYSTEM_SOFT_RESET, SYS_SOFT_RST); 302240488Sgber#else 303183840Sraj write_cpu_ctrl(RSTOUTn_MASK, SOFT_RST_OUT_EN); 304183840Sraj write_cpu_ctrl(SYSTEM_SOFT_RESET, SYS_SOFT_RST); 305240488Sgber#endif 306183840Sraj while (1); 307183840Sraj} 308183840Sraj 309183840Srajuint32_t 310183840Srajcpu_extra_feat(void) 311183840Sraj{ 312186909Sraj uint32_t dev, rev; 313183840Sraj uint32_t ef = 0; 314183840Sraj 315183840Sraj soc_id(&dev, &rev); 316239277Sgonzo 317239277Sgonzo switch (dev) { 318239277Sgonzo case MV_DEV_88F6281: 319239277Sgonzo case MV_DEV_88F6282: 320239277Sgonzo case MV_DEV_88RC8180: 321239277Sgonzo case MV_DEV_MV78100_Z0: 322239277Sgonzo case MV_DEV_MV78100: 323183840Sraj __asm __volatile("mrc p15, 1, %0, c15, c1, 0" : "=r" (ef)); 324239277Sgonzo break; 325239277Sgonzo case MV_DEV_88F5182: 326239277Sgonzo case MV_DEV_88F5281: 327183840Sraj __asm __volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (ef)); 328239277Sgonzo break; 329239277Sgonzo default: 330239277Sgonzo if (bootverbose) 331239277Sgonzo printf("This ARM Core does not support any extra features\n"); 332239277Sgonzo } 333183840Sraj 334183840Sraj return (ef); 335183840Sraj} 336183840Sraj 337196532Sraj/* 338196532Sraj * Get the power status of device. This feature is only supported on 339196532Sraj * Kirkwood and Discovery SoCs. 340196532Sraj */ 341183840Srajuint32_t 342183840Srajsoc_power_ctrl_get(uint32_t mask) 343183840Sraj{ 344183840Sraj 345239277Sgonzo#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS) && !defined(SOC_MV_FREY) 346183840Sraj if (mask != CPU_PM_CTRL_NONE) 347183840Sraj mask &= read_cpu_ctrl(CPU_PM_CTRL); 348183840Sraj 349183840Sraj return (mask); 350196532Sraj#else 351196532Sraj return (mask); 352196532Sraj#endif 353183840Sraj} 354183840Sraj 355196532Sraj/* 356196532Sraj * Set the power status of device. This feature is only supported on 357196532Sraj * Kirkwood and Discovery SoCs. 358196532Sraj */ 359183840Srajvoid 360196532Srajsoc_power_ctrl_set(uint32_t mask) 361196532Sraj{ 362196532Sraj 363239277Sgonzo#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS) 364196532Sraj if (mask != CPU_PM_CTRL_NONE) 365196532Sraj write_cpu_ctrl(CPU_PM_CTRL, mask); 366196532Sraj#endif 367196532Sraj} 368196532Sraj 369196532Srajvoid 370183840Srajsoc_id(uint32_t *dev, uint32_t *rev) 371183840Sraj{ 372183840Sraj 373183840Sraj /* 374183840Sraj * Notice: system identifiers are available in the registers range of 375183840Sraj * PCIE controller, so using this function is only allowed (and 376183840Sraj * possible) after the internal registers range has been mapped in via 377183840Sraj * pmap_devmap_bootstrap(). 378183840Sraj */ 379209131Sraj *dev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 0) >> 16; 380209131Sraj *rev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 8) & 0xff; 381183840Sraj} 382183840Sraj 383209131Srajstatic void 384183840Srajsoc_identify(void) 385183840Sraj{ 386239277Sgonzo uint32_t d, r, size, mode; 387183840Sraj const char *dev; 388183840Sraj const char *rev; 389183840Sraj 390183840Sraj soc_id(&d, &r); 391183840Sraj 392183840Sraj printf("SOC: "); 393183840Sraj if (bootverbose) 394183840Sraj printf("(0x%4x:0x%02x) ", d, r); 395183840Sraj 396183840Sraj rev = ""; 397183840Sraj switch (d) { 398183840Sraj case MV_DEV_88F5181: 399183840Sraj dev = "Marvell 88F5181"; 400183840Sraj if (r == 3) 401183840Sraj rev = "B1"; 402183840Sraj break; 403183840Sraj case MV_DEV_88F5182: 404183840Sraj dev = "Marvell 88F5182"; 405183840Sraj if (r == 2) 406183840Sraj rev = "A2"; 407183840Sraj break; 408183840Sraj case MV_DEV_88F5281: 409183840Sraj dev = "Marvell 88F5281"; 410183840Sraj if (r == 4) 411183840Sraj rev = "D0"; 412183840Sraj else if (r == 5) 413183840Sraj rev = "D1"; 414183840Sraj else if (r == 6) 415183840Sraj rev = "D2"; 416183840Sraj break; 417183840Sraj case MV_DEV_88F6281: 418183840Sraj dev = "Marvell 88F6281"; 419186899Sraj if (r == 0) 420186899Sraj rev = "Z0"; 421186899Sraj else if (r == 2) 422186899Sraj rev = "A0"; 423204764Sraj else if (r == 3) 424204764Sraj rev = "A1"; 425183840Sraj break; 426239277Sgonzo case MV_DEV_88RC8180: 427239277Sgonzo dev = "Marvell 88RC8180"; 428239277Sgonzo break; 429239277Sgonzo case MV_DEV_88RC9480: 430239277Sgonzo dev = "Marvell 88RC9480"; 431239277Sgonzo break; 432239277Sgonzo case MV_DEV_88RC9580: 433239277Sgonzo dev = "Marvell 88RC9580"; 434239277Sgonzo break; 435239277Sgonzo case MV_DEV_88F6781: 436239277Sgonzo dev = "Marvell 88F6781"; 437239277Sgonzo if (r == 2) 438239277Sgonzo rev = "Y0"; 439239277Sgonzo break; 440238873Shrs case MV_DEV_88F6282: 441238873Shrs dev = "Marvell 88F6282"; 442238873Shrs if (r == 0) 443238873Shrs rev = "A0"; 444238873Shrs else if (r == 1) 445238873Shrs rev = "A1"; 446238873Shrs break; 447191140Sraj case MV_DEV_MV78100_Z0: 448191140Sraj dev = "Marvell MV78100 Z0"; 449191140Sraj break; 450183840Sraj case MV_DEV_MV78100: 451183840Sraj dev = "Marvell MV78100"; 452183840Sraj break; 453239277Sgonzo case MV_DEV_MV78160: 454239277Sgonzo dev = "Marvell MV78160"; 455239277Sgonzo break; 456239277Sgonzo case MV_DEV_MV78260: 457239277Sgonzo dev = "Marvell MV78260"; 458239277Sgonzo break; 459239277Sgonzo case MV_DEV_MV78460: 460239277Sgonzo dev = "Marvell MV78460"; 461239277Sgonzo break; 462183840Sraj default: 463183840Sraj dev = "UNKNOWN"; 464183840Sraj break; 465183840Sraj } 466183840Sraj 467183840Sraj printf("%s", dev); 468183840Sraj if (*rev != '\0') 469183840Sraj printf(" rev %s", rev); 470183840Sraj printf(", TClock %dMHz\n", get_tclk() / 1000 / 1000); 471183840Sraj 472239277Sgonzo mode = read_cpu_ctrl(CPU_CONFIG); 473239277Sgonzo printf(" Instruction cache prefetch %s, data cache prefetch %s\n", 474239277Sgonzo (mode & CPU_CONFIG_IC_PREF) ? "enabled" : "disabled", 475239277Sgonzo (mode & CPU_CONFIG_DC_PREF) ? "enabled" : "disabled"); 476239277Sgonzo 477239277Sgonzo switch (d) { 478239277Sgonzo case MV_DEV_88F6281: 479239368Shrs case MV_DEV_88F6282: 480239277Sgonzo mode = read_cpu_ctrl(CPU_L2_CONFIG) & CPU_L2_CONFIG_MODE; 481239277Sgonzo printf(" 256KB 4-way set-associative %s unified L2 cache\n", 482239277Sgonzo mode ? "write-through" : "write-back"); 483239277Sgonzo break; 484239277Sgonzo case MV_DEV_MV78100: 485239277Sgonzo mode = read_cpu_ctrl(CPU_CONTROL); 486239277Sgonzo size = mode & CPU_CONTROL_L2_SIZE; 487239277Sgonzo mode = mode & CPU_CONTROL_L2_MODE; 488239277Sgonzo printf(" %s set-associative %s unified L2 cache\n", 489239277Sgonzo size ? "256KB 4-way" : "512KB 8-way", 490239277Sgonzo mode ? "write-through" : "write-back"); 491239277Sgonzo break; 492239277Sgonzo default: 493239277Sgonzo break; 494239277Sgonzo } 495183840Sraj} 496183840Sraj 497209131Srajstatic void 498209131Srajplatform_identify(void *dummy) 499209131Sraj{ 500209131Sraj 501209131Sraj soc_identify(); 502209131Sraj 503209131Sraj /* 504209131Sraj * XXX Board identification e.g. read out from FPGA or similar should 505209131Sraj * go here 506209131Sraj */ 507209131Sraj} 508209131SrajSYSINIT(platform_identify, SI_SUB_CPU, SI_ORDER_SECOND, platform_identify, 509209131Sraj NULL); 510209131Sraj 511239277Sgonzo#ifdef KDB 512239277Sgonzostatic void 513239277Sgonzomv_enter_debugger(void *dummy) 514239277Sgonzo{ 515239277Sgonzo 516239277Sgonzo if (boothowto & RB_KDB) 517239277Sgonzo kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 518239277Sgonzo} 519239277SgonzoSYSINIT(mv_enter_debugger, SI_SUB_CPU, SI_ORDER_ANY, mv_enter_debugger, NULL); 520239277Sgonzo#endif 521239277Sgonzo 522183840Srajint 523183840Srajsoc_decode_win(void) 524183840Sraj{ 525186909Sraj uint32_t dev, rev; 526209131Sraj int mask, err; 527183840Sraj 528196532Sraj mask = 0; 529196532Sraj TUNABLE_INT_FETCH("hw.pm-disable-mask", &mask); 530196532Sraj 531196532Sraj if (mask != 0) 532196532Sraj pm_disable_device(mask); 533196532Sraj 534209131Sraj /* Retrieve data about physical addresses from device tree. */ 535209131Sraj if ((err = win_cpu_from_dt()) != 0) 536209131Sraj return (err); 537209131Sraj 538183840Sraj /* Retrieve our ID: some windows facilities vary between SoC models */ 539183840Sraj soc_id(&dev, &rev); 540183840Sraj 541250295Sgber#ifdef SOC_MV_ARMADAXP 542250295Sgber if ((err = decode_win_sdram_fixup()) != 0) 543250295Sgber return(err); 544250295Sgber#endif 545250295Sgber 546239277Sgonzo#ifndef SOC_MV_FREY 547209131Sraj if (!decode_win_cpu_valid() || !decode_win_usb_valid() || 548209131Sraj !decode_win_eth_valid() || !decode_win_idma_valid() || 549209131Sraj !decode_win_pcie_valid() || !decode_win_sata_valid() || 550250291Sgber !decode_win_xor_valid()) 551209131Sraj return (EINVAL); 552183840Sraj 553183840Sraj decode_win_cpu_setup(); 554239277Sgonzo#else 555239277Sgonzo if (!decode_win_usb_valid() || 556239277Sgonzo !decode_win_eth_valid() || !decode_win_idma_valid() || 557239277Sgonzo !decode_win_pcie_valid() || !decode_win_sata_valid() || 558250291Sgber !decode_win_xor_valid()) 559239277Sgonzo return (EINVAL); 560239277Sgonzo#endif 561209131Sraj if (MV_DUMP_WIN) 562209131Sraj soc_dump_decode_win(); 563185089Sraj 564209131Sraj eth_port = 0; 565209131Sraj usb_port = 0; 566209131Sraj if ((err = fdt_win_setup()) != 0) 567209131Sraj return (err); 568183840Sraj 569183840Sraj return (0); 570183840Sraj} 571183840Sraj 572183840Sraj/************************************************************************** 573183840Sraj * Decode windows registers accessors 574183840Sraj **************************************************************************/ 575239277Sgonzo#if !defined(SOC_MV_FREY) 576183840SrajWIN_REG_IDX_RD(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE) 577183840SrajWIN_REG_IDX_RD(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) 578183840SrajWIN_REG_IDX_RD(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) 579183840SrajWIN_REG_IDX_RD(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE) 580183840SrajWIN_REG_IDX_WR(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE) 581183840SrajWIN_REG_IDX_WR(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) 582183840SrajWIN_REG_IDX_WR(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) 583183840SrajWIN_REG_IDX_WR(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE) 584239277Sgonzo#endif 585183840Sraj 586209131SrajWIN_REG_BASE_IDX_RD(win_usb, cr, MV_WIN_USB_CTRL) 587209131SrajWIN_REG_BASE_IDX_RD(win_usb, br, MV_WIN_USB_BASE) 588209131SrajWIN_REG_BASE_IDX_WR(win_usb, cr, MV_WIN_USB_CTRL) 589209131SrajWIN_REG_BASE_IDX_WR(win_usb, br, MV_WIN_USB_BASE) 590183840Sraj 591183840SrajWIN_REG_BASE_IDX_RD(win_eth, br, MV_WIN_ETH_BASE) 592183840SrajWIN_REG_BASE_IDX_RD(win_eth, sz, MV_WIN_ETH_SIZE) 593183840SrajWIN_REG_BASE_IDX_RD(win_eth, har, MV_WIN_ETH_REMAP) 594183840SrajWIN_REG_BASE_IDX_WR(win_eth, br, MV_WIN_ETH_BASE) 595183840SrajWIN_REG_BASE_IDX_WR(win_eth, sz, MV_WIN_ETH_SIZE) 596183840SrajWIN_REG_BASE_IDX_WR(win_eth, har, MV_WIN_ETH_REMAP) 597186909Sraj 598209131SrajWIN_REG_BASE_IDX_RD2(win_xor, br, MV_WIN_XOR_BASE) 599209131SrajWIN_REG_BASE_IDX_RD2(win_xor, sz, MV_WIN_XOR_SIZE) 600209131SrajWIN_REG_BASE_IDX_RD2(win_xor, har, MV_WIN_XOR_REMAP) 601209131SrajWIN_REG_BASE_IDX_RD2(win_xor, ctrl, MV_WIN_XOR_CTRL) 602209131SrajWIN_REG_BASE_IDX_WR2(win_xor, br, MV_WIN_XOR_BASE) 603209131SrajWIN_REG_BASE_IDX_WR2(win_xor, sz, MV_WIN_XOR_SIZE) 604209131SrajWIN_REG_BASE_IDX_WR2(win_xor, har, MV_WIN_XOR_REMAP) 605209131SrajWIN_REG_BASE_IDX_WR2(win_xor, ctrl, MV_WIN_XOR_CTRL) 606186909Sraj 607183840SrajWIN_REG_BASE_RD(win_eth, bare, 0x290) 608183840SrajWIN_REG_BASE_RD(win_eth, epap, 0x294) 609183840SrajWIN_REG_BASE_WR(win_eth, bare, 0x290) 610183840SrajWIN_REG_BASE_WR(win_eth, epap, 0x294) 611183840Sraj 612183840SrajWIN_REG_BASE_IDX_RD(win_pcie, cr, MV_WIN_PCIE_CTRL); 613183840SrajWIN_REG_BASE_IDX_RD(win_pcie, br, MV_WIN_PCIE_BASE); 614183840SrajWIN_REG_BASE_IDX_RD(win_pcie, remap, MV_WIN_PCIE_REMAP); 615183840SrajWIN_REG_BASE_IDX_WR(win_pcie, cr, MV_WIN_PCIE_CTRL); 616183840SrajWIN_REG_BASE_IDX_WR(win_pcie, br, MV_WIN_PCIE_BASE); 617183840SrajWIN_REG_BASE_IDX_WR(win_pcie, remap, MV_WIN_PCIE_REMAP); 618239277SgonzoWIN_REG_BASE_IDX_RD(pcie_bar, br, MV_PCIE_BAR_BASE); 619239277SgonzoWIN_REG_BASE_IDX_WR(pcie_bar, br, MV_PCIE_BAR_BASE); 620239277SgonzoWIN_REG_BASE_IDX_WR(pcie_bar, brh, MV_PCIE_BAR_BASE_H); 621239277SgonzoWIN_REG_BASE_IDX_WR(pcie_bar, cr, MV_PCIE_BAR_CTRL); 622183840Sraj 623209131SrajWIN_REG_BASE_IDX_RD(win_idma, br, MV_WIN_IDMA_BASE) 624209131SrajWIN_REG_BASE_IDX_RD(win_idma, sz, MV_WIN_IDMA_SIZE) 625209131SrajWIN_REG_BASE_IDX_RD(win_idma, har, MV_WIN_IDMA_REMAP) 626209131SrajWIN_REG_BASE_IDX_RD(win_idma, cap, MV_WIN_IDMA_CAP) 627209131SrajWIN_REG_BASE_IDX_WR(win_idma, br, MV_WIN_IDMA_BASE) 628209131SrajWIN_REG_BASE_IDX_WR(win_idma, sz, MV_WIN_IDMA_SIZE) 629209131SrajWIN_REG_BASE_IDX_WR(win_idma, har, MV_WIN_IDMA_REMAP) 630209131SrajWIN_REG_BASE_IDX_WR(win_idma, cap, MV_WIN_IDMA_CAP) 631209131SrajWIN_REG_BASE_RD(win_idma, bare, 0xa80) 632209131SrajWIN_REG_BASE_WR(win_idma, bare, 0xa80) 633183840Sraj 634209131SrajWIN_REG_BASE_IDX_RD(win_sata, cr, MV_WIN_SATA_CTRL); 635209131SrajWIN_REG_BASE_IDX_RD(win_sata, br, MV_WIN_SATA_BASE); 636209131SrajWIN_REG_BASE_IDX_WR(win_sata, cr, MV_WIN_SATA_CTRL); 637209131SrajWIN_REG_BASE_IDX_WR(win_sata, br, MV_WIN_SATA_BASE); 638239277Sgonzo#ifndef SOC_MV_DOVE 639239277SgonzoWIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE) 640239277SgonzoWIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE) 641250295SgberWIN_REG_IDX_WR(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE) 642250295SgberWIN_REG_IDX_WR(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE) 643239277Sgonzo#else 644239277Sgonzo/* 645239277Sgonzo * On 88F6781 (Dove) SoC DDR Controller is accessed through 646239277Sgonzo * single MBUS <-> AXI bridge. In this case we provide emulated 647239277Sgonzo * ddr_br_read() and ddr_sz_read() functions to keep compatibility 648239277Sgonzo * with common decoding windows setup code. 649239277Sgonzo */ 650186909Sraj 651239277Sgonzostatic inline uint32_t ddr_br_read(int i) 652239277Sgonzo{ 653239277Sgonzo uint32_t mmap; 654239277Sgonzo 655239277Sgonzo /* Read Memory Address Map Register for CS i */ 656239277Sgonzo mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0); 657239277Sgonzo 658239277Sgonzo /* Return CS i base address */ 659239277Sgonzo return (mmap & 0xFF000000); 660239277Sgonzo} 661239277Sgonzo 662239277Sgonzostatic inline uint32_t ddr_sz_read(int i) 663239277Sgonzo{ 664239277Sgonzo uint32_t mmap, size; 665239277Sgonzo 666239277Sgonzo /* Read Memory Address Map Register for CS i */ 667239277Sgonzo mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0); 668239277Sgonzo 669239277Sgonzo /* Extract size of CS space in 64kB units */ 670239277Sgonzo size = (1 << ((mmap >> 16) & 0x0F)); 671239277Sgonzo 672239277Sgonzo /* Return CS size and enable/disable status */ 673239277Sgonzo return (((size - 1) << 16) | (mmap & 0x01)); 674239277Sgonzo} 675239277Sgonzo#endif 676239277Sgonzo 677239277Sgonzo#if !defined(SOC_MV_FREY) 678183840Sraj/************************************************************************** 679183840Sraj * Decode windows helper routines 680183840Sraj **************************************************************************/ 681183840Srajvoid 682183840Srajsoc_dump_decode_win(void) 683183840Sraj{ 684186909Sraj uint32_t dev, rev; 685183840Sraj int i; 686183840Sraj 687183840Sraj soc_id(&dev, &rev); 688183840Sraj 689183840Sraj for (i = 0; i < MV_WIN_CPU_MAX; i++) { 690183840Sraj printf("CPU window#%d: c 0x%08x, b 0x%08x", i, 691183840Sraj win_cpu_cr_read(i), 692183840Sraj win_cpu_br_read(i)); 693183840Sraj 694183840Sraj if (win_cpu_can_remap(i)) 695183840Sraj printf(", rl 0x%08x, rh 0x%08x", 696183840Sraj win_cpu_remap_l_read(i), 697183840Sraj win_cpu_remap_h_read(i)); 698183840Sraj 699183840Sraj printf("\n"); 700183840Sraj } 701183840Sraj printf("Internal regs base: 0x%08x\n", 702209131Sraj bus_space_read_4(fdtbus_bs_tag, MV_INTREGS_BASE, 0)); 703183840Sraj 704183840Sraj for (i = 0; i < MV_WIN_DDR_MAX; i++) 705183840Sraj printf("DDR CS#%d: b 0x%08x, s 0x%08x\n", i, 706183840Sraj ddr_br_read(i), ddr_sz_read(i)); 707183840Sraj} 708183840Sraj 709183840Sraj/************************************************************************** 710183840Sraj * CPU windows routines 711183840Sraj **************************************************************************/ 712183840Srajint 713183840Srajwin_cpu_can_remap(int i) 714183840Sraj{ 715186909Sraj uint32_t dev, rev; 716183840Sraj 717186909Sraj soc_id(&dev, &rev); 718186909Sraj 719183840Sraj /* Depending on the SoC certain windows have remap capability */ 720183840Sraj if ((dev == MV_DEV_88F5182 && i < 2) || 721183840Sraj (dev == MV_DEV_88F5281 && i < 4) || 722183840Sraj (dev == MV_DEV_88F6281 && i < 4) || 723239368Shrs (dev == MV_DEV_88F6282 && i < 4) || 724239277Sgonzo (dev == MV_DEV_88RC8180 && i < 2) || 725239277Sgonzo (dev == MV_DEV_88F6781 && i < 4) || 726239277Sgonzo (dev == MV_DEV_MV78100_Z0 && i < 8) || 727239277Sgonzo ((dev & MV_DEV_FAMILY_MASK) == MV_DEV_DISCOVERY && i < 8)) 728183840Sraj return (1); 729183840Sraj 730183840Sraj return (0); 731183840Sraj} 732183840Sraj 733183840Sraj/* XXX This should check for overlapping remap fields too.. */ 734183840Srajint 735183840Srajdecode_win_overlap(int win, int win_no, const struct decode_win *wintab) 736183840Sraj{ 737183840Sraj const struct decode_win *tab; 738183840Sraj int i; 739183840Sraj 740183840Sraj tab = wintab; 741183840Sraj 742183840Sraj for (i = 0; i < win_no; i++, tab++) { 743183840Sraj if (i == win) 744183840Sraj /* Skip self */ 745183840Sraj continue; 746183840Sraj 747183840Sraj if ((tab->base + tab->size - 1) < (wintab + win)->base) 748183840Sraj continue; 749183840Sraj 750183840Sraj else if (((wintab + win)->base + (wintab + win)->size - 1) < 751183840Sraj tab->base) 752183840Sraj continue; 753183840Sraj else 754183840Sraj return (i); 755183840Sraj } 756183840Sraj 757183840Sraj return (-1); 758183840Sraj} 759183840Sraj 760183840Srajstatic int 761183840Srajdecode_win_cpu_valid(void) 762183840Sraj{ 763183840Sraj int i, j, rv; 764183840Sraj uint32_t b, e, s; 765183840Sraj 766183840Sraj if (cpu_wins_no > MV_WIN_CPU_MAX) { 767183840Sraj printf("CPU windows: too many entries: %d\n", cpu_wins_no); 768209131Sraj return (0); 769183840Sraj } 770183840Sraj 771183840Sraj rv = 1; 772183840Sraj for (i = 0; i < cpu_wins_no; i++) { 773183840Sraj 774183840Sraj if (cpu_wins[i].target == 0) { 775183840Sraj printf("CPU window#%d: DDR target window is not " 776183840Sraj "supposed to be reprogrammed!\n", i); 777183840Sraj rv = 0; 778183840Sraj } 779183840Sraj 780239277Sgonzo if (cpu_wins[i].remap != ~0 && win_cpu_can_remap(i) != 1) { 781183840Sraj printf("CPU window#%d: not capable of remapping, but " 782183840Sraj "val 0x%08x defined\n", i, cpu_wins[i].remap); 783183840Sraj rv = 0; 784183840Sraj } 785183840Sraj 786183840Sraj s = cpu_wins[i].size; 787183840Sraj b = cpu_wins[i].base; 788183840Sraj e = b + s - 1; 789183840Sraj if (s > (0xFFFFFFFF - b + 1)) { 790183840Sraj /* 791183840Sraj * XXX this boundary check should account for 64bit 792183840Sraj * and remapping.. 793183840Sraj */ 794183840Sraj printf("CPU window#%d: no space for size 0x%08x at " 795183840Sraj "0x%08x\n", i, s, b); 796183840Sraj rv = 0; 797183840Sraj continue; 798183840Sraj } 799183840Sraj 800239277Sgonzo if (b != (b & ~(s - 1))) { 801239277Sgonzo printf("CPU window#%d: address 0x%08x is not aligned " 802239277Sgonzo "to 0x%08x\n", i, b, s); 803239277Sgonzo rv = 0; 804239277Sgonzo continue; 805239277Sgonzo } 806239277Sgonzo 807183840Sraj j = decode_win_overlap(i, cpu_wins_no, &cpu_wins[0]); 808183840Sraj if (j >= 0) { 809183840Sraj printf("CPU window#%d: (0x%08x - 0x%08x) overlaps " 810183840Sraj "with #%d (0x%08x - 0x%08x)\n", i, b, e, j, 811183840Sraj cpu_wins[j].base, 812183840Sraj cpu_wins[j].base + cpu_wins[j].size - 1); 813183840Sraj rv = 0; 814183840Sraj } 815183840Sraj } 816183840Sraj 817183840Sraj return (rv); 818183840Sraj} 819183840Sraj 820185089Srajint 821185089Srajdecode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size, 822239277Sgonzo vm_paddr_t remap) 823185089Sraj{ 824185089Sraj uint32_t br, cr; 825239277Sgonzo int win, i; 826185089Sraj 827239277Sgonzo if (remap == ~0) { 828239277Sgonzo win = MV_WIN_CPU_MAX - 1; 829239277Sgonzo i = -1; 830239277Sgonzo } else { 831239277Sgonzo win = 0; 832239277Sgonzo i = 1; 833239277Sgonzo } 834185089Sraj 835239277Sgonzo while ((win >= 0) && (win < MV_WIN_CPU_MAX)) { 836239277Sgonzo cr = win_cpu_cr_read(win); 837239277Sgonzo if ((cr & MV_WIN_CPU_ENABLE_BIT) == 0) 838239277Sgonzo break; 839239277Sgonzo if ((cr & ((0xff << MV_WIN_CPU_ATTR_SHIFT) | 840239277Sgonzo (0x1f << MV_WIN_CPU_TARGET_SHIFT))) == 841239277Sgonzo ((attr << MV_WIN_CPU_ATTR_SHIFT) | 842239277Sgonzo (target << MV_WIN_CPU_TARGET_SHIFT))) 843239277Sgonzo break; 844239277Sgonzo win += i; 845239277Sgonzo } 846239277Sgonzo if ((win < 0) || (win >= MV_WIN_CPU_MAX) || 847239277Sgonzo ((remap != ~0) && (win_cpu_can_remap(win) == 0))) 848239277Sgonzo return (-1); 849185089Sraj 850185089Sraj br = base & 0xffff0000; 851185089Sraj win_cpu_br_write(win, br); 852185089Sraj 853185089Sraj if (win_cpu_can_remap(win)) { 854239277Sgonzo if (remap != ~0) { 855185089Sraj win_cpu_remap_l_write(win, remap & 0xffff0000); 856185089Sraj win_cpu_remap_h_write(win, 0); 857185089Sraj } else { 858185089Sraj /* 859185089Sraj * Remap function is not used for a given window 860185089Sraj * (capable of remapping) - set remap field with the 861185089Sraj * same value as base. 862185089Sraj */ 863185089Sraj win_cpu_remap_l_write(win, base & 0xffff0000); 864185089Sraj win_cpu_remap_h_write(win, 0); 865185089Sraj } 866185089Sraj } 867185089Sraj 868239277Sgonzo cr = ((size - 1) & 0xffff0000) | (attr << MV_WIN_CPU_ATTR_SHIFT) | 869239277Sgonzo (target << MV_WIN_CPU_TARGET_SHIFT) | MV_WIN_CPU_ENABLE_BIT; 870185089Sraj win_cpu_cr_write(win, cr); 871185089Sraj 872185089Sraj return (0); 873185089Sraj} 874185089Sraj 875183840Srajstatic void 876183840Srajdecode_win_cpu_setup(void) 877183840Sraj{ 878183840Sraj int i; 879183840Sraj 880183840Sraj /* Disable all CPU windows */ 881183840Sraj for (i = 0; i < MV_WIN_CPU_MAX; i++) { 882183840Sraj win_cpu_cr_write(i, 0); 883183840Sraj win_cpu_br_write(i, 0); 884183840Sraj if (win_cpu_can_remap(i)) { 885183840Sraj win_cpu_remap_l_write(i, 0); 886183840Sraj win_cpu_remap_h_write(i, 0); 887183840Sraj } 888183840Sraj } 889183840Sraj 890183840Sraj for (i = 0; i < cpu_wins_no; i++) 891185089Sraj if (cpu_wins[i].target > 0) 892185089Sraj decode_win_cpu_set(cpu_wins[i].target, 893185089Sraj cpu_wins[i].attr, cpu_wins[i].base, 894185089Sraj cpu_wins[i].size, cpu_wins[i].remap); 895183840Sraj 896183840Sraj} 897250324Sgber#endif 898250295Sgber 899250324Sgber#ifdef SOC_MV_ARMADAXP 900250295Sgberstatic int 901250295Sgberdecode_win_sdram_fixup(void) 902250295Sgber{ 903250295Sgber struct mem_region mr[FDT_MEM_REGIONS]; 904250295Sgber uint8_t window_valid[MV_WIN_DDR_MAX]; 905250295Sgber int mr_cnt, memsize, err, i, j; 906250295Sgber uint32_t valid_win_num = 0; 907250295Sgber 908250295Sgber /* Grab physical memory regions information from device tree. */ 909250295Sgber err = fdt_get_mem_regions(mr, &mr_cnt, &memsize); 910250295Sgber if (err != 0) 911250295Sgber return (err); 912250295Sgber 913250295Sgber for (i = 0; i < MV_WIN_DDR_MAX; i++) 914250295Sgber window_valid[i] = 0; 915250295Sgber 916250295Sgber /* Try to match entries from device tree with settings from u-boot */ 917250295Sgber for (i = 0; i < mr_cnt; i++) { 918250295Sgber for (j = 0; j < MV_WIN_DDR_MAX; j++) { 919250295Sgber if (ddr_is_active(j) && 920250295Sgber (ddr_base(j) == mr[i].mr_start) && 921250295Sgber (ddr_size(j) == mr[i].mr_size)) { 922250295Sgber window_valid[j] = 1; 923250295Sgber valid_win_num++; 924250295Sgber } 925250295Sgber } 926250295Sgber } 927250295Sgber 928250295Sgber if (mr_cnt != valid_win_num) 929250295Sgber return (EINVAL); 930250295Sgber 931250295Sgber /* Destroy windows without corresponding device tree entry */ 932250295Sgber for (j = 0; j < MV_WIN_DDR_MAX; j++) { 933250295Sgber if (ddr_is_active(j) && (window_valid[j] != 1)) { 934250295Sgber printf("Disabling SDRAM decoding window: %d\n", j); 935250295Sgber ddr_disable(j); 936250295Sgber } 937250295Sgber } 938250295Sgber 939250295Sgber return (0); 940250295Sgber} 941239277Sgonzo#endif 942183840Sraj/* 943183840Sraj * Check if we're able to cover all active DDR banks. 944183840Sraj */ 945183840Srajstatic int 946183840Srajdecode_win_can_cover_ddr(int max) 947183840Sraj{ 948183840Sraj int i, c; 949183840Sraj 950183840Sraj c = 0; 951183840Sraj for (i = 0; i < MV_WIN_DDR_MAX; i++) 952183840Sraj if (ddr_is_active(i)) 953183840Sraj c++; 954183840Sraj 955183840Sraj if (c > max) { 956183840Sraj printf("Unable to cover all active DDR banks: " 957183840Sraj "%d, available windows: %d\n", c, max); 958183840Sraj return (0); 959183840Sraj } 960183840Sraj 961183840Sraj return (1); 962183840Sraj} 963183840Sraj 964183840Sraj/************************************************************************** 965183840Sraj * DDR windows routines 966183840Sraj **************************************************************************/ 967183840Srajint 968183840Srajddr_is_active(int i) 969183840Sraj{ 970183840Sraj 971183840Sraj if (ddr_sz_read(i) & 0x1) 972183840Sraj return (1); 973183840Sraj 974183840Sraj return (0); 975183840Sraj} 976183840Sraj 977250295Sgbervoid 978250295Sgberddr_disable(int i) 979250295Sgber{ 980250295Sgber 981250295Sgber ddr_sz_write(i, 0); 982250295Sgber ddr_br_write(i, 0); 983250295Sgber} 984250295Sgber 985183840Srajuint32_t 986183840Srajddr_base(int i) 987183840Sraj{ 988183840Sraj 989183840Sraj return (ddr_br_read(i) & 0xff000000); 990183840Sraj} 991183840Sraj 992183840Srajuint32_t 993183840Srajddr_size(int i) 994183840Sraj{ 995183840Sraj 996183840Sraj return ((ddr_sz_read(i) | 0x00ffffff) + 1); 997183840Sraj} 998183840Sraj 999183840Srajuint32_t 1000183840Srajddr_attr(int i) 1001183840Sraj{ 1002239277Sgonzo uint32_t dev, rev; 1003183840Sraj 1004239277Sgonzo soc_id(&dev, &rev); 1005239277Sgonzo if (dev == MV_DEV_88RC8180) 1006239277Sgonzo return ((ddr_sz_read(i) & 0xf0) >> 4); 1007239277Sgonzo if (dev == MV_DEV_88F6781) 1008239277Sgonzo return (0); 1009239277Sgonzo 1010183840Sraj return (i == 0 ? 0xe : 1011183840Sraj (i == 1 ? 0xd : 1012183840Sraj (i == 2 ? 0xb : 1013183840Sraj (i == 3 ? 0x7 : 0xff)))); 1014183840Sraj} 1015183840Sraj 1016183840Srajuint32_t 1017183840Srajddr_target(int i) 1018183840Sraj{ 1019239277Sgonzo uint32_t dev, rev; 1020183840Sraj 1021239277Sgonzo soc_id(&dev, &rev); 1022239277Sgonzo if (dev == MV_DEV_88RC8180) { 1023239277Sgonzo i = (ddr_sz_read(i) & 0xf0) >> 4; 1024239277Sgonzo return (i == 0xe ? 0xc : 1025239277Sgonzo (i == 0xd ? 0xd : 1026239277Sgonzo (i == 0xb ? 0xe : 1027239277Sgonzo (i == 0x7 ? 0xf : 0xc)))); 1028239277Sgonzo } 1029239277Sgonzo 1030239277Sgonzo /* 1031239277Sgonzo * On SOCs other than 88RC8180 Mbus unit ID for 1032239277Sgonzo * DDR SDRAM controller is always 0x0. 1033239277Sgonzo */ 1034183840Sraj return (0); 1035183840Sraj} 1036183840Sraj 1037183840Sraj/************************************************************************** 1038183840Sraj * USB windows routines 1039183840Sraj **************************************************************************/ 1040183840Srajstatic int 1041183840Srajdecode_win_usb_valid(void) 1042183840Sraj{ 1043183840Sraj 1044183840Sraj return (decode_win_can_cover_ddr(MV_WIN_USB_MAX)); 1045183840Sraj} 1046183840Sraj 1047209131Srajstatic void 1048209131Srajdecode_win_usb_dump(u_long base) 1049186909Sraj{ 1050209131Sraj int i; 1051186909Sraj 1052209131Sraj if (pm_is_disabled(CPU_PM_CTRL_USB(usb_port - 1))) 1053209131Sraj return; 1054186909Sraj 1055209131Sraj for (i = 0; i < MV_WIN_USB_MAX; i++) 1056209131Sraj printf("USB window#%d: c 0x%08x, b 0x%08x\n", i, 1057209131Sraj win_usb_cr_read(base, i), win_usb_br_read(base, i)); 1058186909Sraj} 1059186909Sraj 1060183840Sraj/* 1061183840Sraj * Set USB decode windows. 1062183840Sraj */ 1063183840Srajstatic void 1064209131Srajdecode_win_usb_setup(u_long base) 1065183840Sraj{ 1066183840Sraj uint32_t br, cr; 1067209131Sraj int i, j; 1068183840Sraj 1069196532Sraj 1070209131Sraj if (pm_is_disabled(CPU_PM_CTRL_USB(usb_port))) 1071209131Sraj return; 1072183840Sraj 1073209131Sraj usb_port++; 1074196532Sraj 1075209131Sraj for (i = 0; i < MV_WIN_USB_MAX; i++) { 1076209131Sraj win_usb_cr_write(base, i, 0); 1077209131Sraj win_usb_br_write(base, i, 0); 1078209131Sraj } 1079183840Sraj 1080209131Sraj /* Only access to active DRAM banks is required */ 1081209131Sraj for (i = 0; i < MV_WIN_DDR_MAX; i++) { 1082209131Sraj if (ddr_is_active(i)) { 1083209131Sraj br = ddr_base(i); 1084209131Sraj /* 1085209131Sraj * XXX for 6281 we should handle Mbus write 1086209131Sraj * burst limit field in the ctrl reg 1087209131Sraj */ 1088209131Sraj cr = (((ddr_size(i) - 1) & 0xffff0000) | 1089209131Sraj (ddr_attr(i) << 8) | 1090209131Sraj (ddr_target(i) << 4) | 1); 1091183840Sraj 1092209131Sraj /* Set the first free USB window */ 1093209131Sraj for (j = 0; j < MV_WIN_USB_MAX; j++) { 1094209131Sraj if (win_usb_cr_read(base, j) & 0x1) 1095209131Sraj continue; 1096186909Sraj 1097209131Sraj win_usb_br_write(base, j, br); 1098209131Sraj win_usb_cr_write(base, j, cr); 1099209131Sraj break; 1100183840Sraj } 1101183840Sraj } 1102186909Sraj } 1103183840Sraj} 1104183840Sraj 1105183840Sraj/************************************************************************** 1106183840Sraj * ETH windows routines 1107183840Sraj **************************************************************************/ 1108183840Sraj 1109183840Srajstatic int 1110183840Srajwin_eth_can_remap(int i) 1111183840Sraj{ 1112183840Sraj 1113183840Sraj /* ETH encode windows 0-3 have remap capability */ 1114183840Sraj if (i < 4) 1115183840Sraj return (1); 1116239277Sgonzo 1117183840Sraj return (0); 1118183840Sraj} 1119183840Sraj 1120183840Srajstatic int 1121183840Srajeth_bare_read(uint32_t base, int i) 1122183840Sraj{ 1123183840Sraj uint32_t v; 1124183840Sraj 1125183840Sraj v = win_eth_bare_read(base); 1126183840Sraj v &= (1 << i); 1127183840Sraj 1128183840Sraj return (v >> i); 1129183840Sraj} 1130183840Sraj 1131183840Srajstatic void 1132183840Srajeth_bare_write(uint32_t base, int i, int val) 1133183840Sraj{ 1134183840Sraj uint32_t v; 1135183840Sraj 1136183840Sraj v = win_eth_bare_read(base); 1137183840Sraj v &= ~(1 << i); 1138183840Sraj v |= (val << i); 1139183840Sraj win_eth_bare_write(base, v); 1140183840Sraj} 1141183840Sraj 1142183840Srajstatic void 1143183840Srajeth_epap_write(uint32_t base, int i, int val) 1144183840Sraj{ 1145183840Sraj uint32_t v; 1146183840Sraj 1147183840Sraj v = win_eth_epap_read(base); 1148183840Sraj v &= ~(0x3 << (i * 2)); 1149183840Sraj v |= (val << (i * 2)); 1150183840Sraj win_eth_epap_write(base, v); 1151183840Sraj} 1152183840Sraj 1153183840Srajstatic void 1154209131Srajdecode_win_eth_dump(u_long base) 1155183840Sraj{ 1156209131Sraj int i; 1157209131Sraj 1158209131Sraj if (pm_is_disabled(CPU_PM_CTRL_GE(eth_port - 1))) 1159209131Sraj return; 1160209131Sraj 1161209131Sraj for (i = 0; i < MV_WIN_ETH_MAX; i++) { 1162209131Sraj printf("ETH window#%d: b 0x%08x, s 0x%08x", i, 1163209131Sraj win_eth_br_read(base, i), 1164209131Sraj win_eth_sz_read(base, i)); 1165209131Sraj 1166209131Sraj if (win_eth_can_remap(i)) 1167209131Sraj printf(", ha 0x%08x", 1168209131Sraj win_eth_har_read(base, i)); 1169209131Sraj 1170209131Sraj printf("\n"); 1171209131Sraj } 1172209131Sraj printf("ETH windows: bare 0x%08x, epap 0x%08x\n", 1173209131Sraj win_eth_bare_read(base), 1174209131Sraj win_eth_epap_read(base)); 1175209131Sraj} 1176209131Sraj 1177239277Sgonzo#if defined(SOC_MV_LOKIPLUS) 1178239277Sgonzo#define MV_WIN_ETH_DDR_TRGT(n) 0 1179239277Sgonzo#else 1180239277Sgonzo#define MV_WIN_ETH_DDR_TRGT(n) ddr_target(n) 1181239277Sgonzo#endif 1182239277Sgonzo 1183209131Srajstatic void 1184209131Srajdecode_win_eth_setup(u_long base) 1185209131Sraj{ 1186183840Sraj uint32_t br, sz; 1187183840Sraj int i, j; 1188183840Sraj 1189209131Sraj if (pm_is_disabled(CPU_PM_CTRL_GE(eth_port))) 1190196532Sraj return; 1191196532Sraj 1192209131Sraj eth_port++; 1193209131Sraj 1194183840Sraj /* Disable, clear and revoke protection for all ETH windows */ 1195183840Sraj for (i = 0; i < MV_WIN_ETH_MAX; i++) { 1196183840Sraj 1197183840Sraj eth_bare_write(base, i, 1); 1198183840Sraj eth_epap_write(base, i, 0); 1199183840Sraj win_eth_br_write(base, i, 0); 1200183840Sraj win_eth_sz_write(base, i, 0); 1201183840Sraj if (win_eth_can_remap(i)) 1202183840Sraj win_eth_har_write(base, i, 0); 1203183840Sraj } 1204183840Sraj 1205183840Sraj /* Only access to active DRAM banks is required */ 1206183840Sraj for (i = 0; i < MV_WIN_DDR_MAX; i++) 1207183840Sraj if (ddr_is_active(i)) { 1208183840Sraj 1209239277Sgonzo br = ddr_base(i) | (ddr_attr(i) << 8) | MV_WIN_ETH_DDR_TRGT(i); 1210183840Sraj sz = ((ddr_size(i) - 1) & 0xffff0000); 1211183840Sraj 1212183840Sraj /* Set the first free ETH window */ 1213183840Sraj for (j = 0; j < MV_WIN_ETH_MAX; j++) { 1214183840Sraj if (eth_bare_read(base, j) == 0) 1215183840Sraj continue; 1216183840Sraj 1217183840Sraj win_eth_br_write(base, j, br); 1218183840Sraj win_eth_sz_write(base, j, sz); 1219183840Sraj 1220183840Sraj /* XXX remapping ETH windows not supported */ 1221183840Sraj 1222183840Sraj /* Set protection RW */ 1223183840Sraj eth_epap_write(base, j, 0x3); 1224183840Sraj 1225183840Sraj /* Enable window */ 1226183840Sraj eth_bare_write(base, j, 0); 1227183840Sraj break; 1228183840Sraj } 1229183840Sraj } 1230183840Sraj} 1231183840Sraj 1232183840Srajstatic int 1233183840Srajdecode_win_eth_valid(void) 1234183840Sraj{ 1235183840Sraj 1236183840Sraj return (decode_win_can_cover_ddr(MV_WIN_ETH_MAX)); 1237183840Sraj} 1238183840Sraj 1239183840Sraj/************************************************************************** 1240183840Sraj * PCIE windows routines 1241183840Sraj **************************************************************************/ 1242183840Sraj 1243239277Sgonzovoid 1244209131Srajdecode_win_pcie_setup(u_long base) 1245183840Sraj{ 1246239277Sgonzo uint32_t size = 0, ddrbase = ~0; 1247183840Sraj uint32_t cr, br; 1248183840Sraj int i, j; 1249183840Sraj 1250239277Sgonzo for (i = 0; i < MV_PCIE_BAR_MAX; i++) { 1251239277Sgonzo pcie_bar_br_write(base, i, 1252239277Sgonzo MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); 1253239277Sgonzo if (i < 3) 1254239277Sgonzo pcie_bar_brh_write(base, i, 0); 1255239277Sgonzo if (i > 0) 1256239277Sgonzo pcie_bar_cr_write(base, i, 0); 1257239277Sgonzo } 1258183840Sraj 1259183840Sraj for (i = 0; i < MV_WIN_PCIE_MAX; i++) { 1260183840Sraj win_pcie_cr_write(base, i, 0); 1261183840Sraj win_pcie_br_write(base, i, 0); 1262183840Sraj win_pcie_remap_write(base, i, 0); 1263183840Sraj } 1264183840Sraj 1265239277Sgonzo /* On End-Point only set BAR size to 1MB regardless of DDR size */ 1266239277Sgonzo if ((bus_space_read_4(fdtbus_bs_tag, base, MV_PCIE_CONTROL) 1267239277Sgonzo & MV_PCIE_ROOT_CMPLX) == 0) { 1268239277Sgonzo pcie_bar_cr_write(base, 1, 0xf0000 | 1); 1269239277Sgonzo return; 1270239277Sgonzo } 1271239277Sgonzo 1272183840Sraj for (i = 0; i < MV_WIN_DDR_MAX; i++) { 1273183840Sraj if (ddr_is_active(i)) { 1274183840Sraj /* Map DDR to BAR 1 */ 1275183840Sraj cr = (ddr_size(i) - 1) & 0xffff0000; 1276183840Sraj size += ddr_size(i) & 0xffff0000; 1277183840Sraj cr |= (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1; 1278183840Sraj br = ddr_base(i); 1279239277Sgonzo if (br < ddrbase) 1280239277Sgonzo ddrbase = br; 1281183840Sraj 1282183840Sraj /* Use the first available PCIE window */ 1283183840Sraj for (j = 0; j < MV_WIN_PCIE_MAX; j++) { 1284183840Sraj if (win_pcie_cr_read(base, j) != 0) 1285183840Sraj continue; 1286183840Sraj 1287183840Sraj win_pcie_br_write(base, j, br); 1288183840Sraj win_pcie_cr_write(base, j, cr); 1289183840Sraj break; 1290183840Sraj } 1291183840Sraj } 1292183840Sraj } 1293183840Sraj 1294183840Sraj /* 1295183840Sraj * Upper 16 bits in BAR register is interpreted as BAR size 1296183840Sraj * (in 64 kB units) plus 64kB, so substract 0x10000 1297183840Sraj * form value passed to register to get correct value. 1298183840Sraj */ 1299183840Sraj size -= 0x10000; 1300239277Sgonzo pcie_bar_cr_write(base, 1, size | 1); 1301239277Sgonzo pcie_bar_br_write(base, 1, ddrbase | 1302239277Sgonzo MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); 1303239277Sgonzo pcie_bar_br_write(base, 0, fdt_immr_pa | 1304239277Sgonzo MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); 1305183840Sraj} 1306183840Sraj 1307183840Srajstatic int 1308183840Srajdecode_win_pcie_valid(void) 1309183840Sraj{ 1310183840Sraj 1311183840Sraj return (decode_win_can_cover_ddr(MV_WIN_PCIE_MAX)); 1312183840Sraj} 1313183840Sraj 1314183840Sraj/************************************************************************** 1315183840Sraj * IDMA windows routines 1316183840Sraj **************************************************************************/ 1317183840Sraj#if defined(SOC_MV_ORION) || defined(SOC_MV_DISCOVERY) 1318183840Srajstatic int 1319209131Srajidma_bare_read(u_long base, int i) 1320183840Sraj{ 1321183840Sraj uint32_t v; 1322183840Sraj 1323209131Sraj v = win_idma_bare_read(base); 1324183840Sraj v &= (1 << i); 1325183840Sraj 1326183840Sraj return (v >> i); 1327183840Sraj} 1328183840Sraj 1329183840Srajstatic void 1330209131Srajidma_bare_write(u_long base, int i, int val) 1331183840Sraj{ 1332183840Sraj uint32_t v; 1333183840Sraj 1334209131Sraj v = win_idma_bare_read(base); 1335183840Sraj v &= ~(1 << i); 1336183840Sraj v |= (val << i); 1337209131Sraj win_idma_bare_write(base, v); 1338183840Sraj} 1339183840Sraj 1340183840Sraj/* 1341183840Sraj * Sets channel protection 'val' for window 'w' on channel 'c' 1342183840Sraj */ 1343183840Srajstatic void 1344209131Srajidma_cap_write(u_long base, int c, int w, int val) 1345183840Sraj{ 1346183840Sraj uint32_t v; 1347183840Sraj 1348209131Sraj v = win_idma_cap_read(base, c); 1349183840Sraj v &= ~(0x3 << (w * 2)); 1350183840Sraj v |= (val << (w * 2)); 1351209131Sraj win_idma_cap_write(base, c, v); 1352183840Sraj} 1353183840Sraj 1354183840Sraj/* 1355183840Sraj * Set protection 'val' on all channels for window 'w' 1356183840Sraj */ 1357183840Srajstatic void 1358209131Srajidma_set_prot(u_long base, int w, int val) 1359183840Sraj{ 1360183840Sraj int c; 1361183840Sraj 1362183840Sraj for (c = 0; c < MV_IDMA_CHAN_MAX; c++) 1363209131Sraj idma_cap_write(base, c, w, val); 1364183840Sraj} 1365183840Sraj 1366183840Srajstatic int 1367183840Srajwin_idma_can_remap(int i) 1368183840Sraj{ 1369183840Sraj 1370183840Sraj /* IDMA decode windows 0-3 have remap capability */ 1371183840Sraj if (i < 4) 1372183840Sraj return (1); 1373185092Sraj 1374183840Sraj return (0); 1375183840Sraj} 1376183840Sraj 1377183840Srajvoid 1378209131Srajdecode_win_idma_setup(u_long base) 1379183840Sraj{ 1380183840Sraj uint32_t br, sz; 1381183840Sraj int i, j; 1382183840Sraj 1383196532Sraj if (pm_is_disabled(CPU_PM_CTRL_IDMA)) 1384196532Sraj return; 1385183840Sraj /* 1386183840Sraj * Disable and clear all IDMA windows, revoke protection for all channels 1387183840Sraj */ 1388183840Sraj for (i = 0; i < MV_WIN_IDMA_MAX; i++) { 1389183840Sraj 1390209131Sraj idma_bare_write(base, i, 1); 1391209131Sraj win_idma_br_write(base, i, 0); 1392209131Sraj win_idma_sz_write(base, i, 0); 1393183840Sraj if (win_idma_can_remap(i) == 1) 1394209131Sraj win_idma_har_write(base, i, 0); 1395183840Sraj } 1396183840Sraj for (i = 0; i < MV_IDMA_CHAN_MAX; i++) 1397209131Sraj win_idma_cap_write(base, i, 0); 1398183840Sraj 1399183840Sraj /* 1400183840Sraj * Set up access to all active DRAM banks 1401183840Sraj */ 1402183840Sraj for (i = 0; i < MV_WIN_DDR_MAX; i++) 1403183840Sraj if (ddr_is_active(i)) { 1404185092Sraj br = ddr_base(i) | (ddr_attr(i) << 8) | ddr_target(i); 1405183840Sraj sz = ((ddr_size(i) - 1) & 0xffff0000); 1406183840Sraj 1407183840Sraj /* Place DDR entries in non-remapped windows */ 1408183840Sraj for (j = 0; j < MV_WIN_IDMA_MAX; j++) 1409183840Sraj if (win_idma_can_remap(j) != 1 && 1410209131Sraj idma_bare_read(base, j) == 1) { 1411183840Sraj 1412183840Sraj /* Configure window */ 1413209131Sraj win_idma_br_write(base, j, br); 1414209131Sraj win_idma_sz_write(base, j, sz); 1415183840Sraj 1416183840Sraj /* Set protection RW on all channels */ 1417209131Sraj idma_set_prot(base, j, 0x3); 1418183840Sraj 1419183840Sraj /* Enable window */ 1420209131Sraj idma_bare_write(base, j, 0); 1421183840Sraj break; 1422183840Sraj } 1423183840Sraj } 1424183840Sraj 1425183840Sraj /* 1426183840Sraj * Remaining targets -- from statically defined table 1427183840Sraj */ 1428183840Sraj for (i = 0; i < idma_wins_no; i++) 1429183840Sraj if (idma_wins[i].target > 0) { 1430183840Sraj br = (idma_wins[i].base & 0xffff0000) | 1431185092Sraj (idma_wins[i].attr << 8) | idma_wins[i].target; 1432183840Sraj sz = ((idma_wins[i].size - 1) & 0xffff0000); 1433183840Sraj 1434183840Sraj /* Set the first free IDMA window */ 1435183840Sraj for (j = 0; j < MV_WIN_IDMA_MAX; j++) { 1436209131Sraj if (idma_bare_read(base, j) == 0) 1437183840Sraj continue; 1438183840Sraj 1439183840Sraj /* Configure window */ 1440209131Sraj win_idma_br_write(base, j, br); 1441209131Sraj win_idma_sz_write(base, j, sz); 1442185092Sraj if (win_idma_can_remap(j) && 1443185092Sraj idma_wins[j].remap >= 0) 1444209131Sraj win_idma_har_write(base, j, 1445209131Sraj idma_wins[j].remap); 1446183840Sraj 1447183840Sraj /* Set protection RW on all channels */ 1448209131Sraj idma_set_prot(base, j, 0x3); 1449183840Sraj 1450183840Sraj /* Enable window */ 1451209131Sraj idma_bare_write(base, j, 0); 1452183840Sraj break; 1453183840Sraj } 1454183840Sraj } 1455183840Sraj} 1456183840Sraj 1457183840Srajint 1458183840Srajdecode_win_idma_valid(void) 1459183840Sraj{ 1460183840Sraj const struct decode_win *wintab; 1461183840Sraj int c, i, j, rv; 1462183840Sraj uint32_t b, e, s; 1463183840Sraj 1464183840Sraj if (idma_wins_no > MV_WIN_IDMA_MAX) { 1465183840Sraj printf("IDMA windows: too many entries: %d\n", idma_wins_no); 1466209131Sraj return (0); 1467183840Sraj } 1468183840Sraj for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++) 1469183840Sraj if (ddr_is_active(i)) 1470183840Sraj c++; 1471183840Sraj 1472183840Sraj if (idma_wins_no > (MV_WIN_IDMA_MAX - c)) { 1473183840Sraj printf("IDMA windows: too many entries: %d, available: %d\n", 1474183840Sraj idma_wins_no, MV_WIN_IDMA_MAX - c); 1475209131Sraj return (0); 1476183840Sraj } 1477183840Sraj 1478183840Sraj wintab = idma_wins; 1479183840Sraj rv = 1; 1480183840Sraj for (i = 0; i < idma_wins_no; i++, wintab++) { 1481183840Sraj 1482183840Sraj if (wintab->target == 0) { 1483185092Sraj printf("IDMA window#%d: DDR target window is not " 1484185092Sraj "supposed to be reprogrammed!\n", i); 1485183840Sraj rv = 0; 1486183840Sraj } 1487183840Sraj 1488183840Sraj if (wintab->remap >= 0 && win_cpu_can_remap(i) != 1) { 1489183840Sraj printf("IDMA window#%d: not capable of remapping, but " 1490183840Sraj "val 0x%08x defined\n", i, wintab->remap); 1491183840Sraj rv = 0; 1492183840Sraj } 1493183840Sraj 1494183840Sraj s = wintab->size; 1495183840Sraj b = wintab->base; 1496183840Sraj e = b + s - 1; 1497183840Sraj if (s > (0xFFFFFFFF - b + 1)) { 1498185092Sraj /* XXX this boundary check should account for 64bit and 1499183840Sraj * remapping.. */ 1500183840Sraj printf("IDMA window#%d: no space for size 0x%08x at " 1501183840Sraj "0x%08x\n", i, s, b); 1502183840Sraj rv = 0; 1503183840Sraj continue; 1504183840Sraj } 1505183840Sraj 1506183840Sraj j = decode_win_overlap(i, idma_wins_no, &idma_wins[0]); 1507183840Sraj if (j >= 0) { 1508185092Sraj printf("IDMA window#%d: (0x%08x - 0x%08x) overlaps " 1509186909Sraj "with #%d (0x%08x - 0x%08x)\n", i, b, e, j, 1510183840Sraj idma_wins[j].base, 1511183840Sraj idma_wins[j].base + idma_wins[j].size - 1); 1512183840Sraj rv = 0; 1513183840Sraj } 1514183840Sraj } 1515183840Sraj 1516183840Sraj return (rv); 1517183840Sraj} 1518183840Sraj 1519183840Srajvoid 1520209131Srajdecode_win_idma_dump(u_long base) 1521183840Sraj{ 1522183840Sraj int i; 1523183840Sraj 1524209131Sraj if (pm_is_disabled(CPU_PM_CTRL_IDMA)) 1525209131Sraj return; 1526209131Sraj 1527183840Sraj for (i = 0; i < MV_WIN_IDMA_MAX; i++) { 1528183840Sraj printf("IDMA window#%d: b 0x%08x, s 0x%08x", i, 1529209131Sraj win_idma_br_read(base, i), win_idma_sz_read(base, i)); 1530183840Sraj 1531183840Sraj if (win_idma_can_remap(i)) 1532209131Sraj printf(", ha 0x%08x", win_idma_har_read(base, i)); 1533183840Sraj 1534183840Sraj printf("\n"); 1535183840Sraj } 1536183840Sraj for (i = 0; i < MV_IDMA_CHAN_MAX; i++) 1537183840Sraj printf("IDMA channel#%d: ap 0x%08x\n", i, 1538209131Sraj win_idma_cap_read(base, i)); 1539209131Sraj printf("IDMA windows: bare 0x%08x\n", win_idma_bare_read(base)); 1540183840Sraj} 1541183840Sraj#else 1542183840Sraj 1543183840Sraj/* Provide dummy functions to satisfy the build for SoCs not equipped with IDMA */ 1544183840Srajint 1545183840Srajdecode_win_idma_valid(void) 1546183840Sraj{ 1547183840Sraj 1548183840Sraj return (1); 1549183840Sraj} 1550183840Sraj 1551183840Srajvoid 1552209131Srajdecode_win_idma_setup(u_long base) 1553183840Sraj{ 1554183840Sraj} 1555183840Sraj 1556183840Srajvoid 1557209131Srajdecode_win_idma_dump(u_long base) 1558183840Sraj{ 1559183840Sraj} 1560183840Sraj#endif 1561186909Sraj 1562186909Sraj/************************************************************************** 1563186909Sraj * XOR windows routines 1564186909Sraj **************************************************************************/ 1565186909Sraj#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY) 1566186909Srajstatic int 1567209131Srajxor_ctrl_read(u_long base, int i, int c, int e) 1568186909Sraj{ 1569186909Sraj uint32_t v; 1570209131Sraj v = win_xor_ctrl_read(base, c, e); 1571186909Sraj v &= (1 << i); 1572186909Sraj 1573186909Sraj return (v >> i); 1574186909Sraj} 1575186909Sraj 1576186909Srajstatic void 1577209131Srajxor_ctrl_write(u_long base, int i, int c, int e, int val) 1578186909Sraj{ 1579186909Sraj uint32_t v; 1580186909Sraj 1581209131Sraj v = win_xor_ctrl_read(base, c, e); 1582186909Sraj v &= ~(1 << i); 1583186909Sraj v |= (val << i); 1584209131Sraj win_xor_ctrl_write(base, c, e, v); 1585186909Sraj} 1586186909Sraj 1587186909Sraj/* 1588186909Sraj * Set channel protection 'val' for window 'w' on channel 'c' 1589186909Sraj */ 1590186909Srajstatic void 1591209131Srajxor_chan_write(u_long base, int c, int e, int w, int val) 1592186909Sraj{ 1593186909Sraj uint32_t v; 1594186909Sraj 1595209131Sraj v = win_xor_ctrl_read(base, c, e); 1596186909Sraj v &= ~(0x3 << (w * 2 + 16)); 1597186909Sraj v |= (val << (w * 2 + 16)); 1598209131Sraj win_xor_ctrl_write(base, c, e, v); 1599186909Sraj} 1600186909Sraj 1601186909Sraj/* 1602186909Sraj * Set protection 'val' on all channels for window 'w' on engine 'e' 1603186909Sraj */ 1604186909Srajstatic void 1605209131Srajxor_set_prot(u_long base, int w, int e, int val) 1606186909Sraj{ 1607186909Sraj int c; 1608186909Sraj 1609186909Sraj for (c = 0; c < MV_XOR_CHAN_MAX; c++) 1610209131Sraj xor_chan_write(base, c, e, w, val); 1611186909Sraj} 1612186909Sraj 1613186909Srajstatic int 1614186909Srajwin_xor_can_remap(int i) 1615186909Sraj{ 1616186909Sraj 1617186909Sraj /* XOR decode windows 0-3 have remap capability */ 1618186909Sraj if (i < 4) 1619186909Sraj return (1); 1620186909Sraj 1621186909Sraj return (0); 1622186909Sraj} 1623186909Sraj 1624191140Srajstatic int 1625186909Srajxor_max_eng(void) 1626186909Sraj{ 1627186909Sraj uint32_t dev, rev; 1628186909Sraj 1629186909Sraj soc_id(&dev, &rev); 1630239368Shrs switch (dev) { 1631239368Shrs case MV_DEV_88F6281: 1632239368Shrs case MV_DEV_88F6282: 1633239368Shrs case MV_DEV_MV78130: 1634239368Shrs case MV_DEV_MV78160: 1635239368Shrs case MV_DEV_MV78230: 1636239368Shrs case MV_DEV_MV78260: 1637239368Shrs case MV_DEV_MV78460: 1638191140Sraj return (2); 1639239368Shrs case MV_DEV_MV78100: 1640239368Shrs case MV_DEV_MV78100_Z0: 1641191140Sraj return (1); 1642239368Shrs default: 1643191140Sraj return (0); 1644239368Shrs } 1645186909Sraj} 1646186909Sraj 1647186909Srajstatic void 1648209131Srajxor_active_dram(u_long base, int c, int e, int *window) 1649186909Sraj{ 1650186909Sraj uint32_t br, sz; 1651186909Sraj int i, m, w; 1652186909Sraj 1653186909Sraj /* 1654186909Sraj * Set up access to all active DRAM banks 1655186909Sraj */ 1656186909Sraj m = xor_max_eng(); 1657186909Sraj for (i = 0; i < m; i++) 1658186909Sraj if (ddr_is_active(i)) { 1659186909Sraj br = ddr_base(i) | (ddr_attr(i) << 8) | 1660186909Sraj ddr_target(i); 1661186909Sraj sz = ((ddr_size(i) - 1) & 0xffff0000); 1662186909Sraj 1663186909Sraj /* Place DDR entries in non-remapped windows */ 1664186909Sraj for (w = 0; w < MV_WIN_XOR_MAX; w++) 1665186909Sraj if (win_xor_can_remap(w) != 1 && 1666209131Sraj (xor_ctrl_read(base, w, c, e) == 0) && 1667186909Sraj w > *window) { 1668186909Sraj /* Configure window */ 1669209131Sraj win_xor_br_write(base, w, e, br); 1670209131Sraj win_xor_sz_write(base, w, e, sz); 1671186909Sraj 1672186909Sraj /* Set protection RW on all channels */ 1673209131Sraj xor_set_prot(base, w, e, 0x3); 1674186909Sraj 1675186909Sraj /* Enable window */ 1676209131Sraj xor_ctrl_write(base, w, c, e, 1); 1677186909Sraj (*window)++; 1678186909Sraj break; 1679186909Sraj } 1680186909Sraj } 1681186909Sraj} 1682186909Sraj 1683186909Srajvoid 1684209131Srajdecode_win_xor_setup(u_long base) 1685186909Sraj{ 1686186909Sraj uint32_t br, sz; 1687186909Sraj int i, j, z, e = 1, m, window; 1688186909Sraj 1689196532Sraj if (pm_is_disabled(CPU_PM_CTRL_XOR)) 1690196532Sraj return; 1691196532Sraj 1692186909Sraj /* 1693186909Sraj * Disable and clear all XOR windows, revoke protection for all 1694186909Sraj * channels 1695186909Sraj */ 1696186909Sraj m = xor_max_eng(); 1697186909Sraj for (j = 0; j < m; j++, e--) { 1698186909Sraj 1699186909Sraj /* Number of non-remaped windows */ 1700186909Sraj window = MV_XOR_NON_REMAP - 1; 1701186909Sraj 1702186909Sraj for (i = 0; i < MV_WIN_XOR_MAX; i++) { 1703209131Sraj win_xor_br_write(base, i, e, 0); 1704209131Sraj win_xor_sz_write(base, i, e, 0); 1705186909Sraj } 1706186909Sraj 1707186909Sraj if (win_xor_can_remap(i) == 1) 1708209131Sraj win_xor_har_write(base, i, e, 0); 1709186909Sraj 1710186909Sraj for (i = 0; i < MV_XOR_CHAN_MAX; i++) { 1711209131Sraj win_xor_ctrl_write(base, i, e, 0); 1712209131Sraj xor_active_dram(base, i, e, &window); 1713186909Sraj } 1714186909Sraj 1715186909Sraj /* 1716186909Sraj * Remaining targets -- from a statically defined table 1717186909Sraj */ 1718186909Sraj for (i = 0; i < xor_wins_no; i++) 1719186909Sraj if (xor_wins[i].target > 0) { 1720186909Sraj br = (xor_wins[i].base & 0xffff0000) | 1721186909Sraj (xor_wins[i].attr << 8) | 1722186909Sraj xor_wins[i].target; 1723186909Sraj sz = ((xor_wins[i].size - 1) & 0xffff0000); 1724186909Sraj 1725186909Sraj /* Set the first free XOR window */ 1726186909Sraj for (z = 0; z < MV_WIN_XOR_MAX; z++) { 1727209131Sraj if (xor_ctrl_read(base, z, 0, e) && 1728209131Sraj xor_ctrl_read(base, z, 1, e)) 1729186909Sraj continue; 1730186909Sraj 1731186909Sraj /* Configure window */ 1732209131Sraj win_xor_br_write(base, z, e, br); 1733209131Sraj win_xor_sz_write(base, z, e, sz); 1734186909Sraj if (win_xor_can_remap(z) && 1735186909Sraj xor_wins[z].remap >= 0) 1736209131Sraj win_xor_har_write(base, z, e, 1737186909Sraj xor_wins[z].remap); 1738186909Sraj 1739186909Sraj /* Set protection RW on all channels */ 1740209131Sraj xor_set_prot(base, z, e, 0x3); 1741186909Sraj 1742186909Sraj /* Enable window */ 1743209131Sraj xor_ctrl_write(base, z, 0, e, 1); 1744209131Sraj xor_ctrl_write(base, z, 1, e, 1); 1745186909Sraj break; 1746186909Sraj } 1747186909Sraj } 1748186909Sraj } 1749186909Sraj} 1750186909Sraj 1751186909Srajint 1752186909Srajdecode_win_xor_valid(void) 1753186909Sraj{ 1754186909Sraj const struct decode_win *wintab; 1755186909Sraj int c, i, j, rv; 1756186909Sraj uint32_t b, e, s; 1757186909Sraj 1758186909Sraj if (xor_wins_no > MV_WIN_XOR_MAX) { 1759186909Sraj printf("XOR windows: too many entries: %d\n", xor_wins_no); 1760209131Sraj return (0); 1761186909Sraj } 1762186909Sraj for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++) 1763186909Sraj if (ddr_is_active(i)) 1764186909Sraj c++; 1765186909Sraj 1766186909Sraj if (xor_wins_no > (MV_WIN_XOR_MAX - c)) { 1767186909Sraj printf("XOR windows: too many entries: %d, available: %d\n", 1768186909Sraj xor_wins_no, MV_WIN_IDMA_MAX - c); 1769209131Sraj return (0); 1770186909Sraj } 1771186909Sraj 1772186909Sraj wintab = xor_wins; 1773186909Sraj rv = 1; 1774186909Sraj for (i = 0; i < xor_wins_no; i++, wintab++) { 1775186909Sraj 1776186909Sraj if (wintab->target == 0) { 1777186909Sraj printf("XOR window#%d: DDR target window is not " 1778186909Sraj "supposed to be reprogrammed!\n", i); 1779186909Sraj rv = 0; 1780186909Sraj } 1781186909Sraj 1782186909Sraj if (wintab->remap >= 0 && win_cpu_can_remap(i) != 1) { 1783186909Sraj printf("XOR window#%d: not capable of remapping, but " 1784186909Sraj "val 0x%08x defined\n", i, wintab->remap); 1785186909Sraj rv = 0; 1786186909Sraj } 1787186909Sraj 1788186909Sraj s = wintab->size; 1789186909Sraj b = wintab->base; 1790186909Sraj e = b + s - 1; 1791186909Sraj if (s > (0xFFFFFFFF - b + 1)) { 1792186909Sraj /* 1793186909Sraj * XXX this boundary check should account for 64bit 1794186909Sraj * and remapping.. 1795186909Sraj */ 1796186909Sraj printf("XOR window#%d: no space for size 0x%08x at " 1797186909Sraj "0x%08x\n", i, s, b); 1798186909Sraj rv = 0; 1799186909Sraj continue; 1800186909Sraj } 1801186909Sraj 1802186909Sraj j = decode_win_overlap(i, xor_wins_no, &xor_wins[0]); 1803186909Sraj if (j >= 0) { 1804186909Sraj printf("XOR window#%d: (0x%08x - 0x%08x) overlaps " 1805186909Sraj "with #%d (0x%08x - 0x%08x)\n", i, b, e, j, 1806186909Sraj xor_wins[j].base, 1807186909Sraj xor_wins[j].base + xor_wins[j].size - 1); 1808186909Sraj rv = 0; 1809186909Sraj } 1810186909Sraj } 1811186909Sraj 1812186909Sraj return (rv); 1813186909Sraj} 1814186909Sraj 1815186909Srajvoid 1816209131Srajdecode_win_xor_dump(u_long base) 1817186909Sraj{ 1818186909Sraj int i, j; 1819186909Sraj int e = 1; 1820186909Sraj 1821209131Sraj if (pm_is_disabled(CPU_PM_CTRL_XOR)) 1822209131Sraj return; 1823209131Sraj 1824186909Sraj for (j = 0; j < xor_max_eng(); j++, e--) { 1825186909Sraj for (i = 0; i < MV_WIN_XOR_MAX; i++) { 1826186909Sraj printf("XOR window#%d: b 0x%08x, s 0x%08x", i, 1827209131Sraj win_xor_br_read(base, i, e), win_xor_sz_read(base, i, e)); 1828186909Sraj 1829186909Sraj if (win_xor_can_remap(i)) 1830209131Sraj printf(", ha 0x%08x", win_xor_har_read(base, i, e)); 1831186909Sraj 1832186909Sraj printf("\n"); 1833186909Sraj } 1834186909Sraj for (i = 0; i < MV_XOR_CHAN_MAX; i++) 1835186909Sraj printf("XOR control#%d: 0x%08x\n", i, 1836209131Sraj win_xor_ctrl_read(base, i, e)); 1837186909Sraj } 1838186909Sraj} 1839186909Sraj 1840186909Sraj#else 1841186909Sraj/* Provide dummy functions to satisfy the build for SoCs not equipped with XOR */ 1842209131Srajstatic int 1843186909Srajdecode_win_xor_valid(void) 1844186909Sraj{ 1845186909Sraj 1846186909Sraj return (1); 1847186909Sraj} 1848186909Sraj 1849209131Srajstatic void 1850209131Srajdecode_win_xor_setup(u_long base) 1851186909Sraj{ 1852186909Sraj} 1853186909Sraj 1854209131Srajstatic void 1855209131Srajdecode_win_xor_dump(u_long base) 1856186909Sraj{ 1857186909Sraj} 1858186909Sraj#endif 1859186909Sraj 1860186909Sraj/************************************************************************** 1861186909Sraj * SATA windows routines 1862186909Sraj **************************************************************************/ 1863186909Srajstatic void 1864209131Srajdecode_win_sata_setup(u_long base) 1865186909Sraj{ 1866186909Sraj uint32_t cr, br; 1867186909Sraj int i, j; 1868186909Sraj 1869196532Sraj if (pm_is_disabled(CPU_PM_CTRL_SATA)) 1870196532Sraj return; 1871196532Sraj 1872186909Sraj for (i = 0; i < MV_WIN_SATA_MAX; i++) { 1873209131Sraj win_sata_cr_write(base, i, 0); 1874209131Sraj win_sata_br_write(base, i, 0); 1875186909Sraj } 1876186909Sraj 1877186909Sraj for (i = 0; i < MV_WIN_DDR_MAX; i++) 1878186909Sraj if (ddr_is_active(i)) { 1879186909Sraj cr = ((ddr_size(i) - 1) & 0xffff0000) | 1880186909Sraj (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1; 1881186909Sraj br = ddr_base(i); 1882186909Sraj 1883186909Sraj /* Use the first available SATA window */ 1884186909Sraj for (j = 0; j < MV_WIN_SATA_MAX; j++) { 1885209131Sraj if ((win_sata_cr_read(base, j) & 1) != 0) 1886186909Sraj continue; 1887186909Sraj 1888209131Sraj win_sata_br_write(base, j, br); 1889209131Sraj win_sata_cr_write(base, j, cr); 1890186909Sraj break; 1891186909Sraj } 1892186909Sraj } 1893186909Sraj} 1894186909Sraj 1895186909Srajstatic int 1896186909Srajdecode_win_sata_valid(void) 1897186909Sraj{ 1898186909Sraj uint32_t dev, rev; 1899186909Sraj 1900186909Sraj soc_id(&dev, &rev); 1901186909Sraj if (dev == MV_DEV_88F5281) 1902186909Sraj return (1); 1903186909Sraj 1904186909Sraj return (decode_win_can_cover_ddr(MV_WIN_SATA_MAX)); 1905186909Sraj} 1906209131Sraj 1907209131Sraj/************************************************************************** 1908209131Sraj * FDT parsing routines. 1909209131Sraj **************************************************************************/ 1910209131Sraj 1911209131Srajstatic int 1912209131Srajfdt_get_ranges(const char *nodename, void *buf, int size, int *tuples, 1913209131Sraj int *tuplesize) 1914209131Sraj{ 1915209131Sraj phandle_t node; 1916209131Sraj pcell_t addr_cells, par_addr_cells, size_cells; 1917209131Sraj int len, tuple_size, tuples_count; 1918209131Sraj 1919209131Sraj node = OF_finddevice(nodename); 1920228201Sjchandra if (node == -1) 1921209131Sraj return (EINVAL); 1922209131Sraj 1923209131Sraj if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0) 1924209131Sraj return (ENXIO); 1925209131Sraj 1926209131Sraj par_addr_cells = fdt_parent_addr_cells(node); 1927209131Sraj if (par_addr_cells > 2) 1928209131Sraj return (ERANGE); 1929209131Sraj 1930209131Sraj tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells + 1931209131Sraj size_cells); 1932209131Sraj 1933209131Sraj /* Note the OF_getprop_alloc() cannot be used at this early stage. */ 1934209131Sraj len = OF_getprop(node, "ranges", buf, size); 1935209131Sraj 1936209131Sraj /* 1937209131Sraj * XXX this does not handle the empty 'ranges;' case, which is 1938209131Sraj * legitimate and should be allowed. 1939209131Sraj */ 1940209131Sraj tuples_count = len / tuple_size; 1941209131Sraj if (tuples_count <= 0) 1942209131Sraj return (ERANGE); 1943209131Sraj 1944209131Sraj if (fdt_ranges_verify(buf, tuples_count, par_addr_cells, 1945209131Sraj addr_cells, size_cells) != 0) 1946209131Sraj return (ERANGE); 1947209131Sraj 1948209131Sraj *tuples = tuples_count; 1949209131Sraj *tuplesize = tuple_size; 1950209131Sraj return (0); 1951209131Sraj} 1952209131Sraj 1953209131Srajstatic int 1954209131Srajwin_cpu_from_dt(void) 1955209131Sraj{ 1956209131Sraj pcell_t ranges[48]; 1957209131Sraj phandle_t node; 1958209131Sraj int i, entry_size, err, t, tuple_size, tuples; 1959250291Sgber u_long sram_base, sram_size; 1960209131Sraj 1961250291Sgber t = 0; 1962209131Sraj /* Retrieve 'ranges' property of '/localbus' node. */ 1963209131Sraj if ((err = fdt_get_ranges("/localbus", ranges, sizeof(ranges), 1964250291Sgber &tuples, &tuple_size)) == 0) { 1965250291Sgber /* 1966250291Sgber * Fill CPU decode windows table. 1967250291Sgber */ 1968250291Sgber bzero((void *)&cpu_win_tbl, sizeof(cpu_win_tbl)); 1969209131Sraj 1970250291Sgber entry_size = tuple_size / sizeof(pcell_t); 1971250291Sgber cpu_wins_no = tuples; 1972209131Sraj 1973250291Sgber for (i = 0, t = 0; t < tuples; i += entry_size, t++) { 1974250291Sgber cpu_win_tbl[t].target = 1; 1975250291Sgber cpu_win_tbl[t].attr = fdt32_to_cpu(ranges[i + 1]); 1976250291Sgber cpu_win_tbl[t].base = fdt32_to_cpu(ranges[i + 2]); 1977250291Sgber cpu_win_tbl[t].size = fdt32_to_cpu(ranges[i + 3]); 1978250291Sgber cpu_win_tbl[t].remap = ~0; 1979250291Sgber debugf("target = 0x%0x attr = 0x%0x base = 0x%0x " 1980250291Sgber "size = 0x%0x remap = 0x%0x\n", 1981250291Sgber cpu_win_tbl[t].target, 1982250291Sgber cpu_win_tbl[t].attr, cpu_win_tbl[t].base, 1983250291Sgber cpu_win_tbl[t].size, cpu_win_tbl[t].remap); 1984250291Sgber } 1985209131Sraj } 1986209131Sraj 1987209131Sraj /* 1988209131Sraj * Retrieve CESA SRAM data. 1989209131Sraj */ 1990228201Sjchandra if ((node = OF_finddevice("sram")) != -1) 1991209131Sraj if (fdt_is_compatible(node, "mrvl,cesa-sram")) 1992209131Sraj goto moveon; 1993209131Sraj 1994250291Sgber if ((node = OF_finddevice("/")) == 0) 1995209131Sraj return (ENXIO); 1996209131Sraj 1997209131Sraj if ((node = fdt_find_compatible(node, "mrvl,cesa-sram", 0)) == 0) 1998209131Sraj /* SRAM block is not always present. */ 1999209131Sraj return (0); 2000209131Srajmoveon: 2001209131Sraj sram_base = sram_size = 0; 2002209131Sraj if (fdt_regsize(node, &sram_base, &sram_size) != 0) 2003209131Sraj return (EINVAL); 2004209131Sraj 2005250291Sgber cpu_win_tbl[t].target = MV_WIN_CESA_TARGET; 2006250291Sgber cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR(1); 2007209131Sraj cpu_win_tbl[t].base = sram_base; 2008209131Sraj cpu_win_tbl[t].size = sram_size; 2009239277Sgonzo cpu_win_tbl[t].remap = ~0; 2010250291Sgber cpu_wins_no++; 2011209131Sraj debugf("sram: base = 0x%0lx size = 0x%0lx\n", sram_base, sram_size); 2012209131Sraj 2013209131Sraj return (0); 2014209131Sraj} 2015209131Sraj 2016209131Srajstatic int 2017209131Srajfdt_win_setup(void) 2018209131Sraj{ 2019209131Sraj phandle_t node, child; 2020209131Sraj struct soc_node_spec *soc_node; 2021209131Sraj u_long size, base; 2022209131Sraj int err, i; 2023209131Sraj 2024209131Sraj node = OF_finddevice("/"); 2025228201Sjchandra if (node == -1) 2026209131Sraj panic("fdt_win_setup: no root node"); 2027209131Sraj 2028209131Sraj /* 2029239277Sgonzo * Traverse through all children of root and simple-bus nodes. 2030239277Sgonzo * For each found device retrieve decode windows data (if applicable). 2031209131Sraj */ 2032239277Sgonzo child = OF_child(node); 2033239277Sgonzo while (child != 0) { 2034209131Sraj for (i = 0; soc_nodes[i].compat != NULL; i++) { 2035209131Sraj 2036209131Sraj soc_node = &soc_nodes[i]; 2037209131Sraj 2038209131Sraj if (!fdt_is_compatible(child, soc_node->compat)) 2039209131Sraj continue; 2040209131Sraj 2041209131Sraj err = fdt_regsize(child, &base, &size); 2042209131Sraj if (err != 0) 2043209131Sraj return (err); 2044209131Sraj 2045239277Sgonzo base = (base & 0x000fffff) | fdt_immr_va; 2046209131Sraj if (soc_node->decode_handler != NULL) 2047209131Sraj soc_node->decode_handler(base); 2048209131Sraj else 2049209131Sraj return (ENXIO); 2050209131Sraj 2051209131Sraj if (MV_DUMP_WIN && (soc_node->dump_handler != NULL)) 2052209131Sraj soc_node->dump_handler(base); 2053209131Sraj } 2054209131Sraj 2055239277Sgonzo /* 2056239277Sgonzo * Once done with root-level children let's move down to 2057239277Sgonzo * simple-bus and its children. 2058239277Sgonzo */ 2059239277Sgonzo child = OF_peer(child); 2060239277Sgonzo if ((child == 0) && (node == OF_finddevice("/"))) { 2061239277Sgonzo node = fdt_find_compatible(node, "simple-bus", 1); 2062239277Sgonzo if (node == 0) 2063239277Sgonzo return (ENXIO); 2064239277Sgonzo child = OF_child(node); 2065239277Sgonzo } 2066239277Sgonzo } 2067239277Sgonzo 2068209131Sraj return (0); 2069209131Sraj} 2070210246Sraj 2071210246Srajstatic void 2072210246Srajfdt_fixup_busfreq(phandle_t root) 2073210246Sraj{ 2074210246Sraj phandle_t sb; 2075210246Sraj pcell_t freq; 2076210246Sraj 2077240488Sgber freq = cpu_to_fdt32(get_tclk()); 2078240488Sgber 2079210246Sraj /* 2080240488Sgber * Fix bus speed in cpu node 2081240488Sgber */ 2082240488Sgber if ((sb = OF_finddevice("cpu")) != 0) 2083240488Sgber if (fdt_is_compatible_strict(sb, "ARM,88VS584")) 2084240488Sgber OF_setprop(sb, "bus-frequency", (void *)&freq, 2085240488Sgber sizeof(freq)); 2086240488Sgber 2087240488Sgber /* 2088210246Sraj * This fixup sets the simple-bus bus-frequency property. 2089210246Sraj */ 2090240488Sgber if ((sb = fdt_find_compatible(root, "simple-bus", 1)) != 0) 2091240488Sgber OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq)); 2092210246Sraj} 2093210246Sraj 2094257279Szbbstatic void 2095257279Szbbfdt_fixup_ranges(phandle_t root) 2096257279Szbb{ 2097257279Szbb phandle_t node; 2098257279Szbb pcell_t par_addr_cells, addr_cells, size_cells; 2099257279Szbb pcell_t ranges[3], reg[2], *rangesptr; 2100257279Szbb int len, tuple_size, tuples_count; 2101257279Szbb uint32_t base; 2102257279Szbb 2103257279Szbb /* Fix-up SoC ranges according to real fdt_immr_pa */ 2104257279Szbb if ((node = fdt_find_compatible(root, "simple-bus", 1)) != 0) { 2105257279Szbb if (fdt_addrsize_cells(node, &addr_cells, &size_cells) == 0 && 2106257279Szbb (par_addr_cells = fdt_parent_addr_cells(node) <= 2)) { 2107257279Szbb tuple_size = sizeof(pcell_t) * (par_addr_cells + 2108257279Szbb addr_cells + size_cells); 2109257279Szbb len = OF_getprop(node, "ranges", ranges, 2110257279Szbb sizeof(ranges)); 2111257279Szbb tuples_count = len / tuple_size; 2112257279Szbb /* Unexpected settings are not supported */ 2113257279Szbb if (tuples_count != 1) 2114257279Szbb goto fixup_failed; 2115257279Szbb 2116257279Szbb rangesptr = &ranges[0]; 2117257279Szbb rangesptr += par_addr_cells; 2118257279Szbb base = fdt_data_get((void *)rangesptr, addr_cells); 2119257279Szbb *rangesptr = cpu_to_fdt32(fdt_immr_pa); 2120257279Szbb if (OF_setprop(node, "ranges", (void *)&ranges[0], 2121257279Szbb sizeof(ranges)) < 0) 2122257279Szbb goto fixup_failed; 2123257279Szbb } 2124257279Szbb } 2125257279Szbb 2126257279Szbb /* Fix-up PCIe reg according to real PCIe registers' PA */ 2127257279Szbb if ((node = fdt_find_compatible(root, "mrvl,pcie", 1)) != 0) { 2128257279Szbb if (fdt_addrsize_cells(OF_parent(node), &par_addr_cells, 2129257279Szbb &size_cells) == 0) { 2130257279Szbb tuple_size = sizeof(pcell_t) * (par_addr_cells + 2131257279Szbb size_cells); 2132257279Szbb len = OF_getprop(node, "reg", reg, sizeof(reg)); 2133257279Szbb tuples_count = len / tuple_size; 2134257279Szbb /* Unexpected settings are not supported */ 2135257279Szbb if (tuples_count != 1) 2136257279Szbb goto fixup_failed; 2137257279Szbb 2138257279Szbb base = fdt_data_get((void *)®[0], par_addr_cells); 2139257279Szbb base &= ~0xFF000000; 2140257279Szbb base |= fdt_immr_pa; 2141257279Szbb reg[0] = cpu_to_fdt32(base); 2142257279Szbb if (OF_setprop(node, "reg", (void *)®[0], 2143257279Szbb sizeof(reg)) < 0) 2144257279Szbb goto fixup_failed; 2145257279Szbb } 2146257279Szbb } 2147257279Szbb /* Fix-up succeeded. May return and continue */ 2148257279Szbb return; 2149257279Szbb 2150257279Szbbfixup_failed: 2151257279Szbb while (1) { 2152257279Szbb /* 2153257279Szbb * In case of any error while fixing ranges just hang. 2154257279Szbb * 1. No message can be displayed yet since console 2155257279Szbb * is not initialized. 2156257279Szbb * 2. Going further will cause failure on bus_space_map() 2157257279Szbb * relying on the wrong ranges or data abort when 2158257279Szbb * accessing PCIe registers. 2159257279Szbb */ 2160257279Szbb } 2161257279Szbb} 2162257279Szbb 2163210246Srajstruct fdt_fixup_entry fdt_fixup_table[] = { 2164210246Sraj { "mrvl,DB-88F6281", &fdt_fixup_busfreq }, 2165240488Sgber { "mrvl,DB-78460", &fdt_fixup_busfreq }, 2166257279Szbb { "mrvl,DB-78460", &fdt_fixup_ranges }, 2167210246Sraj { NULL, NULL } 2168210246Sraj}; 2169210246Sraj 2170210246Srajstatic int 2171210246Srajfdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, 2172210246Sraj int *pol) 2173210246Sraj{ 2174210246Sraj 2175239277Sgonzo if (!fdt_is_compatible(node, "mrvl,pic") && 2176239277Sgonzo !fdt_is_compatible(node, "mrvl,mpic")) 2177210246Sraj return (ENXIO); 2178210246Sraj 2179210246Sraj *interrupt = fdt32_to_cpu(intr[0]); 2180210246Sraj *trig = INTR_TRIGGER_CONFORM; 2181210246Sraj *pol = INTR_POLARITY_CONFORM; 2182210246Sraj 2183210246Sraj return (0); 2184210246Sraj} 2185210246Sraj 2186210246Srajfdt_pic_decode_t fdt_pic_table[] = { 2187210246Sraj &fdt_pic_decode_ic, 2188210246Sraj NULL 2189210246Sraj}; 2190240488Sgber 2191240488Sgberuint64_t 2192240488Sgberget_sar_value(void) 2193240488Sgber{ 2194240488Sgber uint32_t sar_low, sar_high; 2195240488Sgber 2196240488Sgber#if defined(SOC_MV_ARMADAXP) 2197240488Sgber sar_high = bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE, 2198240488Sgber SAMPLE_AT_RESET_HI); 2199240488Sgber sar_low = bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE, 2200240488Sgber SAMPLE_AT_RESET_LO); 2201240488Sgber#else 2202240488Sgber /* 2203240488Sgber * TODO: Add getting proper values for other SoC configurations 2204240488Sgber */ 2205240488Sgber sar_high = 0; 2206240488Sgber sar_low = 0; 2207240488Sgber#endif 2208240488Sgber 2209240488Sgber return (((uint64_t)sar_high << 32) | sar_low); 2210240488Sgber} 2211