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