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