1/* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License, or 5 * (at your option) any later version. 6 */ 7 8#include <linux/err.h> 9#include <linux/io.h> 10#include <linux/module.h> 11#include <linux/of.h> 12#include <linux/platform_device.h> 13#include <linux/reset-controller.h> 14#include <linux/slab.h> 15#include <linux/types.h> 16#include <mach/hardware.h> 17 18static int ox820_reset_reset(struct reset_controller_dev *rcdev, 19 unsigned long id) 20{ 21 writel(BIT(id), SYS_CTRL_RST_SET_CTRL); 22 writel(BIT(id), SYS_CTRL_RST_CLR_CTRL); 23 return 0; 24} 25 26static int ox820_reset_assert(struct reset_controller_dev *rcdev, 27 unsigned long id) 28{ 29 writel(BIT(id), SYS_CTRL_RST_SET_CTRL); 30 31 return 0; 32} 33 34static int ox820_reset_deassert(struct reset_controller_dev *rcdev, 35 unsigned long id) 36{ 37 writel(BIT(id), SYS_CTRL_RST_CLR_CTRL); 38 39 return 0; 40} 41 42static struct reset_control_ops ox820_reset_ops = { 43 .reset = ox820_reset_reset, 44 .assert = ox820_reset_assert, 45 .deassert = ox820_reset_deassert, 46}; 47 48static const struct of_device_id ox820_reset_dt_ids[] = { 49 { .compatible = "plxtech,nas782x-reset", }, 50 { /* sentinel */ }, 51}; 52MODULE_DEVICE_TABLE(of, ox820_reset_dt_ids); 53 54struct reset_controller_dev rcdev; 55 56static int ox820_reset_probe(struct platform_device *pdev) 57{ 58 struct reset_controller_dev *rcdev; 59 60 rcdev = devm_kzalloc(&pdev->dev, sizeof(*rcdev), GFP_KERNEL); 61 if (!rcdev) 62 return -ENOMEM; 63 64 /* note: reset controller is statically mapped */ 65 66 rcdev->owner = THIS_MODULE; 67 rcdev->nr_resets = 32; 68 rcdev->ops = &ox820_reset_ops; 69 rcdev->of_node = pdev->dev.of_node; 70 reset_controller_register(rcdev); 71 platform_set_drvdata(pdev, rcdev); 72 73 return 0; 74} 75 76static int ox820_reset_remove(struct platform_device *pdev) 77{ 78 struct reset_controller_dev *rcdev = platform_get_drvdata(pdev); 79 80 reset_controller_unregister(rcdev); 81 82 return 0; 83} 84 85static struct platform_driver ox820_reset_driver = { 86 .probe = ox820_reset_probe, 87 .remove = ox820_reset_remove, 88 .driver = { 89 .name = "ox820-reset", 90 .owner = THIS_MODULE, 91 .of_match_table = ox820_reset_dt_ids, 92 }, 93}; 94 95static int __init ox820_reset_init(void) 96{ 97 return platform_driver_probe(&ox820_reset_driver, 98 ox820_reset_probe); 99} 100/* 101 * reset controller does not support probe deferral, so it has to be 102 * initialized before any user, in particular, PCIE uses subsys_initcall. 103 */ 104arch_initcall(ox820_reset_init); 105 106MODULE_AUTHOR("Ma Haijun"); 107MODULE_LICENSE("GPL"); 108