1 /* 2 * PIKA Warp(tm) board specific routines 3 * 4 * Copyright (c) 2008 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 19 #include <asm/machdep.h> 20 #include <asm/prom.h> 21 #include <asm/udbg.h> 22 #include <asm/time.h> 23 #include <asm/uic.h> 24 #include <asm/ppc4xx.h> 25 26 static __initdata struct of_device_id warp_of_bus[] = { 27 { .compatible = "ibm,plb4", }, 28 { .compatible = "ibm,opb", }, 29 { .compatible = "ibm,ebc", }, 30 {}, 31 }; 32 33 static int __init warp_device_probe(void) 34 { 35 of_platform_bus_probe(NULL, warp_of_bus, NULL); 36 return 0; 37 } 38 machine_device_initcall(warp, warp_device_probe); 39 40 static int __init warp_probe(void) 41 { 42 unsigned long root = of_get_flat_dt_root(); 43 44 return of_flat_dt_is_compatible(root, "pika,warp"); 45 } 46 47 define_machine(warp) { 48 .name = "Warp", 49 .probe = warp_probe, 50 .progress = udbg_progress, 51 .init_IRQ = uic_init_tree, 52 .get_irq = uic_get_irq, 53 .restart = ppc4xx_reset_system, 54 .calibrate_decr = generic_calibrate_decr, 55 }; 56 57 58 /* I am not sure this is the best place for this... */ 59 static int __init warp_post_info(void) 60 { 61 struct device_node *np; 62 void __iomem *fpga; 63 u32 post1, post2; 64 65 /* Sighhhh... POST information is in the sd area. */ 66 np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd"); 67 if (np == NULL) 68 return -ENOENT; 69 70 fpga = of_iomap(np, 0); 71 of_node_put(np); 72 if (fpga == NULL) 73 return -ENOENT; 74 75 post1 = in_be32(fpga + 0x40); 76 post2 = in_be32(fpga + 0x44); 77 78 iounmap(fpga); 79 80 if (post1 || post2) 81 printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2); 82 else 83 printk(KERN_INFO "Warp POST OK\n"); 84 85 return 0; 86 } 87 machine_late_initcall(warp, warp_post_info); 88 89 90 #ifdef CONFIG_SENSORS_AD7414 91 92 static LIST_HEAD(dtm_shutdown_list); 93 static void __iomem *dtm_fpga; 94 static void __iomem *gpio_base; 95 96 97 struct dtm_shutdown { 98 struct list_head list; 99 void (*func)(void *arg); 100 void *arg; 101 }; 102 103 104 int 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 120 int 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 134 static irqreturn_t temp_isr(int irq, void *context) 135 { 136 struct dtm_shutdown *shutdown; 137 138 local_irq_disable(); 139 140 /* Run through the shutdown list. */ 141 list_for_each_entry(shutdown, &dtm_shutdown_list, list) 142 shutdown->func(shutdown->arg); 143 144 printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n"); 145 146 while (1) { 147 if (dtm_fpga) { 148 unsigned reset = in_be32(dtm_fpga + 0x14); 149 out_be32(dtm_fpga + 0x14, reset); 150 } 151 152 if (gpio_base) { 153 unsigned leds = in_be32(gpio_base); 154 155 /* green off, red toggle */ 156 leds &= ~0x80000000; 157 leds ^= 0x40000000; 158 159 out_be32(gpio_base, leds); 160 } 161 162 mdelay(500); 163 } 164 } 165 166 static int pika_setup_leds(void) 167 { 168 struct device_node *np; 169 const u32 *gpios; 170 int len; 171 172 np = of_find_compatible_node(NULL, NULL, "linux,gpio-led"); 173 if (!np) { 174 printk(KERN_ERR __FILE__ ": Unable to find gpio-led\n"); 175 return -ENOENT; 176 } 177 178 gpios = of_get_property(np, "gpios", &len); 179 of_node_put(np); 180 if (!gpios || len < 4) { 181 printk(KERN_ERR __FILE__ 182 ": Unable to get gpios property (%d)\n", len); 183 return -ENOENT; 184 } 185 186 np = of_find_node_by_phandle(gpios[0]); 187 if (!np) { 188 printk(KERN_ERR __FILE__ ": Unable to find gpio\n"); 189 return -ENOENT; 190 } 191 192 gpio_base = of_iomap(np, 0); 193 of_node_put(np); 194 if (!gpio_base) { 195 printk(KERN_ERR __FILE__ ": Unable to map gpio"); 196 return -ENOMEM; 197 } 198 199 return 0; 200 } 201 202 static void pika_setup_critical_temp(struct i2c_client *client) 203 { 204 struct device_node *np; 205 int irq, rc; 206 207 /* Do this before enabling critical temp interrupt since we 208 * may immediately interrupt. 209 */ 210 pika_setup_leds(); 211 212 /* These registers are in 1 degree increments. */ 213 i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */ 214 i2c_smbus_write_byte_data(client, 3, 0); /* Tlow */ 215 216 np = of_find_compatible_node(NULL, NULL, "adi,ad7414"); 217 if (np == NULL) { 218 printk(KERN_ERR __FILE__ ": Unable to find ad7414\n"); 219 return; 220 } 221 222 irq = irq_of_parse_and_map(np, 0); 223 of_node_put(np); 224 if (irq == NO_IRQ) { 225 printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n"); 226 return; 227 } 228 229 rc = request_irq(irq, temp_isr, 0, "ad7414", NULL); 230 if (rc) { 231 printk(KERN_ERR __FILE__ 232 ": Unable to request ad7414 irq %d = %d\n", irq, rc); 233 return; 234 } 235 } 236 237 static inline void pika_dtm_check_fan(void __iomem *fpga) 238 { 239 static int fan_state; 240 u32 fan = in_be32(fpga + 0x34) & (1 << 14); 241 242 if (fan_state != fan) { 243 fan_state = fan; 244 if (fan) 245 printk(KERN_WARNING "Fan rotation error detected." 246 " Please check hardware.\n"); 247 } 248 } 249 250 static int pika_dtm_thread(void __iomem *fpga) 251 { 252 struct i2c_adapter *adap; 253 struct i2c_client *client; 254 255 /* We loop in case either driver was compiled as a module and 256 * has not been insmoded yet. 257 */ 258 while (!(adap = i2c_get_adapter(0))) { 259 set_current_state(TASK_INTERRUPTIBLE); 260 schedule_timeout(HZ); 261 } 262 263 while (1) { 264 list_for_each_entry(client, &adap->clients, list) 265 if (client->addr == 0x4a) 266 goto found_it; 267 268 set_current_state(TASK_INTERRUPTIBLE); 269 schedule_timeout(HZ); 270 } 271 272 found_it: 273 i2c_put_adapter(adap); 274 275 pika_setup_critical_temp(client); 276 277 printk(KERN_INFO "PIKA DTM thread running.\n"); 278 279 while (!kthread_should_stop()) { 280 int val; 281 282 val = i2c_smbus_read_word_data(client, 0); 283 if (val < 0) 284 dev_dbg(&client->dev, "DTM read temp failed.\n"); 285 else { 286 s16 temp = swab16(val); 287 out_be32(fpga + 0x20, temp); 288 } 289 290 pika_dtm_check_fan(fpga); 291 292 set_current_state(TASK_INTERRUPTIBLE); 293 schedule_timeout(HZ); 294 } 295 296 return 0; 297 } 298 299 300 static int __init pika_dtm_start(void) 301 { 302 struct task_struct *dtm_thread; 303 struct device_node *np; 304 305 np = of_find_compatible_node(NULL, NULL, "pika,fpga"); 306 if (np == NULL) 307 return -ENOENT; 308 309 dtm_fpga = of_iomap(np, 0); 310 of_node_put(np); 311 if (dtm_fpga == NULL) 312 return -ENOENT; 313 314 dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm"); 315 if (IS_ERR(dtm_thread)) { 316 iounmap(dtm_fpga); 317 return PTR_ERR(dtm_thread); 318 } 319 320 return 0; 321 } 322 machine_late_initcall(warp, pika_dtm_start); 323 324 #else /* !CONFIG_SENSORS_AD7414 */ 325 326 int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg) 327 { 328 return 0; 329 } 330 331 int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg) 332 { 333 return 0; 334 } 335 336 #endif 337 338 EXPORT_SYMBOL(pika_dtm_register_shutdown); 339 EXPORT_SYMBOL(pika_dtm_unregister_shutdown); 340