2007-10-23 23:14:42 +04:00
/*
2008-03-27 21:51:41 +03:00
* arch / arm / mach - orion5x / addr - map . c
2007-10-23 23:14:42 +04:00
*
2008-03-27 21:51:41 +03:00
* Address map functions for Marvell Orion 5 x SoCs
2007-10-23 23:14:42 +04:00
*
* Maintainer : Tzachi Perelstein < tzachi @ marvell . com >
*
2008-03-27 21:51:41 +03:00
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
2007-10-23 23:14:42 +04:00
* warranty of any kind , whether express or implied .
*/
# include <linux/kernel.h>
# include <linux/init.h>
2008-03-27 21:51:39 +03:00
# include <linux/mbus.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2009-05-08 00:59:24 +04:00
# include <linux/errno.h>
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2007-10-23 23:14:42 +04:00
# include "common.h"
/*
2011-03-31 05:57:33 +04:00
* The Orion has fully programmable address map . There ' s a separate address
2008-04-26 00:31:32 +04:00
* map for each of the device _master_ interfaces , e . g . CPU , PCI , PCIe , USB ,
2007-10-23 23:14:42 +04:00
* Gigabit Ethernet , DMA / XOR engines , etc . Each interface has its own
* address decode windows that allow it to access any of the Orion resources .
*
* CPU address decoding - -
* Linux assumes that it is the boot loader that already setup the access to
* DDR and internal registers .
2008-04-26 00:31:32 +04:00
* Setup access to PCI and PCIe IO / MEM space is issued by this file .
2007-10-23 23:14:42 +04:00
* Setup access to various devices located on the device bus interface ( e . g .
* flashes , RTC , etc ) should be issued by machine - setup . c according to
2008-03-27 21:51:41 +03:00
* specific board population ( by using orion5x_setup_ * _win ( ) ) .
2007-10-23 23:14:42 +04:00
*
* Non - CPU Masters address decoding - -
* Unlike the CPU , we setup the access from Orion ' s master interfaces to DDR
* banks only ( the typical use case ) .
2008-04-26 22:48:11 +04:00
* Setup access for each master to DDR is issued by platform device setup .
2007-10-23 23:14:42 +04:00
*/
/*
* Generic Address Decode Windows bit settings
*/
# define TARGET_DDR 0
2008-03-27 21:51:41 +03:00
# define TARGET_DEV_BUS 1
2007-10-23 23:14:42 +04:00
# define TARGET_PCI 3
# define TARGET_PCIE 4
2009-05-08 00:59:24 +04:00
# define TARGET_SRAM 9
2007-10-23 23:14:42 +04:00
# define ATTR_PCIE_MEM 0x59
# define ATTR_PCIE_IO 0x51
2008-03-27 21:51:40 +03:00
# define ATTR_PCIE_WA 0x79
2007-10-23 23:14:42 +04:00
# define ATTR_PCI_MEM 0x59
# define ATTR_PCI_IO 0x51
# define ATTR_DEV_CS0 0x1e
# define ATTR_DEV_CS1 0x1d
# define ATTR_DEV_CS2 0x1b
# define ATTR_DEV_BOOT 0xf
2009-05-08 00:59:24 +04:00
# define ATTR_SRAM 0x0
2007-10-23 23:14:42 +04:00
/*
2008-03-27 21:51:41 +03:00
* Helpers to get DDR bank info
2007-10-23 23:14:42 +04:00
*/
2009-04-22 23:08:17 +04:00
# define ORION5X_DDR_REG(x) (ORION5X_DDR_VIRT_BASE | (x))
2008-04-26 22:48:11 +04:00
# define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) << 3))
# define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) << 3))
2007-10-23 23:14:42 +04:00
/*
* CPU Address Decode Windows registers
*/
2009-04-22 23:08:17 +04:00
# define ORION5X_BRIDGE_REG(x) (ORION5X_BRIDGE_VIRT_BASE | (x))
2008-03-27 21:51:41 +03:00
# define CPU_WIN_CTRL(n) ORION5X_BRIDGE_REG(0x000 | ((n) << 4))
# define CPU_WIN_BASE(n) ORION5X_BRIDGE_REG(0x004 | ((n) << 4))
# define CPU_WIN_REMAP_LO(n) ORION5X_BRIDGE_REG(0x008 | ((n) << 4))
# define CPU_WIN_REMAP_HI(n) ORION5X_BRIDGE_REG(0x00c | ((n) << 4))
2007-10-23 23:14:42 +04:00
2008-03-27 21:51:39 +03:00
2008-03-27 21:51:41 +03:00
struct mbus_dram_target_info orion5x_mbus_dram_info ;
2008-05-11 01:20:50 +04:00
static int __initdata win_alloc_count ;
2008-03-27 21:51:39 +03:00
2008-03-27 21:51:41 +03:00
static int __init orion5x_cpu_win_can_remap ( int win )
2007-10-23 23:14:42 +04:00
{
u32 dev , rev ;
2008-03-27 21:51:41 +03:00
orion5x_pcie_id ( & dev , & rev ) ;
2007-11-11 14:05:11 +03:00
if ( ( dev = = MV88F5281_DEV_ID & & win < 4 )
| | ( dev = = MV88F5182_DEV_ID & & win < 2 )
2009-08-03 18:25:12 +04:00
| | ( dev = = MV88F5181_DEV_ID & & win < 2 )
| | ( dev = = MV88F6183_DEV_ID & & win < 4 ) )
2007-10-23 23:14:42 +04:00
return 1 ;
return 0 ;
}
2009-05-08 00:59:24 +04:00
static int __init setup_cpu_win ( int win , u32 base , u32 size ,
2008-03-27 21:51:40 +03:00
u8 target , u8 attr , int remap )
2007-10-23 23:14:42 +04:00
{
2008-05-11 01:20:50 +04:00
if ( win > = 8 ) {
printk ( KERN_ERR " setup_cpu_win: trying to allocate "
" window %d \n " , win ) ;
2009-05-08 00:59:24 +04:00
return - ENOSPC ;
2008-05-11 01:20:50 +04:00
}
2008-05-28 18:43:48 +04:00
writel ( base & 0xffff0000 , CPU_WIN_BASE ( win ) ) ;
writel ( ( ( size - 1 ) & 0xffff0000 ) | ( attr < < 8 ) | ( target < < 4 ) | 1 ,
CPU_WIN_CTRL ( win ) ) ;
2007-10-23 23:14:42 +04:00
2008-03-27 21:51:41 +03:00
if ( orion5x_cpu_win_can_remap ( win ) ) {
2008-03-27 21:51:40 +03:00
if ( remap < 0 )
remap = base ;
2008-05-28 18:43:48 +04:00
writel ( remap & 0xffff0000 , CPU_WIN_REMAP_LO ( win ) ) ;
writel ( 0 , CPU_WIN_REMAP_HI ( win ) ) ;
2007-10-23 23:14:42 +04:00
}
2009-05-08 00:59:24 +04:00
return 0 ;
2007-10-23 23:14:42 +04:00
}
2008-03-27 21:51:41 +03:00
void __init orion5x_setup_cpu_mbus_bridge ( void )
2007-10-23 23:14:42 +04:00
{
int i ;
2008-03-27 21:51:39 +03:00
int cs ;
2007-10-23 23:14:42 +04:00
/*
2008-03-27 21:51:40 +03:00
* First , disable and clear windows .
2007-10-23 23:14:42 +04:00
*/
2008-03-27 21:51:40 +03:00
for ( i = 0 ; i < 8 ; i + + ) {
2008-05-28 18:43:48 +04:00
writel ( 0 , CPU_WIN_BASE ( i ) ) ;
writel ( 0 , CPU_WIN_CTRL ( i ) ) ;
2008-03-27 21:51:41 +03:00
if ( orion5x_cpu_win_can_remap ( i ) ) {
2008-05-28 18:43:48 +04:00
writel ( 0 , CPU_WIN_REMAP_LO ( i ) ) ;
writel ( 0 , CPU_WIN_REMAP_HI ( i ) ) ;
2007-10-23 23:14:42 +04:00
}
}
/*
2008-02-07 23:55:17 +03:00
* Setup windows for PCI + PCIe IO + MEM space .
2007-10-23 23:14:42 +04:00
*/
2008-03-27 21:51:41 +03:00
setup_cpu_win ( 0 , ORION5X_PCIE_IO_PHYS_BASE , ORION5X_PCIE_IO_SIZE ,
TARGET_PCIE , ATTR_PCIE_IO , ORION5X_PCIE_IO_BUS_BASE ) ;
setup_cpu_win ( 1 , ORION5X_PCI_IO_PHYS_BASE , ORION5X_PCI_IO_SIZE ,
TARGET_PCI , ATTR_PCI_IO , ORION5X_PCI_IO_BUS_BASE ) ;
setup_cpu_win ( 2 , ORION5X_PCIE_MEM_PHYS_BASE , ORION5X_PCIE_MEM_SIZE ,
2008-03-27 21:51:40 +03:00
TARGET_PCIE , ATTR_PCIE_MEM , - 1 ) ;
2008-03-27 21:51:41 +03:00
setup_cpu_win ( 3 , ORION5X_PCI_MEM_PHYS_BASE , ORION5X_PCI_MEM_SIZE ,
2008-03-27 21:51:40 +03:00
TARGET_PCI , ATTR_PCI_MEM , - 1 ) ;
2008-05-11 01:20:50 +04:00
win_alloc_count = 4 ;
2008-03-27 21:51:39 +03:00
/*
* Setup MBUS dram target info .
*/
2008-03-27 21:51:41 +03:00
orion5x_mbus_dram_info . mbus_dram_target_id = TARGET_DDR ;
2008-03-27 21:51:39 +03:00
for ( i = 0 , cs = 0 ; i < 4 ; i + + ) {
u32 base = readl ( DDR_BASE_CS ( i ) ) ;
u32 size = readl ( DDR_SIZE_CS ( i ) ) ;
/*
* Chip select enabled ?
*/
if ( size & 1 ) {
struct mbus_dram_window * w ;
2008-03-27 21:51:41 +03:00
w = & orion5x_mbus_dram_info . cs [ cs + + ] ;
2008-03-27 21:51:39 +03:00
w - > cs_index = i ;
w - > mbus_attr = 0xf & ~ ( 1 < < i ) ;
2008-05-23 10:34:42 +04:00
w - > base = base & 0xffff0000 ;
w - > size = ( size | 0x0000ffff ) + 1 ;
2008-03-27 21:51:39 +03:00
}
}
2008-03-27 21:51:41 +03:00
orion5x_mbus_dram_info . num_cs = cs ;
2007-10-23 23:14:42 +04:00
}
2008-03-27 21:51:41 +03:00
void __init orion5x_setup_dev_boot_win ( u32 base , u32 size )
2008-03-27 21:51:40 +03:00
{
2008-05-11 01:20:50 +04:00
setup_cpu_win ( win_alloc_count + + , base , size ,
TARGET_DEV_BUS , ATTR_DEV_BOOT , - 1 ) ;
2008-03-27 21:51:40 +03:00
}
2008-03-27 21:51:41 +03:00
void __init orion5x_setup_dev0_win ( u32 base , u32 size )
2008-03-27 21:51:40 +03:00
{
2008-05-11 01:20:50 +04:00
setup_cpu_win ( win_alloc_count + + , base , size ,
TARGET_DEV_BUS , ATTR_DEV_CS0 , - 1 ) ;
2008-03-27 21:51:40 +03:00
}
2008-03-27 21:51:41 +03:00
void __init orion5x_setup_dev1_win ( u32 base , u32 size )
2008-03-27 21:51:40 +03:00
{
2008-05-11 01:20:50 +04:00
setup_cpu_win ( win_alloc_count + + , base , size ,
TARGET_DEV_BUS , ATTR_DEV_CS1 , - 1 ) ;
2008-03-27 21:51:40 +03:00
}
2008-03-27 21:51:41 +03:00
void __init orion5x_setup_dev2_win ( u32 base , u32 size )
2008-03-27 21:51:40 +03:00
{
2008-05-11 01:20:50 +04:00
setup_cpu_win ( win_alloc_count + + , base , size ,
TARGET_DEV_BUS , ATTR_DEV_CS2 , - 1 ) ;
2008-03-27 21:51:40 +03:00
}
2008-03-27 21:51:41 +03:00
void __init orion5x_setup_pcie_wa_win ( u32 base , u32 size )
2008-03-27 21:51:40 +03:00
{
2008-05-11 01:20:50 +04:00
setup_cpu_win ( win_alloc_count + + , base , size ,
TARGET_PCIE , ATTR_PCIE_WA , - 1 ) ;
2008-03-27 21:51:40 +03:00
}
2009-05-08 00:59:24 +04:00
int __init orion5x_setup_sram_win ( void )
{
2009-06-12 06:51:12 +04:00
return setup_cpu_win ( win_alloc_count + + , ORION5X_SRAM_PHYS_BASE ,
2009-05-08 00:59:24 +04:00
ORION5X_SRAM_SIZE , TARGET_SRAM , ATTR_SRAM , - 1 ) ;
}