diff options
Diffstat (limited to 'drivers/thermal/qcom/lmh.c')
| -rw-r--r-- | drivers/thermal/qcom/lmh.c | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/drivers/thermal/qcom/lmh.c b/drivers/thermal/qcom/lmh.c index eafa7526eb8b..ddadcfada513 100644 --- a/drivers/thermal/qcom/lmh.c +++ b/drivers/thermal/qcom/lmh.c @@ -5,12 +5,14 @@ */ #include <linux/module.h> #include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdesc.h> #include <linux/irqdomain.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/of_platform.h> #include <linux/slab.h> -#include <linux/qcom_scm.h> +#include <linux/firmware/qcom/qcom_scm.h> #define LMH_NODE_DCVS 0x44435653 #define LMH_CLUSTER0_NODE_ID 0x6370302D @@ -28,6 +30,8 @@ #define LMH_REG_DCVS_INTR_CLR 0x8 +#define LMH_ENABLE_ALGOS 1 + struct lmh_hw_data { void __iomem *base; struct irq_domain *domain; @@ -43,7 +47,7 @@ static irqreturn_t lmh_handle_irq(int hw_irq, void *data) if (irq) generic_handle_irq(irq); - return 0; + return IRQ_HANDLED; } static void lmh_enable_interrupt(struct irq_data *d) @@ -71,7 +75,14 @@ static struct irq_chip lmh_irq_chip = { static int lmh_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { struct lmh_hw_data *lmh_data = d->host_data; + static struct lock_class_key lmh_lock_key; + static struct lock_class_key lmh_request_key; + /* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ + irq_set_lockdep_class(irq, &lmh_lock_key, &lmh_request_key); irq_set_chip_and_handler(irq, &lmh_irq_chip, handle_simple_irq); irq_set_chip_data(irq, lmh_data); @@ -90,8 +101,12 @@ static int lmh_probe(struct platform_device *pdev) struct device_node *cpu_node; struct lmh_hw_data *lmh_data; int temp_low, temp_high, temp_arm, cpu_id, ret; + unsigned int enable_alg; u32 node_id; + if (!qcom_scm_is_available()) + return -EPROBE_DEFER; + lmh_data = devm_kzalloc(dev, sizeof(*lmh_data), GFP_KERNEL); if (!lmh_data) return -ENOMEM; @@ -141,32 +156,36 @@ static int lmh_probe(struct platform_device *pdev) if (!qcom_scm_lmh_dcvsh_available()) return -EINVAL; - ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_CRNT, LMH_ALGO_MODE_ENABLE, 1, - LMH_NODE_DCVS, node_id, 0); - if (ret) - dev_err(dev, "Error %d enabling current subfunction\n", ret); - - ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_REL, LMH_ALGO_MODE_ENABLE, 1, - LMH_NODE_DCVS, node_id, 0); - if (ret) - dev_err(dev, "Error %d enabling reliability subfunction\n", ret); - - ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_BCL, LMH_ALGO_MODE_ENABLE, 1, - LMH_NODE_DCVS, node_id, 0); - if (ret) - dev_err(dev, "Error %d enabling BCL subfunction\n", ret); - - ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_THERMAL, LMH_ALGO_MODE_ENABLE, 1, - LMH_NODE_DCVS, node_id, 0); - if (ret) { - dev_err(dev, "Error %d enabling thermal subfunction\n", ret); - return ret; - } - - ret = qcom_scm_lmh_profile_change(0x1); - if (ret) { - dev_err(dev, "Error %d changing profile\n", ret); - return ret; + enable_alg = (uintptr_t)of_device_get_match_data(dev); + + if (enable_alg) { + ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_CRNT, LMH_ALGO_MODE_ENABLE, 1, + LMH_NODE_DCVS, node_id, 0); + if (ret) + dev_err(dev, "Error %d enabling current subfunction\n", ret); + + ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_REL, LMH_ALGO_MODE_ENABLE, 1, + LMH_NODE_DCVS, node_id, 0); + if (ret) + dev_err(dev, "Error %d enabling reliability subfunction\n", ret); + + ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_BCL, LMH_ALGO_MODE_ENABLE, 1, + LMH_NODE_DCVS, node_id, 0); + if (ret) + dev_err(dev, "Error %d enabling BCL subfunction\n", ret); + + ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_THERMAL, LMH_ALGO_MODE_ENABLE, 1, + LMH_NODE_DCVS, node_id, 0); + if (ret) { + dev_err(dev, "Error %d enabling thermal subfunction\n", ret); + return ret; + } + + ret = qcom_scm_lmh_profile_change(0x1); + if (ret) { + dev_err(dev, "Error %d changing profile\n", ret); + return ret; + } } /* Set default thermal trips */ @@ -187,12 +206,12 @@ static int lmh_probe(struct platform_device *pdev) ret = qcom_scm_lmh_dcvsh(LMH_SUB_FN_THERMAL, LMH_TH_LOW_THRESHOLD, temp_low, LMH_NODE_DCVS, node_id, 0); if (ret) { - dev_err(dev, "Error setting thermal ARM threshold%d\n", ret); + dev_err(dev, "Error setting thermal LOW threshold%d\n", ret); return ret; } lmh_data->irq = platform_get_irq(pdev, 0); - lmh_data->domain = irq_domain_add_linear(np, 1, &lmh_irq_ops, lmh_data); + lmh_data->domain = irq_domain_create_linear(dev_fwnode(dev), 1, &lmh_irq_ops, lmh_data); if (!lmh_data->domain) { dev_err(dev, "Error adding irq_domain\n"); return -EINVAL; @@ -213,7 +232,9 @@ static int lmh_probe(struct platform_device *pdev) } static const struct of_device_id lmh_table[] = { - { .compatible = "qcom,sdm845-lmh", }, + { .compatible = "qcom,sc8180x-lmh", }, + { .compatible = "qcom,sdm845-lmh", .data = (void *)LMH_ENABLE_ALGOS}, + { .compatible = "qcom,sm8150-lmh", }, {} }; MODULE_DEVICE_TABLE(of, lmh_table); |
