mv_common.c revision 196532
142680Smsmith/*- 242680Smsmith * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. 342680Smsmith * All rights reserved. 442680Smsmith * 542680Smsmith * Developed by Semihalf. 642680Smsmith * 742680Smsmith * Redistribution and use in source and binary forms, with or without 842680Smsmith * modification, are permitted provided that the following conditions 942680Smsmith * are met: 1042680Smsmith * 1. Redistributions of source code must retain the above copyright 1142680Smsmith * notice, this list of conditions and the following disclaimer. 1242680Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1342680Smsmith * notice, this list of conditions and the following disclaimer in the 1442680Smsmith * documentation and/or other materials provided with the distribution. 1542680Smsmith * 3. Neither the name of MARVELL nor the names of contributors 1642680Smsmith * may be used to endorse or promote products derived from this software 1742680Smsmith * without specific prior written permission. 1842680Smsmith * 1942680Smsmith * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2042680Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2142680Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2242680Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 2342680Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2442680Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2542680Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2642680Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2742680Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2842680Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2942680Smsmith * SUCH DAMAGE. 3042680Smsmith */ 3142680Smsmith 3242680Smsmith#include <sys/cdefs.h> 3352757Sphk__FBSDID("$FreeBSD: head/sys/arm/mv/common.c 196532 2009-08-25 09:35:50Z raj $"); 3452757Sphk 3542680Smsmith#include <sys/param.h> 3642680Smsmith#include <sys/systm.h> 37116182Sobrien#include <sys/bus.h> 38116182Sobrien#include <sys/kernel.h> 39116182Sobrien 4042680Smsmith#include <machine/bus.h> 4142680Smsmith 4252843Sphk#include <arm/mv/mvreg.h> 43114216Skan#include <arm/mv/mvvar.h> 4442680Smsmith#include <arm/mv/mvwin.h> 4542680Smsmith 4642680Smsmithstatic int win_eth_can_remap(int i); 4742680Smsmith 4842680Smsmithstatic int decode_win_cpu_valid(void); 4942680Smsmithstatic int decode_win_usb_valid(void); 5042680Smsmithstatic int decode_win_eth_valid(void); 5142680Smsmithstatic int decode_win_pcie_valid(void); 5242680Smsmithstatic int decode_win_sata_valid(void); 5342680Smsmithstatic int decode_win_cesa_valid(void); 5442680Smsmith 5542680Smsmithstatic void decode_win_cpu_setup(void); 5642680Smsmithstatic void decode_win_usb_setup(void); 5742680Smsmithstatic void decode_win_eth_setup(uint32_t base); 5842680Smsmithstatic void decode_win_pcie_setup(uint32_t base); 5942680Smsmithstatic void decode_win_sata_setup(void); 6042680Smsmithstatic void decode_win_cesa_setup(void); 6142680Smsmith 62230587Skenstatic void decode_win_cesa_dump(void); 6342680Smsmithstatic void decode_win_usb_dump(void); 6442680Smsmith 6542680Smsmithstatic uint32_t used_cpu_wins; 6642680Smsmith 6742680Smsmithstatic __inline int 6842680Smsmithpm_is_disabled(uint32_t mask) 6942680Smsmith{ 7042680Smsmith 7142680Smsmith return (soc_power_ctrl_get(mask) == mask ? 0 : 1); 7242680Smsmith} 7342680Smsmith 7442680Smsmithstatic __inline uint32_t 7542680Smsmithobio_get_pm_mask(uint32_t base) 7642680Smsmith{ 7742680Smsmith struct obio_device *od; 7842680Smsmith 7942680Smsmith for (od = obio_devices; od->od_name != NULL; od++) 8042680Smsmith if (od->od_base == base) 8142680Smsmith return (od->od_pwr_mask); 8242680Smsmith 8342680Smsmith return (CPU_PM_CTRL_NONE); 8442680Smsmith} 8553648Sarchie 8642680Smsmith/* 8743300Sdillon * Disable device using power management register. 8842680Smsmith * 1 - Device Power On 8942680Smsmith * 0 - Device Power Off 9042680Smsmith * Mask can be set in loader. 9142680Smsmith * EXAMPLE: 9242680Smsmith * loader> set hw.pm-disable-mask=0x2 9342680Smsmith * 9442680Smsmith * Common mask: 9542680Smsmith * |-------------------------------| 9642680Smsmith * | Device | Kirkwood | Discovery | 9742680Smsmith * |-------------------------------| 9842680Smsmith * | USB0 | 0x00008 | 0x020000 | 9942680Smsmith * |-------------------------------| 10042680Smsmith * | USB1 | - | 0x040000 | 10142680Smsmith * |-------------------------------| 10242680Smsmith * | USB2 | - | 0x080000 | 10342680Smsmith * |-------------------------------| 10442680Smsmith * | GE0 | 0x00001 | 0x000002 | 10543300Sdillon * |-------------------------------| 10642680Smsmith * | GE1 | - | 0x000004 | 10742680Smsmith * |-------------------------------| 10842680Smsmith * | IDMA | - | 0x100000 | 10942680Smsmith * |-------------------------------| 11042680Smsmith * | XOR | 0x10000 | 0x200000 | 11142680Smsmith * |-------------------------------| 11242680Smsmith * | CESA | 0x20000 | 0x400000 | 11342680Smsmith * |-------------------------------| 11442680Smsmith * | SATA | 0x04000 | 0x004000 | 11542680Smsmith * --------------------------------| 11642680Smsmith * This feature can be used only on Kirkwood and Discovery 11742680Smsmith * machines. 11842680Smsmith */ 11942680Smsmithstatic __inline void 12042680Smsmithpm_disable_device(int mask) 12142680Smsmith{ 12242680Smsmith#ifdef DIAGNOSTIC 12342680Smsmith uint32_t reg; 12442680Smsmith 12542680Smsmith reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL); 12642680Smsmith printf("Power Management Register: 0%x\n", reg); 12742680Smsmith 12842680Smsmith reg &= ~mask; 12942680Smsmith soc_power_ctrl_set(reg); 13042680Smsmith printf("Device %x is disabled\n", mask); 13142680Smsmith 13242680Smsmith reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL); 13342680Smsmith printf("Power Management Register: 0%x\n", reg); 13442680Smsmith#endif 13542680Smsmith} 13642680Smsmith 13742680Smsmithuint32_t 13842680Smsmithread_cpu_ctrl(uint32_t reg) 13942680Smsmith{ 14042680Smsmith 14142680Smsmith return (bus_space_read_4(obio_tag, MV_CPU_CONTROL_BASE, reg)); 14242680Smsmith} 14342680Smsmith 14442680Smsmithvoid 14542680Smsmithwrite_cpu_ctrl(uint32_t reg, uint32_t val) 14642680Smsmith{ 14742680Smsmith 14842680Smsmith bus_space_write_4(obio_tag, MV_CPU_CONTROL_BASE, reg, val); 14942680Smsmith} 15042680Smsmith 15142680Smsmithvoid 15242680Smsmithcpu_reset(void) 15342680Smsmith{ 15442680Smsmith 15542680Smsmith write_cpu_ctrl(RSTOUTn_MASK, SOFT_RST_OUT_EN); 15642680Smsmith write_cpu_ctrl(SYSTEM_SOFT_RESET, SYS_SOFT_RST); 15742680Smsmith while (1); 15842680Smsmith} 15942680Smsmith 16042680Smsmithuint32_t 16142680Smsmithcpu_extra_feat(void) 16242680Smsmith{ 16342680Smsmith uint32_t dev, rev; 164230587Sken uint32_t ef = 0; 165230587Sken 166230587Sken soc_id(&dev, &rev); 167230587Sken if (dev == MV_DEV_88F6281 || dev == MV_DEV_MV78100_Z0 || 168230587Sken dev == MV_DEV_MV78100) 169230587Sken __asm __volatile("mrc p15, 1, %0, c15, c1, 0" : "=r" (ef)); 17042680Smsmith else if (dev == MV_DEV_88F5182 || dev == MV_DEV_88F5281) 17142680Smsmith __asm __volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (ef)); 17242680Smsmith else if (bootverbose) 17342680Smsmith printf("This ARM Core does not support any extra features\n"); 17442680Smsmith 175230587Sken return (ef); 176230587Sken} 177230587Sken 178230587Sken/* 179230587Sken * Get the power status of device. This feature is only supported on 180230587Sken * Kirkwood and Discovery SoCs. 18142680Smsmith */ 18242680Smsmithuint32_t 18342680Smsmithsoc_power_ctrl_get(uint32_t mask) 18442680Smsmith{ 18542680Smsmith 18642680Smsmith#ifndef SOC_MV_ORION 18742680Smsmith if (mask != CPU_PM_CTRL_NONE) 18842680Smsmith mask &= read_cpu_ctrl(CPU_PM_CTRL); 18942680Smsmith 19042680Smsmith return (mask); 19142680Smsmith#else 19242680Smsmith return (mask); 19342680Smsmith#endif 19442680Smsmith} 19542680Smsmith 19642680Smsmith/* 19742680Smsmith * Set the power status of device. This feature is only supported on 19842680Smsmith * Kirkwood and Discovery SoCs. 19942680Smsmith */ 20042680Smsmithvoid 20142680Smsmithsoc_power_ctrl_set(uint32_t mask) 20242680Smsmith{ 20342680Smsmith 20442680Smsmith#ifndef SOC_MV_ORION 20542680Smsmith if (mask != CPU_PM_CTRL_NONE) 20642680Smsmith write_cpu_ctrl(CPU_PM_CTRL, mask); 20742680Smsmith#endif 20842680Smsmith} 20942680Smsmith 21042680Smsmithvoid 21142680Smsmithsoc_id(uint32_t *dev, uint32_t *rev) 21242680Smsmith{ 21342680Smsmith 21442680Smsmith /* 21542680Smsmith * Notice: system identifiers are available in the registers range of 21642680Smsmith * PCIE controller, so using this function is only allowed (and 21742680Smsmith * possible) after the internal registers range has been mapped in via 21842680Smsmith * pmap_devmap_bootstrap(). 21942680Smsmith */ 22042680Smsmith *dev = bus_space_read_4(obio_tag, MV_PCIE_BASE, 0) >> 16; 22142680Smsmith *rev = bus_space_read_4(obio_tag, MV_PCIE_BASE, 8) & 0xff; 22242680Smsmith} 22342680Smsmith 22442680Smsmithvoid 22542680Smsmithsoc_identify(void) 22642680Smsmith{ 22742680Smsmith uint32_t d, r; 22842680Smsmith const char *dev; 22942680Smsmith const char *rev; 23042680Smsmith 23142680Smsmith soc_id(&d, &r); 23242680Smsmith 23342680Smsmith printf("SOC: "); 23442680Smsmith if (bootverbose) 23542680Smsmith printf("(0x%4x:0x%02x) ", d, r); 23642680Smsmith 23742680Smsmith rev = ""; 23842680Smsmith switch (d) { 23942680Smsmith case MV_DEV_88F5181: 24042680Smsmith dev = "Marvell 88F5181"; 24142680Smsmith if (r == 3) 24242680Smsmith rev = "B1"; 24342680Smsmith break; 24442680Smsmith case MV_DEV_88F5182: 24542680Smsmith dev = "Marvell 88F5182"; 24642680Smsmith if (r == 2) 24742680Smsmith rev = "A2"; 24842680Smsmith break; 249230587Sken case MV_DEV_88F5281: 250230587Sken dev = "Marvell 88F5281"; 251230587Sken if (r == 4) 25242680Smsmith rev = "D0"; 25342680Smsmith else if (r == 5) 25442680Smsmith rev = "D1"; 25542680Smsmith else if (r == 6) 25642680Smsmith rev = "D2"; 25742680Smsmith break; 25842680Smsmith case MV_DEV_88F6281: 25942680Smsmith dev = "Marvell 88F6281"; 26042680Smsmith if (r == 0) 26142680Smsmith rev = "Z0"; 26242680Smsmith else if (r == 2) 26342680Smsmith rev = "A0"; 26442680Smsmith break; 26542680Smsmith case MV_DEV_MV78100_Z0: 26642680Smsmith dev = "Marvell MV78100 Z0"; 26742680Smsmith break; 26842680Smsmith case MV_DEV_MV78100: 26942680Smsmith dev = "Marvell MV78100"; 27042680Smsmith break; 27142680Smsmith default: 27242680Smsmith dev = "UNKNOWN"; 27342680Smsmith break; 27442680Smsmith } 27542680Smsmith 27642680Smsmith printf("%s", dev); 27742680Smsmith if (*rev != '\0') 27842680Smsmith printf(" rev %s", rev); 27942680Smsmith printf(", TClock %dMHz\n", get_tclk() / 1000 / 1000); 28042680Smsmith 28142680Smsmith /* TODO add info on currently set endianess */ 28242680Smsmith} 28342680Smsmith 28442680Smsmithint 28542680Smsmithsoc_decode_win(void) 28642680Smsmith{ 28742680Smsmith uint32_t dev, rev; 28842680Smsmith int mask; 28942680Smsmith 29042680Smsmith mask = 0; 29142680Smsmith TUNABLE_INT_FETCH("hw.pm-disable-mask", &mask); 29242680Smsmith 29342680Smsmith if (mask != 0) 29442680Smsmith pm_disable_device(mask); 29542680Smsmith 29642680Smsmith /* Retrieve our ID: some windows facilities vary between SoC models */ 29742680Smsmith soc_id(&dev, &rev); 29842680Smsmith 29942680Smsmith if (decode_win_cpu_valid() != 1 || decode_win_usb_valid() != 1 || 30042680Smsmith decode_win_eth_valid() != 1 || decode_win_idma_valid() != 1 || 30142680Smsmith decode_win_pcie_valid() != 1 || decode_win_sata_valid() != 1 || 30242680Smsmith decode_win_cesa_valid() != 1) 30342680Smsmith return(-1); 30442680Smsmith 305104363Sphk decode_win_cpu_setup(); 30642680Smsmith decode_win_usb_setup(); 30742680Smsmith decode_win_eth_setup(MV_ETH0_BASE); 30842680Smsmith if (dev == MV_DEV_MV78100 || dev == MV_DEV_MV78100_Z0) 30942680Smsmith decode_win_eth_setup(MV_ETH1_BASE); 31042680Smsmith if (dev == MV_DEV_88F6281 || dev == MV_DEV_MV78100 || 31142680Smsmith dev == MV_DEV_MV78100_Z0) 31242680Smsmith decode_win_cesa_setup(); 31342680Smsmith 31442680Smsmith decode_win_idma_setup(); 31542680Smsmith decode_win_xor_setup(); 31642680Smsmith 31742680Smsmith if (dev == MV_DEV_MV78100 || dev == MV_DEV_MV78100_Z0) { 31842680Smsmith decode_win_pcie_setup(MV_PCIE00_BASE); 31942680Smsmith decode_win_pcie_setup(MV_PCIE01_BASE); 32042680Smsmith decode_win_pcie_setup(MV_PCIE02_BASE); 32142680Smsmith decode_win_pcie_setup(MV_PCIE03_BASE); 32242680Smsmith decode_win_pcie_setup(MV_PCIE10_BASE); 32342680Smsmith decode_win_pcie_setup(MV_PCIE11_BASE); 32442680Smsmith decode_win_pcie_setup(MV_PCIE12_BASE); 32542680Smsmith decode_win_pcie_setup(MV_PCIE13_BASE); 32642680Smsmith } else 32742680Smsmith decode_win_pcie_setup(MV_PCIE_BASE); 32842680Smsmith 32942680Smsmith if (dev != MV_DEV_88F5281) 33042680Smsmith decode_win_sata_setup(); 33144016Sdillon 33242680Smsmith return (0); 33342680Smsmith} 33442680Smsmith 33542680Smsmith/************************************************************************** 33642680Smsmith * Decode windows registers accessors 33742680Smsmith **************************************************************************/ 33842680SmsmithWIN_REG_IDX_RD(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE) 33942680SmsmithWIN_REG_IDX_RD(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) 34042680SmsmithWIN_REG_IDX_RD(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) 34142680SmsmithWIN_REG_IDX_RD(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE) 34242680SmsmithWIN_REG_IDX_WR(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE) 34342680SmsmithWIN_REG_IDX_WR(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) 34442680SmsmithWIN_REG_IDX_WR(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) 34544016SdillonWIN_REG_IDX_WR(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE) 34642680Smsmith 34742680SmsmithWIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE) 34842680SmsmithWIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE) 34942680Smsmith 35042680SmsmithWIN_REG_IDX_RD2(win_usb, cr, MV_WIN_USB_CTRL, MV_USB_AWR_BASE) 35142680SmsmithWIN_REG_IDX_RD2(win_usb, br, MV_WIN_USB_BASE, MV_USB_AWR_BASE) 35242680SmsmithWIN_REG_IDX_WR2(win_usb, cr, MV_WIN_USB_CTRL, MV_USB_AWR_BASE) 35342680SmsmithWIN_REG_IDX_WR2(win_usb, br, MV_WIN_USB_BASE, MV_USB_AWR_BASE) 35442680Smsmith 35542680SmsmithWIN_REG_IDX_RD(win_cesa, cr, MV_WIN_CESA_CTRL, MV_CESA_BASE) 35642680SmsmithWIN_REG_IDX_RD(win_cesa, br, MV_WIN_CESA_BASE, MV_CESA_BASE) 35742680SmsmithWIN_REG_IDX_WR(win_cesa, cr, MV_WIN_CESA_CTRL, MV_CESA_BASE) 35842680SmsmithWIN_REG_IDX_WR(win_cesa, br, MV_WIN_CESA_BASE, MV_CESA_BASE) 35942680Smsmith 36042680SmsmithWIN_REG_BASE_IDX_RD(win_eth, br, MV_WIN_ETH_BASE) 36142680SmsmithWIN_REG_BASE_IDX_RD(win_eth, sz, MV_WIN_ETH_SIZE) 36242680SmsmithWIN_REG_BASE_IDX_RD(win_eth, har, MV_WIN_ETH_REMAP) 36342680SmsmithWIN_REG_BASE_IDX_WR(win_eth, br, MV_WIN_ETH_BASE) 36442680SmsmithWIN_REG_BASE_IDX_WR(win_eth, sz, MV_WIN_ETH_SIZE) 36542680SmsmithWIN_REG_BASE_IDX_WR(win_eth, har, MV_WIN_ETH_REMAP) 36642680Smsmith 36742680SmsmithWIN_REG_IDX_RD2(win_xor, br, MV_WIN_XOR_BASE, MV_XOR_BASE) 36842680SmsmithWIN_REG_IDX_RD2(win_xor, sz, MV_WIN_XOR_SIZE, MV_XOR_BASE) 36942680SmsmithWIN_REG_IDX_RD2(win_xor, har, MV_WIN_XOR_REMAP, MV_XOR_BASE) 37042680SmsmithWIN_REG_IDX_RD2(win_xor, ctrl, MV_WIN_XOR_CTRL, MV_XOR_BASE) 37142680SmsmithWIN_REG_IDX_WR2(win_xor, br, MV_WIN_XOR_BASE, MV_XOR_BASE) 37242680SmsmithWIN_REG_IDX_WR2(win_xor, sz, MV_WIN_XOR_SIZE, MV_XOR_BASE) 37342680SmsmithWIN_REG_IDX_WR2(win_xor, har, MV_WIN_XOR_REMAP, MV_XOR_BASE) 37442680SmsmithWIN_REG_IDX_WR2(win_xor, ctrl, MV_WIN_XOR_CTRL, MV_XOR_BASE) 37542680Smsmith 37642680SmsmithWIN_REG_BASE_RD(win_eth, bare, 0x290) 37742680SmsmithWIN_REG_BASE_RD(win_eth, epap, 0x294) 37842680SmsmithWIN_REG_BASE_WR(win_eth, bare, 0x290) 37942680SmsmithWIN_REG_BASE_WR(win_eth, epap, 0x294) 38042680Smsmith 38142680SmsmithWIN_REG_BASE_IDX_RD(win_pcie, cr, MV_WIN_PCIE_CTRL); 38242680SmsmithWIN_REG_BASE_IDX_RD(win_pcie, br, MV_WIN_PCIE_BASE); 38342680SmsmithWIN_REG_BASE_IDX_RD(win_pcie, remap, MV_WIN_PCIE_REMAP); 38442680SmsmithWIN_REG_BASE_IDX_WR(win_pcie, cr, MV_WIN_PCIE_CTRL); 38542680SmsmithWIN_REG_BASE_IDX_WR(win_pcie, br, MV_WIN_PCIE_BASE); 38642680SmsmithWIN_REG_BASE_IDX_WR(win_pcie, remap, MV_WIN_PCIE_REMAP); 38742680SmsmithWIN_REG_BASE_IDX_WR(pcie, bar, MV_PCIE_BAR); 38842680Smsmith 38942680SmsmithWIN_REG_IDX_RD(win_idma, br, MV_WIN_IDMA_BASE, MV_IDMA_BASE) 39042680SmsmithWIN_REG_IDX_RD(win_idma, sz, MV_WIN_IDMA_SIZE, MV_IDMA_BASE) 39142680SmsmithWIN_REG_IDX_RD(win_idma, har, MV_WIN_IDMA_REMAP, MV_IDMA_BASE) 39242680SmsmithWIN_REG_IDX_RD(win_idma, cap, MV_WIN_IDMA_CAP, MV_IDMA_BASE) 39342680SmsmithWIN_REG_IDX_WR(win_idma, br, MV_WIN_IDMA_BASE, MV_IDMA_BASE) 39442680SmsmithWIN_REG_IDX_WR(win_idma, sz, MV_WIN_IDMA_SIZE, MV_IDMA_BASE) 39542680SmsmithWIN_REG_IDX_WR(win_idma, har, MV_WIN_IDMA_REMAP, MV_IDMA_BASE) 39642680SmsmithWIN_REG_IDX_WR(win_idma, cap, MV_WIN_IDMA_CAP, MV_IDMA_BASE) 39742680SmsmithWIN_REG_RD(win_idma, bare, 0xa80, MV_IDMA_BASE) 39842680SmsmithWIN_REG_WR(win_idma, bare, 0xa80, MV_IDMA_BASE) 39942680Smsmith 40042680SmsmithWIN_REG_IDX_RD(win_sata, cr, MV_WIN_SATA_CTRL, MV_SATAHC_BASE); 40142680SmsmithWIN_REG_IDX_RD(win_sata, br, MV_WIN_SATA_BASE, MV_SATAHC_BASE); 40242680SmsmithWIN_REG_IDX_WR(win_sata, cr, MV_WIN_SATA_CTRL, MV_SATAHC_BASE); 40342680SmsmithWIN_REG_IDX_WR(win_sata, br, MV_WIN_SATA_BASE, MV_SATAHC_BASE); 40442680Smsmith 40542680Smsmith/************************************************************************** 40642680Smsmith * Decode windows helper routines 40742680Smsmith **************************************************************************/ 40842680Smsmithvoid 40942680Smsmithsoc_dump_decode_win(void) 41042680Smsmith{ 41142680Smsmith uint32_t dev, rev; 41242680Smsmith int i; 41342680Smsmith 41442680Smsmith soc_id(&dev, &rev); 41542680Smsmith 41642680Smsmith for (i = 0; i < MV_WIN_CPU_MAX; i++) { 41742680Smsmith printf("CPU window#%d: c 0x%08x, b 0x%08x", i, 41842680Smsmith win_cpu_cr_read(i), 41942680Smsmith win_cpu_br_read(i)); 42042680Smsmith 42142680Smsmith if (win_cpu_can_remap(i)) 42242680Smsmith printf(", rl 0x%08x, rh 0x%08x", 42342680Smsmith win_cpu_remap_l_read(i), 42442680Smsmith win_cpu_remap_h_read(i)); 42542680Smsmith 42642680Smsmith printf("\n"); 42742680Smsmith } 42842680Smsmith printf("Internal regs base: 0x%08x\n", 42942680Smsmith bus_space_read_4(obio_tag, MV_INTREGS_BASE, 0)); 43042680Smsmith 43142680Smsmith for (i = 0; i < MV_WIN_DDR_MAX; i++) 43242680Smsmith printf("DDR CS#%d: b 0x%08x, s 0x%08x\n", i, 43342680Smsmith ddr_br_read(i), ddr_sz_read(i)); 43442680Smsmith 43542680Smsmith for (i = 0; i < MV_WIN_ETH_MAX; i++) { 43642680Smsmith printf("ETH window#%d: b 0x%08x, s 0x%08x", i, 43742680Smsmith win_eth_br_read(MV_ETH0_BASE, i), 43842680Smsmith win_eth_sz_read(MV_ETH0_BASE, i)); 43942680Smsmith 44042680Smsmith if (win_eth_can_remap(i)) 44142680Smsmith printf(", ha 0x%08x", 44242680Smsmith win_eth_har_read(MV_ETH0_BASE, i)); 44342680Smsmith 44442680Smsmith printf("\n"); 44542680Smsmith } 44642680Smsmith printf("ETH windows: bare 0x%08x, epap 0x%08x\n", 44742680Smsmith win_eth_bare_read(MV_ETH0_BASE), 44842680Smsmith win_eth_epap_read(MV_ETH0_BASE)); 44942680Smsmith 45042680Smsmith decode_win_idma_dump(); 45142680Smsmith decode_win_cesa_dump(); 45242680Smsmith decode_win_usb_dump(); 45342680Smsmith printf("\n"); 45442680Smsmith} 45542680Smsmith 45642680Smsmith/************************************************************************** 45742680Smsmith * CPU windows routines 45842680Smsmith **************************************************************************/ 45942680Smsmithint 46042680Smsmithwin_cpu_can_remap(int i) 46142680Smsmith{ 46242680Smsmith uint32_t dev, rev; 46342680Smsmith 46442680Smsmith soc_id(&dev, &rev); 46542680Smsmith 46642680Smsmith /* Depending on the SoC certain windows have remap capability */ 46742680Smsmith if ((dev == MV_DEV_88F5182 && i < 2) || 46842680Smsmith (dev == MV_DEV_88F5281 && i < 4) || 46942680Smsmith (dev == MV_DEV_88F6281 && i < 4) || 47042680Smsmith (dev == MV_DEV_MV78100 && i < 8) || 47142680Smsmith (dev == MV_DEV_MV78100_Z0 && i < 8)) 47242680Smsmith return (1); 47342680Smsmith 47442680Smsmith return (0); 47542680Smsmith} 47642680Smsmith 47742680Smsmith/* XXX This should check for overlapping remap fields too.. */ 47842680Smsmithint 47942680Smsmithdecode_win_overlap(int win, int win_no, const struct decode_win *wintab) 48042680Smsmith{ 48142680Smsmith const struct decode_win *tab; 48242680Smsmith int i; 48342680Smsmith 48442680Smsmith tab = wintab; 48542680Smsmith 48642680Smsmith for (i = 0; i < win_no; i++, tab++) { 48742680Smsmith if (i == win) 48842680Smsmith /* Skip self */ 48942680Smsmith continue; 49042680Smsmith 49142680Smsmith if ((tab->base + tab->size - 1) < (wintab + win)->base) 49242680Smsmith continue; 49342680Smsmith 49442680Smsmith else if (((wintab + win)->base + (wintab + win)->size - 1) < 49542680Smsmith tab->base) 49642680Smsmith continue; 49742680Smsmith else 49842680Smsmith return (i); 49942680Smsmith } 50042680Smsmith 50142680Smsmith return (-1); 50242680Smsmith} 50342680Smsmith 50442680Smsmithstatic int 50542680Smsmithdecode_win_cpu_valid(void) 50642680Smsmith{ 50742680Smsmith int i, j, rv; 50842680Smsmith uint32_t b, e, s; 50942680Smsmith 51042680Smsmith if (cpu_wins_no > MV_WIN_CPU_MAX) { 51142680Smsmith printf("CPU windows: too many entries: %d\n", cpu_wins_no); 51242680Smsmith return (-1); 51342680Smsmith } 51442680Smsmith 51542680Smsmith rv = 1; 51642680Smsmith for (i = 0; i < cpu_wins_no; i++) { 51742680Smsmith 51842680Smsmith if (cpu_wins[i].target == 0) { 51942680Smsmith printf("CPU window#%d: DDR target window is not " 52042680Smsmith "supposed to be reprogrammed!\n", i); 52142680Smsmith rv = 0; 52253648Sarchie } 52342680Smsmith 52442680Smsmith if (cpu_wins[i].remap >= 0 && win_cpu_can_remap(i) != 1) { 52550275Sbde printf("CPU window#%d: not capable of remapping, but " 526230587Sken "val 0x%08x defined\n", i, cpu_wins[i].remap); 527230587Sken rv = 0; 52842680Smsmith } 52942680Smsmith 53042680Smsmith s = cpu_wins[i].size; 53142680Smsmith b = cpu_wins[i].base; 53242680Smsmith e = b + s - 1; 53342680Smsmith if (s > (0xFFFFFFFF - b + 1)) { 53442680Smsmith /* 53542680Smsmith * XXX this boundary check should account for 64bit 53642680Smsmith * and remapping.. 53742680Smsmith */ 53842680Smsmith printf("CPU window#%d: no space for size 0x%08x at " 53942680Smsmith "0x%08x\n", i, s, b); 54042680Smsmith rv = 0; 54142680Smsmith continue; 54242680Smsmith } 54342680Smsmith 54442680Smsmith j = decode_win_overlap(i, cpu_wins_no, &cpu_wins[0]); 54542680Smsmith if (j >= 0) { 54642680Smsmith printf("CPU window#%d: (0x%08x - 0x%08x) overlaps " 54742680Smsmith "with #%d (0x%08x - 0x%08x)\n", i, b, e, j, 54842680Smsmith cpu_wins[j].base, 54942680Smsmith cpu_wins[j].base + cpu_wins[j].size - 1); 55042680Smsmith rv = 0; 55142680Smsmith } 55242680Smsmith } 55342680Smsmith 55442680Smsmith return (rv); 55542680Smsmith} 55643300Sdillon 55743300Sdillonint 55842680Smsmithdecode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size, 55942680Smsmith int remap) 56042680Smsmith{ 56142680Smsmith uint32_t br, cr; 56242680Smsmith int win; 56342680Smsmith 56442680Smsmith if (used_cpu_wins >= MV_WIN_CPU_MAX) 56542680Smsmith return (-1); 56642680Smsmith 56742680Smsmith win = used_cpu_wins++; 56842680Smsmith 56942680Smsmith br = base & 0xffff0000; 57042680Smsmith win_cpu_br_write(win, br); 57142680Smsmith 57242680Smsmith if (win_cpu_can_remap(win)) { 57342680Smsmith if (remap >= 0) { 57442680Smsmith win_cpu_remap_l_write(win, remap & 0xffff0000); 57542680Smsmith win_cpu_remap_h_write(win, 0); 57642680Smsmith } else { 57742680Smsmith /* 57842680Smsmith * Remap function is not used for a given window 57942680Smsmith * (capable of remapping) - set remap field with the 58042680Smsmith * same value as base. 58142680Smsmith */ 58242680Smsmith win_cpu_remap_l_write(win, base & 0xffff0000); 58342680Smsmith win_cpu_remap_h_write(win, 0); 58442680Smsmith } 58542680Smsmith } 58642680Smsmith 58742680Smsmith cr = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1; 58842680Smsmith win_cpu_cr_write(win, cr); 58942680Smsmith 59042680Smsmith return (0); 59142680Smsmith} 59242680Smsmith 59342680Smsmithstatic void 59442680Smsmithdecode_win_cpu_setup(void) 59542680Smsmith{ 59642680Smsmith int i; 59742680Smsmith 59842680Smsmith used_cpu_wins = 0; 59942680Smsmith 60042680Smsmith /* Disable all CPU windows */ 60142680Smsmith for (i = 0; i < MV_WIN_CPU_MAX; i++) { 60242680Smsmith win_cpu_cr_write(i, 0); 60342680Smsmith win_cpu_br_write(i, 0); 60442680Smsmith if (win_cpu_can_remap(i)) { 60542680Smsmith win_cpu_remap_l_write(i, 0); 60642680Smsmith win_cpu_remap_h_write(i, 0); 60742680Smsmith } 60842680Smsmith } 60942680Smsmith 61042680Smsmith for (i = 0; i < cpu_wins_no; i++) 61142680Smsmith if (cpu_wins[i].target > 0) 61242680Smsmith decode_win_cpu_set(cpu_wins[i].target, 61342680Smsmith cpu_wins[i].attr, cpu_wins[i].base, 61442680Smsmith cpu_wins[i].size, cpu_wins[i].remap); 61542680Smsmith 61642680Smsmith} 61742680Smsmith 61842680Smsmith/* 61942680Smsmith * Check if we're able to cover all active DDR banks. 62042680Smsmith */ 62142680Smsmithstatic int 62242680Smsmithdecode_win_can_cover_ddr(int max) 62342680Smsmith{ 62442680Smsmith int i, c; 62542680Smsmith 62642680Smsmith c = 0; 62742680Smsmith for (i = 0; i < MV_WIN_DDR_MAX; i++) 62842680Smsmith if (ddr_is_active(i)) 62942680Smsmith c++; 63042680Smsmith 63142680Smsmith if (c > max) { 63242680Smsmith printf("Unable to cover all active DDR banks: " 63342680Smsmith "%d, available windows: %d\n", c, max); 63442680Smsmith return (0); 63542680Smsmith } 63642680Smsmith 63742680Smsmith return (1); 63842680Smsmith} 63942680Smsmith 64042680Smsmith/************************************************************************** 64142680Smsmith * DDR windows routines 642 **************************************************************************/ 643int 644ddr_is_active(int i) 645{ 646 647 if (ddr_sz_read(i) & 0x1) 648 return (1); 649 650 return (0); 651} 652 653uint32_t 654ddr_base(int i) 655{ 656 657 return (ddr_br_read(i) & 0xff000000); 658} 659 660uint32_t 661ddr_size(int i) 662{ 663 664 return ((ddr_sz_read(i) | 0x00ffffff) + 1); 665} 666 667uint32_t 668ddr_attr(int i) 669{ 670 671 return (i == 0 ? 0xe : 672 (i == 1 ? 0xd : 673 (i == 2 ? 0xb : 674 (i == 3 ? 0x7 : 0xff)))); 675} 676 677uint32_t 678ddr_target(int i) 679{ 680 681 /* Mbus unit ID is 0x0 for DDR SDRAM controller */ 682 return (0); 683} 684 685/************************************************************************** 686 * USB windows routines 687 **************************************************************************/ 688static int 689decode_win_usb_valid(void) 690{ 691 692 return (decode_win_can_cover_ddr(MV_WIN_USB_MAX)); 693} 694 695static __inline int 696usb_max_ports(void) 697{ 698 uint32_t dev, rev; 699 700 soc_id(&dev, &rev); 701 return ((dev == MV_DEV_MV78100 || dev == MV_DEV_MV78100_Z0) ? 3 : 1); 702} 703 704static void 705decode_win_usb_dump(void) 706{ 707 int i, p, m; 708 709 m = usb_max_ports(); 710 for (p = 0; p < m; p++) 711 for (i = 0; i < MV_WIN_USB_MAX; i++) 712 printf("USB window#%d: c 0x%08x, b 0x%08x\n", i, 713 win_usb_cr_read(i, p), win_usb_br_read(i, p)); 714} 715 716/* 717 * Set USB decode windows. 718 */ 719static void 720decode_win_usb_setup(void) 721{ 722 uint32_t br, cr; 723 int i, j, p, m; 724 725 /* Disable and clear all USB windows for all ports */ 726 m = usb_max_ports(); 727 728 for (p = 0; p < m; p++) { 729 730 if (pm_is_disabled(CPU_PM_CTRL_USB(p))) 731 continue; 732 733 for (i = 0; i < MV_WIN_USB_MAX; i++) { 734 win_usb_cr_write(i, p, 0); 735 win_usb_br_write(i, p, 0); 736 } 737 738 /* Only access to active DRAM banks is required */ 739 for (i = 0; i < MV_WIN_DDR_MAX; i++) { 740 if (ddr_is_active(i)) { 741 br = ddr_base(i); 742 /* 743 * XXX for 6281 we should handle Mbus write 744 * burst limit field in the ctrl reg 745 */ 746 cr = (((ddr_size(i) - 1) & 0xffff0000) | 747 (ddr_attr(i) << 8) | 748 (ddr_target(i) << 4) | 1); 749 750 /* Set the first free USB window */ 751 for (j = 0; j < MV_WIN_USB_MAX; j++) { 752 if (win_usb_cr_read(j, p) & 0x1) 753 continue; 754 755 win_usb_br_write(j, p, br); 756 win_usb_cr_write(j, p, cr); 757 break; 758 } 759 } 760 } 761 } 762} 763 764/************************************************************************** 765 * ETH windows routines 766 **************************************************************************/ 767 768static int 769win_eth_can_remap(int i) 770{ 771 772 /* ETH encode windows 0-3 have remap capability */ 773 if (i < 4) 774 return (1); 775 776 return (0); 777} 778 779static int 780eth_bare_read(uint32_t base, int i) 781{ 782 uint32_t v; 783 784 v = win_eth_bare_read(base); 785 v &= (1 << i); 786 787 return (v >> i); 788} 789 790static void 791eth_bare_write(uint32_t base, int i, int val) 792{ 793 uint32_t v; 794 795 v = win_eth_bare_read(base); 796 v &= ~(1 << i); 797 v |= (val << i); 798 win_eth_bare_write(base, v); 799} 800 801static void 802eth_epap_write(uint32_t base, int i, int val) 803{ 804 uint32_t v; 805 806 v = win_eth_epap_read(base); 807 v &= ~(0x3 << (i * 2)); 808 v |= (val << (i * 2)); 809 win_eth_epap_write(base, v); 810} 811 812static void 813decode_win_eth_setup(uint32_t base) 814{ 815 uint32_t br, sz; 816 int i, j; 817 818 if (pm_is_disabled(obio_get_pm_mask(base))) 819 return; 820 821 /* Disable, clear and revoke protection for all ETH windows */ 822 for (i = 0; i < MV_WIN_ETH_MAX; i++) { 823 824 eth_bare_write(base, i, 1); 825 eth_epap_write(base, i, 0); 826 win_eth_br_write(base, i, 0); 827 win_eth_sz_write(base, i, 0); 828 if (win_eth_can_remap(i)) 829 win_eth_har_write(base, i, 0); 830 } 831 832 /* Only access to active DRAM banks is required */ 833 for (i = 0; i < MV_WIN_DDR_MAX; i++) 834 if (ddr_is_active(i)) { 835 836 br = ddr_base(i) | (ddr_attr(i) << 8) | ddr_target(i); 837 sz = ((ddr_size(i) - 1) & 0xffff0000); 838 839 /* Set the first free ETH window */ 840 for (j = 0; j < MV_WIN_ETH_MAX; j++) { 841 if (eth_bare_read(base, j) == 0) 842 continue; 843 844 win_eth_br_write(base, j, br); 845 win_eth_sz_write(base, j, sz); 846 847 /* XXX remapping ETH windows not supported */ 848 849 /* Set protection RW */ 850 eth_epap_write(base, j, 0x3); 851 852 /* Enable window */ 853 eth_bare_write(base, j, 0); 854 break; 855 } 856 } 857} 858 859static int 860decode_win_eth_valid(void) 861{ 862 863 return (decode_win_can_cover_ddr(MV_WIN_ETH_MAX)); 864} 865 866/************************************************************************** 867 * PCIE windows routines 868 **************************************************************************/ 869 870static void 871decode_win_pcie_setup(uint32_t base) 872{ 873 uint32_t size = 0; 874 uint32_t cr, br; 875 int i, j; 876 877 for (i = 0; i < MV_PCIE_BAR_MAX; i++) 878 pcie_bar_write(base, i, 0); 879 880 for (i = 0; i < MV_WIN_PCIE_MAX; i++) { 881 win_pcie_cr_write(base, i, 0); 882 win_pcie_br_write(base, i, 0); 883 win_pcie_remap_write(base, i, 0); 884 } 885 886 for (i = 0; i < MV_WIN_DDR_MAX; i++) { 887 if (ddr_is_active(i)) { 888 /* Map DDR to BAR 1 */ 889 cr = (ddr_size(i) - 1) & 0xffff0000; 890 size += ddr_size(i) & 0xffff0000; 891 cr |= (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1; 892 br = ddr_base(i); 893 894 /* Use the first available PCIE window */ 895 for (j = 0; j < MV_WIN_PCIE_MAX; j++) { 896 if (win_pcie_cr_read(base, j) != 0) 897 continue; 898 899 win_pcie_br_write(base, j, br); 900 win_pcie_cr_write(base, j, cr); 901 break; 902 } 903 } 904 } 905 906 /* 907 * Upper 16 bits in BAR register is interpreted as BAR size 908 * (in 64 kB units) plus 64kB, so substract 0x10000 909 * form value passed to register to get correct value. 910 */ 911 size -= 0x10000; 912 pcie_bar_write(base, 0, size | 1); 913} 914 915static int 916decode_win_pcie_valid(void) 917{ 918 919 return (decode_win_can_cover_ddr(MV_WIN_PCIE_MAX)); 920} 921 922/************************************************************************** 923 * IDMA windows routines 924 **************************************************************************/ 925#if defined(SOC_MV_ORION) || defined(SOC_MV_DISCOVERY) 926static int 927idma_bare_read(int i) 928{ 929 uint32_t v; 930 931 v = win_idma_bare_read(); 932 v &= (1 << i); 933 934 return (v >> i); 935} 936 937static void 938idma_bare_write(int i, int val) 939{ 940 uint32_t v; 941 942 v = win_idma_bare_read(); 943 v &= ~(1 << i); 944 v |= (val << i); 945 win_idma_bare_write(v); 946} 947 948/* 949 * Sets channel protection 'val' for window 'w' on channel 'c' 950 */ 951static void 952idma_cap_write(int c, int w, int val) 953{ 954 uint32_t v; 955 956 v = win_idma_cap_read(c); 957 v &= ~(0x3 << (w * 2)); 958 v |= (val << (w * 2)); 959 win_idma_cap_write(c, v); 960} 961 962/* 963 * Set protection 'val' on all channels for window 'w' 964 */ 965static void 966idma_set_prot(int w, int val) 967{ 968 int c; 969 970 for (c = 0; c < MV_IDMA_CHAN_MAX; c++) 971 idma_cap_write(c, w, val); 972} 973 974static int 975win_idma_can_remap(int i) 976{ 977 978 /* IDMA decode windows 0-3 have remap capability */ 979 if (i < 4) 980 return (1); 981 982 return (0); 983} 984 985void 986decode_win_idma_setup(void) 987{ 988 uint32_t br, sz; 989 int i, j; 990 991 if (pm_is_disabled(CPU_PM_CTRL_IDMA)) 992 return; 993 /* 994 * Disable and clear all IDMA windows, revoke protection for all channels 995 */ 996 for (i = 0; i < MV_WIN_IDMA_MAX; i++) { 997 998 idma_bare_write(i, 1); 999 win_idma_br_write(i, 0); 1000 win_idma_sz_write(i, 0); 1001 if (win_idma_can_remap(i) == 1) 1002 win_idma_har_write(i, 0); 1003 } 1004 for (i = 0; i < MV_IDMA_CHAN_MAX; i++) 1005 win_idma_cap_write(i, 0); 1006 1007 /* 1008 * Set up access to all active DRAM banks 1009 */ 1010 for (i = 0; i < MV_WIN_DDR_MAX; i++) 1011 if (ddr_is_active(i)) { 1012 br = ddr_base(i) | (ddr_attr(i) << 8) | ddr_target(i); 1013 sz = ((ddr_size(i) - 1) & 0xffff0000); 1014 1015 /* Place DDR entries in non-remapped windows */ 1016 for (j = 0; j < MV_WIN_IDMA_MAX; j++) 1017 if (win_idma_can_remap(j) != 1 && 1018 idma_bare_read(j) == 1) { 1019 1020 /* Configure window */ 1021 win_idma_br_write(j, br); 1022 win_idma_sz_write(j, sz); 1023 1024 /* Set protection RW on all channels */ 1025 idma_set_prot(j, 0x3); 1026 1027 /* Enable window */ 1028 idma_bare_write(j, 0); 1029 break; 1030 } 1031 } 1032 1033 /* 1034 * Remaining targets -- from statically defined table 1035 */ 1036 for (i = 0; i < idma_wins_no; i++) 1037 if (idma_wins[i].target > 0) { 1038 br = (idma_wins[i].base & 0xffff0000) | 1039 (idma_wins[i].attr << 8) | idma_wins[i].target; 1040 sz = ((idma_wins[i].size - 1) & 0xffff0000); 1041 1042 /* Set the first free IDMA window */ 1043 for (j = 0; j < MV_WIN_IDMA_MAX; j++) { 1044 if (idma_bare_read(j) == 0) 1045 continue; 1046 1047 /* Configure window */ 1048 win_idma_br_write(j, br); 1049 win_idma_sz_write(j, sz); 1050 if (win_idma_can_remap(j) && 1051 idma_wins[j].remap >= 0) 1052 win_idma_har_write(j, idma_wins[j].remap); 1053 1054 /* Set protection RW on all channels */ 1055 idma_set_prot(j, 0x3); 1056 1057 /* Enable window */ 1058 idma_bare_write(j, 0); 1059 break; 1060 } 1061 } 1062} 1063 1064int 1065decode_win_idma_valid(void) 1066{ 1067 const struct decode_win *wintab; 1068 int c, i, j, rv; 1069 uint32_t b, e, s; 1070 1071 if (idma_wins_no > MV_WIN_IDMA_MAX) { 1072 printf("IDMA windows: too many entries: %d\n", idma_wins_no); 1073 return (-1); 1074 } 1075 for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++) 1076 if (ddr_is_active(i)) 1077 c++; 1078 1079 if (idma_wins_no > (MV_WIN_IDMA_MAX - c)) { 1080 printf("IDMA windows: too many entries: %d, available: %d\n", 1081 idma_wins_no, MV_WIN_IDMA_MAX - c); 1082 return (-1); 1083 } 1084 1085 wintab = idma_wins; 1086 rv = 1; 1087 for (i = 0; i < idma_wins_no; i++, wintab++) { 1088 1089 if (wintab->target == 0) { 1090 printf("IDMA window#%d: DDR target window is not " 1091 "supposed to be reprogrammed!\n", i); 1092 rv = 0; 1093 } 1094 1095 if (wintab->remap >= 0 && win_cpu_can_remap(i) != 1) { 1096 printf("IDMA window#%d: not capable of remapping, but " 1097 "val 0x%08x defined\n", i, wintab->remap); 1098 rv = 0; 1099 } 1100 1101 s = wintab->size; 1102 b = wintab->base; 1103 e = b + s - 1; 1104 if (s > (0xFFFFFFFF - b + 1)) { 1105 /* XXX this boundary check should account for 64bit and 1106 * remapping.. */ 1107 printf("IDMA window#%d: no space for size 0x%08x at " 1108 "0x%08x\n", i, s, b); 1109 rv = 0; 1110 continue; 1111 } 1112 1113 j = decode_win_overlap(i, idma_wins_no, &idma_wins[0]); 1114 if (j >= 0) { 1115 printf("IDMA window#%d: (0x%08x - 0x%08x) overlaps " 1116 "with #%d (0x%08x - 0x%08x)\n", i, b, e, j, 1117 idma_wins[j].base, 1118 idma_wins[j].base + idma_wins[j].size - 1); 1119 rv = 0; 1120 } 1121 } 1122 1123 return (rv); 1124} 1125 1126void 1127decode_win_idma_dump(void) 1128{ 1129 int i; 1130 1131 for (i = 0; i < MV_WIN_IDMA_MAX; i++) { 1132 printf("IDMA window#%d: b 0x%08x, s 0x%08x", i, 1133 win_idma_br_read(i), win_idma_sz_read(i)); 1134 1135 if (win_idma_can_remap(i)) 1136 printf(", ha 0x%08x", win_idma_har_read(i)); 1137 1138 printf("\n"); 1139 } 1140 for (i = 0; i < MV_IDMA_CHAN_MAX; i++) 1141 printf("IDMA channel#%d: ap 0x%08x\n", i, 1142 win_idma_cap_read(i)); 1143 printf("IDMA windows: bare 0x%08x\n", win_idma_bare_read()); 1144} 1145#else 1146 1147/* Provide dummy functions to satisfy the build for SoCs not equipped with IDMA */ 1148int 1149decode_win_idma_valid(void) 1150{ 1151 1152 return (1); 1153} 1154 1155void 1156decode_win_idma_setup(void) 1157{ 1158} 1159 1160void 1161decode_win_idma_dump(void) 1162{ 1163} 1164#endif 1165 1166/************************************************************************** 1167 * XOR windows routines 1168 **************************************************************************/ 1169#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY) 1170static int 1171xor_ctrl_read(int i, int c, int e) 1172{ 1173 uint32_t v; 1174 v = win_xor_ctrl_read(c, e); 1175 v &= (1 << i); 1176 1177 return (v >> i); 1178} 1179 1180static void 1181xor_ctrl_write(int i, int c, int e, int val) 1182{ 1183 uint32_t v; 1184 1185 v = win_xor_ctrl_read(c, e); 1186 v &= ~(1 << i); 1187 v |= (val << i); 1188 win_xor_ctrl_write(c, e, v); 1189} 1190 1191/* 1192 * Set channel protection 'val' for window 'w' on channel 'c' 1193 */ 1194 1195static void 1196xor_chan_write(int c, int e, int w, int val) 1197{ 1198 uint32_t v; 1199 1200 v = win_xor_ctrl_read(c, e); 1201 v &= ~(0x3 << (w * 2 + 16)); 1202 v |= (val << (w * 2 + 16)); 1203 win_xor_ctrl_write(c, e, v); 1204} 1205 1206/* 1207 * Set protection 'val' on all channels for window 'w' on engine 'e' 1208 */ 1209static void 1210xor_set_prot(int w, int e, int val) 1211{ 1212 int c; 1213 1214 for (c = 0; c < MV_XOR_CHAN_MAX; c++) 1215 xor_chan_write(c, e, w, val); 1216} 1217 1218static int 1219win_xor_can_remap(int i) 1220{ 1221 1222 /* XOR decode windows 0-3 have remap capability */ 1223 if (i < 4) 1224 return (1); 1225 1226 return (0); 1227} 1228 1229static int 1230xor_max_eng(void) 1231{ 1232 uint32_t dev, rev; 1233 1234 soc_id(&dev, &rev); 1235 if (dev == MV_DEV_88F6281) 1236 return (2); 1237 else if ((dev == MV_DEV_MV78100) || (dev == MV_DEV_MV78100_Z0)) 1238 return (1); 1239 else 1240 return (0); 1241} 1242 1243static void 1244xor_active_dram(int c, int e, int *window) 1245{ 1246 uint32_t br, sz; 1247 int i, m, w; 1248 1249 /* 1250 * Set up access to all active DRAM banks 1251 */ 1252 m = xor_max_eng(); 1253 for (i = 0; i < m; i++) 1254 if (ddr_is_active(i)) { 1255 br = ddr_base(i) | (ddr_attr(i) << 8) | 1256 ddr_target(i); 1257 sz = ((ddr_size(i) - 1) & 0xffff0000); 1258 1259 /* Place DDR entries in non-remapped windows */ 1260 for (w = 0; w < MV_WIN_XOR_MAX; w++) 1261 if (win_xor_can_remap(w) != 1 && 1262 (xor_ctrl_read(w, c, e) == 0) && 1263 w > *window) { 1264 /* Configure window */ 1265 win_xor_br_write(w, e, br); 1266 win_xor_sz_write(w, e, sz); 1267 1268 /* Set protection RW on all channels */ 1269 xor_set_prot(w, e, 0x3); 1270 1271 /* Enable window */ 1272 xor_ctrl_write(w, c, e, 1); 1273 (*window)++; 1274 break; 1275 } 1276 } 1277} 1278 1279void 1280decode_win_xor_setup(void) 1281{ 1282 uint32_t br, sz; 1283 int i, j, z, e = 1, m, window; 1284 1285 if (pm_is_disabled(CPU_PM_CTRL_XOR)) 1286 return; 1287 1288 /* 1289 * Disable and clear all XOR windows, revoke protection for all 1290 * channels 1291 */ 1292 m = xor_max_eng(); 1293 for (j = 0; j < m; j++, e--) { 1294 1295 /* Number of non-remaped windows */ 1296 window = MV_XOR_NON_REMAP - 1; 1297 1298 for (i = 0; i < MV_WIN_XOR_MAX; i++) { 1299 win_xor_br_write(i, e, 0); 1300 win_xor_sz_write(i, e, 0); 1301 } 1302 1303 if (win_xor_can_remap(i) == 1) 1304 win_xor_har_write(i, e, 0); 1305 1306 for (i = 0; i < MV_XOR_CHAN_MAX; i++) { 1307 win_xor_ctrl_write(i, e, 0); 1308 xor_active_dram(i, e, &window); 1309 } 1310 1311 /* 1312 * Remaining targets -- from a statically defined table 1313 */ 1314 for (i = 0; i < xor_wins_no; i++) 1315 if (xor_wins[i].target > 0) { 1316 br = (xor_wins[i].base & 0xffff0000) | 1317 (xor_wins[i].attr << 8) | 1318 xor_wins[i].target; 1319 sz = ((xor_wins[i].size - 1) & 0xffff0000); 1320 1321 /* Set the first free XOR window */ 1322 for (z = 0; z < MV_WIN_XOR_MAX; z++) { 1323 if (xor_ctrl_read(z, 0, e) && 1324 xor_ctrl_read(z, 1, e)) 1325 continue; 1326 1327 /* Configure window */ 1328 win_xor_br_write(z, e, br); 1329 win_xor_sz_write(z, e, sz); 1330 if (win_xor_can_remap(z) && 1331 xor_wins[z].remap >= 0) 1332 win_xor_har_write(z, e, 1333 xor_wins[z].remap); 1334 1335 /* Set protection RW on all channels */ 1336 xor_set_prot(z, e, 0x3); 1337 1338 /* Enable window */ 1339 xor_ctrl_write(z, 0, e, 1); 1340 xor_ctrl_write(z, 1, e, 1); 1341 break; 1342 } 1343 } 1344 } 1345} 1346 1347int 1348decode_win_xor_valid(void) 1349{ 1350 const struct decode_win *wintab; 1351 int c, i, j, rv; 1352 uint32_t b, e, s; 1353 1354 if (xor_wins_no > MV_WIN_XOR_MAX) { 1355 printf("XOR windows: too many entries: %d\n", xor_wins_no); 1356 return (-1); 1357 } 1358 for (i = 0, c = 0; i < MV_WIN_DDR_MAX; i++) 1359 if (ddr_is_active(i)) 1360 c++; 1361 1362 if (xor_wins_no > (MV_WIN_XOR_MAX - c)) { 1363 printf("XOR windows: too many entries: %d, available: %d\n", 1364 xor_wins_no, MV_WIN_IDMA_MAX - c); 1365 return (-1); 1366 } 1367 1368 wintab = xor_wins; 1369 rv = 1; 1370 for (i = 0; i < xor_wins_no; i++, wintab++) { 1371 1372 if (wintab->target == 0) { 1373 printf("XOR window#%d: DDR target window is not " 1374 "supposed to be reprogrammed!\n", i); 1375 rv = 0; 1376 } 1377 1378 if (wintab->remap >= 0 && win_cpu_can_remap(i) != 1) { 1379 printf("XOR window#%d: not capable of remapping, but " 1380 "val 0x%08x defined\n", i, wintab->remap); 1381 rv = 0; 1382 } 1383 1384 s = wintab->size; 1385 b = wintab->base; 1386 e = b + s - 1; 1387 if (s > (0xFFFFFFFF - b + 1)) { 1388 /* 1389 * XXX this boundary check should account for 64bit 1390 * and remapping.. 1391 */ 1392 printf("XOR window#%d: no space for size 0x%08x at " 1393 "0x%08x\n", i, s, b); 1394 rv = 0; 1395 continue; 1396 } 1397 1398 j = decode_win_overlap(i, xor_wins_no, &xor_wins[0]); 1399 if (j >= 0) { 1400 printf("XOR window#%d: (0x%08x - 0x%08x) overlaps " 1401 "with #%d (0x%08x - 0x%08x)\n", i, b, e, j, 1402 xor_wins[j].base, 1403 xor_wins[j].base + xor_wins[j].size - 1); 1404 rv = 0; 1405 } 1406 } 1407 1408 return (rv); 1409} 1410 1411void 1412decode_win_xor_dump(void) 1413{ 1414 int i, j; 1415 int e = 1; 1416 1417 for (j = 0; j < xor_max_eng(); j++, e--) { 1418 for (i = 0; i < MV_WIN_XOR_MAX; i++) { 1419 printf("XOR window#%d: b 0x%08x, s 0x%08x", i, 1420 win_xor_br_read(i, e), win_xor_sz_read(i, e)); 1421 1422 if (win_xor_can_remap(i)) 1423 printf(", ha 0x%08x", win_xor_har_read(i, e)); 1424 1425 printf("\n"); 1426 } 1427 for (i = 0; i < MV_XOR_CHAN_MAX; i++) 1428 printf("XOR control#%d: 0x%08x\n", i, 1429 win_xor_ctrl_read(i, e)); 1430 } 1431} 1432 1433#else 1434/* Provide dummy functions to satisfy the build for SoCs not equipped with XOR */ 1435int 1436decode_win_xor_valid(void) 1437{ 1438 1439 return (1); 1440} 1441 1442void 1443decode_win_xor_setup(void) 1444{ 1445} 1446 1447void 1448decode_win_xor_dump(void) 1449{ 1450} 1451#endif 1452 1453/************************************************************************** 1454 * CESA TDMA windows routines 1455 **************************************************************************/ 1456#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY) 1457/* 1458 * Dump CESA TDMA decode windows. 1459 */ 1460static void 1461decode_win_cesa_dump(void) 1462{ 1463 int i; 1464 1465 for (i = 0; i < MV_WIN_CESA_MAX; i++) 1466 printf("CESA window#%d: c 0x%08x, b 0x%08x\n", i, 1467 win_cesa_cr_read(i), win_cesa_br_read(i)); 1468} 1469 1470 1471/* 1472 * Set CESA TDMA decode windows. 1473 */ 1474static void 1475decode_win_cesa_setup(void) 1476{ 1477 uint32_t br, cr; 1478 int i, j; 1479 1480 if (pm_is_disabled(CPU_PM_CTRL_CRYPTO)) 1481 return; 1482 1483 /* Disable and clear all CESA windows */ 1484 for (i = 0; i < MV_WIN_CESA_MAX; i++) { 1485 win_cesa_cr_write(i, 0); 1486 win_cesa_br_write(i, 0); 1487 } 1488 1489 /* Only access to active DRAM banks is required. */ 1490 for (i = 0; i < MV_WIN_DDR_MAX; i++) 1491 if (ddr_is_active(i)) { 1492 br = ddr_base(i); 1493 cr = (((ddr_size(i) - 1) & 0xffff0000) | 1494 (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1); 1495 1496 /* Set the first available CESA window */ 1497 for (j = 0; j < MV_WIN_CESA_MAX; j++) { 1498 if (win_cesa_cr_read(j) & 0x1) 1499 continue; 1500 1501 win_cesa_br_write(j, br); 1502 win_cesa_cr_write(j, cr); 1503 break; 1504 } 1505 } 1506} 1507 1508/* 1509 * Check CESA TDMA decode windows. 1510 */ 1511static int 1512decode_win_cesa_valid(void) 1513{ 1514 1515 return (decode_win_can_cover_ddr(MV_WIN_CESA_MAX)); 1516} 1517#else 1518 1519/* 1520 * Provide dummy functions to satisfy the build for SoCs not equipped with 1521 * CESA 1522 */ 1523 1524int 1525decode_win_cesa_valid(void) 1526{ 1527 1528 return (1); 1529} 1530 1531void 1532decode_win_cesa_setup(void) 1533{ 1534} 1535 1536void 1537decode_win_cesa_dump(void) 1538{ 1539} 1540#endif 1541 1542/************************************************************************** 1543 * SATA windows routines 1544 **************************************************************************/ 1545static void 1546decode_win_sata_setup(void) 1547{ 1548 uint32_t cr, br; 1549 int i, j; 1550 1551 if (pm_is_disabled(CPU_PM_CTRL_SATA)) 1552 return; 1553 1554 for (i = 0; i < MV_WIN_SATA_MAX; i++) { 1555 win_sata_cr_write(i, 0); 1556 win_sata_br_write(i, 0); 1557 } 1558 1559 for (i = 0; i < MV_WIN_DDR_MAX; i++) 1560 if (ddr_is_active(i)) { 1561 cr = ((ddr_size(i) - 1) & 0xffff0000) | 1562 (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1; 1563 br = ddr_base(i); 1564 1565 /* Use the first available SATA window */ 1566 for (j = 0; j < MV_WIN_SATA_MAX; j++) { 1567 if ((win_sata_cr_read(j) & 1) != 0) 1568 continue; 1569 1570 win_sata_br_write(j, br); 1571 win_sata_cr_write(j, cr); 1572 break; 1573 } 1574 } 1575} 1576 1577static int 1578decode_win_sata_valid(void) 1579{ 1580 uint32_t dev, rev; 1581 1582 soc_id(&dev, &rev); 1583 if (dev == MV_DEV_88F5281) 1584 return (1); 1585 1586 return (decode_win_can_cover_ddr(MV_WIN_SATA_MAX)); 1587} 1588