0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/init.h>
0010 #include <linux/io.h>
0011 #include <linux/mod_devicetable.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/reset-controller.h>
0014
0015 #define BCM6345_RESET_NUM 32
0016 #define BCM6345_RESET_SLEEP_MIN_US 10000
0017 #define BCM6345_RESET_SLEEP_MAX_US 20000
0018
0019 struct bcm6345_reset {
0020 struct reset_controller_dev rcdev;
0021 void __iomem *base;
0022 spinlock_t lock;
0023 };
0024
0025 static inline struct bcm6345_reset *
0026 to_bcm6345_reset(struct reset_controller_dev *rcdev)
0027 {
0028 return container_of(rcdev, struct bcm6345_reset, rcdev);
0029 }
0030
0031 static int bcm6345_reset_update(struct reset_controller_dev *rcdev,
0032 unsigned long id, bool assert)
0033 {
0034 struct bcm6345_reset *bcm6345_reset = to_bcm6345_reset(rcdev);
0035 unsigned long flags;
0036 uint32_t val;
0037
0038 spin_lock_irqsave(&bcm6345_reset->lock, flags);
0039 val = __raw_readl(bcm6345_reset->base);
0040 if (assert)
0041 val &= ~BIT(id);
0042 else
0043 val |= BIT(id);
0044 __raw_writel(val, bcm6345_reset->base);
0045 spin_unlock_irqrestore(&bcm6345_reset->lock, flags);
0046
0047 return 0;
0048 }
0049
0050 static int bcm6345_reset_assert(struct reset_controller_dev *rcdev,
0051 unsigned long id)
0052 {
0053 return bcm6345_reset_update(rcdev, id, true);
0054 }
0055
0056 static int bcm6345_reset_deassert(struct reset_controller_dev *rcdev,
0057 unsigned long id)
0058 {
0059 return bcm6345_reset_update(rcdev, id, false);
0060 }
0061
0062 static int bcm6345_reset_reset(struct reset_controller_dev *rcdev,
0063 unsigned long id)
0064 {
0065 bcm6345_reset_update(rcdev, id, true);
0066 usleep_range(BCM6345_RESET_SLEEP_MIN_US,
0067 BCM6345_RESET_SLEEP_MAX_US);
0068
0069 bcm6345_reset_update(rcdev, id, false);
0070
0071
0072
0073
0074
0075 usleep_range(BCM6345_RESET_SLEEP_MIN_US,
0076 BCM6345_RESET_SLEEP_MAX_US);
0077
0078 return 0;
0079 }
0080
0081 static int bcm6345_reset_status(struct reset_controller_dev *rcdev,
0082 unsigned long id)
0083 {
0084 struct bcm6345_reset *bcm6345_reset = to_bcm6345_reset(rcdev);
0085
0086 return !(__raw_readl(bcm6345_reset->base) & BIT(id));
0087 }
0088
0089 static const struct reset_control_ops bcm6345_reset_ops = {
0090 .assert = bcm6345_reset_assert,
0091 .deassert = bcm6345_reset_deassert,
0092 .reset = bcm6345_reset_reset,
0093 .status = bcm6345_reset_status,
0094 };
0095
0096 static int bcm6345_reset_probe(struct platform_device *pdev)
0097 {
0098 struct bcm6345_reset *bcm6345_reset;
0099
0100 bcm6345_reset = devm_kzalloc(&pdev->dev,
0101 sizeof(*bcm6345_reset), GFP_KERNEL);
0102 if (!bcm6345_reset)
0103 return -ENOMEM;
0104
0105 platform_set_drvdata(pdev, bcm6345_reset);
0106
0107 bcm6345_reset->base = devm_platform_ioremap_resource(pdev, 0);
0108 if (IS_ERR(bcm6345_reset->base))
0109 return PTR_ERR(bcm6345_reset->base);
0110
0111 spin_lock_init(&bcm6345_reset->lock);
0112 bcm6345_reset->rcdev.ops = &bcm6345_reset_ops;
0113 bcm6345_reset->rcdev.owner = THIS_MODULE;
0114 bcm6345_reset->rcdev.of_node = pdev->dev.of_node;
0115 bcm6345_reset->rcdev.of_reset_n_cells = 1;
0116 bcm6345_reset->rcdev.nr_resets = BCM6345_RESET_NUM;
0117
0118 return devm_reset_controller_register(&pdev->dev,
0119 &bcm6345_reset->rcdev);
0120 }
0121
0122 static const struct of_device_id bcm6345_reset_of_match[] = {
0123 { .compatible = "brcm,bcm6345-reset" },
0124 { },
0125 };
0126
0127 static struct platform_driver bcm6345_reset_driver = {
0128 .probe = bcm6345_reset_probe,
0129 .driver = {
0130 .name = "bcm6345-reset",
0131 .of_match_table = bcm6345_reset_of_match,
0132 .suppress_bind_attrs = true,
0133 },
0134 };
0135 builtin_platform_driver(bcm6345_reset_driver);