Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2015, Sony Mobile Communications Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/soc/qcom/smem_state.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) static LIST_HEAD(smem_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) static DEFINE_MUTEX(list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * struct qcom_smem_state - state context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * @refcount:	refcount for the state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * @orphan:	boolean indicator that this state has been unregistered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * @list:	entry in smem_states list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * @of_node:	of_node to use for matching the state in DT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * @priv:	implementation private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * @ops:	ops for the state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) struct qcom_smem_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct kref refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	bool orphan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	struct device_node *of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	void *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	struct qcom_smem_state_ops ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * qcom_smem_state_update_bits() - update the masked bits in state with value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * @state:	state handle acquired by calling qcom_smem_state_get()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * @mask:	bit mask for the change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * @value:	new value for the masked bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * Returns 0 on success, otherwise negative errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) int qcom_smem_state_update_bits(struct qcom_smem_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 				u32 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 				u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	if (state->orphan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	if (!state->ops.update_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	return state->ops.update_bits(state->priv, mask, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) EXPORT_SYMBOL_GPL(qcom_smem_state_update_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static struct qcom_smem_state *of_node_to_state(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	struct qcom_smem_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	mutex_lock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	list_for_each_entry(state, &smem_states, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		if (state->of_node == np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 			kref_get(&state->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	state = ERR_PTR(-EPROBE_DEFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	mutex_unlock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * qcom_smem_state_get() - acquire handle to a state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * @dev:	client device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * @con_id:	name of the state to lookup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * @bit:	flags from the state reference, indicating which bit's affected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * Returns handle to the state, or ERR_PTR(). qcom_smem_state_put() must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * called to release the returned state handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) struct qcom_smem_state *qcom_smem_state_get(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 					    const char *con_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 					    unsigned *bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	struct qcom_smem_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	struct of_phandle_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	if (con_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		index = of_property_match_string(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 						 "qcom,smem-state-names",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 						 con_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		if (index < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			dev_err(dev, "missing qcom,smem-state-names\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			return ERR_PTR(index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	ret = of_parse_phandle_with_args(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 					 "qcom,smem-states",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 					 "#qcom,smem-state-cells",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 					 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 					 &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		dev_err(dev, "failed to parse qcom,smem-states property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (args.args_count != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		dev_err(dev, "invalid #qcom,smem-state-cells\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	state = of_node_to_state(args.np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (IS_ERR(state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	*bit = args.args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	of_node_put(args.np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) EXPORT_SYMBOL_GPL(qcom_smem_state_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void qcom_smem_state_release(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct qcom_smem_state *state = container_of(ref, struct qcom_smem_state, refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	list_del(&state->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * qcom_smem_state_put() - release state handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * @state:	state handle to be released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) void qcom_smem_state_put(struct qcom_smem_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	mutex_lock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	kref_put(&state->refcount, qcom_smem_state_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	mutex_unlock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) EXPORT_SYMBOL_GPL(qcom_smem_state_put);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * qcom_smem_state_register() - register a new state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  * @of_node:	of_node used for matching client lookups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  * @ops:	implementation ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  * @priv:	implementation specific private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 						 const struct qcom_smem_state_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 						 void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	struct qcom_smem_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	state = kzalloc(sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	kref_init(&state->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	state->of_node = of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	state->ops = *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	state->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	mutex_lock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	list_add(&state->list, &smem_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	mutex_unlock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) EXPORT_SYMBOL_GPL(qcom_smem_state_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * qcom_smem_state_unregister() - unregister a registered state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * @state:	state handle to be unregistered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) void qcom_smem_state_unregister(struct qcom_smem_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	state->orphan = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	qcom_smem_state_put(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) EXPORT_SYMBOL_GPL(qcom_smem_state_unregister);