1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Amlogic Meson Reset Controller driver
5 * Copyright (c) 2016 BayLibre, SAS.
6 * Author: Neil Armstrong <narmstrong@baylibre.com>
9 #include <linux/init.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 <linux/of_device.h>
19 #define BITS_PER_REG 32
20 #define LEVEL_OFFSET 0x7c
23 void __iomem
*reg_base
;
24 struct reset_controller_dev rcdev
;
28 static int meson_reset_reset(struct reset_controller_dev
*rcdev
,
31 struct meson_reset
*data
=
32 container_of(rcdev
, struct meson_reset
, rcdev
);
33 unsigned int bank
= id
/ BITS_PER_REG
;
34 unsigned int offset
= id
% BITS_PER_REG
;
35 void __iomem
*reg_addr
= data
->reg_base
+ (bank
<< 2);
37 writel(BIT(offset
), reg_addr
);
42 static int meson_reset_level(struct reset_controller_dev
*rcdev
,
43 unsigned long id
, bool assert)
45 struct meson_reset
*data
=
46 container_of(rcdev
, struct meson_reset
, rcdev
);
47 unsigned int bank
= id
/ BITS_PER_REG
;
48 unsigned int offset
= id
% BITS_PER_REG
;
49 void __iomem
*reg_addr
= data
->reg_base
+ LEVEL_OFFSET
+ (bank
<< 2);
53 spin_lock_irqsave(&data
->lock
, flags
);
55 reg
= readl(reg_addr
);
57 writel(reg
& ~BIT(offset
), reg_addr
);
59 writel(reg
| BIT(offset
), reg_addr
);
61 spin_unlock_irqrestore(&data
->lock
, flags
);
66 static int meson_reset_assert(struct reset_controller_dev
*rcdev
,
69 return meson_reset_level(rcdev
, id
, true);
72 static int meson_reset_deassert(struct reset_controller_dev
*rcdev
,
75 return meson_reset_level(rcdev
, id
, false);
78 static const struct reset_control_ops meson_reset_ops
= {
79 .reset
= meson_reset_reset
,
80 .assert = meson_reset_assert
,
81 .deassert
= meson_reset_deassert
,
84 static const struct of_device_id meson_reset_dt_ids
[] = {
85 { .compatible
= "amlogic,meson8b-reset" },
86 { .compatible
= "amlogic,meson-gxbb-reset" },
87 { .compatible
= "amlogic,meson-axg-reset" },
91 static int meson_reset_probe(struct platform_device
*pdev
)
93 struct meson_reset
*data
;
96 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
100 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
101 data
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
102 if (IS_ERR(data
->reg_base
))
103 return PTR_ERR(data
->reg_base
);
105 platform_set_drvdata(pdev
, data
);
107 spin_lock_init(&data
->lock
);
109 data
->rcdev
.owner
= THIS_MODULE
;
110 data
->rcdev
.nr_resets
= REG_COUNT
* BITS_PER_REG
;
111 data
->rcdev
.ops
= &meson_reset_ops
;
112 data
->rcdev
.of_node
= pdev
->dev
.of_node
;
114 return devm_reset_controller_register(&pdev
->dev
, &data
->rcdev
);
117 static struct platform_driver meson_reset_driver
= {
118 .probe
= meson_reset_probe
,
120 .name
= "meson_reset",
121 .of_match_table
= meson_reset_dt_ids
,
124 builtin_platform_driver(meson_reset_driver
);