platforms += cobalt
platforms += dec
platforms += emma
+platforms += goldfish
platforms += jazz
platforms += jz4740
platforms += lantiq
the ICT (Institute of Computing Technology) and the Chinese Academy
of Sciences.
-config MIPS_GOLDFISH
- bool "Goldfish (Virtual Platform)"
+config MIPS_RANCHU
+ bool "Ranchu (Virtual Platform)"
select BOOT_ELF32
select BOOT_RAW
select CEVT_R4K
RTC emulation when determining guest CPU Frequency. Instead, the guest
processor frequency is automatically derived from the host frequency.
+config 64BIT_PHYS_ADDR
+ bool "Kernel supports 64 bit physical addresses" if EXPERIMENTAL
+ depends on 64BIT
+ help
+ Defines 64 bit physical addresses in kernel.
+ Increases page table sizes.
+
+ It is an alternative for HIGHMEM usage of huge physical memory.
+ Requires 64bit capable CPU and 64 bit kernel code model.
+
+ Note: without this option kernel can support up to 4GB physical
+ memory for 4KB pages and up to 64GB for 64KB pages.
+
+config ARCH_PHYS_ADDR_T_64BIT
+ def_bool 64BIT_PHYS_ADDR
+
+
choice
prompt "Kernel page size"
default PAGE_SIZE_4KB
default y
-config 64BIT_PHYS_ADDR
- bool
-
-config ARCH_PHYS_ADDR_T_64BIT
- def_bool 64BIT_PHYS_ADDR
-
config CPU_HAS_SMARTMIPS
depends on SYS_SUPPORTS_SMARTMIPS
bool "Support for the SmartMIPS ASE"
--- /dev/null
+#
+# Makefile for Goldfish virtual platform
+#
+
+EXTRA_CFLAGS += -Wno-error
+
+obj-$(CONFIG_GOLDFISH) += goldfish-platform.o
+obj-$(CONFIG_GOLDFISH) += goldfish-interrupt.o
+obj-$(CONFIG_GOLDFISH) += goldfish-time.o
+obj-$(CONFIG_GOLDFISH) += switch.o
+obj-$(CONFIG_GOLDFISH) += pm.o
+
+obj-$(CONFIG_MIPS_RANCHU) += ranchu.dtb.o
+
+$(obj)/%.dtb: $(obj)/%.dts
+ $(call if_changed,dtc)
--- /dev/null
+#
+# Goldfish
+#
+platform-$(CONFIG_GOLDFISH) := goldfish/
+cflags-$(CONFIG_GOLDFISH) += -Iarch/mips/include/asm/mach-goldfish -Iarch/mips/goldfish/include
+load-$(CONFIG_GOLDFISH) += 0xffffffff80010000
+all-$(CONFIG_GOLDFISH) := $(COMPRESSION_FNAME).bin
+
--- /dev/null
+/* arch/mips/mach-goldfish/goldfish-platform.c
+**
+** Copyright (C) 2007 Google, Inc.
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irqchip.h>
+#include <linux/of.h>
+
+#include <mach/hardware.h>
+#include <mach/irq.h>
+#include <asm/io.h>
+#include <asm/irq_cpu.h>
+#include <asm/setup.h>
+
+#define GOLDFISH_INTERRUPT_STATUS 0x00 // number of pending interrupts
+#define GOLDFISH_INTERRUPT_NUMBER 0x04
+#define GOLDFISH_INTERRUPT_DISABLE_ALL 0x08
+#define GOLDFISH_INTERRUPT_DISABLE 0x0c
+#define GOLDFISH_INTERRUPT_ENABLE 0x10
+
+static void __iomem *goldfish_interrupt;
+
+void goldfish_mask_irq(struct irq_data *d)
+{
+ writel(d->irq-GOLDFISH_IRQ_BASE,
+ goldfish_interrupt + GOLDFISH_INTERRUPT_DISABLE);
+}
+
+void goldfish_unmask_irq(struct irq_data *d)
+{
+ writel(d->irq-GOLDFISH_IRQ_BASE,
+ goldfish_interrupt + GOLDFISH_INTERRUPT_ENABLE);
+}
+
+static struct irq_chip goldfish_irq_chip = {
+ .name = "goldfish",
+ .irq_mask = goldfish_mask_irq,
+ .irq_mask_ack = goldfish_mask_irq,
+ .irq_unmask = goldfish_unmask_irq,
+};
+
+void goldfish_init_irq(void)
+{
+ unsigned int i;
+ uint32_t base;
+ struct device_node *dn;
+
+ if ((dn = of_find_node_by_name(NULL, "goldfish_pic")) == NULL) {
+ panic("goldfish_init_irq() failed to "
+ "fetch device node \'goldfish-pic\'!\n");
+ }
+
+ if (of_property_read_u32(dn, "reg", &base) < 0) {
+ panic("goldfish_init_irq() failed to "
+ "fetch device base address property \'reg\'!\n");
+ }
+
+ goldfish_interrupt = IO_ADDRESS(base);
+
+ /*
+ * Disable all interrupt sources
+ */
+ writel(1, goldfish_interrupt + GOLDFISH_INTERRUPT_DISABLE_ALL);
+
+ for (i = GOLDFISH_IRQ_BASE; i < GOLDFISH_IRQ_BASE+32; i++) {
+ irq_set_chip(i, &goldfish_irq_chip);
+ irq_set_handler(i, handle_level_irq);
+#if 0
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+#endif
+ }
+}
+
+void goldfish_irq_dispatch(void)
+{
+ uint32_t irq;
+ /*
+ * Disable all interrupt sources
+ */
+ irq = readl(goldfish_interrupt + GOLDFISH_INTERRUPT_NUMBER);
+ do_IRQ(GOLDFISH_IRQ_BASE+irq);
+}
+
+void goldfish_fiq_dispatch(void)
+{
+ panic("goldfish_fiq_dispatch");
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP2)
+ goldfish_irq_dispatch();
+ else if (pending & CAUSEF_IP3)
+ goldfish_fiq_dispatch();
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+ else
+ spurious_interrupt();
+}
+
+static struct irqaction cascade = {
+ .handler = no_action,
+ .flags = IRQF_NO_THREAD,
+ .name = "cascade",
+};
+
+static void mips_timer_dispatch(void)
+{
+ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IRQ_COMPARE);
+}
+
+void __init goldfish_pic_init(struct device_node *node, struct device_node *parent)
+{
+ mips_cpu_irq_init();
+ goldfish_init_irq();
+
+ if (cpu_has_vint) {
+ set_vi_handler(MIPS_CPU_IRQ_PIC, goldfish_irq_dispatch);
+ set_vi_handler(MIPS_CPU_IRQ_PIC, goldfish_fiq_dispatch);
+ }
+ setup_irq(MIPS_CPU_IRQ_BASE+MIPS_CPU_IRQ_PIC, &cascade);
+ setup_irq(MIPS_CPU_IRQ_BASE+MIPS_CPU_IRQ_FIQ, &cascade);
+
+ if (cpu_has_vint)
+ set_vi_handler(MIPS_CPU_IRQ_COMPARE, mips_timer_dispatch);
+}
+
+void __init arch_init_irq(void)
+{
+ irqchip_init();
+}
+
+static const struct of_device_id irqchip_of_match_goldfish_pic
+__used __section(__irqchip_of_table)
+= { .compatible = "generic,goldfish-pic", .data = goldfish_pic_init };
--- /dev/null
+/* arch/mips/mach-goldfish/goldfish-platform.c
+**
+** Copyright (C) 2007 Google, Inc.
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/bootmem.h>
+
+#include <mach/hardware.h>
+#include <mach/irq.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/mips-boards/generic.h>
+
+void __init prom_init(void)
+{
+ char *cmdline = (char *)fw_arg0;
+ strcpy(arcs_cmdline, cmdline);
+}
+
+void prom_free_prom_memory(void)
+{
+}
+
+#ifdef CONFIG_64BIT
+#define GOLDFISH_TTY_PUT_CHAR (*(volatile unsigned int *)0xffffffffbf002000)
+#else
+#define GOLDFISH_TTY_PUT_CHAR (*(volatile unsigned int *)0xbf002000)
+#endif
+
+void prom_putchar(int c)
+{
+ GOLDFISH_TTY_PUT_CHAR = c;
+}
+
+const char *get_system_type(void)
+{
+ return "MIPS-Goldfish";
+}
+
+void __init plat_mem_setup(void)
+{
+ /*
+ * Load the builtin devicetree. This causes the chosen node to be
+ * parsed resulting in our memory appearing
+ */
+ __dt_setup_arch(&__dtb_start);
+}
+
+void __init device_tree_init(void)
+{
+ unsigned long base, size;
+
+ if (!initial_boot_params)
+ return;
+
+ base = virt_to_phys((void *)initial_boot_params);
+ size = be32_to_cpu(initial_boot_params->totalsize);
+
+ /* Before we do anything, lets reserve the dt blob */
+ reserve_bootmem(base, size, BOOTMEM_DEFAULT);
+
+ unflatten_device_tree();
+}
+
+static struct of_device_id __initdata goldfish_ids[] = {
+ { .compatible = "simple-bus", },
+ {},
+};
+
+int __init plat_of_setup(void)
+{
+ if (!of_have_populated_dt())
+ panic("device tree not present");
+
+ return of_platform_populate(NULL, goldfish_ids, NULL, NULL);
+}
+
+arch_initcall(plat_of_setup);
--- /dev/null
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/of.h>
+
+#include <mach/hardware.h>
+#include <mach/irq.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/div64.h>
+
+#define GOLDFISH_TIMER_LOW 0x00
+#define GOLDFISH_TIMER_HIGH 0x04
+
+/*
+ * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect
+ */
+static unsigned int __init estimate_cpu_frequency(void)
+{
+ uint32_t base;
+ struct device_node *dn;
+ void __iomem *rtc_base;
+ unsigned int start, count;
+ unsigned long rtcstart, rtcdelta;
+ unsigned int prid = read_c0_prid() & 0xffff00;
+
+ if ((dn = of_find_node_by_name(NULL, "goldfish_timer")) == NULL) {
+ panic("goldfish_timer_init() failed to "
+ "fetch device node \'goldfish-timer\'!\n");
+ }
+
+ if (of_property_read_u32(dn, "reg", &base) < 0) {
+ panic("goldfish_timer_init() failed to "
+ "fetch device base address property \'reg\'!\n");
+ }
+
+ rtc_base = IO_ADDRESS(base);
+
+ /*
+ * poll the nanosecond resolution RTC for 1s
+ * to calibrate the CPU frequency
+ */
+ rtcstart = readl(rtc_base+GOLDFISH_TIMER_LOW);
+ start = read_c0_count();
+ do {
+ rtcdelta = readl(rtc_base+GOLDFISH_TIMER_LOW) - rtcstart;
+ } while (rtcdelta < 1000000000);
+ count = read_c0_count() - start;
+
+ mips_hpt_frequency = count;
+ if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+ (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+ count *= 2;
+
+ count += 5000; /* round */
+ count -= count%10000;
+
+ return count;
+}
+
+unsigned long cpu_khz;
+
+void plat_time_init(void)
+{
+ unsigned int est_freq;
+
+ est_freq = estimate_cpu_frequency();
+
+ printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq/1000000,
+ (est_freq%1000000)*100/1000000);
+
+ cpu_khz = est_freq / 1000;
+
+}
+
+/**
+ * save_time_delta - Save the offset between system time and RTC time
+ * @delta: pointer to timespec to store delta
+ * @rtc: pointer to timespec for current RTC time
+ *
+ * Return a delta between the system time and the RTC time, such
+ * that system time can be restored later with restore_time_delta()
+ */
+void save_time_delta(struct timespec *delta, struct timespec *rtc)
+{
+ set_normalized_timespec(delta,
+ __current_kernel_time().tv_sec - rtc->tv_sec,
+ __current_kernel_time().tv_nsec - rtc->tv_nsec);
+}
+EXPORT_SYMBOL(save_time_delta);
+
+/**
+ * restore_time_delta - Restore the current system time
+ * @delta: delta returned by save_time_delta()
+ * @rtc: pointer to timespec for current RTC time
+ */
+void restore_time_delta(struct timespec *delta, struct timespec *rtc)
+{
+ struct timespec ts;
+
+ set_normalized_timespec(&ts,
+ delta->tv_sec + rtc->tv_sec,
+ delta->tv_nsec + rtc->tv_nsec);
+
+ do_settimeofday(&ts);
+}
+EXPORT_SYMBOL(restore_time_delta);
--- /dev/null
+#ifdef CONFIG_GOLDFISH
+#include <asm/mach-goldfish/hardware.h>
+#endif
--- /dev/null
+#ifdef CONFIG_GOLDFISH
+#include <asm/mach-goldfish/irq.h>
+#endif
--- /dev/null
+#ifdef CONFIG_GOLDFISH
+#include <asm/mach-goldfish/time.h>
+#endif
--- /dev/null
+/* arch/arm/mach-msm/pm.c
+ *
+ * Goldfish Power Management Routines
+ *
+ * Copyright (C) 2007 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+
+extern void (*cpu_wait)(void);
+
+static int goldfish_pm_enter(suspend_state_t state)
+{
+ if (cpu_wait)
+ (*cpu_wait)();
+ return 0;
+}
+
+static struct platform_suspend_ops goldfish_pm_ops = {
+ .enter = goldfish_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init goldfish_pm_init(void)
+{
+ suspend_set_ops(&goldfish_pm_ops);
+ return 0;
+}
+
+device_initcall(goldfish_pm_init);
+
--- /dev/null
+/dts-v1/;
+
+/ {
+ interrupt-parent = <0x8000>;
+ #size-cells = <0x1>;
+ #address-cells = <0x1>;
+ compatible = "mti,goldfish";
+ model = "ranchu";
+
+ virtio_mmio@1f011e00 {
+ interrupts = <0x27>;
+ reg = <0x1f011e00 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f011c00 {
+ interrupts = <0x26>;
+ reg = <0x1f011c00 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f011a00 {
+ interrupts = <0x25>;
+ reg = <0x1f011a00 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f011800 {
+ interrupts = <0x24>;
+ reg = <0x1f011800 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f011600 {
+ interrupts = <0x23>;
+ reg = <0x1f011600 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f011400 {
+ interrupts = <0x22>;
+ reg = <0x1f011400 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f011200 {
+ interrupts = <0x21>;
+ reg = <0x1f011200 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f011000 {
+ interrupts = <0x20>;
+ reg = <0x1f011000 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010e00 {
+ interrupts = <0x1f>;
+ reg = <0x1f010e00 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010c00 {
+ interrupts = <0x1e>;
+ reg = <0x1f010c00 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010a00 {
+ interrupts = <0x1d>;
+ reg = <0x1f010a00 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010800 {
+ interrupts = <0x1c>;
+ reg = <0x1f010800 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010600 {
+ interrupts = <0x1b>;
+ reg = <0x1f010600 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010400 {
+ interrupts = <0x1a>;
+ reg = <0x1f010400 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010200 {
+ interrupts = <0x19>;
+ reg = <0x1f010200 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ virtio_mmio@1f010000 {
+ interrupts = <0x18>;
+ reg = <0x1f010000 0x200>;
+ compatible = "virtio,mmio";
+ };
+
+ goldfish_timer@1f005000 {
+ interrupts = <0xd>;
+ reg = <0x1f005000 0x1000>;
+ compatible = "generic,goldfish-timer";
+ };
+
+ goldfish_rtc@1f006000 {
+ interrupts = <0xe>;
+ reg = <0x1f006000 0x1000>;
+ compatible = "generic,goldfish-rtc";
+ };
+
+ goldfish_battery@1f007000 {
+ interrupts = <0xf>;
+ reg = <0x1f007000 0x1000>;
+ compatible = "generic,goldfish-battery";
+ };
+
+ goldfish_fb@1f008000 {
+ interrupts = <0x10>;
+ reg = <0x1f008000 0x100>;
+ compatible = "generic,goldfish-fb";
+ };
+
+ goldfish_events@1f009000 {
+ interrupts = <0x11>;
+ reg = <0x1f009000 0x1000>;
+ compatible = "generic,goldfish-events-keypad";
+ };
+
+ android_pipe@1f00a000 {
+ interrupts = <0x12>;
+ reg = <0x1f00a000 0x2000>;
+ compatible = "generic,android-pipe";
+ };
+
+ goldfish_tty@1f004000 {
+ interrupts = <0xc>;
+ reg = <0x1f004000 0x1000>;
+ compatible = "generic,goldfish-tty";
+ };
+
+ goldfish_tty@1f003000 {
+ interrupts = <0xb>;
+ reg = <0x1f003000 0x1000>;
+ compatible = "generic,goldfish-tty";
+ };
+
+ goldfish_tty@1f002000 {
+ interrupts = <0xa>;
+ reg = <0x1f002000 0x1000>;
+ compatible = "generic,goldfish-tty";
+ };
+
+ goldfish_pic@1f000000 {
+ #interrupt-cells = <0x1>;
+ phandle = <0x8000>;
+ interrupt-controller;
+ reg = <0x1f000000 0x1000>;
+ compatible = "generic,goldfish-pic";
+ };
+
+ memory {
+ reg = <0x0 0x1f000000>;
+ device_type = "memory";
+ };
+
+ cpus {
+
+ cpu@0 {
+ compatible = "mti,5KEf";
+ device_type = "cpu";
+ };
+ };
+};
--- /dev/null
+/* arch/mips/mach-goldfish/timer.c
+**
+** Copyright (C) 2007 Google, Inc.
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+*/
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+
+enum {
+ SW_NAME_LEN = 0x00,
+ SW_NAME_PTR = 0x04,
+ SW_FLAGS = 0x08,
+ SW_STATE = 0x0c,
+ SW_INT_STATUS = 0x10,
+ SW_INT_ENABLE = 0x14,
+
+ SW_FLAGS_OUTPUT = 1U << 0
+};
+
+static struct class *goldfish_switch_class;
+
+struct goldfish_switch {
+ void __iomem *base;
+ int irq;
+ uint32_t state;
+ uint32_t flags;
+ struct device *cdev;
+ struct work_struct work;
+ char name[0];
+};
+
+static irqreturn_t
+goldfish_switch_interrupt(int irq, void *dev_id)
+{
+ struct goldfish_switch *qs = dev_id;
+ uint32_t status;
+
+ status = readl(qs->base + SW_INT_STATUS);
+ if (status) {
+ qs->state = readl(qs->base + SW_STATE);
+ schedule_work(&qs->work);
+ }
+
+ return status ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static ssize_t goldfish_switch_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct goldfish_switch *qs = dev_get_drvdata(dev);
+ uint32_t state;
+
+ if (!(qs->flags & SW_FLAGS_OUTPUT))
+ return -EPERM;
+
+ if (sscanf(buf, "%d", &state) != 1)
+ return -EINVAL;
+
+ writel(state, qs->base + SW_STATE);
+ qs->state = readl(qs->base + SW_STATE);
+ if (state != qs->state)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t goldfish_switch_state_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct goldfish_switch *qs = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n", qs->state);
+}
+
+static ssize_t goldfish_switch_direction_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct goldfish_switch *qs = dev_get_drvdata(dev);
+ return sprintf(buf, "%s\n", (qs->flags & SW_FLAGS_OUTPUT) ? "output" : "input");
+}
+
+
+static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, goldfish_switch_state_show, goldfish_switch_state_store);
+static DEVICE_ATTR(direction, S_IRUGO, goldfish_switch_direction_show, NULL);
+
+void goldfish_switch_work(struct work_struct *work)
+{
+#if 0 /* TODO: use some other update notification */
+ struct goldfish_switch *qs = container_of(work, struct goldfish_switch, work);
+ int ret;
+ ret = sysfs_update_file(&qs->cdev->kobj, &class_device_attr_state.attr);
+#endif
+}
+
+static int goldfish_switch_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *r;
+ struct goldfish_switch *qs;
+ void __iomem *base;
+ uint32_t name_len;
+ unsigned long swdev_addr;
+ unsigned long swdev_len;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (r == NULL) {
+ ret = -ENODEV;
+ goto err_no_io_base;
+ }
+ swdev_addr = r->start;
+ swdev_len = resource_size(r);
+ base = ioremap(swdev_addr, swdev_len);
+ name_len = readl(base + SW_NAME_LEN);
+
+ qs = kzalloc(sizeof(*qs) + name_len + 1, GFP_KERNEL);
+ if (qs == NULL) {
+ ret = -ENOMEM;
+ goto err_qs_alloc_failed;
+ }
+ platform_set_drvdata(pdev, qs);
+ qs->base = base;
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (r == NULL) {
+ ret = -ENODEV;
+ goto err_no_irq;
+ }
+ qs->irq = r->start;
+
+ writel((u32)(qs->name), base + SW_NAME_PTR);
+ qs->name[name_len] = '\0';
+ writel(0, base + SW_INT_ENABLE);
+
+ qs->flags = readl(base + SW_FLAGS);
+ qs->state = readl(base + SW_STATE);
+ INIT_WORK(&qs->work, goldfish_switch_work);
+
+ qs->cdev = device_create(goldfish_switch_class, &pdev->dev, 0,
+ NULL, "%s", qs->name);
+ if (unlikely(IS_ERR(qs->cdev))) {
+ ret = PTR_ERR(qs->cdev);
+ goto err_device_create_failed;
+ }
+ dev_set_drvdata(qs->cdev, qs);
+
+ ret = device_create_file(qs->cdev, &dev_attr_state);
+ if (ret)
+ goto err_device_create_file_failed;
+
+ ret = device_create_file(qs->cdev, &dev_attr_direction);
+ if (ret)
+ goto err_device_create_file_failed;
+
+ ret = request_irq(qs->irq, goldfish_switch_interrupt, IRQF_SHARED, "goldfish_switch", qs);
+ if (ret)
+ goto err_request_irq_failed;
+ writel(1, base + SW_INT_ENABLE);
+
+ return 0;
+
+
+// free_irq(qs->irq, qs);
+err_request_irq_failed:
+err_device_create_file_failed:
+ device_unregister(qs->cdev);
+err_device_create_failed:
+err_no_irq:
+ kfree(qs);
+err_qs_alloc_failed:
+err_no_io_base:
+ printk(KERN_ERR "goldfish_switch_probe failed %d\n", ret);
+ return ret;
+}
+
+static int goldfish_switch_remove(struct platform_device *pdev)
+{
+ struct goldfish_switch *qs = platform_get_drvdata(pdev);
+ writel(0, qs->base + SW_INT_ENABLE);
+ free_irq(qs->irq, qs);
+ device_unregister(qs->cdev);
+ kfree(qs);
+ return 0;
+}
+
+static struct platform_driver goldfish_switch_driver = {
+ .probe = goldfish_switch_probe,
+ .remove = goldfish_switch_remove,
+ .driver = {
+ .name = "goldfish-switch"
+ }
+};
+
+static int __init goldfish_switch_init(void)
+{
+ goldfish_switch_class = class_create(THIS_MODULE, "switch");
+ if (IS_ERR(goldfish_switch_class))
+ return PTR_ERR(goldfish_switch_class);
+ return platform_driver_register(&goldfish_switch_driver);
+}
+
+static void goldfish_switch_exit(void)
+{
+ platform_driver_unregister(&goldfish_switch_driver);
+ class_destroy(goldfish_switch_class);
+}
+
+module_init(goldfish_switch_init);
+module_exit(goldfish_switch_exit);
+
--- /dev/null
+/* include/asm-mips/mach-goldfish/hardware.h
+**
+** Copyright (C) 2007 Google, Inc.
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+*/
+
+#ifndef __ASM_MACH_GOLDFISH_HARDWARE_H
+#define __ASM_ARCH_GOLDFISH_HARDWARE_H
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ */
+#define IO_SIZE 0x00800000 // How much?
+#define IO_START 0x00000000 // PA of IO
+
+#define IO_ADDRESS(x) (ioremap(IO_START, IO_SIZE) + (x))
+
+/* For now... */
+#define dma_alloc_writecombine(dev, size, handle, gfp) \
+ dma_alloc_coherent(dev, size, handle, gfp)
+
+
+#define dma_free_writecombine(dev, size, cpu_addr, handle) \
+ dma_free_coherent(dev, size, cpu_addr, handle)
+
+#endif
--- /dev/null
+/* include/asm-mips/mach-goldfish/irq.h
+**
+** Copyright (C) 2007 Google, Inc.
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+*/
+
+#ifndef __ASM_MACH_GOLDFISH_IRQ_H
+#define __ASM_MACH_GOLDFISH_IRQ_H
+
+/* 0..7 MIPS CPU interrupts */
+#define MIPS_CPU_IRQ_BASE 0
+#define MIPS_CPU_IRQ_PIC 2
+#define MIPS_CPU_IRQ_FIQ 3 /* Not used? */
+#define MIPS_CPU_IRQ_COMPARE 7
+
+/* 8..39 Cascaded Goldfish PIC interrupts */
+#define GOLDFISH_IRQ_BASE 8
+#define GOLDFISH_IRQ_PBUS 1
+#define GOLDFISH_IRQ_RTC 3
+#define GOLDFISH_IRQ_TTY 4
+
+#define NR_IRQS 40
+
+#endif
--- /dev/null
+/* include/asm-mips/mach-goldfish/time.h
+**
+** Copyright (C) 2008 MIPS Technologies, Inc.
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+*/
+
+struct timespec;
+extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
+extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_GOLDFISH_WAR_H
+#define __ASM_MIPS_MACH_GOLDFISH_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MIPS_MACH_GOLDFISH_WAR_H */
*/
if (n == 0) {
seq_printf(m, "system type\t\t: %s\n", get_system_type());
+#ifndef CONFIG_GOLDFISH
if (mips_get_machine_name())
seq_printf(m, "machine\t\t\t: %s\n",
mips_get_machine_name());
+#else
+ /*
+ * This is needed by the Android init process to run
+ * target specific startup code
+ */
+ seq_printf(m, "Hardware\t\t: %s\n", mips_get_machine_name());
+ seq_printf(m, "Revison\t\t\t: %d\n", 1);
+#endif
+
}
seq_printf(m, "processor\t\t: %ld\n", n);