--- linux-2.6.22.14/arch/powerpc/platforms/85xx/rb1000.c 1970-01-01 03:00:00.000000000 +0300 +++ linux/arch/powerpc/platforms/85xx/rb1000.c 2008-01-15 10:59:57.000000000 +0200 @@ -0,0 +1,247 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mpc85xx.h" + +#ifdef MT_DEBUG +static int inited = 0; + +void rb1000_putc(char c) +{ + if (!inited) return; + + while (!(*(volatile unsigned char *) 0xf0004505 & 0x20)); + + *(char *) 0xf0004500 = c; +} + +void rb1000_puts(char *str) +{ + while (*str) { + if (*str == '\n') rb1000_putc('\r'); + rb1000_putc(*str); + ++str; + } +} + +void rb1000_printk(const char *fmt, ...) { + va_list args; + int r; + char buf[256]; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + rb1000_puts(buf); +} + +void rb1000_init(void) +{ + if (inited) return; + + settlbcam(3, 0xf0000000, 0xe0000000, 0x10000, _PAGE_IO, 0); + inited = 1; +} +#endif + +#define GPIO(x) (0x80000000 >> (x)) +static unsigned *gpio_data = NULL; +static unsigned *picr = NULL; + +const unsigned *beep1; +const unsigned *beep2; + +#define GT0_BASE_COUNT (picr + (0x1110 / 4)) + +static void ioremap_from_node(const unsigned *property, unsigned **ptr) { + struct resource res; + struct device_node *nd; + + nd = of_find_node_by_phandle(property[0]); + if (!nd || of_address_to_resource(nd, 0, &res)) return; + of_node_put(nd); + + *ptr = ioremap_nocache(res.start, res.end - res.start + 1); +} + +irqreturn_t beeper_irq(int irq, void *ptr) +{ + static int toggle = 1; + if (toggle) { + out_be32(gpio_data, in_be32(gpio_data) & ~GPIO(beep1[0])); + out_be32(gpio_data, in_be32(gpio_data) & ~GPIO(beep2[0])); + } + else { + out_be32(gpio_data, in_be32(gpio_data) | GPIO(beep1[0])); + out_be32(gpio_data, in_be32(gpio_data) | GPIO(beep2[0])); + } + toggle ^= 1; + return IRQ_HANDLED; +} + +void consume(int x) { } + +extern unsigned long ppc_tb_freq; +static unsigned long ppc_tb_freq_kHz; + +static void __init rb1000_beeper_init(struct device_node *beeper) +{ + unsigned interrupt; + const unsigned *int_p; + const unsigned *gpio; + + printk("beeper init\n"); + + beep1 = get_property(beeper, "beep1", NULL); + beep2 = get_property(beeper, "beep2", NULL); + gpio = get_property(beeper, "gpio", NULL); + int_p = get_property(beeper, "interrupt-parent", NULL); + + ioremap_from_node(gpio, &gpio_data); + ioremap_from_node(int_p, &picr); + + ppc_tb_freq_kHz = (ppc_tb_freq / 1000); + + interrupt = irq_of_parse_and_map(beeper, 0); + printk("irq=%u\n", interrupt); + if (interrupt != NO_IRQ) { + consume(request_irq(interrupt, beeper_irq, + IRQF_TRIGGER_RISING, + "beeper", NULL)); + } + + printk("beeper done\n"); +} + +void rbppc_beep(unsigned freq) { + if (freq) { + out_be32(GT0_BASE_COUNT, (500 * ppc_tb_freq_kHz) / freq); + } + else { + out_be32(GT0_BASE_COUNT, 0x80000000); + } +} +EXPORT_SYMBOL(rbppc_beep); + +static void __init rb1000_pic_init(void) +{ + struct device_node *np; + struct resource r; + struct mpic *mpic; + void *gcr; + unsigned i; + + np = of_find_node_by_type(NULL, "open-pic"); + + if (!np) + return; + + if (of_address_to_resource(np, 0, &r)) { + printk(KERN_ERR "mpic error: no region specified\n"); + of_node_put(np); + return; + } + + gcr = ioremap(r.start + 0x1020, 4); + out_be32(gcr, in_be32(gcr) | (1 << 29)); + iounmap(gcr); + + mpic = mpic_alloc(np, r.start, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 1, 0, " OpenPIC "); + of_node_put(np); + + for (i = 0; i < 31; ++i) { + if (i == 11 || i == 12) { + /* Ext IRQ4 and IRQ5 is mapped to 11 & 12 respectively */ + mpic_assign_isu(mpic, i, r.start + 0x10000 + (i - 11 + 4) * 0x20); + } else if (i == 30) { + mpic_assign_isu(mpic, i, r.start + 0x10000 + 7 * 0x20); + } else { + mpic_assign_isu(mpic, i, r.start + 0x10200 + i * 0x20); + } + } + mpic_assign_isu(mpic, 31, r.start + 0x1120); + mpic_init(mpic); +} + +static void __init rb1000_setup_arch(void) +{ + struct device_node *np; + + mtspr(SPRN_HID0, 1 << 14); /* set TBEN */ + mb(); + + np = of_find_node_by_type(NULL, "cpu"); + if (np) { + const unsigned *fp = get_property(np, "clock-frequency", NULL); + loops_per_jiffy = fp ? *fp / HZ : 0; + + of_node_put(np); + } +} + +static void rb1000_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "Vendor\t\t: Mikrotik\n"); + seq_printf(m, "Machine\t\t: RB1000\n"); + seq_printf(m, "Memory\t\t: %lu MB\n", total_memory / (1024 * 1024)); +} + +static int __init rb1000_probe(void) +{ + char *model; + + model = of_get_flat_dt_prop(of_get_flat_dt_root(), "model", NULL); + + if (!model) + return 0; + + if (strcmp(model, "RB1000") == 0) + return 1; + + return 0; +} + +static int __init rb1000_declare_of_platform_devices(void) +{ + struct device_node *beep_np; + struct device_node *np; + unsigned idx; + + np = of_find_node_by_name(NULL, "nand"); + if (np) of_platform_device_create(np, "nand", NULL); + + idx = 0; + for_each_node_by_type(np, "rb,cf") { + char dev_name[12]; + snprintf(dev_name, sizeof(dev_name), "cf.%u", idx); + of_platform_device_create(np, dev_name, NULL); + ++idx; + } + + beep_np = of_find_node_by_name(NULL, "beeper"); + if (beep_np) rb1000_beeper_init(beep_np); + + return 0; +} +device_initcall(rb1000_declare_of_platform_devices); + +define_machine(mpc85xx_ads) { + .name = "RB1000", + .probe = rb1000_probe, + .setup_arch = rb1000_setup_arch, + .init_IRQ = rb1000_pic_init, + .show_cpuinfo = rb1000_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc85xx_restart, + .calibrate_decr = generic_calibrate_decr, +};