linux/arch/powerpc/platforms/44x/warp.c
<<
>>
Prefs
   1/*
   2 * PIKA Warp(tm) board specific routines
   3 *
   4 * Copyright (c) 2008-2009 PIKA Technologies
   5 *   Sean MacLennan <smaclennan@pikatech.com>
   6 *
   7 * This program is free software; you can redistribute  it and/or modify it
   8 * under  the terms of  the GNU General  Public License as published by the
   9 * Free Software Foundation;  either version 2 of the  License, or (at your
  10 * option) any later version.
  11 */
  12#include <linux/init.h>
  13#include <linux/of_platform.h>
  14#include <linux/kthread.h>
  15#include <linux/i2c.h>
  16#include <linux/interrupt.h>
  17#include <linux/delay.h>
  18#include <linux/of_gpio.h>
  19#include <linux/of_i2c.h>
  20#include <linux/slab.h>
  21
  22#include <asm/machdep.h>
  23#include <asm/prom.h>
  24#include <asm/udbg.h>
  25#include <asm/time.h>
  26#include <asm/uic.h>
  27#include <asm/ppc4xx.h>
  28
  29
  30static __initdata struct of_device_id warp_of_bus[] = {
  31        { .compatible = "ibm,plb4", },
  32        { .compatible = "ibm,opb", },
  33        { .compatible = "ibm,ebc", },
  34        {},
  35};
  36
  37static int __init warp_device_probe(void)
  38{
  39        of_platform_bus_probe(NULL, warp_of_bus, NULL);
  40        return 0;
  41}
  42machine_device_initcall(warp, warp_device_probe);
  43
  44static int __init warp_probe(void)
  45{
  46        unsigned long root = of_get_flat_dt_root();
  47
  48        if (!of_flat_dt_is_compatible(root, "pika,warp"))
  49                return 0;
  50
  51        /* For __dma_alloc_coherent */
  52        ISA_DMA_THRESHOLD = ~0L;
  53
  54        return 1;
  55}
  56
  57define_machine(warp) {
  58        .name           = "Warp",
  59        .probe          = warp_probe,
  60        .progress       = udbg_progress,
  61        .init_IRQ       = uic_init_tree,
  62        .get_irq        = uic_get_irq,
  63        .restart        = ppc4xx_reset_system,
  64        .calibrate_decr = generic_calibrate_decr,
  65};
  66
  67
  68static int __init warp_post_info(void)
  69{
  70        struct device_node *np;
  71        void __iomem *fpga;
  72        u32 post1, post2;
  73
  74        /* Sighhhh... POST information is in the sd area. */
  75        np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
  76        if (np == NULL)
  77                return -ENOENT;
  78
  79        fpga = of_iomap(np, 0);
  80        of_node_put(np);
  81        if (fpga == NULL)
  82                return -ENOENT;
  83
  84        post1 = in_be32(fpga + 0x40);
  85        post2 = in_be32(fpga + 0x44);
  86
  87        iounmap(fpga);
  88
  89        if (post1 || post2)
  90                printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
  91        else
  92                printk(KERN_INFO "Warp POST OK\n");
  93
  94        return 0;
  95}
  96
  97
  98#ifdef CONFIG_SENSORS_AD7414
  99
 100static LIST_HEAD(dtm_shutdown_list);
 101static void __iomem *dtm_fpga;
 102static unsigned green_led, red_led;
 103
 104
 105struct dtm_shutdown {
 106        struct list_head list;
 107        void (*func)(void *arg);
 108        void *arg;
 109};
 110
 111
 112int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
 113{
 114        struct dtm_shutdown *shutdown;
 115
 116        shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
 117        if (shutdown == NULL)
 118                return -ENOMEM;
 119
 120        shutdown->func = func;
 121        shutdown->arg = arg;
 122
 123        list_add(&shutdown->list, &dtm_shutdown_list);
 124
 125        return 0;
 126}
 127
 128int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
 129{
 130        struct dtm_shutdown *shutdown;
 131
 132        list_for_each_entry(shutdown, &dtm_shutdown_list, list)
 133                if (shutdown->func == func && shutdown->arg == arg) {
 134                        list_del(&shutdown->list);
 135                        kfree(shutdown);
 136                        return 0;
 137                }
 138
 139        return -EINVAL;
 140}
 141
 142static irqreturn_t temp_isr(int irq, void *context)
 143{
 144        struct dtm_shutdown *shutdown;
 145        int value = 1;
 146
 147        local_irq_disable();
 148
 149        gpio_set_value(green_led, 0);
 150
 151        /* Run through the shutdown list. */
 152        list_for_each_entry(shutdown, &dtm_shutdown_list, list)
 153                shutdown->func(shutdown->arg);
 154
 155        printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n\n");
 156
 157        while (1) {
 158                if (dtm_fpga) {
 159                        unsigned reset = in_be32(dtm_fpga + 0x14);
 160                        out_be32(dtm_fpga + 0x14, reset);
 161                }
 162
 163                gpio_set_value(red_led, value);
 164                value ^= 1;
 165                mdelay(500);
 166        }
 167
 168        /* Not reached */
 169        return IRQ_HANDLED;
 170}
 171
 172static int pika_setup_leds(void)
 173{
 174        struct device_node *np, *child;
 175
 176        np = of_find_compatible_node(NULL, NULL, "gpio-leds");
 177        if (!np) {
 178                printk(KERN_ERR __FILE__ ": Unable to find leds\n");
 179                return -ENOENT;
 180        }
 181
 182        for_each_child_of_node(np, child)
 183                if (strcmp(child->name, "green") == 0)
 184                        green_led = of_get_gpio(child, 0);
 185                else if (strcmp(child->name, "red") == 0)
 186                        red_led = of_get_gpio(child, 0);
 187
 188        of_node_put(np);
 189
 190        return 0;
 191}
 192
 193static void pika_setup_critical_temp(struct device_node *np,
 194                                     struct i2c_client *client)
 195{
 196        int irq, rc;
 197
 198        /* Do this before enabling critical temp interrupt since we
 199         * may immediately interrupt.
 200         */
 201        pika_setup_leds();
 202
 203        /* These registers are in 1 degree increments. */
 204        i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
 205        i2c_smbus_write_byte_data(client, 3,  0); /* Tlow */
 206
 207        irq = irq_of_parse_and_map(np, 0);
 208        if (irq  == NO_IRQ) {
 209                printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
 210                return;
 211        }
 212
 213        rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
 214        if (rc) {
 215                printk(KERN_ERR __FILE__
 216                       ": Unable to request ad7414 irq %d = %d\n", irq, rc);
 217                return;
 218        }
 219}
 220
 221static inline void pika_dtm_check_fan(void __iomem *fpga)
 222{
 223        static int fan_state;
 224        u32 fan = in_be32(fpga + 0x34) & (1 << 14);
 225
 226        if (fan_state != fan) {
 227                fan_state = fan;
 228                if (fan)
 229                        printk(KERN_WARNING "Fan rotation error detected."
 230                                   " Please check hardware.\n");
 231        }
 232}
 233
 234static int pika_dtm_thread(void __iomem *fpga)
 235{
 236        struct device_node *np;
 237        struct i2c_client *client;
 238
 239        np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
 240        if (np == NULL)
 241                return -ENOENT;
 242
 243        client = of_find_i2c_device_by_node(np);
 244        if (client == NULL) {
 245                of_node_put(np);
 246                return -ENOENT;
 247        }
 248
 249        pika_setup_critical_temp(np, client);
 250
 251        of_node_put(np);
 252
 253        printk(KERN_INFO "Warp DTM thread running.\n");
 254
 255        while (!kthread_should_stop()) {
 256                int val;
 257
 258                val = i2c_smbus_read_word_data(client, 0);
 259                if (val < 0)
 260                        dev_dbg(&client->dev, "DTM read temp failed.\n");
 261                else {
 262                        s16 temp = swab16(val);
 263                        out_be32(fpga + 0x20, temp);
 264                }
 265
 266                pika_dtm_check_fan(fpga);
 267
 268                set_current_state(TASK_INTERRUPTIBLE);
 269                schedule_timeout(HZ);
 270        }
 271
 272        return 0;
 273}
 274
 275static int __init pika_dtm_start(void)
 276{
 277        struct task_struct *dtm_thread;
 278        struct device_node *np;
 279
 280        np = of_find_compatible_node(NULL, NULL, "pika,fpga");
 281        if (np == NULL)
 282                return -ENOENT;
 283
 284        dtm_fpga = of_iomap(np, 0);
 285        of_node_put(np);
 286        if (dtm_fpga == NULL)
 287                return -ENOENT;
 288
 289        /* Must get post info before thread starts. */
 290        warp_post_info();
 291
 292        dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
 293        if (IS_ERR(dtm_thread)) {
 294                iounmap(dtm_fpga);
 295                return PTR_ERR(dtm_thread);
 296        }
 297
 298        return 0;
 299}
 300machine_late_initcall(warp, pika_dtm_start);
 301
 302#else /* !CONFIG_SENSORS_AD7414 */
 303
 304int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
 305{
 306        return 0;
 307}
 308
 309int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
 310{
 311        return 0;
 312}
 313
 314machine_late_initcall(warp, warp_post_info);
 315
 316#endif
 317
 318EXPORT_SYMBOL(pika_dtm_register_shutdown);
 319EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
 320