2005-04-16 15:20:36 -07:00
/*
* linux / arch / arm / mach - integrator / core . c
*
* Copyright ( C ) 2000 - 2003 Deep Blue Solutions Ltd
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 , as
* published by the Free Software Foundation .
*/
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/device.h>
2012-08-04 10:31:24 +00:00
# include <linux/export.h>
2005-04-16 15:20:36 -07:00
# include <linux/spinlock.h>
# include <linux/interrupt.h>
2006-07-01 22:32:32 +01:00
# include <linux/irq.h>
2010-05-22 19:47:18 +01:00
# include <linux/memblock.h>
2005-04-16 15:20:36 -07:00
# include <linux/sched.h>
2005-06-18 10:15:46 +01:00
# include <linux/smp.h>
2006-01-07 13:52:45 +00:00
# include <linux/amba/bus.h>
2006-03-26 23:13:39 +01:00
# include <linux/amba/serial.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2012-11-02 01:31:10 +01:00
# include <linux/stat.h>
2013-06-16 02:44:27 +02:00
# include <linux/of.h>
# include <linux/of_address.h>
2005-04-16 15:20:36 -07:00
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
2010-01-14 19:59:37 +00:00
# include <mach/platform.h>
2012-02-26 10:46:48 +01:00
2011-12-20 11:55:19 +01:00
# include <asm/mach-types.h>
2005-04-16 15:20:36 -07:00
# include <asm/mach/time.h>
2010-05-22 18:18:57 +01:00
# include <asm/pgtable.h>
2005-04-16 15:20:36 -07:00
2013-06-16 02:44:27 +02:00
# include "cm.h"
2012-09-06 09:08:47 +01:00
# include "common.h"
2009-07-03 08:44:46 -05:00
static DEFINE_RAW_SPINLOCK ( cm_lock ) ;
2013-06-16 02:44:27 +02:00
static void __iomem * cm_base ;
2005-04-16 15:20:36 -07:00
2013-10-10 14:11:18 +02:00
/**
* cm_get - get the value from the CM_CTRL register
*/
u32 cm_get ( void )
{
return readl ( cm_base + INTEGRATOR_HDR_CTRL_OFFSET ) ;
}
2005-04-16 15:20:36 -07:00
/**
* cm_control - update the CM_CTRL register .
* @ mask : bits to change
* @ set : bits to set
*/
void cm_control ( u32 mask , u32 set )
{
unsigned long flags ;
u32 val ;
2009-07-03 08:44:46 -05:00
raw_spin_lock_irqsave ( & cm_lock , flags ) ;
2013-06-16 02:44:27 +02:00
val = readl ( cm_base + INTEGRATOR_HDR_CTRL_OFFSET ) & ~ mask ;
writel ( val | set , cm_base + INTEGRATOR_HDR_CTRL_OFFSET ) ;
2009-07-03 08:44:46 -05:00
raw_spin_unlock_irqrestore ( & cm_lock , flags ) ;
2005-04-16 15:20:36 -07:00
}
2013-06-16 02:44:27 +02:00
static const char * integrator_arch_str ( u32 id )
{
switch ( ( id > > 16 ) & 0xff ) {
case 0x00 :
return " ASB little-endian " ;
case 0x01 :
return " AHB little-endian " ;
case 0x03 :
return " AHB-Lite system bus, bi-endian " ;
case 0x04 :
return " AHB " ;
case 0x08 :
return " AHB system bus, ASB processor bus " ;
default :
return " Unknown " ;
}
}
static const char * integrator_fpga_str ( u32 id )
{
switch ( ( id > > 12 ) & 0xf ) {
case 0x01 :
return " XC4062 " ;
case 0x02 :
return " XC4085 " ;
case 0x03 :
return " XVC600 " ;
case 0x04 :
return " EPM7256AE (Altera PLD) " ;
default :
return " Unknown " ;
}
}
void cm_clear_irqs ( void )
{
/* disable core module IRQs */
writel ( 0xffffffffU , cm_base + INTEGRATOR_HDR_IC_OFFSET +
IRQ_ENABLE_CLEAR ) ;
}
static const struct of_device_id cm_match [ ] = {
{ . compatible = " arm,core-module-integrator " } ,
{ } ,
} ;
void cm_init ( void )
{
struct device_node * cm = of_find_matching_node ( NULL , cm_match ) ;
u32 val ;
if ( ! cm ) {
pr_crit ( " no core module node found in device tree \n " ) ;
return ;
}
cm_base = of_iomap ( cm , 0 ) ;
if ( ! cm_base ) {
pr_crit ( " could not remap core module \n " ) ;
return ;
}
cm_clear_irqs ( ) ;
val = readl ( cm_base + INTEGRATOR_HDR_ID_OFFSET ) ;
pr_info ( " Detected ARM core module: \n " ) ;
pr_info ( " Manufacturer: %02x \n " , ( val > > 24 ) ) ;
pr_info ( " Architecture: %s \n " , integrator_arch_str ( val ) ) ;
pr_info ( " FPGA: %s \n " , integrator_fpga_str ( val ) ) ;
pr_info ( " Build: %02x \n " , ( val > > 4 ) & 0xFF ) ;
pr_info ( " Rev: %c \n " , ( ' A ' + ( val & 0x03 ) ) ) ;
}
2010-05-22 18:18:57 +01:00
/*
* We need to stop things allocating the low memory ; ideally we need a
* better implementation of GFP_DMA which does not assume that DMA - able
* memory starts at zero .
*/
void __init integrator_reserve ( void )
{
2010-05-22 19:47:18 +01:00
memblock_reserve ( PHYS_OFFSET , __pa ( swapper_pg_dir ) - PHYS_OFFSET ) ;
2010-05-22 18:18:57 +01:00
}
2011-11-03 19:54:37 +00:00
/*
* To reset , we hit the on - board reset register in the system FPGA
*/
2013-07-08 16:01:40 -07:00
void integrator_restart ( enum reboot_mode mode , const char * cmd )
2011-11-03 19:54:37 +00:00
{
cm_control ( CM_CTRL_RESET , CM_CTRL_RESET ) ;
}
2012-11-02 01:31:10 +01:00
static u32 integrator_id ;
static ssize_t intcp_get_manf ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
return sprintf ( buf , " %02x \n " , integrator_id > > 24 ) ;
}
static struct device_attribute intcp_manf_attr =
__ATTR ( manufacturer , S_IRUGO , intcp_get_manf , NULL ) ;
static ssize_t intcp_get_arch ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
2013-06-16 02:44:27 +02:00
return sprintf ( buf , " %s \n " , integrator_arch_str ( integrator_id ) ) ;
2012-11-02 01:31:10 +01:00
}
static struct device_attribute intcp_arch_attr =
__ATTR ( architecture , S_IRUGO , intcp_get_arch , NULL ) ;
static ssize_t intcp_get_fpga ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
2013-06-16 02:44:27 +02:00
return sprintf ( buf , " %s \n " , integrator_fpga_str ( integrator_id ) ) ;
2012-11-02 01:31:10 +01:00
}
static struct device_attribute intcp_fpga_attr =
__ATTR ( fpga , S_IRUGO , intcp_get_fpga , NULL ) ;
static ssize_t intcp_get_build ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
return sprintf ( buf , " %02x \n " , ( integrator_id > > 4 ) & 0xFF ) ;
}
static struct device_attribute intcp_build_attr =
__ATTR ( build , S_IRUGO , intcp_get_build , NULL ) ;
void integrator_init_sysfs ( struct device * parent , u32 id )
{
integrator_id = id ;
device_create_file ( parent , & intcp_manf_attr ) ;
device_create_file ( parent , & intcp_arch_attr ) ;
device_create_file ( parent , & intcp_fpga_attr ) ;
device_create_file ( parent , & intcp_build_attr ) ;
}