看看
void platform_clock_init(void)
{
if (platform_is_msm8939() || platform_is_msm8929())
msm8939_clock_override();
clk_init(msm_clocks_8916, ARRAY_SIZE(msm_clocks_8916));
}
先判断平台
然后
void msm8939_clock_override()
{
mdss_mdp_clk_src.freq_tbl = ftbl_mdss_mdp_clk_src;
}
这个有讲究
static struct clk_freq_tbl ftbl_mdss_mdp_clk_src[] = {
F_MM( 50000000, gpll0, 16, 0, 0),
F_MM( 80000000, gpll0, 10, 0, 0),
F_MM( 100000000, gpll0, 8, 0, 0),
F_MM( 153600000, gpll1, 4, 0, 0),
F_MM( 160000000, gpll0, 5, 0, 0),
F_MM( 177780000, gpll0, 4.5, 0, 0),
F_MM( 200000000, gpll0, 4, 0, 0),
F_MM( 266670000, gpll0, 3, 0, 0),
F_MM( 307200000, gpll1, 2, 0, 0),
F_END
};
看看
#define F_MM(f, s, div, m, n) \
{ \
.freq_hz = (f), \
.src_clk = &s##_clk_src.c, \
.m_val = (m), \
.n_val = ~((n)-(m)) * !!(n), \
.d_val = ~(n),\
.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
| BVAL(10, 8, s##_mm_source_val), \
}
然后看
void clk_init(struct clk_lookup *clist, unsigned num)
{
if(clist && num)
{
msm_clk_list.clist = (struct clk_lookup *)clist;
msm_clk_list.num = num;
}
}
这个
static struct clk_lookup msm_clocks_8916[] =
{
CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
CLK_LOOKUP("sdc1_core_clk", gcc_sdcc1_apps_clk.c),
};
看看
#define CLK_LOOKUP(con, c) { .con_id = con, .clk = &c }
再看
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
也就是多用宏定义来完成一些值
接着是第三个函数
void qgic_init(void)
{
qgic_dist_init();
qgic_cpu_init();
}
一个一个看
/* Intialize distributor */
static void qgic_dist_init(void)
{
uint32_t i;
uint32_t num_irq = 0;
uint32_t cpumask;
cpumask = qgic_get_cpumask();
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
/* Disabling GIC */
writel(0, GIC_DIST_CTRL); //#define writel(v, a) (*REG32(a) = (v))
/*
* Find out how many interrupts are supported.
*/
num_irq = readl(GIC_DIST_CTR) & 0x1f; //#define readl(a) (*REG32(a))
num_irq = (num_irq + 1) * 32;
/* Set each interrupt line to use N-N software model
* and edge sensitive, active high
*/
for (i = 32; i < num_irq; i += 16)
writel(0xffffffff, GIC_DIST_CONFIG + i * 4 / 16);
writel(0xffffffff, GIC_DIST_CONFIG + 4);
/* Set up interrupts for this CPU */
for (i = 32; i < num_irq; i += 4)
writel(cpumask, GIC_DIST_TARGET + i * 4 / 4);
/* Set priority of all interrupts */
/*
* In bootloader we dont care about priority so
* setting up equal priorities for all
*/
for (i = 0; i < num_irq; i += 4)
writel(0xa0a0a0a0, GIC_DIST_PRI + i * 4 / 4);
/* Disabling interrupts */
for (i = 0; i < num_irq; i += 32)
writel(0xffffffff, GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
writel(0x0000ffff, GIC_DIST_ENABLE_SET);
/*Enabling GIC */
writel(1, GIC_DIST_CTRL);
}
还有一个
static void qgic_cpu_init(void)
{
writel(0xf0, GIC_CPU_PRIMASK);
writel(1, GIC_CPU_CTRL);
}
看看第四个
void qtimer_init()
{
ticks_per_sec = qtimer_get_frequency();
}
接着
/* Function to return the frequency of the timer */
uint32_t qtimer_get_frequency()
{
uint32_t freq;
/* Read the Global counter frequency */
__asm__ volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq));
return freq;
}
看看第五个
void scm_init()
{
int ret;
ret = scm_arm_support_available(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
if (ret)
dprintf(CRITICAL, "Failed to initialize SCM\n");
}
接着
static int scm_arm_support_available(uint32_t svc_id, uint32_t cmd_id)
{
int ret;
ret = is_scm_call_available(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
if (ret > 0)
scm_arm_support = true;
return ret;
}
最后
int is_scm_call_available(uint32_t svc_id, uint32_t cmd_id)
{
uint32_t ret;
scmcall_arg scm_arg = {0};
scmcall_ret scm_ret = {0};
scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
scm_arg.x1 = MAKE_SCM_ARGS(0x1);
scm_arg.x2 = MAKE_SIP_SCM_CMD(svc_id, cmd_id);
ret = scm_call2(&scm_arg, &scm_ret);
if (!ret)
return scm_ret.x1;
return ret;
}
typedef struct {
<span style="white-space:pre"> </span>uint32_t x0;/* command ID details as per ARMv8 spec :
<span style="white-space:pre"> </span>0:7 command, 8:15 service id
<span style="white-space:pre"> </span>0x02000000: SIP calls
<span style="white-space:pre"> </span>30: SMC32 or SMC64
<span style="white-space:pre"> </span>31: Standard or fast calls*/
<span style="white-space:pre"> </span>uint32_t x1; /* # of args and attributes for buffers
<span style="white-space:pre"> </span> * 0-3: arg #
<span style="white-space:pre"> </span> * 4-5: type of arg1
<span style="white-space:pre"> </span> * 6-7: type of arg2
<span style="white-space:pre"> </span> * :
<span style="white-space:pre"> </span> * :
<span style="white-space:pre"> </span> * 20-21: type of arg8
<span style="white-space:pre"> </span> * 22-23: type of arg9
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>uint32_t x2; /* Param1 */
<span style="white-space:pre"> </span>uint32_t x3; /* Param2 */
<span style="white-space:pre"> </span>uint32_t x4; /* Param3 */
<span style="white-space:pre"> </span>uint32_t x5[10]; /* Indirect parameter list */
<span style="white-space:pre"> </span>uint32_t atomic; /* To indicate if its standard or fast call */
} scmcall_arg;
完成一些初始化,需要porting guide来看