source: src/linux/universal/linux-4.9/arch/arm/plat-brcm/bcm5301x.c @ 31707

Last change on this file since 31707 was 31707, checked in by brainslayer, 10 days ago

compiles on northstar, but nand driver will likelly not work yet. still something todo

File size: 20.1 KB
Line 
1/*
2 * Northstar SoC main platform file.
3 *
4 */
5
6#include <asm/cacheflush.h>
7#include <linux/types.h>
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/io.h>
11#include <linux/ioport.h>
12#include <linux/platform_device.h>
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/serial_8250.h>
16#include <linux/proc_fs.h>
17#include <linux/spi/spi.h>
18#include <linux/irq.h>
19#include <linux/spinlock.h>
20#include <asm/hardware/cache-l2x0.h>
21#include <asm/mach/map.h>
22#include <asm/clkdev.h>
23#include <asm/uaccess.h>
24#include <asm/ptrace.h>
25#include <mach/clkdev.h>
26#include <mach/io_map.h>
27#include <plat/bsp.h>
28#include <plat/mpcore.h>
29#include <plat/plat-bcm5301x.h>
30
31#include <typedefs.h>
32#include <sbchipc.h>
33#include <bcmutils.h>
34#include <siutils.h>
35#include <bcmdefs.h>
36#include <bcmdevs.h>
37
38#ifdef  CONFIG_SMP
39#include <asm/spinlock.h>
40#endif
41
42#define SOC_CHIPCOMON_A_REG_VA(offset)          (SOC_CHIPCOMON_A_BASE_VA + (offset))
43#define SOC_CHIPCOMON_A_INTSTATUS_VA            SOC_CHIPCOMON_A_REG_VA(CC_INTSTATUS)
44#define SOC_CHIPCOMON_A_INTMASK_VA              SOC_CHIPCOMON_A_REG_VA(CC_INTMASK)
45#define SOC_CHIPCOMON_A_GPIOINPUT_VA            SOC_CHIPCOMON_A_REG_VA(CC_GPIOIN)
46#define SOC_CHIPCOMON_A_GPIOINTPOLARITY_VA      SOC_CHIPCOMON_A_REG_VA(CC_GPIOPOL)
47#define SOC_CHIPCOMON_A_GPIOINTMASK_VA          SOC_CHIPCOMON_A_REG_VA(CC_GPIOINTM)
48#define SOC_CHIPCOMON_A_GPIOEVENT_VA            SOC_CHIPCOMON_A_REG_VA(CC_GPIOEVENT)
49#define SOC_CHIPCOMON_A_GPIOEVENTINTMASK_VA     SOC_CHIPCOMON_A_REG_VA(CC_GPIOEVENTMASK)
50#define SOC_CHIPCOMON_A_GPIOEVENTINTPOLARITY_VA SOC_CHIPCOMON_A_REG_VA(CC_GPIOEVENTPOL)
51#define SOC_CHIPCOMON_A_CORECAP                 SOC_CHIPCOMON_A_REG_VA(CC_CAPABILITIES)
52#define SOC_CHIPCOMON_A_CORECTRL                SOC_CHIPCOMON_A_REG_VA(0x08)
53#define SOC_CHIPCOMON_A_CLKDIV                  SOC_CHIPCOMON_A_REG_VA(CC_CLKDIV)
54
55#define SOC_CHIPCOMON_A_INTMASK_UART            (1 << 6)
56#define SOC_CHIPCOMON_A_INTMASK_GPIO            (1 << 0)
57
58#define SOC_CHIPCOMON_A_CORECAP_UARTCLKSEL_M    0x3
59#define SOC_CHIPCOMON_A_CORECAP_UARTCLKSEL_S    3
60
61#define SOC_CHIPCOMON_A_CORECTRL_UARTCLKOVR_M   0x1
62#define SOC_CHIPCOMON_A_CORECTRL_UARTCLKOVR_S   0
63
64#define SOC_CHIPCOMON_A_CLKDIV_UARTCLKDIV_M     0xFF
65#define SOC_CHIPCOMON_A_CLKDIV_UARTCLKDIV_S     0
66
67#define SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT      (SOC_IDM_BASE_VA + 0x21408)
68
69#define SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT_UARTCLKSEL_M 0x1
70#define SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT_UARTCLKSEL_S 17
71
72#define PLAT_SM_CLR(val, field)                 ((val) & ~(field##_M << field##_S))
73#define PLAT_SM_SET(val, field, field_val)      ((val) | (((field_val) & field##_M) << field##_S))
74#define PLAT_SM_GET(val, field)                 (((val) >> field##_S) & field##_M)
75#define PLAT_SM_ASSIGN(val, field, field_val)   PLAT_SM_SET(PLAT_SM_CLR(val, field), field, field_val)
76
77static struct clk * _soc_refclk = NULL;
78
79#ifdef CONFIG_PLAT_UART_CLOCKS
80
81#if CONFIG_PLAT_CCA_UART0_DIVIDER <= 0xFFFF
82# define CONFIG_PLAT_CCA_UART0_DIVIDER_FLAG     UPF_SPD_CUST
83#else
84# define CONFIG_PLAT_CCA_UART0_DIVIDER_FLAG     0
85#endif
86
87#if CONFIG_PLAT_CCA_UART1_DIVIDER <= 0xFFFF
88# define CONFIG_PLAT_CCA_UART1_DIVIDER_FLAG     UPF_SPD_CUST
89#else
90# define CONFIG_PLAT_CCA_UART1_DIVIDER_FLAG     0
91#endif
92
93#if CONFIG_PLAT_CCB_UART0_DIVIDER <= 0xFFFF
94# define CONFIG_PLAT_CCB_UART0_DIVIDER_FLAG     UPF_SPD_CUST
95#else
96# define CONFIG_PLAT_CCB_UART0_DIVIDER_FLAG     0
97#endif
98
99#else
100
101#define CONFIG_PLAT_CCA_UART0_DIVIDER           0
102#define CONFIG_PLAT_CCA_UART1_DIVIDER           0
103#define CONFIG_PLAT_CCB_UART0_DIVIDER           0
104
105#define CONFIG_PLAT_CCA_UART0_DIVIDER_FLAG      0
106#define CONFIG_PLAT_CCA_UART1_DIVIDER_FLAG      0
107#define CONFIG_PLAT_CCB_UART0_DIVIDER_FLAG      0
108
109#endif /* PLAT_UART_CLOCKS */
110
111/* Global SB handle */
112extern si_t *bcm947xx_sih;
113#define sih bcm947xx_sih
114
115extern int _chipid;
116
117static struct plat_serial8250_port uart_ports[] = {
118        {
119        .type       = PORT_16550,
120        .flags      = UPF_FIXED_TYPE | UPF_SHARE_IRQ | CONFIG_PLAT_CCA_UART0_DIVIDER_FLAG,
121        .regshift   = 0,
122        .iotype     = UPIO_MEM,
123        .mapbase    = (resource_size_t)(PLAT_UART1_PA),
124        .membase    = (void __iomem *) PLAT_UART1_VA,
125        .irq        = IRQ_CCA_UART,
126        .custom_divisor = CONFIG_PLAT_CCA_UART0_DIVIDER,
127        },
128        {
129        .type       = PORT_16550,
130        .flags      = UPF_FIXED_TYPE | UPF_SHARE_IRQ | CONFIG_PLAT_CCA_UART1_DIVIDER_FLAG,
131        .regshift   = 0,
132        .iotype     = UPIO_MEM,
133        .mapbase    = (resource_size_t)(PLAT_UART2_PA),
134        .membase    = (void __iomem *) PLAT_UART2_VA,
135        .irq        = IRQ_CCA_UART,
136        .custom_divisor = CONFIG_PLAT_CCA_UART1_DIVIDER,
137        },
138#ifdef CONFIG_PLAT_MUX_CONSOLE_CCB
139        {
140        .type       = PORT_16550,
141        .flags      = UPF_FIXED_TYPE | CONFIG_PLAT_CCB_UART0_DIVIDER_FLAG,
142        .regshift   = 2,        /* Chipcommon B regs are 32-bit aligned */
143        .iotype     = UPIO_MEM,
144        .mapbase    = (resource_size_t)(PLAT_UART0_PA),
145        .membase    = (void __iomem *) PLAT_UART0_VA,
146        .irq        = IRQ_CCB_UART0,
147        .custom_divisor = CONFIG_PLAT_CCB_UART0_DIVIDER,
148        },
149#endif /* CONFIG_PLAT_MUX_CONSOLE_CCB */
150        { .flags = 0, },        /* List terminatoir */
151};
152
153static struct platform_device platform_serial_device = {
154        .name = "serial8250",
155        .id = PLAT8250_DEV_PLATFORM,    /* <linux/serial_8250.h> */
156        .dev = {
157                .platform_data = uart_ports,
158        },
159};
160
161static struct platform_device platform_spi_master_device = {
162        .name = "bcm5301x-spi-master",
163        .id = 1, /* Bus number */
164        .dev = {
165                .platform_data = NULL, /* Passed to driver */
166        },
167};
168
169/*
170 * Map fix-mapped I/O that is needed before full MMU operation
171 */
172void __init soc_map_io(struct clk * refclk)
173{
174        struct map_desc desc[2];
175
176        /*
177        * Map Chipcommon A & B to a fixed virtual location
178        * as these contain all the system UARTs, which are
179        * needed for low-level debugging,
180        * it have already been mapped from mach_desc earlier
181        * but that is undone from page_init()
182        */
183
184        desc[0].virtual = IO_BASE_VA;
185        desc[0].pfn = __phys_to_pfn(IO_BASE_PA);
186        if (BCM53573_CHIP(_chipid)) {
187                desc[0].length = SZ_2M;
188        } else {
189                desc[0].length = SZ_16M;        /* CCA+CCB: 0x18000000-0x18ffffff */
190        }
191
192        desc[0].type = MT_DEVICE;
193
194        iotable_init(desc, 1);
195
196        mpcore_map_io();
197        /* Save refclk for later use */
198        _soc_refclk = refclk;
199}
200
201static int soc_abort_handler(unsigned long addr, unsigned int fsr,
202                                      struct pt_regs *regs)
203{
204        /*
205         * These happen for no good reason
206         * possibly left over from CFE
207         */
208        printk(KERN_WARNING
209                "External imprecise Data abort at "
210                "addr=%#lx, fsr=%#x, pc=%#lx lr=%#lx ignored.\n",
211                addr, fsr, regs->ARM_pc, regs->ARM_lr);
212
213        /* Returning non-zero causes fault display and panic */
214        return 0;
215}
216
217static void __init soc_aborts_enable(void)
218{
219        u32 x;
220
221        /* Install our hook */
222        hook_fault_code(16 + 6, soc_abort_handler, SIGBUS, 0,
223                        "imprecise external abort");
224
225        /* Enable external aborts - clear "A" bit in CPSR */
226
227        /* Read CPSR */
228        asm( "mrs       %0,cpsr": "=&r" (x) : : );
229
230        x &= ~ PSR_A_BIT ;
231
232        /* Update CPSR, affect bits 8-15 */
233        asm( "msr       cpsr_x,%0; nop; nop": : "r" (x) : "cc" );
234
235}
236
237#ifdef CONFIG_PLAT_CCA_GPIO_IRQ
238
239#include <asm/gpio.h>
240
241struct soc_cca_gpio_irq_data {
242        unsigned int type;
243};
244
245static void soc_cca_gpio_handle(void)
246{
247        uint32 mask = readl(SOC_CHIPCOMON_A_GPIOINTMASK_VA);
248        uint32 polarity = readl(SOC_CHIPCOMON_A_GPIOINTPOLARITY_VA);
249        uint32 input = readl(SOC_CHIPCOMON_A_GPIOINPUT_VA);
250        uint32 event = readl(SOC_CHIPCOMON_A_GPIOEVENT_VA);
251        uint32 eventmask = readl(SOC_CHIPCOMON_A_GPIOEVENTINTMASK_VA);
252        int gpio;
253
254        for (gpio = 0; gpio < IRQ_CCA_GPIO_N; ++gpio) {
255                uint32 gpio_bit = (1 << gpio);
256                uint32 level_triggered = ((input ^ polarity) & mask & gpio_bit);
257                uint32 edge_triggered = (event & eventmask & gpio_bit);
258
259                if (level_triggered || edge_triggered) {
260                        generic_handle_irq(IRQ_CCA_GPIO(gpio));
261                }
262        }
263}
264
265static void soc_cca_irq_handler(unsigned int irq, struct irq_desc *desc)
266{
267        uint32 status = readl(SOC_CHIPCOMON_A_INTSTATUS_VA);
268
269        desc->chip->mask(irq);
270        desc->chip->ack(irq);
271
272        if (status & SOC_CHIPCOMON_A_INTMASK_UART) {
273                generic_handle_irq(IRQ_CCA_UART);
274        }
275
276        if (status & SOC_CHIPCOMON_A_INTMASK_GPIO) {
277                soc_cca_gpio_handle();
278        }
279
280        desc->chip->unmask(irq);
281}
282
283static void soc_cca_gpio_irq_update_type(unsigned int irq)
284{
285        int gpio = irq_to_gpio(irq);
286        struct soc_cca_gpio_irq_data *pdata;
287        uint32 gpio_bit;
288        unsigned int type;
289
290        if (gpio < 0) {
291                return;
292        }
293
294        pdata = get_irq_data(irq);
295        type = pdata->type;
296        gpio_bit = (1 << gpio);
297
298        if (type & IRQ_TYPE_LEVEL_LOW) {
299                writel(readl(SOC_CHIPCOMON_A_GPIOINTPOLARITY_VA) | gpio_bit,
300                        SOC_CHIPCOMON_A_GPIOINTPOLARITY_VA);
301        } else if (type & IRQ_TYPE_LEVEL_HIGH) {
302                writel(readl(SOC_CHIPCOMON_A_GPIOINTPOLARITY_VA) & ~gpio_bit,
303                        SOC_CHIPCOMON_A_GPIOINTPOLARITY_VA);
304        } else if (type & IRQ_TYPE_EDGE_FALLING) {
305                writel(readl(SOC_CHIPCOMON_A_GPIOEVENTINTPOLARITY_VA) | gpio_bit,
306                        SOC_CHIPCOMON_A_GPIOEVENTINTPOLARITY_VA);
307        } else if (type & IRQ_TYPE_EDGE_RISING) {
308                writel(readl(SOC_CHIPCOMON_A_GPIOEVENTINTPOLARITY_VA) & ~gpio_bit,
309                        SOC_CHIPCOMON_A_GPIOEVENTINTPOLARITY_VA);
310        }
311}
312
313static void soc_cca_gpio_irq_ack(unsigned int irq)
314{
315        int gpio = irq_to_gpio(irq);
316
317        if (gpio < 0) {
318                return;
319        }
320
321        writel((1 << gpio), SOC_CHIPCOMON_A_GPIOEVENT_VA);
322}
323
324static void soc_cca_gpio_irq_maskunmask(unsigned int irq, bool mask)
325{
326        int gpio = irq_to_gpio(irq);
327        struct soc_cca_gpio_irq_data *data;
328        uint32 mask_addr;
329        uint32 gpio_bit;
330        uint32 val;
331
332        if (gpio < 0) {
333                return;
334        }
335
336        data = get_irq_data(irq);
337        gpio_bit = (1 << gpio);
338
339        if (data->type & IRQ_TYPE_EDGE_BOTH) {
340                mask_addr = SOC_CHIPCOMON_A_GPIOEVENTINTMASK_VA;
341        } else {
342                mask_addr = SOC_CHIPCOMON_A_GPIOINTMASK_VA;
343        }
344
345        val = readl(mask_addr);
346        if (mask) {
347                val &= ~gpio_bit;
348        } else {
349                val |= gpio_bit;
350        }
351        writel(val, mask_addr);
352}
353
354static void soc_cca_gpio_irq_mask(unsigned int irq)
355{
356        soc_cca_gpio_irq_maskunmask(irq, true);
357}
358
359static void soc_cca_gpio_irq_unmask(unsigned int irq)
360{
361        soc_cca_gpio_irq_maskunmask(irq, false);
362}
363
364static void soc_cca_gpio_irq_enable(unsigned int irq)
365{
366        soc_cca_gpio_irq_update_type(irq);
367        soc_cca_gpio_irq_ack(irq);
368        soc_cca_gpio_irq_unmask(irq);
369}
370
371static void soc_cca_gpio_irq_disable(unsigned int irq)
372{
373        soc_cca_gpio_irq_mask(irq);
374}
375
376static int soc_cca_gpio_irq_set_type(unsigned int irq, unsigned int type)
377{
378        struct soc_cca_gpio_irq_data *pdata;
379
380        if (irq_to_gpio(irq) < 0) {
381                return -EINVAL;
382        }
383
384        if ((type & IRQ_TYPE_SENSE_MASK) == 0) {
385                return -EINVAL;
386        }
387
388        pdata = get_irq_data(irq);
389        pdata->type = type & IRQ_TYPE_SENSE_MASK;
390
391        return 0;
392}
393
394static struct irq_chip cca_gpio_irq_chip = {
395        .name           = "CCA_GPIO",
396        .ack            = soc_cca_gpio_irq_ack,
397        .mask           = soc_cca_gpio_irq_mask,
398        .unmask         = soc_cca_gpio_irq_unmask,
399        .enable         = soc_cca_gpio_irq_enable,
400        .disable        = soc_cca_gpio_irq_disable,
401        .set_type       = soc_cca_gpio_irq_set_type,
402};
403
404static void __init soc_cca_irq_enable(void)
405{
406        static struct soc_cca_gpio_irq_data irq_data[IRQ_CCA_GPIO_N];
407        int irq;
408
409        for (irq = IRQ_CCA_FIRST; irq <= IRQ_CCA_LAST; ++irq) {
410                if (irq == IRQ_CCA_UART) {
411                        set_irq_chip(irq, NULL);
412                } else {
413                        set_irq_chip(irq, &cca_gpio_irq_chip);
414                        set_irq_data(irq, &irq_data[irq_to_gpio(irq)]);
415                }
416                set_irq_handler(irq, handle_level_irq);
417                set_irq_flags(irq, IRQF_VALID);
418        }
419
420        set_irq_chained_handler(IRQ_CCA, soc_cca_irq_handler);
421
422        printk(KERN_INFO"%d IRQ chained: UART, GPIOs\n", IRQ_CCA);
423}
424
425#else
426
427static void __init soc_cca_irq_enable(void)
428{
429}
430
431#endif /* CONFIG_PLAT_CCA_GPIO_IRQ */
432
433/*
434 * This SoC relies on MPCORE GIC interrupt controller
435 */
436void __init soc_init_irq( void )
437{
438        mpcore_init_gic();
439        soc_aborts_enable();
440        soc_cca_irq_enable();
441}
442
443/*
444 * Do timer clock (using ILP clock) calibration for BCM53573
445 */
446static u32 __init soc_timerclk_calibration(void)
447{
448        void * __iomem reg_base = (void *)SOC_PMU_BASE_VA;
449        u32 val1, val2, val_sum = 0, val_num = 0, loop_num = 0;
450        u32 timer_clk;
451
452        /* Enable XtalCntrEanble bit, bit[31] of PMU_XtalFreqRatio register */
453        writel(0x80000000, reg_base + PMU_XTALFREQ_RATIO_OFF);
454        val1 = readl(reg_base + PMU_XTALFREQ_RATIO_OFF) & 0x1fff;
455
456        /*
457         * Get some valid values of the field AlpPer4Ilp of the above register, and
458         * average it as timer clock.
459         */
460        while (val_num < 20) {
461                /* Check next valid value */
462                val2 = readl(reg_base + PMU_XTALFREQ_RATIO_OFF) & 0x1fff;
463                if (val1 == val2) {
464                        if (++loop_num > 5000) {
465                                val_sum += val2;
466                                val_num++;
467                                break;
468                        }
469                        continue;
470                }
471                val1 = val2;
472                val_sum += val1;
473                val_num++;
474                loop_num = 0;
475        }
476
477        /* Disable XtalCntrEanble bit, bit[31] of PMU_XtalFreqRatio register */
478        writel(0x0, reg_base + PMU_XTALFREQ_RATIO_OFF);
479
480        val_sum /= val_num;
481        timer_clk = (si_alp_clock(sih) * 4) / val_sum;
482
483        return timer_clk;
484}
485
486/*
487 * Initialize SoC timers
488 */
489void __init soc_init_timer(void)
490{
491        unsigned long periphclk_freq;
492        struct clk * clk;
493        if (BCM53573_CHIP(sih->chip)) {
494                soc_pmu_clk_init(_soc_refclk);
495                periphclk_freq = (unsigned long)soc_timerclk_calibration();
496        } else {
497                /* Clocks need to be setup early */
498                soc_dmu_init(_soc_refclk);
499                soc_cru_init(_soc_refclk);
500
501                /* get mpcore PERIPHCLK from clock modules */
502                clk = clk_get_sys(NULL, "periph_clk");
503                BUG_ON(IS_ERR_OR_NULL(clk));
504                periphclk_freq = clk_get_rate(clk);
505        }
506
507        BUG_ON(!periphclk_freq);
508
509        /* Fire up the global MPCORE timer */
510        mpcore_init_timer(periphclk_freq);
511
512}
513
514static void __init soc_config_cca_uart_clock(void)
515{
516        if (BCM53573_CHIP(sih->chip)) {
517                return;
518        }
519
520#if defined(CONFIG_PLAT_CCA_UART_CLK_DEFAULT)
521        /* Do nothing. Use what already set. */
522#elif defined(CONFIG_PLAT_CCA_UART_CLK_INTERNAL_OVERRIDE)
523        writel(PLAT_SM_SET(readl(SOC_CHIPCOMON_A_CORECTRL), SOC_CHIPCOMON_A_CORECTRL_UARTCLKOVR, 1),
524                SOC_CHIPCOMON_A_CORECTRL);
525#elif defined(CONFIG_PLAT_CCA_UART_CLK_INTERNAL_DIVIDER)
526        writel(PLAT_SM_ASSIGN(readl(SOC_CHIPCOMON_A_CLKDIV), SOC_CHIPCOMON_A_CLKDIV_UARTCLKDIV, CONFIG_PLAT_CCA_UART_CLK_INTERNAL_DIVIDER_VAL),
527                SOC_CHIPCOMON_A_CLKDIV);
528        writel(PLAT_SM_CLR(readl(SOC_CHIPCOMON_A_CORECTRL), SOC_CHIPCOMON_A_CORECTRL_UARTCLKOVR),
529                SOC_CHIPCOMON_A_CORECTRL);
530        writel(PLAT_SM_SET(readl(SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT), SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT_UARTCLKSEL, 1),
531                SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT);
532#elif defined(CONFIG_PLAT_CCA_UART_CLK_EXTERNAL)
533        writel(PLAT_SM_CLR(readl(SOC_CHIPCOMON_A_CORECTRL), SOC_CHIPCOMON_A_CORECTRL_UARTCLKOVR),
534                SOC_CHIPCOMON_A_CORECTRL);
535        writel(PLAT_SM_CLR(readl(SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT), SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT_UARTCLKSEL),
536                SOC_APBX_IDM_IDM_IO_CONTROL_DIRECT);
537#endif
538}
539
540static void __init soc_get_uart_clk_rate(u32 *clk_rate_cca, u32 *clk_rate_ccb)
541{
542        struct clk *clk_ext = _soc_refclk;
543        struct clk *clk_int = NULL;
544        u32 clk_rate_int;
545        u32 UARTClkSel = PLAT_SM_GET(readl(SOC_CHIPCOMON_A_CORECAP), SOC_CHIPCOMON_A_CORECAP_UARTCLKSEL);
546        u32 UARTClkOvr = PLAT_SM_GET(readl(SOC_CHIPCOMON_A_CORECTRL), SOC_CHIPCOMON_A_CORECTRL_UARTCLKOVR);
547        u32 UARTClkDiv = PLAT_SM_GET(readl(SOC_CHIPCOMON_A_CLKDIV), SOC_CHIPCOMON_A_CLKDIV_UARTCLKDIV);
548
549        BUG_ON(!clk_ext);
550        BUG_ON(UARTClkSel > 1);
551        if (BCM53573_CHIP(sih->chip)) {
552                clk_rate_int = si_alp_clock(sih);
553        } else {
554                clk_int = clk_get_sys(NULL, "iproc_slow_clk");
555                BUG_ON(!clk_int);
556                clk_rate_int = clk_get_rate(clk_int);
557        }
558   
559        if (UARTClkDiv == 0) {
560                UARTClkDiv = 0x100;
561        }
562
563        if (UARTClkOvr) {
564                /* internal reference clock source */
565                *clk_rate_cca = clk_rate_int;
566        } else if (UARTClkSel) {
567                /* internal reference clock source with applied divider */
568                *clk_rate_cca = clk_rate_int / UARTClkDiv;
569        } else {
570                /* external reference clock source */
571                *clk_rate_cca = clk_get_rate(clk_ext);
572        }
573
574        printk(KERN_INFO "CCA UART Clock Config: Sel=%d Ovr=%d Div=%d\n",
575                UARTClkSel, UARTClkOvr, UARTClkDiv);
576
577        if (BCM53573_CHIP(sih->chip)) {
578                /* Don't care about CCB for BCM53573 */
579                *clk_rate_ccb = 0;
580
581                printk(KERN_INFO "CCA UART Clock rate %uHz\n", *clk_rate_cca);
582        } else {
583                *clk_rate_ccb = clk_rate_int;
584
585                printk(KERN_INFO "CCA UART Clock rate %uHz CCB UART Clock rate %uHz\n",
586                *clk_rate_cca, *clk_rate_ccb);
587        }
588}
589
590
591static void __init soc_fixup_uart_ports(void)
592{
593        u32 clk_rate_cca, clk_rate_ccb;
594        unsigned i;
595
596        soc_config_cca_uart_clock();
597
598        soc_get_uart_clk_rate(&clk_rate_cca, &clk_rate_ccb);
599
600        for (i = 0; i < ARRAY_SIZE(uart_ports); i++) {
601                /* Last empty entry */
602                if (uart_ports[i].flags == 0)
603                        break;
604
605                if (uart_ports[i].irq == 0)
606                        uart_ports[i].flags |= UPF_AUTO_IRQ;
607
608                /* UART clock rate */
609                uart_ports[i].uartclk =
610                (uart_ports[i].irq == IRQ_CCA_UART || uart_ports[i].irq == IRQ_CC_UART) ?
611                clk_rate_cca : clk_rate_ccb;
612        }
613}
614
615/*
616 * Install all other SoC device drivers
617 * that are not automatically discoverable.
618 */
619void __init soc_add_devices( void )
620{
621        u32 i;
622
623        if (BCM53573_CHIP(sih->chip)) {
624                /* BCM53573 only has one uart port */
625                for (i = 1; i < ARRAY_SIZE(uart_ports); i++) {
626                        memset(&uart_ports[i], 0x0, sizeof(uart_ports[i]));
627                }
628                /* BCM53573 uses different interrupt ID number */
629                uart_ports[0].irq = IRQ_CC_UART;
630                /* Select 16550A to enable UART FIFO mode */
631                uart_ports[0].type = PORT_16550A;
632        }
633
634        /* Fixup UART port structure */
635        soc_fixup_uart_ports();
636
637        /* Install SoC devices in the system: uarts */
638        if (platform_device_register(&platform_serial_device) != 0) {
639                printk(KERN_WARNING "Fail to register serial device\n");
640        }
641
642        /* Install SoC devices in the system: SPI master */
643        if (platform_device_register(&platform_spi_master_device) != 0) {
644                printk(KERN_WARNING "Fail to register SPI master device\n");
645        }
646
647        /* Enable UART interrupt in ChipcommonA */
648        i = readl(SOC_CHIPCOMON_A_BASE_VA + 0x24);
649        i |= SOC_CHIPCOMON_A_INTMASK_UART;
650        writel(i, SOC_CHIPCOMON_A_BASE_VA + 0x24);
651
652#ifdef CONFIG_PLAT_CCA_GPIO_IRQ
653        /* Enable GPIO interrupts in ChipcommonA */
654        i = readl(SOC_CHIPCOMON_A_INTMASK_VA);
655        i |= SOC_CHIPCOMON_A_INTMASK_GPIO;
656        writel(i, SOC_CHIPCOMON_A_INTMASK_VA);
657#endif /* CONFIG_PLAT_CCA_GPIO_IRQ */
658
659}
660
661void plat_wake_secondary_cpu( unsigned cpu, void (* _sec_entry_va)(void) )
662{
663        void __iomem * rombase = NULL;
664        phys_addr_t lut_pa;
665        u32 offset, mask;
666        u32 val ;
667
668        mask = ( 1UL << PAGE_SHIFT) -1 ;
669
670        lut_pa = SOC_ROM_BASE_PA & ~mask ;
671        offset = SOC_ROM_BASE_PA &  mask ;
672        offset += SOC_ROM_LUT_OFF;
673       
674        rombase = ioremap( lut_pa, PAGE_SIZE );
675        if( rombase == NULL )
676                return;
677        val = virt_to_phys( _sec_entry_va );
678
679        writel( val, rombase + offset );
680
681        smp_wmb();      /* probably not needed - io regs are not cached */
682
683#ifdef  CONFIG_SMP
684        dsb_sev();      /* Exit WFI */
685#endif
686        mb();
687
688        iounmap( rombase );
689}
690
691#ifdef CONFIG_CACHE_L310
692/*
693 * SoC initialization that need to be done early,
694 * e.g. L2 cache, clock, I/O pin mux, power management
695 */
696static int  __init bcm5301_pl310_init( void )
697{
698        void __iomem *l2cache_base;
699        u32 auxctl_val, auxctl_msk ;
700
701        if (BCM53573_CHIP(sih->chip)) {
702                outer_cache.inv_range = NULL;
703                outer_cache.clean_range = NULL;
704                outer_cache.flush_range = NULL;
705#ifdef CONFIG_OUTER_CACHE_SYNC
706                outer_cache.sync = NULL;
707#endif
708                return 0;
709        }
710        /* Default AUXCTL modifiers */
711        auxctl_val = 0UL;
712        auxctl_msk = ~0UL ;
713
714        /* Customize AUXCTL */
715        auxctl_val |= 0 << 0 ;  /* Full line of zero Enable - requires A9 cfg */
716        auxctl_val |= 1 << 25;  /* Cache replacement policy - round robin */
717        auxctl_val |= 1 << 29;  /* Instruction prefetch enable */
718        auxctl_val |= 1 << 28;  /* Data prefetch enable */
719        auxctl_val |= 1 << 30;  /* Early BRESP enable */
720        auxctl_val |= 1 << 22;  /* for dma coherency */
721       
722        if (ACP_WAR_ENAB())
723                auxctl_val |= 1 << 11; /* Store buffer device limitation enable */
724
725        l2cache_base = ioremap( L2CC_BASE_PA, SZ_4K );
726
727        /* Configure using default aux control value */
728        if( l2cache_base != NULL )
729                l2x0_init( l2cache_base, auxctl_val, auxctl_msk);
730
731        return 0;
732}
733early_initcall( bcm5301_pl310_init );
734#endif
735
736#ifdef CONFIG_PROC_FS
737#define BCM_CHIPINFO_PROC_NAME  "bcm_chipinfo"
738static ssize_t chipinfo_read_proc(struct file *file, char __user *buf,
739                          size_t count, loff_t *ppos)
740{
741        int len;
742        off_t pos, begin;
743        u32 reg, val;
744        void __iomem *reg_map;
745        char buffer[256];
746
747        len = 0;
748        pos = begin = 0;
749
750        reg = SOC_CHIPCOMON_A_BASE_PA;
751        reg_map = ioremap_nocache(reg, 4);
752        val = readl(reg_map);
753        iounmap((void *)reg_map);
754
755        len += sprintf(&buffer[len], "ChipID: 0x%x\n", val & 0xffff);
756        len += sprintf(&buffer[len], "ChipRevision: 0x%x\n", (val >> 16) & 0xf);
757        len += sprintf(&buffer[len], "PackageOption: 0x%x\n", (val >> 20) & 0xf);
758
759        return simple_read_from_buffer(buf, count, ppos, buffer, len);
760}
761
762static const struct file_operations chipinfo_fops = {
763        .read = chipinfo_read_proc,
764        .llseek = default_llseek,
765};
766
767static int __init chipinfo_proc_init(void)
768{
769        struct proc_dir_entry *chip_info;
770
771        chip_info = proc_create_data(BCM_CHIPINFO_PROC_NAME, 0, NULL, &chipinfo_fops, NULL);
772        if (!chip_info) {
773                printk(KERN_ERR "%s: Create proc entry failed.\n", __FUNCTION__);
774                return -1;
775        }
776        return 0;
777}
778
779
780module_init(chipinfo_proc_init);
781#endif /* CONFIG_PROC_FS */
Note: See TracBrowser for help on using the repository browser.