2012-08-02 11:17:51 +03:00
/*
* Power Management Service Unit ( PMSU ) support for Armada 370 / XP platforms .
*
* Copyright ( C ) 2012 Marvell
*
* Yehuda Yitschak < yehuday @ marvell . com >
* Gregory Clement < gregory . clement @ free - electrons . com >
* Thomas Petazzoni < thomas . petazzoni @ free - electrons . com >
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*
* The Armada 370 and Armada XP SOCs have a power management service
* unit which is responsible for powering down and waking up CPUs and
* other SOC units
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/of_address.h>
# include <linux/io.h>
# include <linux/smp.h>
# include <asm/smp_plat.h>
2013-11-07 17:02:38 +08:00
# include "pmsu.h"
2012-08-02 11:17:51 +03:00
static void __iomem * pmsu_mp_base ;
static void __iomem * pmsu_reset_base ;
# define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x24)
# define PMSU_RESET_CTL_OFFSET(cpu) (cpu * 0x8)
static struct of_device_id of_pmsu_table [ ] = {
{ . compatible = " marvell,armada-370-xp-pmsu " } ,
{ /* end of list */ } ,
} ;
# ifdef CONFIG_SMP
int armada_xp_boot_cpu ( unsigned int cpu_id , void * boot_addr )
{
int reg , hw_cpu ;
if ( ! pmsu_mp_base | | ! pmsu_reset_base ) {
pr_warn ( " Can't boot CPU. PMSU is uninitialized \n " ) ;
return 1 ;
}
hw_cpu = cpu_logical_map ( cpu_id ) ;
writel ( virt_to_phys ( boot_addr ) , pmsu_mp_base +
PMSU_BOOT_ADDR_REDIRECT_OFFSET ( hw_cpu ) ) ;
/* Release CPU from reset by clearing reset bit*/
reg = readl ( pmsu_reset_base + PMSU_RESET_CTL_OFFSET ( hw_cpu ) ) ;
reg & = ( ~ 0x1 ) ;
writel ( reg , pmsu_reset_base + PMSU_RESET_CTL_OFFSET ( hw_cpu ) ) ;
return 0 ;
}
# endif
2013-11-07 17:02:38 +08:00
static int __init armada_370_xp_pmsu_init ( void )
2012-08-02 11:17:51 +03:00
{
struct device_node * np ;
np = of_find_matching_node ( NULL , of_pmsu_table ) ;
if ( np ) {
pr_info ( " Initializing Power Management Service Unit \n " ) ;
pmsu_mp_base = of_iomap ( np , 0 ) ;
pmsu_reset_base = of_iomap ( np , 1 ) ;
2013-08-27 12:41:14 +08:00
of_node_put ( np ) ;
2012-08-02 11:17:51 +03:00
}
return 0 ;
}
early_initcall ( armada_370_xp_pmsu_init ) ;