linux/arch/arm/mach-cns3xxx/core.c
<<
>>
Prefs
   1/*
   2 * Copyright 1999 - 2003 ARM Limited
   3 * Copyright 2000 Deep Blue Solutions Ltd
   4 * Copyright 2008 Cavium Networks
   5 *
   6 * This file is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License, Version 2, as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/init.h>
  12#include <linux/interrupt.h>
  13#include <linux/clockchips.h>
  14#include <linux/io.h>
  15#include <linux/irqchip/arm-gic.h>
  16#include <linux/of_platform.h>
  17#include <linux/platform_device.h>
  18#include <linux/usb/ehci_pdriver.h>
  19#include <linux/usb/ohci_pdriver.h>
  20#include <asm/mach/arch.h>
  21#include <asm/mach/map.h>
  22#include <asm/mach/time.h>
  23#include <asm/mach/irq.h>
  24#include <asm/hardware/cache-l2x0.h>
  25#include "cns3xxx.h"
  26#include "core.h"
  27#include "pm.h"
  28
  29static struct map_desc cns3xxx_io_desc[] __initdata = {
  30        {
  31                .virtual        = CNS3XXX_TC11MP_SCU_BASE_VIRT,
  32                .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE),
  33                .length         = SZ_8K,
  34                .type           = MT_DEVICE,
  35        }, {
  36                .virtual        = CNS3XXX_TIMER1_2_3_BASE_VIRT,
  37                .pfn            = __phys_to_pfn(CNS3XXX_TIMER1_2_3_BASE),
  38                .length         = SZ_4K,
  39                .type           = MT_DEVICE,
  40        }, {
  41                .virtual        = CNS3XXX_MISC_BASE_VIRT,
  42                .pfn            = __phys_to_pfn(CNS3XXX_MISC_BASE),
  43                .length         = SZ_4K,
  44                .type           = MT_DEVICE,
  45        }, {
  46                .virtual        = CNS3XXX_PM_BASE_VIRT,
  47                .pfn            = __phys_to_pfn(CNS3XXX_PM_BASE),
  48                .length         = SZ_4K,
  49                .type           = MT_DEVICE,
  50#ifdef CONFIG_PCI
  51        }, {
  52                .virtual        = CNS3XXX_PCIE0_HOST_BASE_VIRT,
  53                .pfn            = __phys_to_pfn(CNS3XXX_PCIE0_HOST_BASE),
  54                .length         = SZ_4K,
  55                .type           = MT_DEVICE,
  56        }, {
  57                .virtual        = CNS3XXX_PCIE0_CFG0_BASE_VIRT,
  58                .pfn            = __phys_to_pfn(CNS3XXX_PCIE0_CFG0_BASE),
  59                .length         = SZ_64K, /* really 4 KiB at offset 32 KiB */
  60                .type           = MT_DEVICE,
  61        }, {
  62                .virtual        = CNS3XXX_PCIE0_CFG1_BASE_VIRT,
  63                .pfn            = __phys_to_pfn(CNS3XXX_PCIE0_CFG1_BASE),
  64                .length         = SZ_16M,
  65                .type           = MT_DEVICE,
  66        }, {
  67                .virtual        = CNS3XXX_PCIE1_HOST_BASE_VIRT,
  68                .pfn            = __phys_to_pfn(CNS3XXX_PCIE1_HOST_BASE),
  69                .length         = SZ_4K,
  70                .type           = MT_DEVICE,
  71        }, {
  72                .virtual        = CNS3XXX_PCIE1_CFG0_BASE_VIRT,
  73                .pfn            = __phys_to_pfn(CNS3XXX_PCIE1_CFG0_BASE),
  74                .length         = SZ_64K, /* really 4 KiB at offset 32 KiB */
  75                .type           = MT_DEVICE,
  76        }, {
  77                .virtual        = CNS3XXX_PCIE1_CFG1_BASE_VIRT,
  78                .pfn            = __phys_to_pfn(CNS3XXX_PCIE1_CFG1_BASE),
  79                .length         = SZ_16M,
  80                .type           = MT_DEVICE,
  81#endif
  82        },
  83};
  84
  85void __init cns3xxx_map_io(void)
  86{
  87        iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
  88}
  89
  90/* used by entry-macro.S */
  91void __init cns3xxx_init_irq(void)
  92{
  93        gic_init(0, 29, IOMEM(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
  94                 IOMEM(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
  95}
  96
  97void cns3xxx_power_off(void)
  98{
  99        u32 __iomem *pm_base = IOMEM(CNS3XXX_PM_BASE_VIRT);
 100        u32 clkctrl;
 101
 102        printk(KERN_INFO "powering system down...\n");
 103
 104        clkctrl = readl(pm_base + PM_SYS_CLK_CTRL_OFFSET);
 105        clkctrl &= 0xfffff1ff;
 106        clkctrl |= (0x5 << 9);          /* Hibernate */
 107        writel(clkctrl, pm_base + PM_SYS_CLK_CTRL_OFFSET);
 108
 109}
 110
 111/*
 112 * Timer
 113 */
 114static void __iomem *cns3xxx_tmr1;
 115
 116static int cns3xxx_shutdown(struct clock_event_device *clk)
 117{
 118        writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 119        return 0;
 120}
 121
 122static int cns3xxx_set_oneshot(struct clock_event_device *clk)
 123{
 124        unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 125
 126        /* period set, and timer enabled in 'next_event' hook */
 127        ctrl |= (1 << 2) | (1 << 9);
 128        writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 129        return 0;
 130}
 131
 132static int cns3xxx_set_periodic(struct clock_event_device *clk)
 133{
 134        unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 135        int pclk = cns3xxx_cpu_clock() / 8;
 136        int reload;
 137
 138        reload = pclk * 20 / (3 * HZ) * 0x25000;
 139        writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
 140        ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
 141        writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 142        return 0;
 143}
 144
 145static int cns3xxx_timer_set_next_event(unsigned long evt,
 146                                        struct clock_event_device *unused)
 147{
 148        unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 149
 150        writel(evt, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
 151        writel(ctrl | (1 << 0), cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 152
 153        return 0;
 154}
 155
 156static struct clock_event_device cns3xxx_tmr1_clockevent = {
 157        .name                   = "cns3xxx timer1",
 158        .features               = CLOCK_EVT_FEAT_PERIODIC |
 159                                  CLOCK_EVT_FEAT_ONESHOT,
 160        .set_state_shutdown     = cns3xxx_shutdown,
 161        .set_state_periodic     = cns3xxx_set_periodic,
 162        .set_state_oneshot      = cns3xxx_set_oneshot,
 163        .tick_resume            = cns3xxx_shutdown,
 164        .set_next_event         = cns3xxx_timer_set_next_event,
 165        .rating                 = 350,
 166        .cpumask                = cpu_all_mask,
 167};
 168
 169static void __init cns3xxx_clockevents_init(unsigned int timer_irq)
 170{
 171        cns3xxx_tmr1_clockevent.irq = timer_irq;
 172        clockevents_config_and_register(&cns3xxx_tmr1_clockevent,
 173                                        (cns3xxx_cpu_clock() >> 3) * 1000000,
 174                                        0xf, 0xffffffff);
 175}
 176
 177/*
 178 * IRQ handler for the timer
 179 */
 180static irqreturn_t cns3xxx_timer_interrupt(int irq, void *dev_id)
 181{
 182        struct clock_event_device *evt = &cns3xxx_tmr1_clockevent;
 183        u32 __iomem *stat = cns3xxx_tmr1 + TIMER1_2_INTERRUPT_STATUS_OFFSET;
 184        u32 val;
 185
 186        /* Clear the interrupt */
 187        val = readl(stat);
 188        writel(val & ~(1 << 2), stat);
 189
 190        evt->event_handler(evt);
 191
 192        return IRQ_HANDLED;
 193}
 194
 195static struct irqaction cns3xxx_timer_irq = {
 196        .name           = "timer",
 197        .flags          = IRQF_TIMER | IRQF_IRQPOLL,
 198        .handler        = cns3xxx_timer_interrupt,
 199};
 200
 201/*
 202 * Set up the clock source and clock events devices
 203 */
 204static void __init __cns3xxx_timer_init(unsigned int timer_irq)
 205{
 206        u32 val;
 207        u32 irq_mask;
 208
 209        /*
 210         * Initialise to a known state (all timers off)
 211         */
 212
 213        /* disable timer1 and timer2 */
 214        writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 215        /* stop free running timer3 */
 216        writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
 217
 218        /* timer1 */
 219        writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
 220        writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
 221
 222        writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
 223        writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
 224
 225        /* mask irq, non-mask timer1 overflow */
 226        irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 227        irq_mask &= ~(1 << 2);
 228        irq_mask |= 0x03;
 229        writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 230
 231        /* down counter */
 232        val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 233        val |= (1 << 9);
 234        writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 235
 236        /* timer2 */
 237        writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
 238        writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
 239
 240        /* mask irq */
 241        irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 242        irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
 243        writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 244
 245        /* down counter */
 246        val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 247        val |= (1 << 10);
 248        writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 249
 250        /* Make irqs happen for the system timer */
 251        setup_irq(timer_irq, &cns3xxx_timer_irq);
 252
 253        cns3xxx_clockevents_init(timer_irq);
 254}
 255
 256void __init cns3xxx_timer_init(void)
 257{
 258        cns3xxx_tmr1 = IOMEM(CNS3XXX_TIMER1_2_3_BASE_VIRT);
 259
 260        __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0);
 261}
 262
 263#ifdef CONFIG_CACHE_L2X0
 264
 265void __init cns3xxx_l2x0_init(void)
 266{
 267        void __iomem *base = ioremap(CNS3XXX_L2C_BASE, SZ_4K);
 268        u32 val;
 269
 270        if (WARN_ON(!base))
 271                return;
 272
 273        /*
 274         * Tag RAM Control register
 275         *
 276         * bit[10:8]    - 1 cycle of write accesses latency
 277         * bit[6:4]     - 1 cycle of read accesses latency
 278         * bit[3:0]     - 1 cycle of setup latency
 279         *
 280         * 1 cycle of latency for setup, read and write accesses
 281         */
 282        val = readl(base + L310_TAG_LATENCY_CTRL);
 283        val &= 0xfffff888;
 284        writel(val, base + L310_TAG_LATENCY_CTRL);
 285
 286        /*
 287         * Data RAM Control register
 288         *
 289         * bit[10:8]    - 1 cycles of write accesses latency
 290         * bit[6:4]     - 1 cycles of read accesses latency
 291         * bit[3:0]     - 1 cycle of setup latency
 292         *
 293         * 1 cycle of latency for setup, read and write accesses
 294         */
 295        val = readl(base + L310_DATA_LATENCY_CTRL);
 296        val &= 0xfffff888;
 297        writel(val, base + L310_DATA_LATENCY_CTRL);
 298
 299        /* 32 KiB, 8-way, parity disable */
 300        l2x0_init(base, 0x00500000, 0xfe0f0fff);
 301}
 302
 303#endif /* CONFIG_CACHE_L2X0 */
 304
 305static int csn3xxx_usb_power_on(struct platform_device *pdev)
 306{
 307        /*
 308         * EHCI and OHCI share the same clock and power,
 309         * resetting twice would cause the 1st controller been reset.
 310         * Therefore only do power up  at the first up device, and
 311         * power down at the last down device.
 312         *
 313         * Set USB AHB INCR length to 16
 314         */
 315        if (atomic_inc_return(&usb_pwr_ref) == 1) {
 316                cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
 317                cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
 318                cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
 319                __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
 320                        MISC_CHIP_CONFIG_REG);
 321        }
 322
 323        return 0;
 324}
 325
 326static void csn3xxx_usb_power_off(struct platform_device *pdev)
 327{
 328        /*
 329         * EHCI and OHCI share the same clock and power,
 330         * resetting twice would cause the 1st controller been reset.
 331         * Therefore only do power up  at the first up device, and
 332         * power down at the last down device.
 333         */
 334        if (atomic_dec_return(&usb_pwr_ref) == 0)
 335                cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
 336}
 337
 338static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
 339        .power_on       = csn3xxx_usb_power_on,
 340        .power_off      = csn3xxx_usb_power_off,
 341};
 342
 343static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
 344        .num_ports      = 1,
 345        .power_on       = csn3xxx_usb_power_on,
 346        .power_off      = csn3xxx_usb_power_off,
 347};
 348
 349static const struct of_dev_auxdata cns3xxx_auxdata[] __initconst = {
 350        { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata },
 351        { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata },
 352        { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL },
 353        { "cavium,cns3420-sdhci", CNS3XXX_SDIO_BASE, "ahci", NULL },
 354        {},
 355};
 356
 357static void __init cns3xxx_init(void)
 358{
 359        struct device_node *dn;
 360
 361        cns3xxx_l2x0_init();
 362
 363        dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-ahci");
 364        if (of_device_is_available(dn)) {
 365                u32 tmp;
 366        
 367                tmp = __raw_readl(MISC_SATA_POWER_MODE);
 368                tmp |= 0x1 << 16; /* Disable SATA PHY 0 from SLUMBER Mode */
 369                tmp |= 0x1 << 17; /* Disable SATA PHY 1 from SLUMBER Mode */
 370                __raw_writel(tmp, MISC_SATA_POWER_MODE);
 371        
 372                /* Enable SATA PHY */
 373                cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0);
 374                cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1);
 375        
 376                /* Enable SATA Clock */
 377                cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_SATA);
 378        
 379                /* De-Asscer SATA Reset */
 380                cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SATA));
 381        }
 382
 383        dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-sdhci");
 384        if (of_device_is_available(dn)) {
 385                u32 __iomem *gpioa = IOMEM(CNS3XXX_MISC_BASE_VIRT + 0x0014);
 386                u32 gpioa_pins = __raw_readl(gpioa);
 387        
 388                /* MMC/SD pins share with GPIOA */
 389                gpioa_pins |= 0x1fff0004;
 390                __raw_writel(gpioa_pins, gpioa);
 391        
 392                cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
 393                cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
 394        }
 395
 396        pm_power_off = cns3xxx_power_off;
 397
 398        of_platform_default_populate(NULL, cns3xxx_auxdata, NULL);
 399}
 400
 401static const char *const cns3xxx_dt_compat[] __initconst = {
 402        "cavium,cns3410",
 403        "cavium,cns3420",
 404        NULL,
 405};
 406
 407DT_MACHINE_START(CNS3XXX_DT, "Cavium Networks CNS3xxx")
 408        .dt_compat      = cns3xxx_dt_compat,
 409        .map_io         = cns3xxx_map_io,
 410        .init_irq       = cns3xxx_init_irq,
 411        .init_time      = cns3xxx_timer_init,
 412        .init_machine   = cns3xxx_init,
 413        .init_late      = cns3xxx_pcie_init_late,
 414        .restart        = cns3xxx_restart,
 415MACHINE_END
 416