|
@@ -85,23 +85,17 @@
|
|
|
#define RTC_WPR_2ND_KEY 0x53
|
|
|
#define RTC_WPR_WRONG_KEY 0xFF
|
|
|
|
|
|
-/*
|
|
|
- * RTC registers are protected against parasitic write access.
|
|
|
- * PWR_CR_DBP bit must be set to enable write access to RTC registers.
|
|
|
- */
|
|
|
-/* STM32_PWR_CR */
|
|
|
-#define PWR_CR 0x00
|
|
|
-/* STM32_PWR_CR bit field */
|
|
|
-#define PWR_CR_DBP BIT(8)
|
|
|
-
|
|
|
struct stm32_rtc_data {
|
|
|
bool has_pclk;
|
|
|
+ bool need_dbp;
|
|
|
};
|
|
|
|
|
|
struct stm32_rtc {
|
|
|
struct rtc_device *rtc_dev;
|
|
|
void __iomem *base;
|
|
|
struct regmap *dbp;
|
|
|
+ unsigned int dbp_reg;
|
|
|
+ unsigned int dbp_mask;
|
|
|
struct stm32_rtc_data *data;
|
|
|
struct clk *pclk;
|
|
|
struct clk *rtc_ck;
|
|
@@ -498,10 +492,12 @@ static const struct rtc_class_ops stm32_rtc_ops = {
|
|
|
|
|
|
static const struct stm32_rtc_data stm32_rtc_data = {
|
|
|
.has_pclk = false,
|
|
|
+ .need_dbp = true,
|
|
|
};
|
|
|
|
|
|
static const struct stm32_rtc_data stm32h7_rtc_data = {
|
|
|
.has_pclk = true,
|
|
|
+ .need_dbp = true,
|
|
|
};
|
|
|
|
|
|
static const struct of_device_id stm32_rtc_of_match[] = {
|
|
@@ -576,7 +572,6 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct stm32_rtc *rtc;
|
|
|
struct resource *res;
|
|
|
- const struct of_device_id *match;
|
|
|
int ret;
|
|
|
|
|
|
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
|
|
@@ -588,15 +583,31 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
|
if (IS_ERR(rtc->base))
|
|
|
return PTR_ERR(rtc->base);
|
|
|
|
|
|
- rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
|
|
- "st,syscfg");
|
|
|
- if (IS_ERR(rtc->dbp)) {
|
|
|
- dev_err(&pdev->dev, "no st,syscfg\n");
|
|
|
- return PTR_ERR(rtc->dbp);
|
|
|
- }
|
|
|
+ rtc->data = (struct stm32_rtc_data *)
|
|
|
+ of_device_get_match_data(&pdev->dev);
|
|
|
+
|
|
|
+ if (rtc->data->need_dbp) {
|
|
|
+ rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
|
|
+ "st,syscfg");
|
|
|
+ if (IS_ERR(rtc->dbp)) {
|
|
|
+ dev_err(&pdev->dev, "no st,syscfg\n");
|
|
|
+ return PTR_ERR(rtc->dbp);
|
|
|
+ }
|
|
|
|
|
|
- match = of_match_device(stm32_rtc_of_match, &pdev->dev);
|
|
|
- rtc->data = (struct stm32_rtc_data *)match->data;
|
|
|
+ ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
|
|
|
+ 1, &rtc->dbp_reg);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(&pdev->dev, "can't read DBP register offset\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
|
|
|
+ 2, &rtc->dbp_mask);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(&pdev->dev, "can't read DBP register mask\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if (!rtc->data->has_pclk) {
|
|
|
rtc->pclk = NULL;
|
|
@@ -624,7 +635,9 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
|
if (ret)
|
|
|
goto err;
|
|
|
|
|
|
- regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
|
|
|
+ if (rtc->data->need_dbp)
|
|
|
+ regmap_update_bits(rtc->dbp, rtc->dbp_reg,
|
|
|
+ rtc->dbp_mask, rtc->dbp_mask);
|
|
|
|
|
|
/*
|
|
|
* After a system reset, RTC_ISR.INITS flag can be read to check if
|
|
@@ -684,7 +697,8 @@ err:
|
|
|
clk_disable_unprepare(rtc->pclk);
|
|
|
clk_disable_unprepare(rtc->rtc_ck);
|
|
|
|
|
|
- regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
|
|
|
+ if (rtc->data->need_dbp)
|
|
|
+ regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
|
|
|
|
|
|
device_init_wakeup(&pdev->dev, false);
|
|
|
|
|
@@ -707,8 +721,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
|
|
|
if (rtc->data->has_pclk)
|
|
|
clk_disable_unprepare(rtc->pclk);
|
|
|
|
|
|
- /* Enable backup domain write protection */
|
|
|
- regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
|
|
|
+ /* Enable backup domain write protection if needed */
|
|
|
+ if (rtc->data->need_dbp)
|
|
|
+ regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
|
|
|
|
|
|
device_init_wakeup(&pdev->dev, false);
|
|
|
|