Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * PIKA Warp(tm) board specific routines
0004  *
0005  * Copyright (c) 2008-2009 PIKA Technologies
0006  *   Sean MacLennan <smaclennan@pikatech.com>
0007  */
0008 #include <linux/init.h>
0009 #include <linux/of_platform.h>
0010 #include <linux/kthread.h>
0011 #include <linux/i2c.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/delay.h>
0014 #include <linux/of_address.h>
0015 #include <linux/of_irq.h>
0016 #include <linux/of_gpio.h>
0017 #include <linux/slab.h>
0018 #include <linux/export.h>
0019 
0020 #include <asm/machdep.h>
0021 #include <asm/udbg.h>
0022 #include <asm/time.h>
0023 #include <asm/uic.h>
0024 #include <asm/ppc4xx.h>
0025 #include <asm/dma.h>
0026 
0027 
0028 static const struct of_device_id warp_of_bus[] __initconst = {
0029     { .compatible = "ibm,plb4", },
0030     { .compatible = "ibm,opb", },
0031     { .compatible = "ibm,ebc", },
0032     {},
0033 };
0034 
0035 static int __init warp_device_probe(void)
0036 {
0037     of_platform_bus_probe(NULL, warp_of_bus, NULL);
0038     return 0;
0039 }
0040 machine_device_initcall(warp, warp_device_probe);
0041 
0042 static int __init warp_probe(void)
0043 {
0044     if (!of_machine_is_compatible("pika,warp"))
0045         return 0;
0046 
0047     return 1;
0048 }
0049 
0050 define_machine(warp) {
0051     .name       = "Warp",
0052     .probe      = warp_probe,
0053     .progress   = udbg_progress,
0054     .init_IRQ   = uic_init_tree,
0055     .get_irq    = uic_get_irq,
0056     .restart    = ppc4xx_reset_system,
0057     .calibrate_decr = generic_calibrate_decr,
0058 };
0059 
0060 
0061 static int __init warp_post_info(void)
0062 {
0063     struct device_node *np;
0064     void __iomem *fpga;
0065     u32 post1, post2;
0066 
0067     /* Sighhhh... POST information is in the sd area. */
0068     np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
0069     if (np == NULL)
0070         return -ENOENT;
0071 
0072     fpga = of_iomap(np, 0);
0073     of_node_put(np);
0074     if (fpga == NULL)
0075         return -ENOENT;
0076 
0077     post1 = in_be32(fpga + 0x40);
0078     post2 = in_be32(fpga + 0x44);
0079 
0080     iounmap(fpga);
0081 
0082     if (post1 || post2)
0083         printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
0084     else
0085         printk(KERN_INFO "Warp POST OK\n");
0086 
0087     return 0;
0088 }
0089 
0090 
0091 #ifdef CONFIG_SENSORS_AD7414
0092 
0093 static LIST_HEAD(dtm_shutdown_list);
0094 static void __iomem *dtm_fpga;
0095 static unsigned green_led, red_led;
0096 
0097 
0098 struct dtm_shutdown {
0099     struct list_head list;
0100     void (*func)(void *arg);
0101     void *arg;
0102 };
0103 
0104 
0105 int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
0106 {
0107     struct dtm_shutdown *shutdown;
0108 
0109     shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
0110     if (shutdown == NULL)
0111         return -ENOMEM;
0112 
0113     shutdown->func = func;
0114     shutdown->arg = arg;
0115 
0116     list_add(&shutdown->list, &dtm_shutdown_list);
0117 
0118     return 0;
0119 }
0120 
0121 int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
0122 {
0123     struct dtm_shutdown *shutdown;
0124 
0125     list_for_each_entry(shutdown, &dtm_shutdown_list, list)
0126         if (shutdown->func == func && shutdown->arg == arg) {
0127             list_del(&shutdown->list);
0128             kfree(shutdown);
0129             return 0;
0130         }
0131 
0132     return -EINVAL;
0133 }
0134 
0135 static irqreturn_t temp_isr(int irq, void *context)
0136 {
0137     struct dtm_shutdown *shutdown;
0138     int value = 1;
0139 
0140     local_irq_disable();
0141 
0142     gpio_set_value(green_led, 0);
0143 
0144     /* Run through the shutdown list. */
0145     list_for_each_entry(shutdown, &dtm_shutdown_list, list)
0146         shutdown->func(shutdown->arg);
0147 
0148     printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n\n");
0149 
0150     while (1) {
0151         if (dtm_fpga) {
0152             unsigned reset = in_be32(dtm_fpga + 0x14);
0153             out_be32(dtm_fpga + 0x14, reset);
0154         }
0155 
0156         gpio_set_value(red_led, value);
0157         value ^= 1;
0158         mdelay(500);
0159     }
0160 
0161     /* Not reached */
0162     return IRQ_HANDLED;
0163 }
0164 
0165 static int pika_setup_leds(void)
0166 {
0167     struct device_node *np, *child;
0168 
0169     np = of_find_compatible_node(NULL, NULL, "gpio-leds");
0170     if (!np) {
0171         printk(KERN_ERR __FILE__ ": Unable to find leds\n");
0172         return -ENOENT;
0173     }
0174 
0175     for_each_child_of_node(np, child)
0176         if (of_node_name_eq(child, "green"))
0177             green_led = of_get_gpio(child, 0);
0178         else if (of_node_name_eq(child, "red"))
0179             red_led = of_get_gpio(child, 0);
0180 
0181     of_node_put(np);
0182 
0183     return 0;
0184 }
0185 
0186 static void pika_setup_critical_temp(struct device_node *np,
0187                      struct i2c_client *client)
0188 {
0189     int irq, rc;
0190 
0191     /* Do this before enabling critical temp interrupt since we
0192      * may immediately interrupt.
0193      */
0194     pika_setup_leds();
0195 
0196     /* These registers are in 1 degree increments. */
0197     i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
0198     i2c_smbus_write_byte_data(client, 3,  0); /* Tlow */
0199 
0200     irq = irq_of_parse_and_map(np, 0);
0201     if (!irq) {
0202         printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
0203         return;
0204     }
0205 
0206     rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
0207     if (rc) {
0208         printk(KERN_ERR __FILE__
0209                ": Unable to request ad7414 irq %d = %d\n", irq, rc);
0210         return;
0211     }
0212 }
0213 
0214 static inline void pika_dtm_check_fan(void __iomem *fpga)
0215 {
0216     static int fan_state;
0217     u32 fan = in_be32(fpga + 0x34) & (1 << 14);
0218 
0219     if (fan_state != fan) {
0220         fan_state = fan;
0221         if (fan)
0222             printk(KERN_WARNING "Fan rotation error detected."
0223                    " Please check hardware.\n");
0224     }
0225 }
0226 
0227 static int pika_dtm_thread(void __iomem *fpga)
0228 {
0229     struct device_node *np;
0230     struct i2c_client *client;
0231 
0232     np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
0233     if (np == NULL)
0234         return -ENOENT;
0235 
0236     client = of_find_i2c_device_by_node(np);
0237     if (client == NULL) {
0238         of_node_put(np);
0239         return -ENOENT;
0240     }
0241 
0242     pika_setup_critical_temp(np, client);
0243 
0244     of_node_put(np);
0245 
0246     printk(KERN_INFO "Warp DTM thread running.\n");
0247 
0248     while (!kthread_should_stop()) {
0249         int val;
0250 
0251         val = i2c_smbus_read_word_data(client, 0);
0252         if (val < 0)
0253             dev_dbg(&client->dev, "DTM read temp failed.\n");
0254         else {
0255             s16 temp = swab16(val);
0256             out_be32(fpga + 0x20, temp);
0257         }
0258 
0259         pika_dtm_check_fan(fpga);
0260 
0261         set_current_state(TASK_INTERRUPTIBLE);
0262         schedule_timeout(HZ);
0263     }
0264 
0265     return 0;
0266 }
0267 
0268 static int __init pika_dtm_start(void)
0269 {
0270     struct task_struct *dtm_thread;
0271     struct device_node *np;
0272 
0273     np = of_find_compatible_node(NULL, NULL, "pika,fpga");
0274     if (np == NULL)
0275         return -ENOENT;
0276 
0277     dtm_fpga = of_iomap(np, 0);
0278     of_node_put(np);
0279     if (dtm_fpga == NULL)
0280         return -ENOENT;
0281 
0282     /* Must get post info before thread starts. */
0283     warp_post_info();
0284 
0285     dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
0286     if (IS_ERR(dtm_thread)) {
0287         iounmap(dtm_fpga);
0288         return PTR_ERR(dtm_thread);
0289     }
0290 
0291     return 0;
0292 }
0293 machine_late_initcall(warp, pika_dtm_start);
0294 
0295 #else /* !CONFIG_SENSORS_AD7414 */
0296 
0297 int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
0298 {
0299     return 0;
0300 }
0301 
0302 int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
0303 {
0304     return 0;
0305 }
0306 
0307 machine_late_initcall(warp, warp_post_info);
0308 
0309 #endif
0310 
0311 EXPORT_SYMBOL(pika_dtm_register_shutdown);
0312 EXPORT_SYMBOL(pika_dtm_unregister_shutdown);