|
@@ -864,3 +864,140 @@ err_request:
|
|
|
#ifdef CONFIG_CPU_FREQ
|
|
|
static int viper_cpufreq_notifier(struct notifier_block *nb,
|
|
|
unsigned long val, void *data)
|
|
|
+{
|
|
|
+ struct cpufreq_freqs *freq = data;
|
|
|
+
|
|
|
+ /* TODO: Adjust timings??? */
|
|
|
+
|
|
|
+ switch (val) {
|
|
|
+ case CPUFREQ_PRECHANGE:
|
|
|
+ if (freq->old < freq->new) {
|
|
|
+ /* we are getting faster so raise the voltage
|
|
|
+ * before we change freq */
|
|
|
+ viper_set_core_cpu_voltage(freq->new, 0);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CPUFREQ_POSTCHANGE:
|
|
|
+ if (freq->old > freq->new) {
|
|
|
+ /* we are slowing down so drop the power
|
|
|
+ * after we change freq */
|
|
|
+ viper_set_core_cpu_voltage(freq->new, 0);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CPUFREQ_RESUMECHANGE:
|
|
|
+ viper_set_core_cpu_voltage(freq->new, 0);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* ignore */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block viper_cpufreq_notifier_block = {
|
|
|
+ .notifier_call = viper_cpufreq_notifier
|
|
|
+};
|
|
|
+
|
|
|
+static void __init viper_init_cpufreq(void)
|
|
|
+{
|
|
|
+ if (cpufreq_register_notifier(&viper_cpufreq_notifier_block,
|
|
|
+ CPUFREQ_TRANSITION_NOTIFIER))
|
|
|
+ pr_err("viper: Failed to setup cpufreq notifier\n");
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline void viper_init_cpufreq(void) {}
|
|
|
+#endif
|
|
|
+
|
|
|
+static void viper_power_off(void)
|
|
|
+{
|
|
|
+ pr_notice("Shutting off UPS\n");
|
|
|
+ gpio_set_value(VIPER_UPS_GPIO, 1);
|
|
|
+ /* Spin to death... */
|
|
|
+ while (1);
|
|
|
+}
|
|
|
+
|
|
|
+static void __init viper_init(void)
|
|
|
+{
|
|
|
+ u8 version;
|
|
|
+
|
|
|
+ pm_power_off = viper_power_off;
|
|
|
+
|
|
|
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(viper_pin_config));
|
|
|
+
|
|
|
+ pxa_set_ffuart_info(NULL);
|
|
|
+ pxa_set_btuart_info(NULL);
|
|
|
+ pxa_set_stuart_info(NULL);
|
|
|
+
|
|
|
+ /* Wake-up serial console */
|
|
|
+ viper_init_serial_gpio();
|
|
|
+
|
|
|
+ pxa_set_fb_info(NULL, &fb_info);
|
|
|
+
|
|
|
+ /* v1 hardware cannot use the datacs line */
|
|
|
+ version = viper_hw_version();
|
|
|
+ if (version == 0)
|
|
|
+ smc91x_device.num_resources--;
|
|
|
+
|
|
|
+ pxa_set_i2c_info(NULL);
|
|
|
+ platform_add_devices(viper_devs, ARRAY_SIZE(viper_devs));
|
|
|
+
|
|
|
+ viper_init_vcore_gpios();
|
|
|
+ viper_init_cpufreq();
|
|
|
+
|
|
|
+ register_syscore_ops(&viper_cpu_syscore_ops);
|
|
|
+
|
|
|
+ if (version) {
|
|
|
+ pr_info("viper: hardware v%di%d detected. "
|
|
|
+ "CPLD revision %d.\n",
|
|
|
+ VIPER_BOARD_VERSION(version),
|
|
|
+ VIPER_BOARD_ISSUE(version),
|
|
|
+ VIPER_CPLD_REVISION(version));
|
|
|
+ system_rev = (VIPER_BOARD_VERSION(version) << 8) |
|
|
|
+ (VIPER_BOARD_ISSUE(version) << 4) |
|
|
|
+ VIPER_CPLD_REVISION(version);
|
|
|
+ } else {
|
|
|
+ pr_info("viper: No version register.\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ i2c_register_board_info(1, ARRAY_AND_SIZE(viper_i2c_devices));
|
|
|
+
|
|
|
+ viper_tpm_init();
|
|
|
+ pxa_set_ac97_info(NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static struct map_desc viper_io_desc[] __initdata = {
|
|
|
+ {
|
|
|
+ .virtual = VIPER_CPLD_BASE,
|
|
|
+ .pfn = __phys_to_pfn(VIPER_CPLD_PHYS),
|
|
|
+ .length = 0x00300000,
|
|
|
+ .type = MT_DEVICE,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .virtual = VIPER_PC104IO_BASE,
|
|
|
+ .pfn = __phys_to_pfn(0x30000000),
|
|
|
+ .length = 0x00800000,
|
|
|
+ .type = MT_DEVICE,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static void __init viper_map_io(void)
|
|
|
+{
|
|
|
+ pxa25x_map_io();
|
|
|
+
|
|
|
+ iotable_init(viper_io_desc, ARRAY_SIZE(viper_io_desc));
|
|
|
+
|
|
|
+ PCFR |= PCFR_OPDE;
|
|
|
+}
|
|
|
+
|
|
|
+MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
|
|
|
+ /* Maintainer: Marc Zyngier <maz@misterjones.org> */
|
|
|
+ .atag_offset = 0x100,
|
|
|
+ .map_io = viper_map_io,
|
|
|
+ .nr_irqs = PXA_NR_IRQS,
|
|
|
+ .init_irq = viper_init_irq,
|
|
|
+ .handle_irq = pxa25x_handle_irq,
|
|
|
+ .timer = &pxa_timer,
|
|
|
+ .init_machine = viper_init,
|
|
|
+ .restart = pxa_restart,
|
|
|
+MACHINE_END
|