2007-09-25 17:40:12 +04:00
/*
* Copyright ( C ) 2004 Florian Schirmer < jolt @ tuxbox . org >
2007-09-25 17:41:24 +04:00
* Copyright ( C ) 2007 Aurelien Jarno < aurelien @ aurel32 . net >
2012-10-03 15:34:17 +04:00
* Copyright ( C ) 2010 - 2012 Hauke Mehrtens < hauke @ hauke - m . de >
2007-09-25 17:40:12 +04:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND ANY EXPRESS OR IMPLIED
* WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF
* USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/init.h>
2007-09-25 17:41:24 +04:00
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/spinlock.h>
2013-09-25 02:36:56 +04:00
# include <linux/ssb/ssb_driver_chipcommon.h>
# include <linux/ssb/ssb_regs.h>
2012-10-03 15:34:16 +04:00
# include <linux/smp.h>
2007-09-25 17:40:12 +04:00
# include <asm/bootinfo.h>
2013-09-18 15:29:58 +04:00
# include <bcm47xx.h>
# include <bcm47xx_board.h>
2007-09-25 17:41:24 +04:00
2013-09-20 01:40:09 +04:00
static char bcm47xx_system_type [ 20 ] = " Broadcom BCM47XX " ;
2013-09-18 15:29:58 +04:00
2007-09-25 17:40:12 +04:00
const char * get_system_type ( void )
{
2013-09-20 01:40:09 +04:00
return bcm47xx_system_type ;
}
2013-09-18 15:29:58 +04:00
2013-09-20 01:40:09 +04:00
__init void bcm47xx_set_system_type ( u16 chip_id )
{
snprintf ( bcm47xx_system_type , sizeof ( bcm47xx_system_type ) ,
( chip_id > 0x9999 ) ? " Broadcom BCM%d " :
" Broadcom BCM%04X " ,
chip_id ) ;
2007-09-25 17:40:12 +04:00
}
2014-07-18 01:26:33 +04:00
static unsigned long lowmem __initdata ;
2007-09-25 17:41:24 +04:00
static __init void prom_init_mem ( void )
2007-09-25 17:40:12 +04:00
{
unsigned long mem ;
2010-07-28 00:12:43 +04:00
unsigned long max ;
2012-10-03 15:34:17 +04:00
unsigned long off ;
2012-10-03 15:34:16 +04:00
struct cpuinfo_mips * c = & current_cpu_data ;
2007-09-25 17:40:12 +04:00
2007-09-25 17:41:24 +04:00
/* Figure out memory size by finding aliases.
*
* We should theoretically use the mapping from CFE using cfe_enummem ( ) .
* However as the BCM47XX is mostly used on low - memory systems , we
* want to reuse the memory used by CFE ( around 4 MB ) . That means cfe_ *
* functions stop to work at some point during the boot , we should only
* call them at the beginning of the boot .
2010-07-28 00:12:43 +04:00
*
* BCM47XX uses 128 MB for addressing the ram , if the system contains
* less that that amount of ram it remaps the ram more often into the
* available space .
2007-09-25 17:41:24 +04:00
*/
2014-04-19 14:49:46 +04:00
/* Physical address, without mapping to any kernel segment */
off = CPHYSADDR ( ( unsigned long ) prom_init ) ;
/* Accessing memory after 128 MiB will cause an exception */
max = 128 < < 20 ;
for ( mem = 1 < < 20 ; mem < max ; mem + = 1 < < 20 ) {
/* Loop condition may be not enough, off may be over 1 MiB */
if ( off + mem > = max ) {
mem = max ;
2014-12-10 19:38:26 +03:00
pr_debug ( " Assume 128MB RAM \n " ) ;
2010-07-28 00:12:43 +04:00
break ;
}
2012-10-03 15:34:17 +04:00
if ( ! memcmp ( prom_init , prom_init + mem , 32 ) )
2007-09-25 17:40:12 +04:00
break ;
}
2014-07-18 01:26:33 +04:00
lowmem = mem ;
2007-09-25 17:40:12 +04:00
2012-10-03 15:34:16 +04:00
/* Ignoring the last page when ddr size is 128M. Cached
* accesses to last page is causing the processor to prefetch
* using address above 128 M stepping out of the ddr address
* space .
*/
if ( c - > cputype = = CPU_74K & & ( mem = = ( 128 < < 20 ) ) )
mem - = 0x1000 ;
2007-09-25 17:40:12 +04:00
add_memory_region ( 0 , mem , BOOT_MEM_RAM ) ;
}
2013-09-25 02:36:56 +04:00
/*
* This is the first serial on the chip common core , it is at this position
* for sb ( ssb ) and ai ( bcma ) bus .
*/
# define BCM47XX_SERIAL_ADDR (SSB_ENUM_BASE + SSB_CHIPCO_UART0_DATA)
2007-09-25 17:41:24 +04:00
void __init prom_init ( void )
{
prom_init_mem ( ) ;
2013-09-25 02:36:56 +04:00
setup_8250_early_printk_port ( CKSEG1ADDR ( BCM47XX_SERIAL_ADDR ) , 0 , 0 ) ;
2007-09-25 17:41:24 +04:00
}
2007-09-25 17:40:12 +04:00
void __init prom_free_prom_memory ( void )
{
}
2014-07-18 01:26:33 +04:00
# if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
# define EXTVBASE 0xc0000000
# define ENTRYLO(x) ((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
# include <asm/tlbflush.h>
/* Stripped version of tlb_init, with the call to build_tlb_refill_handler
* dropped . Calling it at this stage causes a hang .
*/
2015-04-28 01:47:56 +03:00
void early_tlb_init ( void )
2014-07-18 01:26:33 +04:00
{
write_c0_pagemask ( PM_DEFAULT_MASK ) ;
write_c0_wired ( 0 ) ;
temp_tlb_entry = current_cpu_data . tlbsize - 1 ;
local_flush_tlb_all ( ) ;
}
void __init bcm47xx_prom_highmem_init ( void )
{
unsigned long off = ( unsigned long ) prom_init ;
unsigned long extmem = 0 ;
bool highmem_region = false ;
if ( WARN_ON ( bcm47xx_bus_type ! = BCM47XX_BUS_TYPE_BCMA ) )
return ;
if ( bcm47xx_bus . bcma . bus . chipinfo . id = = BCMA_CHIP_ID_BCM4706 )
highmem_region = true ;
if ( lowmem ! = 128 < < 20 | | ! highmem_region )
return ;
early_tlb_init ( ) ;
/* Add one temporary TLB entry to map SDRAM Region 2.
* Physical Virtual
* 0x80000000 0xc0000000 ( 1 st : 256 MB )
* 0x90000000 0xd0000000 ( 2 nd : 256 MB )
*/
add_temporary_entry ( ENTRYLO ( 0x80000000 ) ,
ENTRYLO ( 0x80000000 + ( 256 < < 20 ) ) ,
EXTVBASE , PM_256M ) ;
off = EXTVBASE + __pa ( off ) ;
for ( extmem = 128 < < 20 ; extmem < 512 < < 20 ; extmem < < = 1 ) {
if ( ! memcmp ( prom_init , ( void * ) ( off + extmem ) , 16 ) )
break ;
}
extmem - = lowmem ;
early_tlb_init ( ) ;
if ( ! extmem )
return ;
pr_warn ( " Found %lu MiB of extra memory, but highmem is unsupported yet! \n " ,
extmem > > 20 ) ;
/* TODO: Register extra memory */
}
# endif /* defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM) */