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