2 * Atheros AR71XX/AR724X/AR913X common routines
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/err.h>
15 #include <linux/clk.h>
17 #include <asm/mach-ath79/ath79.h>
18 #include <asm/mach-ath79/ar71xx_regs.h>
21 #define AR71XX_BASE_FREQ 40000000
22 #define AR724X_BASE_FREQ 5000000
23 #define AR913X_BASE_FREQ 5000000
29 static struct clk ath79_ref_clk
;
30 static struct clk ath79_cpu_clk
;
31 static struct clk ath79_ddr_clk
;
32 static struct clk ath79_ahb_clk
;
33 static struct clk ath79_wdt_clk
;
34 static struct clk ath79_uart_clk
;
36 static void __init
ar71xx_clocks_init(void)
42 ath79_ref_clk
.rate
= AR71XX_BASE_FREQ
;
44 pll
= ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG
);
46 div
= ((pll
>> AR71XX_PLL_DIV_SHIFT
) & AR71XX_PLL_DIV_MASK
) + 1;
47 freq
= div
* ath79_ref_clk
.rate
;
49 div
= ((pll
>> AR71XX_CPU_DIV_SHIFT
) & AR71XX_CPU_DIV_MASK
) + 1;
50 ath79_cpu_clk
.rate
= freq
/ div
;
52 div
= ((pll
>> AR71XX_DDR_DIV_SHIFT
) & AR71XX_DDR_DIV_MASK
) + 1;
53 ath79_ddr_clk
.rate
= freq
/ div
;
55 div
= (((pll
>> AR71XX_AHB_DIV_SHIFT
) & AR71XX_AHB_DIV_MASK
) + 1) * 2;
56 ath79_ahb_clk
.rate
= ath79_cpu_clk
.rate
/ div
;
58 ath79_wdt_clk
.rate
= ath79_ahb_clk
.rate
;
59 ath79_uart_clk
.rate
= ath79_ahb_clk
.rate
;
62 static void __init
ar724x_clocks_init(void)
68 ath79_ref_clk
.rate
= AR724X_BASE_FREQ
;
69 pll
= ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG
);
71 div
= ((pll
>> AR724X_PLL_DIV_SHIFT
) & AR724X_PLL_DIV_MASK
);
72 freq
= div
* ath79_ref_clk
.rate
;
74 div
= ((pll
>> AR724X_PLL_REF_DIV_SHIFT
) & AR724X_PLL_REF_DIV_MASK
);
77 ath79_cpu_clk
.rate
= freq
;
79 div
= ((pll
>> AR724X_DDR_DIV_SHIFT
) & AR724X_DDR_DIV_MASK
) + 1;
80 ath79_ddr_clk
.rate
= freq
/ div
;
82 div
= (((pll
>> AR724X_AHB_DIV_SHIFT
) & AR724X_AHB_DIV_MASK
) + 1) * 2;
83 ath79_ahb_clk
.rate
= ath79_cpu_clk
.rate
/ div
;
85 ath79_wdt_clk
.rate
= ath79_ahb_clk
.rate
;
86 ath79_uart_clk
.rate
= ath79_ahb_clk
.rate
;
89 static void __init
ar913x_clocks_init(void)
95 ath79_ref_clk
.rate
= AR913X_BASE_FREQ
;
96 pll
= ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG
);
98 div
= ((pll
>> AR913X_PLL_DIV_SHIFT
) & AR913X_PLL_DIV_MASK
);
99 freq
= div
* ath79_ref_clk
.rate
;
101 ath79_cpu_clk
.rate
= freq
;
103 div
= ((pll
>> AR913X_DDR_DIV_SHIFT
) & AR913X_DDR_DIV_MASK
) + 1;
104 ath79_ddr_clk
.rate
= freq
/ div
;
106 div
= (((pll
>> AR913X_AHB_DIV_SHIFT
) & AR913X_AHB_DIV_MASK
) + 1) * 2;
107 ath79_ahb_clk
.rate
= ath79_cpu_clk
.rate
/ div
;
109 ath79_wdt_clk
.rate
= ath79_ahb_clk
.rate
;
110 ath79_uart_clk
.rate
= ath79_ahb_clk
.rate
;
113 void __init
ath79_clocks_init(void)
116 ar71xx_clocks_init();
117 else if (soc_is_ar724x())
118 ar724x_clocks_init();
119 else if (soc_is_ar913x())
120 ar913x_clocks_init();
124 pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, "
126 ath79_cpu_clk
.rate
/ 1000000,
127 (ath79_cpu_clk
.rate
/ 1000) % 1000,
128 ath79_ddr_clk
.rate
/ 1000000,
129 (ath79_ddr_clk
.rate
/ 1000) % 1000,
130 ath79_ahb_clk
.rate
/ 1000000,
131 (ath79_ahb_clk
.rate
/ 1000) % 1000,
132 ath79_ref_clk
.rate
/ 1000000,
133 (ath79_ref_clk
.rate
/ 1000) % 1000);
139 struct clk
*clk_get(struct device
*dev
, const char *id
)
141 if (!strcmp(id
, "ref"))
142 return &ath79_ref_clk
;
144 if (!strcmp(id
, "cpu"))
145 return &ath79_cpu_clk
;
147 if (!strcmp(id
, "ddr"))
148 return &ath79_ddr_clk
;
150 if (!strcmp(id
, "ahb"))
151 return &ath79_ahb_clk
;
153 if (!strcmp(id
, "wdt"))
154 return &ath79_wdt_clk
;
156 if (!strcmp(id
, "uart"))
157 return &ath79_uart_clk
;
159 return ERR_PTR(-ENOENT
);
161 EXPORT_SYMBOL(clk_get
);
163 int clk_enable(struct clk
*clk
)
167 EXPORT_SYMBOL(clk_enable
);
169 void clk_disable(struct clk
*clk
)
172 EXPORT_SYMBOL(clk_disable
);
174 unsigned long clk_get_rate(struct clk
*clk
)
178 EXPORT_SYMBOL(clk_get_rate
);
180 void clk_put(struct clk
*clk
)
183 EXPORT_SYMBOL(clk_put
);