1/* 2 * Northstar SoC main platform file. 3 * 4 */ 5 6#include <linux/types.h> 7#include <linux/init.h> 8#include <linux/kernel.h> 9#include <linux/io.h> 10#include <linux/ioport.h> 11#include <linux/platform_device.h> 12#include <linux/clk.h> 13#include <linux/delay.h> 14#include <linux/serial_8250.h> 15#include <linux/proc_fs.h> 16#include <asm/hardware/cache-l2x0.h> 17#include <asm/mach/map.h> 18#include <asm/clkdev.h> 19#include <asm/uaccess.h> 20#include <mach/clkdev.h> 21#include <mach/io_map.h> 22#include <plat/bsp.h> 23#include <plat/mpcore.h> 24#include <plat/plat-bcm5301x.h> 25 26#ifdef CONFIG_SMP 27#include <asm/spinlock.h> 28#endif 29 30static struct clk * _soc_refclk = NULL; 31 32static struct plat_serial8250_port uart_ports[] = { 33 { 34 .type = PORT_16550, 35 .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, 36 .regshift = 0, 37 .iotype = UPIO_MEM, 38 .mapbase = (resource_size_t)(PLAT_UART1_PA), 39 .membase = (void __iomem *) PLAT_UART1_VA, 40 .irq = IRQ_CCA, 41 }, 42 { 43 .type = PORT_16550, 44 .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, 45 .regshift = 0, 46 .iotype = UPIO_MEM, 47 .mapbase = (resource_size_t)(PLAT_UART2_PA), 48 .membase = (void __iomem *) PLAT_UART2_VA, 49 .irq = IRQ_CCA, 50 }, 51 { .flags = 0, }, /* List terminatoir */ 52}; 53 54static struct platform_device platform_serial_devices = { 55 .name = "serial8250", 56 .id = PLAT8250_DEV_PLATFORM, /* <linux/serial_8250.h> */ 57 .dev = { 58 .platform_data = uart_ports, 59 }, 60}; 61 62/* 63 * Map fix-mapped I/O that is needed before full MMU operation 64 */ 65void __init soc_map_io( struct clk * refclk ) 66{ 67 struct map_desc desc[2] ; 68 69 /* 70 * Map Chipcommon A & B to a fixed virtual location 71 * as these contain all the system UARTs, which are 72 * needed for low-level debugging, 73 * it have already been mapped from mach_desc earlier 74 * but that is undone from page_init() 75 */ 76 77 desc[0].virtual = IO_BASE_VA; 78 desc[0].pfn = __phys_to_pfn( IO_BASE_PA ); 79 desc[0].length = SZ_16M ; /* CCA+CCB: 0x18000000-0x18ffffff */ 80 desc[0].type = MT_DEVICE ; 81 82 iotable_init( desc, 1); 83 84 mpcore_map_io( ); 85 /* Save refclk for later use */ 86 _soc_refclk = refclk ; 87} 88 89static int soc_abort_handler(unsigned long addr, unsigned int fsr, 90 struct pt_regs *regs) 91{ 92 /* 93 * These happen for no good reason 94 * possibly left over from CFE 95 */ 96 printk( KERN_WARNING 97 "External imprecise Data abort at " 98 "addr=%#lx, fsr=%#x ignored.\n", 99 addr, fsr ); 100 101 /* Returning non-zero causes fault display and panic */ 102 return 0; 103} 104 105static void soc_aborts_enable(void) 106{ 107 u32 x; 108 109 /* Install our hook */ 110 hook_fault_code(16 + 6, soc_abort_handler, SIGBUS, 0, 111 "imprecise external abort"); 112 113 /* Enable external aborts - clear "A" bit in CPSR */ 114 115 /* Read CPSR */ 116 asm( "mrs %0,cpsr": "=&r" (x) : : ); 117 118 x &= ~ PSR_A_BIT ; 119 120 /* Update CPSR, affect bits 8-15 */ 121 asm( "msr cpsr_x,%0; nop; nop": : "r" (x) : "cc" ); 122 123} 124 125/* 126 * This SoC relies on MPCORE GIC interrupt controller 127 */ 128void __init soc_init_irq( void ) 129{ 130 mpcore_init_gic(); 131 soc_aborts_enable(); 132 133} 134 135/* 136 * Initialize SoC timers 137 */ 138void __init soc_init_timer( void ) 139{ 140 unsigned long periphclk_freq; 141 struct clk * clk ; 142 143 /* Clocks need to be setup early */ 144 soc_dmu_init( _soc_refclk ); 145 soc_cru_init( _soc_refclk ); 146 147 /* get mpcore PERIPHCLK from clock modules */ 148 clk = clk_get_sys( NULL, "periph_clk"); 149 BUG_ON( IS_ERR_OR_NULL (clk) ); 150 periphclk_freq = clk_get_rate( clk ); 151 BUG_ON( !periphclk_freq ); 152 153 /* Fire up the global MPCORE timer */ 154 mpcore_init_timer( periphclk_freq ); 155 156} 157 158 159/* 160 * Install all other SoC device drivers 161 * that are not automatically discoverable. 162 */ 163void __init soc_add_devices( void ) 164{ 165 u32 i, clk_rate = 0; 166 u8 UARTClkSel, UARTClkOvr; 167 u16 UARTClkDiv ; 168 struct clk * clk = NULL ; 169 170 i = readl( SOC_CHIPCOMON_A_BASE_VA + 0x04 ); 171 /* UARTClkSel ChipcommonA_CoreCapabilities bit 4..3 */ 172 UARTClkSel = ( i >> 3 ) & 0x3 ; 173 /* UARTClkOvr ChipcommonA_CoreCtrl bit 0 */ 174 UARTClkOvr = 1 & readl( SOC_CHIPCOMON_A_BASE_VA + 0x08 ); 175 /* UARTClkDiv: ChipcommonA_ClkDiv bits 0..7 */ 176 UARTClkDiv = 0xff & readl( SOC_CHIPCOMON_A_BASE_VA + 0xa4 ); 177 if( UARTClkDiv == 0 ) UARTClkDiv = 0x100 ; 178 179 if( UARTClkSel == 0 ) 180 { 181 /* UARTClkSel = 0 -> external reference clock source */ 182 clk = _soc_refclk ; 183 BUG_ON( !clk ); 184 clk_rate = clk_get_rate(clk); 185 } 186 else if( UARTClkSel == 1 ) 187 { 188 /* UARTClkSel = 1 -> Internal clock optionally divided */ 189 clk = clk_get_sys( NULL, "iproc_slow_clk"); 190 BUG_ON( !clk ); 191 clk_rate = clk_get_rate(clk) ; 192 if( ! UARTClkOvr ) 193 clk_rate /= UARTClkDiv; 194 } 195 196 printk( KERN_INFO "CCA UART Clock Config: Sel=%d Ovr=%d Div=%d\n", 197 UARTClkSel, UARTClkOvr, UARTClkDiv ); 198 printk( KERN_INFO "CCA UART Clock rate %uHz\n", clk_rate ); 199 200 /* fixup UART port structure */ 201 for(i = 0; i < ARRAY_SIZE(uart_ports); i++ ) 202 { 203 if( uart_ports[i].flags == 0 ) 204 break; 205 if( uart_ports[i].irq == 0 ) 206 uart_ports[i].flags |= UPF_AUTO_IRQ; 207 208 /* UART input clock source and rate */ 209 uart_ports[i].uartclk = clk_rate ; 210 } 211 212 /* Install SoC devices in the system: uarts */ 213 platform_device_register( & platform_serial_devices ); 214 215 /* Enable UART interrupt in ChipcommonA */ 216 i = readl( SOC_CHIPCOMON_A_BASE_VA + 0x24 ); 217 i |= 1 << 6; 218 writel( i, SOC_CHIPCOMON_A_BASE_VA + 0x24 ); 219 220} 221 222void plat_wake_secondary_cpu( unsigned cpu, void (* _sec_entry_va)(void) ) 223{ 224 void __iomem * rombase = NULL; 225 phys_addr_t lut_pa; 226 u32 offset, mask; 227 u32 val ; 228 229 mask = ( 1UL << PAGE_SHIFT) -1 ; 230 231 lut_pa = SOC_ROM_BASE_PA & ~mask ; 232 offset = SOC_ROM_BASE_PA & mask ; 233 offset += SOC_ROM_LUT_OFF; 234 235 rombase = ioremap( lut_pa, PAGE_SIZE ); 236 if( rombase == NULL ) 237 return; 238 val = virt_to_phys( _sec_entry_va ); 239 240 writel( val, rombase + offset ); 241 242 smp_wmb(); /* probably not needed - io regs are not cached */ 243 244#ifdef CONFIG_SMP 245 dsb_sev(); /* Exit WFI */ 246#endif 247 mb(); 248 249 iounmap( rombase ); 250} 251 252#ifdef CONFIG_CACHE_L310 253/* 254 * SoC initialization that need to be done early, 255 * e.g. L2 cache, clock, I/O pin mux, power management 256 */ 257static int __init bcm5301_pl310_init( void ) 258{ 259 void __iomem *l2cache_base; 260 u32 auxctl_val, auxctl_msk ; 261 extern void __init l310_init( void __iomem *, u32, u32, int ); 262 263 /* Default AUXCTL modifiers */ 264 auxctl_val = 0UL; 265 auxctl_msk = ~0UL ; 266 267 /* Customize AUXCTL */ 268 auxctl_val |= 0 << 0 ; /* Full line of zero Enable - requires A9 cfg */ 269 auxctl_val |= 1 << 25; /* Cache replacement policy - round robin */ 270 auxctl_val |= 1 << 29; /* Instruction prefetch enable */ 271 auxctl_val |= 1 << 28; /* Data prefetch enable */ 272 auxctl_val |= 1 << 30; /* Early BRESP enable */ 273 274 l2cache_base = ioremap( L2CC_BASE_PA, SZ_4K ); 275 276 /* Configure using default aux control value */ 277 if( l2cache_base != NULL ) 278 l310_init( l2cache_base, auxctl_val, auxctl_msk, 32 ); 279 280 return 0; 281} 282early_initcall( bcm5301_pl310_init ); 283#endif 284