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

Last change on this file since 31574 was 31574, checked in by brainslayer, 3 months ago

kernel 4.9 update

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 void __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;
775        }
776}
777
778
779module_init(chipinfo_proc_init);
780#endif /* CONFIG_PROC_FS */
Note: See TracBrowser for help on using the repository browser.