0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/clockchips.h>
0011 #include <linux/io.h>
0012 #include <linux/irqchip/arm-gic.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/usb/ehci_pdriver.h>
0016 #include <linux/usb/ohci_pdriver.h>
0017 #include <asm/mach/arch.h>
0018 #include <asm/mach/map.h>
0019 #include <asm/mach/time.h>
0020 #include <asm/mach/irq.h>
0021 #include <asm/hardware/cache-l2x0.h>
0022 #include "cns3xxx.h"
0023 #include "core.h"
0024 #include "pm.h"
0025
0026 static struct map_desc cns3xxx_io_desc[] __initdata = {
0027 {
0028 .virtual = CNS3XXX_TC11MP_SCU_BASE_VIRT,
0029 .pfn = __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE),
0030 .length = SZ_8K,
0031 .type = MT_DEVICE,
0032 }, {
0033 .virtual = CNS3XXX_TIMER1_2_3_BASE_VIRT,
0034 .pfn = __phys_to_pfn(CNS3XXX_TIMER1_2_3_BASE),
0035 .length = SZ_4K,
0036 .type = MT_DEVICE,
0037 }, {
0038 .virtual = CNS3XXX_MISC_BASE_VIRT,
0039 .pfn = __phys_to_pfn(CNS3XXX_MISC_BASE),
0040 .length = SZ_4K,
0041 .type = MT_DEVICE,
0042 }, {
0043 .virtual = CNS3XXX_PM_BASE_VIRT,
0044 .pfn = __phys_to_pfn(CNS3XXX_PM_BASE),
0045 .length = SZ_4K,
0046 .type = MT_DEVICE,
0047 #ifdef CONFIG_PCI
0048 }, {
0049 .virtual = CNS3XXX_PCIE0_HOST_BASE_VIRT,
0050 .pfn = __phys_to_pfn(CNS3XXX_PCIE0_HOST_BASE),
0051 .length = SZ_4K,
0052 .type = MT_DEVICE,
0053 }, {
0054 .virtual = CNS3XXX_PCIE0_CFG0_BASE_VIRT,
0055 .pfn = __phys_to_pfn(CNS3XXX_PCIE0_CFG0_BASE),
0056 .length = SZ_64K,
0057 .type = MT_DEVICE,
0058 }, {
0059 .virtual = CNS3XXX_PCIE0_CFG1_BASE_VIRT,
0060 .pfn = __phys_to_pfn(CNS3XXX_PCIE0_CFG1_BASE),
0061 .length = SZ_16M,
0062 .type = MT_DEVICE,
0063 }, {
0064 .virtual = CNS3XXX_PCIE1_HOST_BASE_VIRT,
0065 .pfn = __phys_to_pfn(CNS3XXX_PCIE1_HOST_BASE),
0066 .length = SZ_4K,
0067 .type = MT_DEVICE,
0068 }, {
0069 .virtual = CNS3XXX_PCIE1_CFG0_BASE_VIRT,
0070 .pfn = __phys_to_pfn(CNS3XXX_PCIE1_CFG0_BASE),
0071 .length = SZ_64K,
0072 .type = MT_DEVICE,
0073 }, {
0074 .virtual = CNS3XXX_PCIE1_CFG1_BASE_VIRT,
0075 .pfn = __phys_to_pfn(CNS3XXX_PCIE1_CFG1_BASE),
0076 .length = SZ_16M,
0077 .type = MT_DEVICE,
0078 #endif
0079 },
0080 };
0081
0082 void __init cns3xxx_map_io(void)
0083 {
0084 iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
0085 }
0086
0087
0088 void __init cns3xxx_init_irq(void)
0089 {
0090 gic_init(IOMEM(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
0091 IOMEM(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
0092 }
0093
0094 void cns3xxx_power_off(void)
0095 {
0096 u32 __iomem *pm_base = IOMEM(CNS3XXX_PM_BASE_VIRT);
0097 u32 clkctrl;
0098
0099 printk(KERN_INFO "powering system down...\n");
0100
0101 clkctrl = readl(pm_base + PM_SYS_CLK_CTRL_OFFSET);
0102 clkctrl &= 0xfffff1ff;
0103 clkctrl |= (0x5 << 9);
0104 writel(clkctrl, pm_base + PM_SYS_CLK_CTRL_OFFSET);
0105
0106 }
0107
0108
0109
0110
0111 static void __iomem *cns3xxx_tmr1;
0112
0113 static int cns3xxx_shutdown(struct clock_event_device *clk)
0114 {
0115 writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0116 return 0;
0117 }
0118
0119 static int cns3xxx_set_oneshot(struct clock_event_device *clk)
0120 {
0121 unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0122
0123
0124 ctrl |= (1 << 2) | (1 << 9);
0125 writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0126 return 0;
0127 }
0128
0129 static int cns3xxx_set_periodic(struct clock_event_device *clk)
0130 {
0131 unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0132 int pclk = cns3xxx_cpu_clock() / 8;
0133 int reload;
0134
0135 reload = pclk * 20 / (3 * HZ) * 0x25000;
0136 writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
0137 ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
0138 writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0139 return 0;
0140 }
0141
0142 static int cns3xxx_timer_set_next_event(unsigned long evt,
0143 struct clock_event_device *unused)
0144 {
0145 unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0146
0147 writel(evt, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
0148 writel(ctrl | (1 << 0), cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0149
0150 return 0;
0151 }
0152
0153 static struct clock_event_device cns3xxx_tmr1_clockevent = {
0154 .name = "cns3xxx timer1",
0155 .features = CLOCK_EVT_FEAT_PERIODIC |
0156 CLOCK_EVT_FEAT_ONESHOT,
0157 .set_state_shutdown = cns3xxx_shutdown,
0158 .set_state_periodic = cns3xxx_set_periodic,
0159 .set_state_oneshot = cns3xxx_set_oneshot,
0160 .tick_resume = cns3xxx_shutdown,
0161 .set_next_event = cns3xxx_timer_set_next_event,
0162 .rating = 350,
0163 .cpumask = cpu_all_mask,
0164 };
0165
0166 static void __init cns3xxx_clockevents_init(unsigned int timer_irq)
0167 {
0168 cns3xxx_tmr1_clockevent.irq = timer_irq;
0169 clockevents_config_and_register(&cns3xxx_tmr1_clockevent,
0170 (cns3xxx_cpu_clock() >> 3) * 1000000,
0171 0xf, 0xffffffff);
0172 }
0173
0174
0175
0176
0177 static irqreturn_t cns3xxx_timer_interrupt(int irq, void *dev_id)
0178 {
0179 struct clock_event_device *evt = &cns3xxx_tmr1_clockevent;
0180 u32 __iomem *stat = cns3xxx_tmr1 + TIMER1_2_INTERRUPT_STATUS_OFFSET;
0181 u32 val;
0182
0183
0184 val = readl(stat);
0185 writel(val & ~(1 << 2), stat);
0186
0187 evt->event_handler(evt);
0188
0189 return IRQ_HANDLED;
0190 }
0191
0192
0193
0194
0195 static void __init __cns3xxx_timer_init(unsigned int timer_irq)
0196 {
0197 u32 val;
0198 u32 irq_mask;
0199
0200
0201
0202
0203
0204
0205 writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0206
0207 writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
0208
0209
0210 writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
0211 writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
0212
0213 writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
0214 writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
0215
0216
0217 irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
0218 irq_mask &= ~(1 << 2);
0219 irq_mask |= 0x03;
0220 writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
0221
0222
0223 val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0224 val |= (1 << 9);
0225 writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0226
0227
0228 writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
0229 writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
0230
0231
0232 irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
0233 irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
0234 writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
0235
0236
0237 val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0238 val |= (1 << 10);
0239 writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
0240
0241
0242 if (request_irq(timer_irq, cns3xxx_timer_interrupt,
0243 IRQF_TIMER | IRQF_IRQPOLL, "timer", NULL))
0244 pr_err("Failed to request irq %d (timer)\n", timer_irq);
0245
0246 cns3xxx_clockevents_init(timer_irq);
0247 }
0248
0249 void __init cns3xxx_timer_init(void)
0250 {
0251 cns3xxx_tmr1 = IOMEM(CNS3XXX_TIMER1_2_3_BASE_VIRT);
0252
0253 __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0);
0254 }
0255
0256 #ifdef CONFIG_CACHE_L2X0
0257
0258 void __init cns3xxx_l2x0_init(void)
0259 {
0260 void __iomem *base = ioremap(CNS3XXX_L2C_BASE, SZ_4K);
0261 u32 val;
0262
0263 if (WARN_ON(!base))
0264 return;
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 val = readl(base + L310_TAG_LATENCY_CTRL);
0276 val &= 0xfffff888;
0277 writel(val, base + L310_TAG_LATENCY_CTRL);
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 val = readl(base + L310_DATA_LATENCY_CTRL);
0289 val &= 0xfffff888;
0290 writel(val, base + L310_DATA_LATENCY_CTRL);
0291
0292
0293 l2x0_init(base, 0x00500000, 0xfe0f0fff);
0294 }
0295
0296 #endif
0297
0298 static int csn3xxx_usb_power_on(struct platform_device *pdev)
0299 {
0300
0301
0302
0303
0304
0305
0306
0307
0308 if (atomic_inc_return(&usb_pwr_ref) == 1) {
0309 cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
0310 cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
0311 cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
0312 __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
0313 MISC_CHIP_CONFIG_REG);
0314 }
0315
0316 return 0;
0317 }
0318
0319 static void csn3xxx_usb_power_off(struct platform_device *pdev)
0320 {
0321
0322
0323
0324
0325
0326
0327 if (atomic_dec_return(&usb_pwr_ref) == 0)
0328 cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
0329 }
0330
0331 static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
0332 .power_on = csn3xxx_usb_power_on,
0333 .power_off = csn3xxx_usb_power_off,
0334 };
0335
0336 static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
0337 .num_ports = 1,
0338 .power_on = csn3xxx_usb_power_on,
0339 .power_off = csn3xxx_usb_power_off,
0340 };
0341
0342 static const struct of_dev_auxdata cns3xxx_auxdata[] __initconst = {
0343 { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata },
0344 { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata },
0345 { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL },
0346 { "cavium,cns3420-sdhci", CNS3XXX_SDIO_BASE, "ahci", NULL },
0347 {},
0348 };
0349
0350 static void __init cns3xxx_init(void)
0351 {
0352 struct device_node *dn;
0353
0354 cns3xxx_l2x0_init();
0355
0356 dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-ahci");
0357 if (of_device_is_available(dn)) {
0358 u32 tmp;
0359
0360 tmp = __raw_readl(MISC_SATA_POWER_MODE);
0361 tmp |= 0x1 << 16;
0362 tmp |= 0x1 << 17;
0363 __raw_writel(tmp, MISC_SATA_POWER_MODE);
0364
0365
0366 cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0);
0367 cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1);
0368
0369
0370 cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_SATA);
0371
0372
0373 cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SATA));
0374 }
0375 of_node_put(dn);
0376
0377 dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-sdhci");
0378 if (of_device_is_available(dn)) {
0379 u32 __iomem *gpioa = IOMEM(CNS3XXX_MISC_BASE_VIRT + 0x0014);
0380 u32 gpioa_pins = __raw_readl(gpioa);
0381
0382
0383 gpioa_pins |= 0x1fff0004;
0384 __raw_writel(gpioa_pins, gpioa);
0385
0386 cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
0387 cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
0388 }
0389 of_node_put(dn);
0390
0391 pm_power_off = cns3xxx_power_off;
0392
0393 of_platform_default_populate(NULL, cns3xxx_auxdata, NULL);
0394 }
0395
0396 static const char *const cns3xxx_dt_compat[] __initconst = {
0397 "cavium,cns3410",
0398 "cavium,cns3420",
0399 NULL,
0400 };
0401
0402 DT_MACHINE_START(CNS3XXX_DT, "Cavium Networks CNS3xxx")
0403 .dt_compat = cns3xxx_dt_compat,
0404 .map_io = cns3xxx_map_io,
0405 .init_irq = cns3xxx_init_irq,
0406 .init_time = cns3xxx_timer_init,
0407 .init_machine = cns3xxx_init,
0408 .init_late = cns3xxx_pcie_init_late,
0409 .restart = cns3xxx_restart,
0410 MACHINE_END