1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public
3*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive
4*4882a593Smuzhiyun * for more details.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
7*4882a593Smuzhiyun * Copyright (C) 2006 FON Technology, SL.
8*4882a593Smuzhiyun * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
9*4882a593Smuzhiyun * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
10*4882a593Smuzhiyun * Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com>
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun * Platform devices for Atheros AR2315 SoCs
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/init.h>
18*4882a593Smuzhiyun #include <linux/kernel.h>
19*4882a593Smuzhiyun #include <linux/bitops.h>
20*4882a593Smuzhiyun #include <linux/irqdomain.h>
21*4882a593Smuzhiyun #include <linux/interrupt.h>
22*4882a593Smuzhiyun #include <linux/memblock.h>
23*4882a593Smuzhiyun #include <linux/platform_device.h>
24*4882a593Smuzhiyun #include <linux/reboot.h>
25*4882a593Smuzhiyun #include <asm/bootinfo.h>
26*4882a593Smuzhiyun #include <asm/reboot.h>
27*4882a593Smuzhiyun #include <asm/time.h>
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include <ath25_platform.h>
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include "devices.h"
32*4882a593Smuzhiyun #include "ar2315.h"
33*4882a593Smuzhiyun #include "ar2315_regs.h"
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun static void __iomem *ar2315_rst_base;
36*4882a593Smuzhiyun static struct irq_domain *ar2315_misc_irq_domain;
37*4882a593Smuzhiyun
ar2315_rst_reg_read(u32 reg)38*4882a593Smuzhiyun static inline u32 ar2315_rst_reg_read(u32 reg)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun return __raw_readl(ar2315_rst_base + reg);
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
ar2315_rst_reg_write(u32 reg,u32 val)43*4882a593Smuzhiyun static inline void ar2315_rst_reg_write(u32 reg, u32 val)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun __raw_writel(val, ar2315_rst_base + reg);
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun
ar2315_rst_reg_mask(u32 reg,u32 mask,u32 val)48*4882a593Smuzhiyun static inline void ar2315_rst_reg_mask(u32 reg, u32 mask, u32 val)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun u32 ret = ar2315_rst_reg_read(reg);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun ret &= ~mask;
53*4882a593Smuzhiyun ret |= val;
54*4882a593Smuzhiyun ar2315_rst_reg_write(reg, ret);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
ar2315_ahb_err_handler(int cpl,void * dev_id)57*4882a593Smuzhiyun static irqreturn_t ar2315_ahb_err_handler(int cpl, void *dev_id)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun ar2315_rst_reg_write(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
60*4882a593Smuzhiyun ar2315_rst_reg_read(AR2315_AHB_ERR1);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun pr_emerg("AHB fatal error\n");
63*4882a593Smuzhiyun machine_restart("AHB error"); /* Catastrophic failure */
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun return IRQ_HANDLED;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
ar2315_misc_irq_handler(struct irq_desc * desc)68*4882a593Smuzhiyun static void ar2315_misc_irq_handler(struct irq_desc *desc)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun u32 pending = ar2315_rst_reg_read(AR2315_ISR) &
71*4882a593Smuzhiyun ar2315_rst_reg_read(AR2315_IMR);
72*4882a593Smuzhiyun unsigned nr, misc_irq = 0;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun if (pending) {
75*4882a593Smuzhiyun struct irq_domain *domain = irq_desc_get_handler_data(desc);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun nr = __ffs(pending);
78*4882a593Smuzhiyun misc_irq = irq_find_mapping(domain, nr);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun if (misc_irq) {
82*4882a593Smuzhiyun if (nr == AR2315_MISC_IRQ_GPIO)
83*4882a593Smuzhiyun ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO);
84*4882a593Smuzhiyun else if (nr == AR2315_MISC_IRQ_WATCHDOG)
85*4882a593Smuzhiyun ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD);
86*4882a593Smuzhiyun generic_handle_irq(misc_irq);
87*4882a593Smuzhiyun } else {
88*4882a593Smuzhiyun spurious_interrupt();
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
ar2315_misc_irq_unmask(struct irq_data * d)92*4882a593Smuzhiyun static void ar2315_misc_irq_unmask(struct irq_data *d)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun ar2315_rst_reg_mask(AR2315_IMR, 0, BIT(d->hwirq));
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
ar2315_misc_irq_mask(struct irq_data * d)97*4882a593Smuzhiyun static void ar2315_misc_irq_mask(struct irq_data *d)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun ar2315_rst_reg_mask(AR2315_IMR, BIT(d->hwirq), 0);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun static struct irq_chip ar2315_misc_irq_chip = {
103*4882a593Smuzhiyun .name = "ar2315-misc",
104*4882a593Smuzhiyun .irq_unmask = ar2315_misc_irq_unmask,
105*4882a593Smuzhiyun .irq_mask = ar2315_misc_irq_mask,
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun
ar2315_misc_irq_map(struct irq_domain * d,unsigned irq,irq_hw_number_t hw)108*4882a593Smuzhiyun static int ar2315_misc_irq_map(struct irq_domain *d, unsigned irq,
109*4882a593Smuzhiyun irq_hw_number_t hw)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip, handle_level_irq);
112*4882a593Smuzhiyun return 0;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static struct irq_domain_ops ar2315_misc_irq_domain_ops = {
116*4882a593Smuzhiyun .map = ar2315_misc_irq_map,
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /*
120*4882a593Smuzhiyun * Called when an interrupt is received, this function
121*4882a593Smuzhiyun * determines exactly which interrupt it was, and it
122*4882a593Smuzhiyun * invokes the appropriate handler.
123*4882a593Smuzhiyun *
124*4882a593Smuzhiyun * Implicitly, we also define interrupt priority by
125*4882a593Smuzhiyun * choosing which to dispatch first.
126*4882a593Smuzhiyun */
ar2315_irq_dispatch(void)127*4882a593Smuzhiyun static void ar2315_irq_dispatch(void)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun u32 pending = read_c0_status() & read_c0_cause();
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (pending & CAUSEF_IP3)
132*4882a593Smuzhiyun do_IRQ(AR2315_IRQ_WLAN0);
133*4882a593Smuzhiyun #ifdef CONFIG_PCI_AR2315
134*4882a593Smuzhiyun else if (pending & CAUSEF_IP5)
135*4882a593Smuzhiyun do_IRQ(AR2315_IRQ_LCBUS_PCI);
136*4882a593Smuzhiyun #endif
137*4882a593Smuzhiyun else if (pending & CAUSEF_IP2)
138*4882a593Smuzhiyun do_IRQ(AR2315_IRQ_MISC);
139*4882a593Smuzhiyun else if (pending & CAUSEF_IP7)
140*4882a593Smuzhiyun do_IRQ(ATH25_IRQ_CPU_CLOCK);
141*4882a593Smuzhiyun else
142*4882a593Smuzhiyun spurious_interrupt();
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
ar2315_arch_init_irq(void)145*4882a593Smuzhiyun void __init ar2315_arch_init_irq(void)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun struct irq_domain *domain;
148*4882a593Smuzhiyun unsigned irq;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun ath25_irq_dispatch = ar2315_irq_dispatch;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun domain = irq_domain_add_linear(NULL, AR2315_MISC_IRQ_COUNT,
153*4882a593Smuzhiyun &ar2315_misc_irq_domain_ops, NULL);
154*4882a593Smuzhiyun if (!domain)
155*4882a593Smuzhiyun panic("Failed to add IRQ domain");
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun irq = irq_create_mapping(domain, AR2315_MISC_IRQ_AHB);
158*4882a593Smuzhiyun if (request_irq(irq, ar2315_ahb_err_handler, 0, "ar2315-ahb-error",
159*4882a593Smuzhiyun NULL))
160*4882a593Smuzhiyun pr_err("Failed to register ar2315-ahb-error interrupt\n");
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun irq_set_chained_handler_and_data(AR2315_IRQ_MISC,
163*4882a593Smuzhiyun ar2315_misc_irq_handler, domain);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun ar2315_misc_irq_domain = domain;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
ar2315_init_devices(void)168*4882a593Smuzhiyun void __init ar2315_init_devices(void)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun /* Find board configuration */
171*4882a593Smuzhiyun ath25_find_config(AR2315_SPI_READ_BASE, AR2315_SPI_READ_SIZE);
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun ath25_add_wmac(0, AR2315_WLAN0_BASE, AR2315_IRQ_WLAN0);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
ar2315_restart(char * command)176*4882a593Smuzhiyun static void ar2315_restart(char *command)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun void (*mips_reset_vec)(void) = (void *)0xbfc00000;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun local_irq_disable();
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* try reset the system via reset control */
183*4882a593Smuzhiyun ar2315_rst_reg_write(AR2315_COLD_RESET, AR2317_RESET_SYSTEM);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* Cold reset does not work on the AR2315/6, use the GPIO reset bits
186*4882a593Smuzhiyun * a workaround. Give it some time to attempt a gpio based hardware
187*4882a593Smuzhiyun * reset (atheros reference design workaround) */
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /* TODO: implement the GPIO reset workaround */
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /* Some boards (e.g. Senao EOC-2610) don't implement the reset logic
192*4882a593Smuzhiyun * workaround. Attempt to jump to the mips reset location -
193*4882a593Smuzhiyun * the boot loader itself might be able to recover the system */
194*4882a593Smuzhiyun mips_reset_vec();
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /*
198*4882a593Smuzhiyun * This table is indexed by bits 5..4 of the CLOCKCTL1 register
199*4882a593Smuzhiyun * to determine the predevisor value.
200*4882a593Smuzhiyun */
201*4882a593Smuzhiyun static int clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
202*4882a593Smuzhiyun static int pllc_divide_table[5] __initdata = { 2, 3, 4, 6, 3 };
203*4882a593Smuzhiyun
ar2315_sys_clk(u32 clock_ctl)204*4882a593Smuzhiyun static unsigned __init ar2315_sys_clk(u32 clock_ctl)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun unsigned int pllc_ctrl, cpu_div;
207*4882a593Smuzhiyun unsigned int pllc_out, refdiv, fdiv, divby2;
208*4882a593Smuzhiyun unsigned int clk_div;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun pllc_ctrl = ar2315_rst_reg_read(AR2315_PLLC_CTL);
211*4882a593Smuzhiyun refdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_REF_DIV);
212*4882a593Smuzhiyun refdiv = clockctl1_predivide_table[refdiv];
213*4882a593Smuzhiyun fdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_FDBACK_DIV);
214*4882a593Smuzhiyun divby2 = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_ADD_FDBACK_DIV) + 1;
215*4882a593Smuzhiyun pllc_out = (40000000 / refdiv) * (2 * divby2) * fdiv;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* clkm input selected */
218*4882a593Smuzhiyun switch (clock_ctl & AR2315_CPUCLK_CLK_SEL_M) {
219*4882a593Smuzhiyun case 0:
220*4882a593Smuzhiyun case 1:
221*4882a593Smuzhiyun clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKM_DIV);
222*4882a593Smuzhiyun clk_div = pllc_divide_table[clk_div];
223*4882a593Smuzhiyun break;
224*4882a593Smuzhiyun case 2:
225*4882a593Smuzhiyun clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKC_DIV);
226*4882a593Smuzhiyun clk_div = pllc_divide_table[clk_div];
227*4882a593Smuzhiyun break;
228*4882a593Smuzhiyun default:
229*4882a593Smuzhiyun pllc_out = 40000000;
230*4882a593Smuzhiyun clk_div = 1;
231*4882a593Smuzhiyun break;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun cpu_div = ATH25_REG_MS(clock_ctl, AR2315_CPUCLK_CLK_DIV);
235*4882a593Smuzhiyun cpu_div = cpu_div * 2 ?: 1;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun return pllc_out / (clk_div * cpu_div);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
ar2315_cpu_frequency(void)240*4882a593Smuzhiyun static inline unsigned ar2315_cpu_frequency(void)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_CPUCLK));
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
ar2315_apb_frequency(void)245*4882a593Smuzhiyun static inline unsigned ar2315_apb_frequency(void)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_AMBACLK));
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
ar2315_plat_time_init(void)250*4882a593Smuzhiyun void __init ar2315_plat_time_init(void)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun mips_hpt_frequency = ar2315_cpu_frequency() / 2;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
ar2315_plat_mem_setup(void)255*4882a593Smuzhiyun void __init ar2315_plat_mem_setup(void)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun void __iomem *sdram_base;
258*4882a593Smuzhiyun u32 memsize, memcfg;
259*4882a593Smuzhiyun u32 devid;
260*4882a593Smuzhiyun u32 config;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* Detect memory size */
263*4882a593Smuzhiyun sdram_base = ioremap(AR2315_SDRAMCTL_BASE,
264*4882a593Smuzhiyun AR2315_SDRAMCTL_SIZE);
265*4882a593Smuzhiyun memcfg = __raw_readl(sdram_base + AR2315_MEM_CFG);
266*4882a593Smuzhiyun memsize = 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_DATA_WIDTH);
267*4882a593Smuzhiyun memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_COL_WIDTH);
268*4882a593Smuzhiyun memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_ROW_WIDTH);
269*4882a593Smuzhiyun memsize <<= 3;
270*4882a593Smuzhiyun memblock_add(0, memsize);
271*4882a593Smuzhiyun iounmap(sdram_base);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun ar2315_rst_base = ioremap(AR2315_RST_BASE, AR2315_RST_SIZE);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /* Detect the hardware based on the device ID */
276*4882a593Smuzhiyun devid = ar2315_rst_reg_read(AR2315_SREV) & AR2315_REV_CHIP;
277*4882a593Smuzhiyun switch (devid) {
278*4882a593Smuzhiyun case 0x91: /* Need to check */
279*4882a593Smuzhiyun ath25_soc = ATH25_SOC_AR2318;
280*4882a593Smuzhiyun break;
281*4882a593Smuzhiyun case 0x90:
282*4882a593Smuzhiyun ath25_soc = ATH25_SOC_AR2317;
283*4882a593Smuzhiyun break;
284*4882a593Smuzhiyun case 0x87:
285*4882a593Smuzhiyun ath25_soc = ATH25_SOC_AR2316;
286*4882a593Smuzhiyun break;
287*4882a593Smuzhiyun case 0x86:
288*4882a593Smuzhiyun default:
289*4882a593Smuzhiyun ath25_soc = ATH25_SOC_AR2315;
290*4882a593Smuzhiyun break;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun ath25_board.devid = devid;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /* Clear any lingering AHB errors */
295*4882a593Smuzhiyun config = read_c0_config();
296*4882a593Smuzhiyun write_c0_config(config & ~0x3);
297*4882a593Smuzhiyun ar2315_rst_reg_write(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
298*4882a593Smuzhiyun ar2315_rst_reg_read(AR2315_AHB_ERR1);
299*4882a593Smuzhiyun ar2315_rst_reg_write(AR2315_WDT_CTRL, AR2315_WDT_CTRL_IGNORE);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun _machine_restart = ar2315_restart;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun #ifdef CONFIG_PCI_AR2315
305*4882a593Smuzhiyun static struct resource ar2315_pci_res[] = {
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun .name = "ar2315-pci-ctrl",
308*4882a593Smuzhiyun .flags = IORESOURCE_MEM,
309*4882a593Smuzhiyun .start = AR2315_PCI_BASE,
310*4882a593Smuzhiyun .end = AR2315_PCI_BASE + AR2315_PCI_SIZE - 1,
311*4882a593Smuzhiyun },
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun .name = "ar2315-pci-ext",
314*4882a593Smuzhiyun .flags = IORESOURCE_MEM,
315*4882a593Smuzhiyun .start = AR2315_PCI_EXT_BASE,
316*4882a593Smuzhiyun .end = AR2315_PCI_EXT_BASE + AR2315_PCI_EXT_SIZE - 1,
317*4882a593Smuzhiyun },
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun .name = "ar2315-pci",
320*4882a593Smuzhiyun .flags = IORESOURCE_IRQ,
321*4882a593Smuzhiyun .start = AR2315_IRQ_LCBUS_PCI,
322*4882a593Smuzhiyun .end = AR2315_IRQ_LCBUS_PCI,
323*4882a593Smuzhiyun },
324*4882a593Smuzhiyun };
325*4882a593Smuzhiyun #endif
326*4882a593Smuzhiyun
ar2315_arch_init(void)327*4882a593Smuzhiyun void __init ar2315_arch_init(void)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun unsigned irq = irq_create_mapping(ar2315_misc_irq_domain,
330*4882a593Smuzhiyun AR2315_MISC_IRQ_UART0);
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun ath25_serial_setup(AR2315_UART0_BASE, irq, ar2315_apb_frequency());
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun #ifdef CONFIG_PCI_AR2315
335*4882a593Smuzhiyun if (ath25_soc == ATH25_SOC_AR2315) {
336*4882a593Smuzhiyun /* Reset PCI DMA logic */
337*4882a593Smuzhiyun ar2315_rst_reg_mask(AR2315_RESET, 0, AR2315_RESET_PCIDMA);
338*4882a593Smuzhiyun msleep(20);
339*4882a593Smuzhiyun ar2315_rst_reg_mask(AR2315_RESET, AR2315_RESET_PCIDMA, 0);
340*4882a593Smuzhiyun msleep(20);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* Configure endians */
343*4882a593Smuzhiyun ar2315_rst_reg_mask(AR2315_ENDIAN_CTL, 0, AR2315_CONFIG_PCIAHB |
344*4882a593Smuzhiyun AR2315_CONFIG_PCIAHB_BRIDGE);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /* Configure as PCI host with DMA */
347*4882a593Smuzhiyun ar2315_rst_reg_write(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM |
348*4882a593Smuzhiyun (AR2315_PCICLK_IN_FREQ_DIV_6 <<
349*4882a593Smuzhiyun AR2315_PCICLK_DIV_S));
350*4882a593Smuzhiyun ar2315_rst_reg_mask(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI);
351*4882a593Smuzhiyun ar2315_rst_reg_mask(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK |
352*4882a593Smuzhiyun AR2315_IF_MASK, AR2315_IF_PCI |
353*4882a593Smuzhiyun AR2315_IF_PCI_HOST | AR2315_IF_PCI_INTR |
354*4882a593Smuzhiyun (AR2315_IF_PCI_CLK_OUTPUT_CLK <<
355*4882a593Smuzhiyun AR2315_IF_PCI_CLK_SHIFT));
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun platform_device_register_simple("ar2315-pci", -1,
358*4882a593Smuzhiyun ar2315_pci_res,
359*4882a593Smuzhiyun ARRAY_SIZE(ar2315_pci_res));
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun #endif
362*4882a593Smuzhiyun }
363