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
 192/*
 193 * Set up the clock source and clock events devices
 194 */
 195static void __init __cns3xxx_timer_init(unsigned int timer_irq)
 196{
 197        u32 val;
 198        u32 irq_mask;
 199
 200        /*
 201         * Initialise to a known state (all timers off)
 202         */
 203
 204        /* disable timer1 and timer2 */
 205        writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 206        /* stop free running timer3 */
 207        writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
 208
 209        /* timer1 */
 210        writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
 211        writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
 212
 213        writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
 214        writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
 215
 216        /* mask irq, non-mask timer1 overflow */
 217        irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 218        irq_mask &= ~(1 << 2);
 219        irq_mask |= 0x03;
 220        writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 221
 222        /* down counter */
 223        val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 224        val |= (1 << 9);
 225        writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 226
 227        /* timer2 */
 228        writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
 229        writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
 230
 231        /* mask irq */
 232        irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 233        irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
 234        writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
 235
 236        /* down counter */
 237        val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 238        val |= (1 << 10);
 239        writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
 240
 241        /* Make irqs happen for the system timer */
 242        if (request_irq(timer_irq, cns3xxx_timer_interrupt,
 243                        IRQF_TIMER | IRQF_IRQPOLL, "timer", NULL))
 244                pr_err("Failed to request irq %d (timer)\n", timer_irq);
 245
 246        cns3xxx_clockevents_init(timer_irq);
 247}
 248
 249void __init cns3xxx_timer_init(void)
 250{
 251        cns3xxx_tmr1 = IOMEM(CNS3XXX_TIMER1_2_3_BASE_VIRT);
 252
 253        __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0);
 254}
 255
 256#ifdef CONFIG_CACHE_L2X0
 257
 258void __init cns3xxx_l2x0_init(void)
 259{
 260        void __iomem *base = ioremap(CNS3XXX_L2C_BASE, SZ_4K);
 261        u32 val;
 262
 263        if (WARN_ON(!base))
 264                return;
 265
 266        /*
 267         * Tag RAM Control register
 268         *
 269         * bit[10:8]    - 1 cycle of write accesses latency
 270         * bit[6:4]     - 1 cycle of read accesses latency
 271         * bit[3:0]     - 1 cycle of setup latency
 272         *
 273         * 1 cycle of latency for setup, read and write accesses
 274         */
 275        val = readl(base + L310_TAG_LATENCY_CTRL);
 276        val &= 0xfffff888;
 277        writel(val, base + L310_TAG_LATENCY_CTRL);
 278
 279        /*
 280         * Data RAM Control register
 281         *
 282         * bit[10:8]    - 1 cycles of write accesses latency
 283         * bit[6:4]     - 1 cycles of read accesses latency
 284         * bit[3:0]     - 1 cycle of setup latency
 285         *
 286         * 1 cycle of latency for setup, read and write accesses
 287         */
 288        val = readl(base + L310_DATA_LATENCY_CTRL);
 289        val &= 0xfffff888;
 290        writel(val, base + L310_DATA_LATENCY_CTRL);
 291
 292        /* 32 KiB, 8-way, parity disable */
 293        l2x0_init(base, 0x00500000, 0xfe0f0fff);
 294}
 295
 296#endif /* CONFIG_CACHE_L2X0 */
 297
 298static int csn3xxx_usb_power_on(struct platform_device *pdev)
 299{
 300        /*
 301         * EHCI and OHCI share the same clock and power,
 302         * resetting twice would cause the 1st controller been reset.
 303         * Therefore only do power up  at the first up device, and
 304         * power down at the last down device.
 305         *
 306         * Set USB AHB INCR length to 16
 307         */
 308        if (atomic_inc_return(&usb_pwr_ref) == 1) {
 309                cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
 310                cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
 311                cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
 312                __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
 313                        MISC_CHIP_CONFIG_REG);
 314        }
 315
 316        return 0;
 317}
 318
 319static void csn3xxx_usb_power_off(struct platform_device *pdev)
 320{
 321        /*
 322         * EHCI and OHCI share the same clock and power,
 323         * resetting twice would cause the 1st controller been reset.
 324         * Therefore only do power up  at the first up device, and
 325         * power down at the last down device.
 326         */
 327        if (atomic_dec_return(&usb_pwr_ref) == 0)
 328                cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
 329}
 330
 331static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
 332        .power_on       = csn3xxx_usb_power_on,
 333        .power_off      = csn3xxx_usb_power_off,
 334};
 335
 336static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
 337        .num_ports      = 1,
 338        .power_on       = csn3xxx_usb_power_on,
 339        .power_off      = csn3xxx_usb_power_off,
 340};
 341
 342static const struct of_dev_auxdata cns3xxx_auxdata[] __initconst = {
 343        { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata },
 344        { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata },
 345        { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL },
 346        { "cavium,cns3420-sdhci", CNS3XXX_SDIO_BASE, "ahci", NULL },
 347        {},
 348};
 349
 350static void __init cns3xxx_init(void)
 351{
 352        struct device_node *dn;
 353
 354        cns3xxx_l2x0_init();
 355
 356        dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-ahci");
 357        if (of_device_is_available(dn)) {
 358                u32 tmp;
 359        
 360                tmp = __raw_readl(MISC_SATA_POWER_MODE);
 361                tmp |= 0x1 << 16; /* Disable SATA PHY 0 from SLUMBER Mode */
 362                tmp |= 0x1 << 17; /* Disable SATA PHY 1 from SLUMBER Mode */
 363                __raw_writel(tmp, MISC_SATA_POWER_MODE);
 364        
 365                /* Enable SATA PHY */
 366                cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0);
 367                cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1);
 368        
 369                /* Enable SATA Clock */
 370                cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_SATA);
 371        
 372                /* De-Asscer SATA Reset */
 373                cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SATA));
 374        }
 375
 376        dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-sdhci");
 377        if (of_device_is_available(dn)) {
 378                u32 __iomem *gpioa = IOMEM(CNS3XXX_MISC_BASE_VIRT + 0x0014);
 379                u32 gpioa_pins = __raw_readl(gpioa);
 380        
 381                /* MMC/SD pins share with GPIOA */
 382                gpioa_pins |= 0x1fff0004;
 383                __raw_writel(gpioa_pins, gpioa);
 384        
 385                cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
 386                cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
 387        }
 388
 389        pm_power_off = cns3xxx_power_off;
 390
 391        of_platform_default_populate(NULL, cns3xxx_auxdata, NULL);
 392}
 393
 394static const char *const cns3xxx_dt_compat[] __initconst = {
 395        "cavium,cns3410",
 396        "cavium,cns3420",
 397        NULL,
 398};
 399
 400DT_MACHINE_START(CNS3XXX_DT, "Cavium Networks CNS3xxx")
 401        .dt_compat      = cns3xxx_dt_compat,
 402        .map_io         = cns3xxx_map_io,
 403        .init_irq       = cns3xxx_init_irq,
 404        .init_time      = cns3xxx_timer_init,
 405        .init_machine   = cns3xxx_init,
 406        .init_late      = cns3xxx_pcie_init_late,
 407        .restart        = cns3xxx_restart,
 408MACHINE_END
 409