/* * linux/arch/arm/kernel/smp_scu.c * * Copyright (C) 2002 ARM Ltd. * All Rights Reserved * * 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/init.h> #include <linux/io.h> #include <asm/smp_scu.h> #include <asm/cacheflush.h> #define SCU_CTRL 0x00 #define SCU_CONFIG 0x04 #define SCU_CPU_STATUS 0x08 #define SCU_INVALIDATE 0x0c #define SCU_FPGA_REVISION 0x10 /* * Get the number of CPU cores from the SCU configuration */ unsigned int __init scu_get_core_count(void __iomem *scu_base) { unsigned int ncores = __raw_readl(scu_base + SCU_CONFIG); return (ncores & 0x03) + 1; } /* * Enable the SCU */ void __init scu_enable(void __iomem *scu_base) { u32 scu_ctrl; scu_ctrl = __raw_readl(scu_base + SCU_CTRL); /* already enabled? */ if (scu_ctrl & 1) return; scu_ctrl |= 1; __raw_writel(scu_ctrl, scu_base + SCU_CTRL); /* * Ensure that the data accessed by CPU0 before the SCU was * initialised is visible to the other CPUs. */ flush_cache_all(); } /* * Set the executing CPUs power mode as defined. This will be in * preparation for it executing a WFI instruction. * * This function must be called with preemption disabled, and as it * has the side effect of disabling coherency, caches must have been * flushed. Interrupts must also have been disabled. */ int scu_power_mode(void __iomem *scu_base, unsigned int mode) { unsigned int val; int cpu = smp_processor_id(); if (mode > 3 || mode == 1 || cpu > 3) return -EINVAL; val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; val |= mode; __raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu); return 0; }