aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ath25/ar2315.c
diff options
context:
space:
mode:
authorSergey Ryazanov <ryazanov.s.a@gmail.com>2014-10-28 19:18:40 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-11-24 01:45:26 -0500
commitba910345034aea52d292bdc26b9c6831ab7b54e8 (patch)
tree97a83a99f2fd8cac612a64f2ec78008ad2698a4f /arch/mips/ath25/ar2315.c
parent3b12308f3337c09b424a2b9cf73c2c06521abe7e (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.c155
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
28static void __iomem *ar2315_rst_base;
29
30static inline u32 ar2315_rst_reg_read(u32 reg)
31{
32 return __raw_readl(ar2315_rst_base + reg);
33}
34
35static inline void ar2315_rst_reg_write(u32 reg, u32 val)
36{
37 __raw_writel(val, ar2315_rst_base + reg);
38}
39
40static 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
49static 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 */
74static int clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
75static int pllc_divide_table[5] __initdata = { 2, 3, 4, 6, 3 };
76
77static 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
113static inline unsigned ar2315_cpu_frequency(void)
114{
115 return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_CPUCLK));
116}
117
118static inline unsigned ar2315_apb_frequency(void)
119{
120 return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_AMBACLK));
121}
122
123void __init ar2315_plat_time_init(void)
124{
125 mips_hpt_frequency = ar2315_cpu_frequency() / 2;
126}
127
128void __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}