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