/* * drivers/power/axp/nmi/sunxi-nmi.c * (C) Copyright 2010-2016 * Allwinner Technology Co., Ltd. * Pannan * * driver of suxi nmi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * */ #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_SUNXI_ARISC #include #endif #include "sunxi-nmi.h" void sunxi_nmi_clear_status(void) { #ifdef CONFIG_SUNXI_ARISC arisc_clear_nmi_status(); #else __clear_nmi_status(); #endif } EXPORT_SYMBOL(sunxi_nmi_clear_status); void sunxi_nmi_enable(void) { #ifdef CONFIG_SUNXI_ARISC arisc_enable_nmi_irq(); #else __enable_nmi_irq(); #endif } EXPORT_SYMBOL(sunxi_nmi_enable); void sunxi_nmi_disable(void) { #ifdef CONFIG_SUNXI_ARISC arisc_disable_nmi_irq(); #else __disable_nmi_irq(); #endif } EXPORT_SYMBOL(sunxi_nmi_disable); void sunxi_nmi_set_trigger(u32 trigger) { u32 tmp = 0; if (IRQF_TRIGGER_LOW == trigger) tmp = NMI_IRQ_LOW_LEVEL; else if (IRQF_TRIGGER_FALLING == trigger) tmp = NMI_IRQ_NE_EDGE; else if (IRQF_TRIGGER_HIGH == trigger) tmp = NMI_IRQ_HIGH_LEVEL; else if (IRQF_TRIGGER_RISING == trigger) tmp = NMI_IRQ_PO_EDGE; #ifdef CONFIG_SUNXI_ARISC arisc_set_nmi_trigger(tmp); #else __set_nmi_trigger(tmp); #endif } EXPORT_SYMBOL(sunxi_nmi_set_trigger); #ifndef CONFIG_SUNXI_ARISC static int sunxi_nmi_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct resource *mem_res = NULL; s32 ret = 0; if (!of_device_is_available(node)) { pr_err("%s: nmi status disable!!\n", __func__); return -EPERM; } nmi_data = kzalloc(sizeof(*nmi_data), GFP_KERNEL); if (nmi_data == NULL) { pr_err("%s: no memory for nmi data\n", __func__); return -ENOMEM; } mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (mem_res == NULL) { pr_err("%s: failed to get MEM res\n", __func__); ret = -ENXIO; goto mem_io_err; } if (!request_mem_region(mem_res->start, resource_size(mem_res), mem_res->name)) { pr_err("%s: failed to request mem region\n", __func__); ret = -EINVAL; goto mem_io_err; } nmi_data->base_addr = ioremap(mem_res->start, resource_size(mem_res)); if (!nmi_data->base_addr) { pr_err("%s: failed to io remap\n", __func__); ret = -EIO; goto mem_io_err; } if (of_property_read_u32(node, "nmi_irq_ctrl", &nmi_data->nmi_irq_ctrl)) goto of_property_err; if (of_property_read_u32(node, "nmi_irq_en", &nmi_data->nmi_irq_en)) goto of_property_err; if (of_property_read_u32(node, "nmi_irq_status", &nmi_data->nmi_irq_status)) goto of_property_err; return 0; of_property_err: iounmap(nmi_data->base_addr); mem_io_err: kfree(nmi_data); return ret; } static int sunxi_nmi_remove(struct platform_device *pdev) { pr_info("%s: module unloaded\n", __func__); return 0; } static const struct of_device_id sunxi_nmi_match[] = { { .compatible = "allwinner,sunxi-nmi", }, {}, }; MODULE_DEVICE_TABLE(of, sunxi_nmi_match); static struct platform_driver nmi_platform_driver = { .probe = sunxi_nmi_probe, .remove = sunxi_nmi_remove, .driver = { .name = NMI_MODULE_NAME, .owner = THIS_MODULE, .of_match_table = sunxi_nmi_match, }, }; static int __init sunxi_nmi_init(void) { return platform_driver_register(&nmi_platform_driver); } arch_initcall(sunxi_nmi_init); static void __exit sunxi_nmi_exit(void) { platform_driver_unregister(&nmi_platform_driver); } module_exit(sunxi_nmi_exit); MODULE_DESCRIPTION("Driver of nmi"); MODULE_AUTHOR("pannan"); MODULE_LICENSE("GPL"); #endif