1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
/*
* OMAP2xxx APLL clock control functions
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* 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.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/clock.h>
#include <plat/prcm.h>
#include "clock.h"
#include "clock2xxx.h"
#include "cm2xxx_3xxx.h"
#include "cm-regbits-24xx.h"
/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
#define EN_APLL_STOPPED 0
#define EN_APLL_LOCKED 3
/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
#define APLLS_CLKIN_19_2MHZ 0
#define APLLS_CLKIN_13MHZ 2
#define APLLS_CLKIN_12MHZ 3
void __iomem *cm_idlest_pll;
/* Private functions */
/* Enable an APLL if off */
static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask)
{
u32 cval, apll_mask;
apll_mask = EN_APLL_LOCKED << clk->enable_bit;
cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
if ((cval & apll_mask) == apll_mask)
return 0; /* apll already enabled */
cval &= ~apll_mask;
cval |= apll_mask;
cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
omap2_cm_wait_idlest(cm_idlest_pll, status_mask,
OMAP24XX_CM_IDLEST_VAL, clk->name);
/*
* REVISIT: Should we return an error code if omap2_wait_clock_ready()
* fails?
*/
return 0;
}
static int omap2_clk_apll96_enable(struct clk *clk)
{
return omap2_clk_apll_enable(clk, OMAP24XX_ST_96M_APLL_MASK);
}
static int omap2_clk_apll54_enable(struct clk *clk)
{
return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL_MASK);
}
/* Stop APLL */
static void omap2_clk_apll_disable(struct clk *clk)
{
u32 cval;
cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
}
/* Public data */
const struct clkops clkops_apll96 = {
.enable = omap2_clk_apll96_enable,
.disable = omap2_clk_apll_disable,
};
const struct clkops clkops_apll54 = {
.enable = omap2_clk_apll54_enable,
.disable = omap2_clk_apll_disable,
};
/* Public functions */
u32 omap2xxx_get_apll_clkin(void)
{
u32 aplls, srate = 0;
aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
aplls &= OMAP24XX_APLLS_CLKIN_MASK;
aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
if (aplls == APLLS_CLKIN_19_2MHZ)
srate = 19200000;
else if (aplls == APLLS_CLKIN_13MHZ)
srate = 13000000;
else if (aplls == APLLS_CLKIN_12MHZ)
srate = 12000000;
return srate;
}
|