static __init int add_rtc_cmos(void) { #ifdef CONFIG_PNP static const char *ids[] __initconst = { "PNP0b00", "PNP0b01", "PNP0b02", }; struct pnp_dev *dev; struct pnp_id *id; int i; pnp_for_each_dev(dev) { for (id = dev->id; id; id = id->next) { for (i = 0; i < ARRAY_SIZE(ids); i++) { if (compare_pnp_id(id, ids[i]) != 0) return 0; } } } #endif if (of_have_populated_dt()) return 0; if (mrst_identify_cpu()) return -ENODEV; platform_device_register(&rtc_device); dev_info(&rtc_device.dev, "registered platform RTC device (no PNP device found)\n"); return 0; }
void mrst_early_console_init(void) { u32 ctrlr0 = 0; u32 spi0_cdiv; u32 freq; /* Freqency info only need be searched once */ /* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */ pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, MRST_CLK_SPI0_REG); spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9; freq = 100000000 / (spi0_cdiv + 1); if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL) mrst_spi_paddr = MRST_REGBASE_SPI1; pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, mrst_spi_paddr); /* Disable SPI controller */ dw_writel(pspi, ssienr, 0); /* Set control param, 8 bits, transmit only mode */ ctrlr0 = dw_readl(pspi, ctrl0); ctrlr0 &= 0xfcc0; ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET) | (SPI_TMOD_TO << SPI_TMOD_OFFSET); dw_writel(pspi, ctrl0, ctrlr0); /* * Change the spi0 clk to comply with 115200 bps, use 100000 to * calculate the clk dividor to make the clock a little slower * than real baud rate. */ dw_writel(pspi, baudr, freq/100000); /* Disable all INT for early phase */ dw_writel(pspi, imr, 0x0); /* Set the cs to spi-uart */ dw_writel(pspi, ser, 0x2); /* Enable the HW, the last step for HW init */ dw_writel(pspi, ssienr, 0x1); /* Set the default configuration */ max3110_write_config(); /* Register the kmsg dumper */ if (!dumper_registered) { dw_dumper.dump = dw_kmsg_dump; kmsg_dump_register(&dw_dumper); dumper_registered = 1; } }
/* Register the RTC device if appropriate */ static int __init mrst_device_create(void) { /* No Moorestown, no device */ if (!mrst_identify_cpu()) return -ENODEV; /* No timer, no device */ if (!sfi_mrtc_num) return -ENODEV; /* iomem resource */ vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr; vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr + MRST_VRTC_MAP_SZ; /* irq resource */ vrtc_resources[1].start = sfi_mrtc_array[0].irq; vrtc_resources[1].end = sfi_mrtc_array[0].irq; return platform_device_register(&vrtc_device); }
static long intel_scu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; u32 __user *p = argp; u32 new_margin; static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .firmware_version = 0, /* @todo Get from SCU via ipc_get_scu_fw_version()? */ .identity = "Intel_SCU IOH Watchdog" /* len < 32 */ }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: intel_scu_keepalive(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, p)) return -EFAULT; if (check_timer_margin(new_margin)) return -EINVAL; if (intel_scu_set_heartbeat(new_margin)) return -EINVAL; return 0; case WDIOC_GETTIMEOUT: return put_user(watchdog_device.soft_threshold, p); default: return -ENOTTY; } } /* * Notifier for system down */ static int intel_scu_notify_sys(struct notifier_block *this, unsigned long code, void *another_unused) { if (code == SYS_DOWN || code == SYS_HALT) /* Turn off the watchdog timer. */ intel_scu_stop(); return NOTIFY_DONE; } /* * Kernel Interfaces */ static const struct file_operations intel_scu_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = intel_scu_write, .unlocked_ioctl = intel_scu_ioctl, .open = intel_scu_open, .release = intel_scu_release, }; static int __init intel_scu_watchdog_init(void) { int ret; u32 __iomem *tmp_addr; /* * We don't really need to check this as the SFI timer get will fail * but if we do so we can exit with a clearer reason and no noise. * * If it isn't an intel MID device then it doesn't have this watchdog */ if (!mrst_identify_cpu()) return -ENODEV; /* Check boot parameters to verify that their initial values */ /* are in range. */ /* Check value of timer_set boot parameter */ if ((timer_set < MIN_TIME_CYCLE) || (timer_set > MAX_TIME - MIN_TIME_CYCLE)) { pr_err("Watchdog timer: value of timer_set %x (hex) " "is out of range from %x to %x (hex)\n", timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE); return -EINVAL; } /* Check value of timer_margin boot parameter */ if (check_timer_margin(timer_margin)) return -EINVAL; watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1); if (watchdog_device.timer_tbl_ptr == NULL) { pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n"); return -ENODEV; } /* make sure the timer exists */ if (watchdog_device.timer_tbl_ptr->phys_addr == 0) { pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n", sfi_mtimer_num); return -ENODEV; } if (watchdog_device.timer_tbl_ptr->irq == 0) { pr_debug("Watchdog timer: timer %d invalid irq\n", sfi_mtimer_num); return -ENODEV; } tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr, 20); if (tmp_addr == NULL) { pr_debug("Watchdog timer: timer unable to ioremap\n"); return -ENOMEM; } watchdog_device.timer_load_count_addr = tmp_addr++; watchdog_device.timer_current_value_addr = tmp_addr++; watchdog_device.timer_control_addr = tmp_addr++; watchdog_device.timer_clear_interrupt_addr = tmp_addr++; watchdog_device.timer_interrupt_status_addr = tmp_addr++; /* Set the default time values in device structure */ watchdog_device.timer_set = timer_set; watchdog_device.threshold = timer_margin * watchdog_device.timer_tbl_ptr->freq_hz; watchdog_device.soft_threshold = (watchdog_device.timer_set - timer_margin) * watchdog_device.timer_tbl_ptr->freq_hz; watchdog_device.intel_scu_notifier.notifier_call = intel_scu_notify_sys; ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier); if (ret) { pr_err("Watchdog timer: cannot register notifier %d)\n", ret); goto register_reboot_error; } watchdog_device.miscdev.minor = WATCHDOG_MINOR; watchdog_device.miscdev.name = "watchdog"; watchdog_device.miscdev.fops = &intel_scu_fops; ret = misc_register(&watchdog_device.miscdev); if (ret) { pr_err("Watchdog timer: cannot register miscdev %d err =%d\n", WATCHDOG_MINOR, ret); goto misc_register_error; } ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq, watchdog_timer_interrupt, IRQF_SHARED, "watchdog", &watchdog_device.timer_load_count_addr); if (ret) { pr_err("Watchdog timer: error requesting irq %d\n", ret); goto request_irq_error; } /* Make sure timer is disabled before returning */ intel_scu_stop(); return 0; /* error cleanup */ request_irq_error: misc_deregister(&watchdog_device.miscdev); misc_register_error: unregister_reboot_notifier(&watchdog_device.intel_scu_notifier); register_reboot_error: intel_scu_stop(); iounmap(watchdog_device.timer_load_count_addr); return ret; }