diff options
author | Kevin Hilman <khilman@deeprootsystems.com> | 2009-03-20 20:29:01 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2009-04-23 12:31:00 -0400 |
commit | c5b736d093217890245a33e9a98fe92d6f3529bf (patch) | |
tree | 387755844593ae99cdc38b4556d775a100cde7da /arch/arm/mach-davinci/psc.c | |
parent | e653034e66ec406f37427f588115badc6fc6af64 (diff) |
davinci: major rework of clock, PLL, PSC infrastructure
This is a significant rework of the low-level clock, PLL and Power
Sleep Controller (PSC) implementation for the DaVinci family. The
primary goal is to have better modeling if the hardware clocks and
features with the aim of DVFS functionality.
Highlights:
- model PLLs and all PLL-derived clocks
- model parent/child relationships of PLLs and clocks
- convert to new clkdev layer
- view clock frequency and refcount via /proc/davinci_clocks
Special thanks to significant contributions and testing by David
Brownell.
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/psc.c')
-rw-r--r-- | arch/arm/mach-davinci/psc.c | 81 |
1 files changed, 23 insertions, 58 deletions
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 58754f066d5b..c5098831741f 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | 25 | ||
26 | #include <mach/cputype.h> | ||
26 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
27 | #include <mach/psc.h> | 28 | #include <mach/psc.h> |
28 | #include <mach/mux.h> | 29 | #include <mach/mux.h> |
@@ -36,76 +37,57 @@ | |||
36 | #define MDSTAT 0x800 | 37 | #define MDSTAT 0x800 |
37 | #define MDCTL 0xA00 | 38 | #define MDCTL 0xA00 |
38 | 39 | ||
39 | /* System control register offsets */ | ||
40 | #define VDD3P3V_PWDN 0x48 | ||
41 | 40 | ||
42 | static void davinci_psc_mux(unsigned int id) | 41 | /* Return nonzero iff the domain's clock is active */ |
42 | int __init davinci_psc_is_clk_active(unsigned int id) | ||
43 | { | 43 | { |
44 | switch (id) { | 44 | void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE); |
45 | case DAVINCI_LPSC_ATA: | 45 | u32 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); |
46 | davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1); | 46 | |
47 | davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1); | 47 | /* if clocked, state can be "Enable" or "SyncReset" */ |
48 | break; | 48 | return mdstat & BIT(12); |
49 | case DAVINCI_LPSC_MMC_SD: | ||
50 | /* VDD power manupulations are done in U-Boot for CPMAC | ||
51 | * so applies to MMC as well | ||
52 | */ | ||
53 | /*Set up the pull regiter for MMC */ | ||
54 | davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN); | ||
55 | davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0); | ||
56 | break; | ||
57 | case DAVINCI_LPSC_I2C: | ||
58 | davinci_mux_peripheral(DAVINCI_MUX_I2C, 1); | ||
59 | break; | ||
60 | case DAVINCI_LPSC_McBSP: | ||
61 | davinci_mux_peripheral(DAVINCI_MUX_ASP, 1); | ||
62 | break; | ||
63 | default: | ||
64 | break; | ||
65 | } | ||
66 | } | 49 | } |
67 | 50 | ||
68 | /* Enable or disable a PSC domain */ | 51 | /* Enable or disable a PSC domain */ |
69 | void davinci_psc_config(unsigned int domain, unsigned int id, char enable) | 52 | void davinci_psc_config(unsigned int domain, unsigned int id, char enable) |
70 | { | 53 | { |
71 | u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; | 54 | u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; |
55 | void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE); | ||
72 | 56 | ||
73 | mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); | 57 | mdctl = __raw_readl(psc_base + MDCTL + 4 * id); |
74 | if (enable) | 58 | if (enable) |
75 | mdctl |= 0x00000003; /* Enable Module */ | 59 | mdctl |= 0x00000003; /* Enable Module */ |
76 | else | 60 | else |
77 | mdctl &= 0xFFFFFFF2; /* Disable Module */ | 61 | mdctl &= 0xFFFFFFE2; /* Disable Module */ |
78 | davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); | 62 | __raw_writel(mdctl, psc_base + MDCTL + 4 * id); |
79 | 63 | ||
80 | pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT); | 64 | pdstat = __raw_readl(psc_base + PDSTAT); |
81 | if ((pdstat & 0x00000001) == 0) { | 65 | if ((pdstat & 0x00000001) == 0) { |
82 | pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 66 | pdctl1 = __raw_readl(psc_base + PDCTL1); |
83 | pdctl1 |= 0x1; | 67 | pdctl1 |= 0x1; |
84 | davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 68 | __raw_writel(pdctl1, psc_base + PDCTL1); |
85 | 69 | ||
86 | ptcmd = 1 << domain; | 70 | ptcmd = 1 << domain; |
87 | davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); | 71 | __raw_writel(ptcmd, psc_base + PTCMD); |
88 | 72 | ||
89 | do { | 73 | do { |
90 | epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 74 | epcpr = __raw_readl(psc_base + EPCPR); |
91 | EPCPR); | ||
92 | } while ((((epcpr >> domain) & 1) == 0)); | 75 | } while ((((epcpr >> domain) & 1) == 0)); |
93 | 76 | ||
94 | pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 77 | pdctl1 = __raw_readl(psc_base + PDCTL1); |
95 | pdctl1 |= 0x100; | 78 | pdctl1 |= 0x100; |
96 | davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | 79 | __raw_writel(pdctl1, psc_base + PDCTL1); |
97 | 80 | ||
98 | do { | 81 | do { |
99 | ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 82 | ptstat = __raw_readl(psc_base + |
100 | PTSTAT); | 83 | PTSTAT); |
101 | } while (!(((ptstat >> domain) & 1) == 0)); | 84 | } while (!(((ptstat >> domain) & 1) == 0)); |
102 | } else { | 85 | } else { |
103 | ptcmd = 1 << domain; | 86 | ptcmd = 1 << domain; |
104 | davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); | 87 | __raw_writel(ptcmd, psc_base + PTCMD); |
105 | 88 | ||
106 | do { | 89 | do { |
107 | ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 90 | ptstat = __raw_readl(psc_base + PTSTAT); |
108 | PTSTAT); | ||
109 | } while (!(((ptstat >> domain) & 1) == 0)); | 91 | } while (!(((ptstat >> domain) & 1) == 0)); |
110 | } | 92 | } |
111 | 93 | ||
@@ -115,23 +97,6 @@ void davinci_psc_config(unsigned int domain, unsigned int id, char enable) | |||
115 | mdstat_mask = 0x2; | 97 | mdstat_mask = 0x2; |
116 | 98 | ||
117 | do { | 99 | do { |
118 | mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | 100 | mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); |
119 | MDSTAT + 4 * id); | ||
120 | } while (!((mdstat & 0x0000001F) == mdstat_mask)); | 101 | } while (!((mdstat & 0x0000001F) == mdstat_mask)); |
121 | |||
122 | if (enable) | ||
123 | davinci_psc_mux(id); | ||
124 | } | ||
125 | |||
126 | void __init davinci_psc_init(void) | ||
127 | { | ||
128 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1); | ||
129 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1); | ||
130 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1); | ||
131 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1); | ||
132 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1); | ||
133 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1); | ||
134 | |||
135 | /* Turn on WatchDog timer LPSC. Needed for RESET to work */ | ||
136 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1); | ||
137 | } | 102 | } |