1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2018-2020 Broadcom */
4 #include <linux/device.h>
5 #include <linux/iopoll.h>
6 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/reset-controller.h>
11 #define BRCM_RESCAL_START 0x0
12 #define BRCM_RESCAL_START_BIT BIT(0)
13 #define BRCM_RESCAL_CTRL 0x4
14 #define BRCM_RESCAL_STATUS 0x8
15 #define BRCM_RESCAL_STATUS_BIT BIT(0)
17 struct brcm_rescal_reset
{
20 struct reset_controller_dev rcdev
;
23 static int brcm_rescal_reset_set(struct reset_controller_dev
*rcdev
,
26 struct brcm_rescal_reset
*data
=
27 container_of(rcdev
, struct brcm_rescal_reset
, rcdev
);
28 void __iomem
*base
= data
->base
;
32 reg
= readl(base
+ BRCM_RESCAL_START
);
33 writel(reg
| BRCM_RESCAL_START_BIT
, base
+ BRCM_RESCAL_START
);
34 reg
= readl(base
+ BRCM_RESCAL_START
);
35 if (!(reg
& BRCM_RESCAL_START_BIT
)) {
36 dev_err(data
->dev
, "failed to start SATA/PCIe rescal\n");
40 ret
= readl_poll_timeout(base
+ BRCM_RESCAL_STATUS
, reg
,
41 (reg
& BRCM_RESCAL_STATUS_BIT
), 100, 1000);
43 dev_err(data
->dev
, "time out on SATA/PCIe rescal\n");
47 reg
= readl(base
+ BRCM_RESCAL_START
);
48 writel(reg
& ~BRCM_RESCAL_START_BIT
, base
+ BRCM_RESCAL_START
);
50 dev_dbg(data
->dev
, "SATA/PCIe rescal success\n");
55 static int brcm_rescal_reset_xlate(struct reset_controller_dev
*rcdev
,
56 const struct of_phandle_args
*reset_spec
)
58 /* This is needed if #reset-cells == 0. */
62 static const struct reset_control_ops brcm_rescal_reset_ops
= {
63 .reset
= brcm_rescal_reset_set
,
66 static int brcm_rescal_reset_probe(struct platform_device
*pdev
)
68 struct brcm_rescal_reset
*data
;
70 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
74 data
->base
= devm_platform_ioremap_resource(pdev
, 0);
75 if (IS_ERR(data
->base
))
76 return PTR_ERR(data
->base
);
78 data
->rcdev
.owner
= THIS_MODULE
;
79 data
->rcdev
.nr_resets
= 1;
80 data
->rcdev
.ops
= &brcm_rescal_reset_ops
;
81 data
->rcdev
.of_node
= pdev
->dev
.of_node
;
82 data
->rcdev
.of_xlate
= brcm_rescal_reset_xlate
;
83 data
->dev
= &pdev
->dev
;
85 return devm_reset_controller_register(&pdev
->dev
, &data
->rcdev
);
88 static const struct of_device_id brcm_rescal_reset_of_match
[] = {
89 { .compatible
= "brcm,bcm7216-pcie-sata-rescal" },
92 MODULE_DEVICE_TABLE(of
, brcm_rescal_reset_of_match
);
94 static struct platform_driver brcm_rescal_reset_driver
= {
95 .probe
= brcm_rescal_reset_probe
,
97 .name
= "brcm-rescal-reset",
98 .of_match_table
= brcm_rescal_reset_of_match
,
101 module_platform_driver(brcm_rescal_reset_driver
);
103 MODULE_AUTHOR("Broadcom");
104 MODULE_DESCRIPTION("Broadcom SATA/PCIe rescal reset controller");
105 MODULE_LICENSE("GPL v2");