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