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