1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2017-18 Linaro Limited
4 #include <linux/delay.h>
5 #include <linux/errno.h>
6 #include <linux/kernel.h>
7 #include <linux/module.h>
9 #include <linux/of_platform.h>
10 #include <linux/platform_device.h>
11 #include <linux/reboot.h>
12 #include <linux/reboot-mode.h>
13 #include <linux/regmap.h>
15 #define PON_SOFT_RB_SPARE 0x8f
17 #define GEN1_REASON_SHIFT 2
18 #define GEN2_REASON_SHIFT 1
22 struct regmap
*regmap
;
24 struct reboot_mode_driver reboot_mode
;
28 static int pm8916_reboot_mode_write(struct reboot_mode_driver
*reboot
,
31 struct pm8916_pon
*pon
= container_of
32 (reboot
, struct pm8916_pon
, reboot_mode
);
35 ret
= regmap_update_bits(pon
->regmap
,
36 pon
->baseaddr
+ PON_SOFT_RB_SPARE
,
37 GENMASK(7, pon
->reason_shift
),
38 magic
<< pon
->reason_shift
);
40 dev_err(pon
->dev
, "update reboot mode bits failed\n");
45 static int pm8916_pon_probe(struct platform_device
*pdev
)
47 struct pm8916_pon
*pon
;
50 pon
= devm_kzalloc(&pdev
->dev
, sizeof(*pon
), GFP_KERNEL
);
54 pon
->dev
= &pdev
->dev
;
56 pon
->regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
58 dev_err(&pdev
->dev
, "failed to locate regmap\n");
62 error
= of_property_read_u32(pdev
->dev
.of_node
, "reg",
67 pon
->reboot_mode
.dev
= &pdev
->dev
;
68 pon
->reason_shift
= (long)of_device_get_match_data(&pdev
->dev
);
69 pon
->reboot_mode
.write
= pm8916_reboot_mode_write
;
70 error
= devm_reboot_mode_register(&pdev
->dev
, &pon
->reboot_mode
);
72 dev_err(&pdev
->dev
, "can't register reboot mode\n");
76 platform_set_drvdata(pdev
, pon
);
78 return devm_of_platform_populate(&pdev
->dev
);
81 static const struct of_device_id pm8916_pon_id_table
[] = {
82 { .compatible
= "qcom,pm8916-pon", .data
= (void *)GEN1_REASON_SHIFT
},
83 { .compatible
= "qcom,pms405-pon", .data
= (void *)GEN1_REASON_SHIFT
},
84 { .compatible
= "qcom,pm8998-pon", .data
= (void *)GEN2_REASON_SHIFT
},
87 MODULE_DEVICE_TABLE(of
, pm8916_pon_id_table
);
89 static struct platform_driver pm8916_pon_driver
= {
90 .probe
= pm8916_pon_probe
,
93 .of_match_table
= of_match_ptr(pm8916_pon_id_table
),
96 module_platform_driver(pm8916_pon_driver
);
98 MODULE_DESCRIPTION("pm8916 Power On driver");
99 MODULE_LICENSE("GPL v2");