1 | /* |
2 | * Copyright (C) 2017 Synopsys. |
3 | * |
4 | * Synopsys AXS10x reset driver. |
5 | * |
6 | * This file is licensed under the terms of the GNU General Public |
7 | * License version 2. This program is licensed "as is" without any |
8 | * warranty of any kind, whether express or implied. |
9 | */ |
10 | |
11 | #include <linux/io.h> |
12 | #include <linux/module.h> |
13 | #include <linux/mod_devicetable.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/reset-controller.h> |
16 | |
17 | #define to_axs10x_rst(p) container_of((p), struct axs10x_rst, rcdev) |
18 | |
19 | #define AXS10X_MAX_RESETS 32 |
20 | |
21 | struct axs10x_rst { |
22 | void __iomem *regs_rst; |
23 | spinlock_t lock; |
24 | struct reset_controller_dev rcdev; |
25 | }; |
26 | |
27 | static int axs10x_reset_reset(struct reset_controller_dev *rcdev, |
28 | unsigned long id) |
29 | { |
30 | struct axs10x_rst *rst = to_axs10x_rst(rcdev); |
31 | unsigned long flags; |
32 | |
33 | spin_lock_irqsave(&rst->lock, flags); |
34 | writel(BIT(id), addr: rst->regs_rst); |
35 | spin_unlock_irqrestore(lock: &rst->lock, flags); |
36 | |
37 | return 0; |
38 | } |
39 | |
40 | static const struct reset_control_ops axs10x_reset_ops = { |
41 | .reset = axs10x_reset_reset, |
42 | }; |
43 | |
44 | static int axs10x_reset_probe(struct platform_device *pdev) |
45 | { |
46 | struct axs10x_rst *rst; |
47 | |
48 | rst = devm_kzalloc(dev: &pdev->dev, size: sizeof(*rst), GFP_KERNEL); |
49 | if (!rst) |
50 | return -ENOMEM; |
51 | |
52 | rst->regs_rst = devm_platform_ioremap_resource(pdev, index: 0); |
53 | if (IS_ERR(ptr: rst->regs_rst)) |
54 | return PTR_ERR(ptr: rst->regs_rst); |
55 | |
56 | spin_lock_init(&rst->lock); |
57 | |
58 | rst->rcdev.owner = THIS_MODULE; |
59 | rst->rcdev.ops = &axs10x_reset_ops; |
60 | rst->rcdev.of_node = pdev->dev.of_node; |
61 | rst->rcdev.nr_resets = AXS10X_MAX_RESETS; |
62 | |
63 | return devm_reset_controller_register(dev: &pdev->dev, rcdev: &rst->rcdev); |
64 | } |
65 | |
66 | static const struct of_device_id axs10x_reset_dt_match[] = { |
67 | { .compatible = "snps,axs10x-reset" }, |
68 | { }, |
69 | }; |
70 | |
71 | static struct platform_driver axs10x_reset_driver = { |
72 | .probe = axs10x_reset_probe, |
73 | .driver = { |
74 | .name = "axs10x-reset" , |
75 | .of_match_table = axs10x_reset_dt_match, |
76 | }, |
77 | }; |
78 | builtin_platform_driver(axs10x_reset_driver); |
79 | |
80 | MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>" ); |
81 | MODULE_DESCRIPTION("Synopsys AXS10x reset driver" ); |
82 | MODULE_LICENSE("GPL v2" ); |
83 | |