/*++
linux/arch/arm/mach-wmt/wmt_clock.c
Copyright (c) 2013 WonderMedia Technologies, Inc.
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 program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see .
WonderMedia Technologies, Inc.
10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
--*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef CONFIG_OTZONE_ASYNC_NOTIFY_SUPPORT
#include
#endif
struct smc_cdata {
unsigned int fn;
unsigned int arg;
unsigned int ret;
};
/**
* @brief
*
* @param otz_smc handler for secondary cores
*
* @return
*/
static u32 wmt_smc1(u32 fn, u32 arg)
{
register u32 r0 asm("r0") = fn;
register u32 r1 asm("r1") = arg;
do {
asm volatile(
".arch_extension sec\n\t"
__asmeq("%0", "r0")
__asmeq("%1", "r0")
__asmeq("%2", "r1")
"smc #0 @ switch to secure world\n"
: "=r" (r0)
: "r" (r0), "r" (r1));
} while (0);
return r0;
}
static void wmt_secondary_smc_handler(void *info)
{
struct smc_cdata *cd = (struct smc_cdata *)info;
rmb();
cd->ret = wmt_smc1(cd->fn, cd->arg);
wmb();
}
/**
* @brief
*
* @param This function takes care of posting the smc to the
* primary core
*
* @return
*/
static unsigned int post_otz_smc(int cpu_id, u32 fn, u32 arg)
{
struct smc_cdata cd;
cd.fn = fn;
cd.arg = arg;
wmb();
smp_call_function_single(0, wmt_secondary_smc_handler,
(void *)&cd, 1);
rmb();
return cd.ret;
}
/**
* @brief
*
* @param otz_smc wrapper to handle the multi core case
*
* @return
*/
unsigned int wmt_smc(u32 fn, u32 arg)
{
int cpu_id = smp_processor_id();
unsigned int ret;
if (cpu_id != 0) {
mb();
ret = post_otz_smc(cpu_id, fn, arg); /* post it to primary */
} else {
ret = wmt_smc1(fn, arg); /* called directly on primary core */
}
return ret;
}
MODULE_AUTHOR("WonderMedia Technologies, Inc");
MODULE_DESCRIPTION("WMT SMC Function");
MODULE_LICENSE("Dual BSD/GPL");