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