linux/drivers/reset/reset-qcom-pdc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2018 The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/module.h>
   7#include <linux/of_device.h>
   8#include <linux/platform_device.h>
   9#include <linux/regmap.h>
  10#include <linux/reset-controller.h>
  11
  12#include <dt-bindings/reset/qcom,sdm845-pdc.h>
  13
  14#define RPMH_PDC_SYNC_RESET     0x100
  15
  16struct qcom_pdc_reset_map {
  17        u8 bit;
  18};
  19
  20struct qcom_pdc_reset_data {
  21        struct reset_controller_dev rcdev;
  22        struct regmap *regmap;
  23};
  24
  25static const struct regmap_config sdm845_pdc_regmap_config = {
  26        .name           = "pdc-reset",
  27        .reg_bits       = 32,
  28        .reg_stride     = 4,
  29        .val_bits       = 32,
  30        .max_register   = 0x20000,
  31        .fast_io        = true,
  32};
  33
  34static const struct qcom_pdc_reset_map sdm845_pdc_resets[] = {
  35        [PDC_APPS_SYNC_RESET] = {0},
  36        [PDC_SP_SYNC_RESET] = {1},
  37        [PDC_AUDIO_SYNC_RESET] = {2},
  38        [PDC_SENSORS_SYNC_RESET] = {3},
  39        [PDC_AOP_SYNC_RESET] = {4},
  40        [PDC_DEBUG_SYNC_RESET] = {5},
  41        [PDC_GPU_SYNC_RESET] = {6},
  42        [PDC_DISPLAY_SYNC_RESET] = {7},
  43        [PDC_COMPUTE_SYNC_RESET] = {8},
  44        [PDC_MODEM_SYNC_RESET] = {9},
  45};
  46
  47static inline struct qcom_pdc_reset_data *to_qcom_pdc_reset_data(
  48                                struct reset_controller_dev *rcdev)
  49{
  50        return container_of(rcdev, struct qcom_pdc_reset_data, rcdev);
  51}
  52
  53static int qcom_pdc_control_assert(struct reset_controller_dev *rcdev,
  54                                        unsigned long idx)
  55{
  56        struct qcom_pdc_reset_data *data = to_qcom_pdc_reset_data(rcdev);
  57
  58        return regmap_update_bits(data->regmap, RPMH_PDC_SYNC_RESET,
  59                                  BIT(sdm845_pdc_resets[idx].bit),
  60                                  BIT(sdm845_pdc_resets[idx].bit));
  61}
  62
  63static int qcom_pdc_control_deassert(struct reset_controller_dev *rcdev,
  64                                        unsigned long idx)
  65{
  66        struct qcom_pdc_reset_data *data = to_qcom_pdc_reset_data(rcdev);
  67
  68        return regmap_update_bits(data->regmap, RPMH_PDC_SYNC_RESET,
  69                                  BIT(sdm845_pdc_resets[idx].bit), 0);
  70}
  71
  72static const struct reset_control_ops qcom_pdc_reset_ops = {
  73        .assert = qcom_pdc_control_assert,
  74        .deassert = qcom_pdc_control_deassert,
  75};
  76
  77static int qcom_pdc_reset_probe(struct platform_device *pdev)
  78{
  79        struct qcom_pdc_reset_data *data;
  80        struct device *dev = &pdev->dev;
  81        void __iomem *base;
  82        struct resource *res;
  83
  84        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
  85        if (!data)
  86                return -ENOMEM;
  87
  88        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  89        base = devm_ioremap_resource(dev, res);
  90        if (IS_ERR(base))
  91                return PTR_ERR(base);
  92
  93        data->regmap = devm_regmap_init_mmio(dev, base,
  94                                             &sdm845_pdc_regmap_config);
  95        if (IS_ERR(data->regmap)) {
  96                dev_err(dev, "Unable to initialize regmap\n");
  97                return PTR_ERR(data->regmap);
  98        }
  99
 100        data->rcdev.owner = THIS_MODULE;
 101        data->rcdev.ops = &qcom_pdc_reset_ops;
 102        data->rcdev.nr_resets = ARRAY_SIZE(sdm845_pdc_resets);
 103        data->rcdev.of_node = dev->of_node;
 104
 105        return devm_reset_controller_register(dev, &data->rcdev);
 106}
 107
 108static const struct of_device_id qcom_pdc_reset_of_match[] = {
 109        { .compatible = "qcom,sdm845-pdc-global" },
 110        {}
 111};
 112MODULE_DEVICE_TABLE(of, qcom_pdc_reset_of_match);
 113
 114static struct platform_driver qcom_pdc_reset_driver = {
 115        .probe = qcom_pdc_reset_probe,
 116        .driver = {
 117                .name = "qcom_pdc_reset",
 118                .of_match_table = qcom_pdc_reset_of_match,
 119        },
 120};
 121module_platform_driver(qcom_pdc_reset_driver);
 122
 123MODULE_DESCRIPTION("Qualcomm PDC Reset Driver");
 124MODULE_LICENSE("GPL v2");
 125