diff options
author | Sergey Ryazanov <ryazanov.s.a@gmail.com> | 2014-10-28 19:18:40 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:45:26 -0500 |
commit | ba910345034aea52d292bdc26b9c6831ab7b54e8 (patch) | |
tree | 97a83a99f2fd8cac612a64f2ec78008ad2698a4f /arch/mips/ath25/ar2315.c | |
parent | 3b12308f3337c09b424a2b9cf73c2c06521abe7e (diff) |
MIPS: ath25: Add basic AR2315 SoC support
Add basic support for Atheros AR2315+ SoCs: registers definition file
and initial setup code.
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Cc: Linux MIPS <linux-mips@linux-mips.org>
Patchwork: https://patchwork.linux-mips.org/patch/8239/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/ath25/ar2315.c')
-rw-r--r-- | arch/mips/ath25/ar2315.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c new file mode 100644 index 000000000000..828943212f03 --- /dev/null +++ b/arch/mips/ath25/ar2315.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. | ||
7 | * Copyright (C) 2006 FON Technology, SL. | ||
8 | * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
9 | * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> | ||
10 | * Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com> | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * Platform devices for Atheros AR2315 SoCs | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <asm/bootinfo.h> | ||
21 | #include <asm/reboot.h> | ||
22 | #include <asm/time.h> | ||
23 | |||
24 | #include "devices.h" | ||
25 | #include "ar2315.h" | ||
26 | #include "ar2315_regs.h" | ||
27 | |||
28 | static void __iomem *ar2315_rst_base; | ||
29 | |||
30 | static inline u32 ar2315_rst_reg_read(u32 reg) | ||
31 | { | ||
32 | return __raw_readl(ar2315_rst_base + reg); | ||
33 | } | ||
34 | |||
35 | static inline void ar2315_rst_reg_write(u32 reg, u32 val) | ||
36 | { | ||
37 | __raw_writel(val, ar2315_rst_base + reg); | ||
38 | } | ||
39 | |||
40 | static inline void ar2315_rst_reg_mask(u32 reg, u32 mask, u32 val) | ||
41 | { | ||
42 | u32 ret = ar2315_rst_reg_read(reg); | ||
43 | |||
44 | ret &= ~mask; | ||
45 | ret |= val; | ||
46 | ar2315_rst_reg_write(reg, ret); | ||
47 | } | ||
48 | |||
49 | static void ar2315_restart(char *command) | ||
50 | { | ||
51 | void (*mips_reset_vec)(void) = (void *)0xbfc00000; | ||
52 | |||
53 | local_irq_disable(); | ||
54 | |||
55 | /* try reset the system via reset control */ | ||
56 | ar2315_rst_reg_write(AR2315_COLD_RESET, AR2317_RESET_SYSTEM); | ||
57 | |||
58 | /* Cold reset does not work on the AR2315/6, use the GPIO reset bits | ||
59 | * a workaround. Give it some time to attempt a gpio based hardware | ||
60 | * reset (atheros reference design workaround) */ | ||
61 | |||
62 | /* TODO: implement the GPIO reset workaround */ | ||
63 | |||
64 | /* Some boards (e.g. Senao EOC-2610) don't implement the reset logic | ||
65 | * workaround. Attempt to jump to the mips reset location - | ||
66 | * the boot loader itself might be able to recover the system */ | ||
67 | mips_reset_vec(); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * This table is indexed by bits 5..4 of the CLOCKCTL1 register | ||
72 | * to determine the predevisor value. | ||
73 | */ | ||
74 | static int clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 }; | ||
75 | static int pllc_divide_table[5] __initdata = { 2, 3, 4, 6, 3 }; | ||
76 | |||
77 | static unsigned __init ar2315_sys_clk(u32 clock_ctl) | ||
78 | { | ||
79 | unsigned int pllc_ctrl, cpu_div; | ||
80 | unsigned int pllc_out, refdiv, fdiv, divby2; | ||
81 | unsigned int clk_div; | ||
82 | |||
83 | pllc_ctrl = ar2315_rst_reg_read(AR2315_PLLC_CTL); | ||
84 | refdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_REF_DIV); | ||
85 | refdiv = clockctl1_predivide_table[refdiv]; | ||
86 | fdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_FDBACK_DIV); | ||
87 | divby2 = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_ADD_FDBACK_DIV) + 1; | ||
88 | pllc_out = (40000000 / refdiv) * (2 * divby2) * fdiv; | ||
89 | |||
90 | /* clkm input selected */ | ||
91 | switch (clock_ctl & AR2315_CPUCLK_CLK_SEL_M) { | ||
92 | case 0: | ||
93 | case 1: | ||
94 | clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKM_DIV); | ||
95 | clk_div = pllc_divide_table[clk_div]; | ||
96 | break; | ||
97 | case 2: | ||
98 | clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKC_DIV); | ||
99 | clk_div = pllc_divide_table[clk_div]; | ||
100 | break; | ||
101 | default: | ||
102 | pllc_out = 40000000; | ||
103 | clk_div = 1; | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | cpu_div = ATH25_REG_MS(clock_ctl, AR2315_CPUCLK_CLK_DIV); | ||
108 | cpu_div = cpu_div * 2 ?: 1; | ||
109 | |||
110 | return pllc_out / (clk_div * cpu_div); | ||
111 | } | ||
112 | |||
113 | static inline unsigned ar2315_cpu_frequency(void) | ||
114 | { | ||
115 | return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_CPUCLK)); | ||
116 | } | ||
117 | |||
118 | static inline unsigned ar2315_apb_frequency(void) | ||
119 | { | ||
120 | return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_AMBACLK)); | ||
121 | } | ||
122 | |||
123 | void __init ar2315_plat_time_init(void) | ||
124 | { | ||
125 | mips_hpt_frequency = ar2315_cpu_frequency() / 2; | ||
126 | } | ||
127 | |||
128 | void __init ar2315_plat_mem_setup(void) | ||
129 | { | ||
130 | void __iomem *sdram_base; | ||
131 | u32 memsize, memcfg; | ||
132 | u32 config; | ||
133 | |||
134 | /* Detect memory size */ | ||
135 | sdram_base = ioremap_nocache(AR2315_SDRAMCTL_BASE, | ||
136 | AR2315_SDRAMCTL_SIZE); | ||
137 | memcfg = __raw_readl(sdram_base + AR2315_MEM_CFG); | ||
138 | memsize = 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_DATA_WIDTH); | ||
139 | memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_COL_WIDTH); | ||
140 | memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_ROW_WIDTH); | ||
141 | memsize <<= 3; | ||
142 | add_memory_region(0, memsize, BOOT_MEM_RAM); | ||
143 | iounmap(sdram_base); | ||
144 | |||
145 | ar2315_rst_base = ioremap_nocache(AR2315_RST_BASE, AR2315_RST_SIZE); | ||
146 | |||
147 | /* Clear any lingering AHB errors */ | ||
148 | config = read_c0_config(); | ||
149 | write_c0_config(config & ~0x3); | ||
150 | ar2315_rst_reg_write(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET); | ||
151 | ar2315_rst_reg_read(AR2315_AHB_ERR1); | ||
152 | ar2315_rst_reg_write(AR2315_WDT_CTRL, AR2315_WDT_CTRL_IGNORE); | ||
153 | |||
154 | _machine_restart = ar2315_restart; | ||
155 | } | ||