Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag '20210927135559.738-6-srinivas.kandagatla@linaro.org' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into v11_20211026_srinivas_kandagatla_asoc_qcom_add_audioreach_support for audioreach support

v5.15-rc1 + 20210927135559.738-[23456]-srinivas.kandagatla@linaro.org

This immutable branch is based on v5.15-rc1 and contains the following
patches extending the existig APR driver to also implement GPR:
20210927135559.738-2-srinivas.kandagatla@linaro.org
20210927135559.738-3-srinivas.kandagatla@linaro.org
20210927135559.738-4-srinivas.kandagatla@linaro.org
20210927135559.738-5-srinivas.kandagatla@linaro.org
20210927135559.738-6-srinivas.kandagatla@linaro.org

+501 -188
-134
Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt
··· 1 - Qualcomm APR (Asynchronous Packet Router) binding 2 - 3 - This binding describes the Qualcomm APR. APR is a IPC protocol for 4 - communication between Application processor and QDSP. APR is mainly 5 - used for audio/voice services on the QDSP. 6 - 7 - - compatible: 8 - Usage: required 9 - Value type: <stringlist> 10 - Definition: must be "qcom,apr-v<VERSION-NUMBER>", example "qcom,apr-v2" 11 - 12 - - qcom,apr-domain 13 - Usage: required 14 - Value type: <u32> 15 - Definition: Destination processor ID. 16 - Possible values are : 17 - 1 - APR simulator 18 - 2 - PC 19 - 3 - MODEM 20 - 4 - ADSP 21 - 5 - APPS 22 - 6 - MODEM2 23 - 7 - APPS2 24 - 25 - = APR SERVICES 26 - Each subnode of the APR node represents service tied to this apr. The name 27 - of the nodes are not important. The properties of these nodes are defined 28 - by the individual bindings for the specific service 29 - - All APR services MUST contain the following property: 30 - 31 - - reg 32 - Usage: required 33 - Value type: <u32> 34 - Definition: APR Service ID 35 - Possible values are : 36 - 3 - DSP Core Service 37 - 4 - Audio Front End Service. 38 - 5 - Voice Stream Manager Service. 39 - 6 - Voice processing manager. 40 - 7 - Audio Stream Manager Service. 41 - 8 - Audio Device Manager Service. 42 - 9 - Multimode voice manager. 43 - 10 - Core voice stream. 44 - 11 - Core voice processor. 45 - 12 - Ultrasound stream manager. 46 - 13 - Listen stream manager. 47 - 48 - - qcom,protection-domain 49 - Usage: optional 50 - Value type: <stringlist> 51 - Definition: Must list the protection domain service name and path 52 - that the particular apr service has a dependency on. 53 - Possible values are : 54 - "avs/audio", "msm/adsp/audio_pd". 55 - "kernel/elf_loader", "msm/modem/wlan_pd". 56 - "tms/servreg", "msm/adsp/audio_pd". 57 - "tms/servreg", "msm/modem/wlan_pd". 58 - "tms/servreg", "msm/slpi/sensor_pd". 59 - 60 - = EXAMPLE 61 - The following example represents a QDSP based sound card on a MSM8996 device 62 - which uses apr as communication between Apps and QDSP. 63 - 64 - apr { 65 - compatible = "qcom,apr-v2"; 66 - qcom,apr-domain = <APR_DOMAIN_ADSP>; 67 - 68 - apr-service@3 { 69 - compatible = "qcom,q6core"; 70 - reg = <APR_SVC_ADSP_CORE>; 71 - }; 72 - 73 - apr-service@4 { 74 - compatible = "qcom,q6afe"; 75 - reg = <APR_SVC_AFE>; 76 - 77 - dais { 78 - #sound-dai-cells = <1>; 79 - dai@1 { 80 - reg = <HDMI_RX>; 81 - }; 82 - }; 83 - }; 84 - 85 - apr-service@7 { 86 - compatible = "qcom,q6asm"; 87 - reg = <APR_SVC_ASM>; 88 - ... 89 - }; 90 - 91 - apr-service@8 { 92 - compatible = "qcom,q6adm"; 93 - reg = <APR_SVC_ADM>; 94 - ... 95 - }; 96 - }; 97 - 98 - = EXAMPLE 2 99 - The following example represents a QDSP based sound card with protection domain 100 - dependencies specified. Here some of the apr services are dependent on services 101 - running on protection domain hosted on ADSP/SLPI remote processors while others 102 - have no such dependency. 103 - 104 - apr { 105 - compatible = "qcom,apr-v2"; 106 - qcom,glink-channels = "apr_audio_svc"; 107 - qcom,apr-domain = <APR_DOMAIN_ADSP>; 108 - 109 - apr-service@3 { 110 - compatible = "qcom,q6core"; 111 - reg = <APR_SVC_ADSP_CORE>; 112 - }; 113 - 114 - q6afe: apr-service@4 { 115 - compatible = "qcom,q6afe"; 116 - reg = <APR_SVC_AFE>; 117 - qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; 118 - ... 119 - }; 120 - 121 - q6asm: apr-service@7 { 122 - compatible = "qcom,q6asm"; 123 - reg = <APR_SVC_ASM>; 124 - qcom,protection-domain = "tms/servreg", "msm/slpi/sensor_pd"; 125 - ... 126 - }; 127 - 128 - q6adm: apr-service@8 { 129 - compatible = "qcom,q6adm"; 130 - reg = <APR_SVC_ADM>; 131 - qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; 132 - ... 133 - }; 134 - };
+177
Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: "http://devicetree.org/schemas/soc/qcom/qcom,apr.yaml#" 5 + $schema: "http://devicetree.org/meta-schemas/core.yaml#" 6 + 7 + title: Qualcomm APR/GPR (Asynchronous/Generic Packet Router) binding 8 + 9 + maintainers: 10 + - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> 11 + 12 + description: | 13 + This binding describes the Qualcomm APR/GPR, APR/GPR is a IPC protocol for 14 + communication between Application processor and QDSP. APR/GPR is mainly 15 + used for audio/voice services on the QDSP. 16 + 17 + properties: 18 + compatible: 19 + enum: 20 + - qcom,apr-v2 21 + - qcom,gpr 22 + 23 + qcom,apr-domain: 24 + $ref: /schemas/types.yaml#/definitions/uint32 25 + enum: [1, 2, 3, 4, 5, 6, 7] 26 + description: 27 + Selects the processor domain for apr 28 + 1 = APR simulator 29 + 2 = PC Domain 30 + 3 = Modem Domain 31 + 4 = ADSP Domain 32 + 5 = Application processor Domain 33 + 6 = Modem2 Domain 34 + 7 = Application Processor2 Domain 35 + deprecated: true 36 + 37 + qcom,domain: 38 + $ref: /schemas/types.yaml#/definitions/uint32 39 + minimum: 1 40 + maximum: 7 41 + description: 42 + Selects the processor domain for apr 43 + 1 = APR simulator 44 + 2 = PC Domain 45 + 3 = Modem Domain 46 + 4 = ADSP Domain 47 + 5 = Application processor Domain 48 + 6 = Modem2 Domain 49 + 7 = Application Processor2 Domain 50 + Selects the processor domain for gpr 51 + 1 = Modem Domain 52 + 2 = Audio DSP Domain 53 + 3 = Application Processor Domain 54 + 55 + '#address-cells': 56 + const: 1 57 + 58 + '#size-cells': 59 + const: 0 60 + 61 + #APR/GPR Services 62 + patternProperties: 63 + "^service@[1-9a-d]$": 64 + type: object 65 + description: 66 + APR/GPR node's client devices use subnodes for desired static port services. 67 + 68 + properties: 69 + compatible: 70 + enum: 71 + - qcom,q6core 72 + - qcom,q6asm 73 + - qcom,q6afe 74 + - qcom,q6adm 75 + - qcom,q6apm 76 + - qcom,q6prm 77 + 78 + reg: 79 + minimum: 1 80 + maximum: 13 81 + description: 82 + APR Service ID 83 + 3 = DSP Core Service 84 + 4 = Audio Front End Service. 85 + 5 = Voice Stream Manager Service. 86 + 6 = Voice processing manager. 87 + 7 = Audio Stream Manager Service. 88 + 8 = Audio Device Manager Service. 89 + 9 = Multimode voice manager. 90 + 10 = Core voice stream. 91 + 11 = Core voice processor. 92 + 12 = Ultrasound stream manager. 93 + 13 = Listen stream manager. 94 + GPR Service ID 95 + 1 = Audio Process Manager Service 96 + 2 = Proxy Resource Manager Service. 97 + 3 = AMDB Service. 98 + 4 = Voice processing manager. 99 + 100 + qcom,protection-domain: 101 + $ref: /schemas/types.yaml#/definitions/string-array 102 + description: protection domain service name and path for apr service 103 + possible values are 104 + "avs/audio", "msm/adsp/audio_pd". 105 + "kernel/elf_loader", "msm/modem/wlan_pd". 106 + "tms/servreg", "msm/adsp/audio_pd". 107 + "tms/servreg", "msm/modem/wlan_pd". 108 + "tms/servreg", "msm/slpi/sensor_pd". 109 + 110 + '#address-cells': 111 + const: 1 112 + 113 + '#size-cells': 114 + const: 0 115 + 116 + patternProperties: 117 + "^.*@[0-9a-f]+$": 118 + type: object 119 + description: 120 + Service based devices like clock controllers or digital audio interfaces. 121 + 122 + additionalProperties: false 123 + 124 + required: 125 + - compatible 126 + - qcom,domain 127 + 128 + additionalProperties: false 129 + 130 + examples: 131 + - | 132 + #include <dt-bindings/soc/qcom,apr.h> 133 + apr { 134 + compatible = "qcom,apr-v2"; 135 + qcom,domain = <APR_DOMAIN_ADSP>; 136 + #address-cells = <1>; 137 + #size-cells = <0>; 138 + 139 + q6core: service@3 { 140 + compatible = "qcom,q6core"; 141 + reg = <APR_SVC_ADSP_CORE>; 142 + qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; 143 + }; 144 + 145 + q6afe: service@4 { 146 + compatible = "qcom,q6afe"; 147 + reg = <APR_SVC_AFE>; 148 + qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; 149 + }; 150 + 151 + q6asm: service@7 { 152 + compatible = "qcom,q6asm"; 153 + reg = <APR_SVC_ASM>; 154 + qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; 155 + }; 156 + 157 + q6adm: service@8 { 158 + compatible = "qcom,q6adm"; 159 + reg = <APR_SVC_ADM>; 160 + qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; 161 + }; 162 + }; 163 + 164 + - | 165 + #include <dt-bindings/soc/qcom,gpr.h> 166 + gpr { 167 + compatible = "qcom,gpr"; 168 + qcom,domain = <GPR_DOMAIN_ID_ADSP>; 169 + #address-cells = <1>; 170 + #size-cells = <0>; 171 + 172 + service@1 { 173 + compatible = "qcom,q6apm"; 174 + reg = <GPR_APM_MODULE_IID>; 175 + qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd"; 176 + }; 177 + };
+1 -1
drivers/soc/qcom/Kconfig
··· 199 199 firmware to a newly booted WCNSS chip. 200 200 201 201 config QCOM_APR 202 - tristate "Qualcomm APR Bus (Asynchronous Packet Router)" 202 + tristate "Qualcomm APR/GPR Bus (Asynchronous/Generic Packet Router)" 203 203 depends on ARCH_QCOM || COMPILE_TEST 204 204 depends on RPMSG 205 205 depends on NET
+235 -52
drivers/soc/qcom/apr.c
··· 15 15 #include <linux/rpmsg.h> 16 16 #include <linux/of.h> 17 17 18 - struct apr { 18 + enum { 19 + PR_TYPE_APR = 0, 20 + PR_TYPE_GPR, 21 + }; 22 + 23 + /* Some random values tbh which does not collide with static modules */ 24 + #define GPR_DYNAMIC_PORT_START 0x10000000 25 + #define GPR_DYNAMIC_PORT_END 0x20000000 26 + 27 + struct packet_router { 19 28 struct rpmsg_endpoint *ch; 20 29 struct device *dev; 21 30 spinlock_t svcs_lock; 22 31 spinlock_t rx_lock; 23 32 struct idr svcs_idr; 24 33 int dest_domain_id; 34 + int type; 25 35 struct pdr_handle *pdr; 26 36 struct workqueue_struct *rxwq; 27 37 struct work_struct rx_work; ··· 54 44 */ 55 45 int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt) 56 46 { 57 - struct apr *apr = dev_get_drvdata(adev->dev.parent); 47 + struct packet_router *apr = dev_get_drvdata(adev->dev.parent); 58 48 struct apr_hdr *hdr; 59 49 unsigned long flags; 60 50 int ret; 61 51 62 - spin_lock_irqsave(&adev->lock, flags); 52 + spin_lock_irqsave(&adev->svc.lock, flags); 63 53 64 54 hdr = &pkt->hdr; 65 55 hdr->src_domain = APR_DOMAIN_APPS; 66 - hdr->src_svc = adev->svc_id; 56 + hdr->src_svc = adev->svc.id; 67 57 hdr->dest_domain = adev->domain_id; 68 - hdr->dest_svc = adev->svc_id; 58 + hdr->dest_svc = adev->svc.id; 69 59 70 60 ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size); 71 - spin_unlock_irqrestore(&adev->lock, flags); 61 + spin_unlock_irqrestore(&adev->svc.lock, flags); 72 62 73 63 return ret ? ret : hdr->pkt_size; 74 64 } 75 65 EXPORT_SYMBOL_GPL(apr_send_pkt); 66 + 67 + void gpr_free_port(gpr_port_t *port) 68 + { 69 + struct packet_router *gpr = port->pr; 70 + unsigned long flags; 71 + 72 + spin_lock_irqsave(&gpr->svcs_lock, flags); 73 + idr_remove(&gpr->svcs_idr, port->id); 74 + spin_unlock_irqrestore(&gpr->svcs_lock, flags); 75 + 76 + kfree(port); 77 + } 78 + EXPORT_SYMBOL_GPL(gpr_free_port); 79 + 80 + gpr_port_t *gpr_alloc_port(struct apr_device *gdev, struct device *dev, 81 + gpr_port_cb cb, void *priv) 82 + { 83 + struct packet_router *pr = dev_get_drvdata(gdev->dev.parent); 84 + gpr_port_t *port; 85 + struct pkt_router_svc *svc; 86 + int id; 87 + 88 + port = kzalloc(sizeof(*port), GFP_KERNEL); 89 + if (!port) 90 + return ERR_PTR(-ENOMEM); 91 + 92 + svc = port; 93 + svc->callback = cb; 94 + svc->pr = pr; 95 + svc->priv = priv; 96 + svc->dev = dev; 97 + spin_lock_init(&svc->lock); 98 + 99 + spin_lock(&pr->svcs_lock); 100 + id = idr_alloc_cyclic(&pr->svcs_idr, svc, GPR_DYNAMIC_PORT_START, 101 + GPR_DYNAMIC_PORT_END, GFP_ATOMIC); 102 + if (id < 0) { 103 + dev_err(dev, "Unable to allocate dynamic GPR src port\n"); 104 + kfree(port); 105 + spin_unlock(&pr->svcs_lock); 106 + return ERR_PTR(id); 107 + } 108 + 109 + svc->id = id; 110 + spin_unlock(&pr->svcs_lock); 111 + 112 + return port; 113 + } 114 + EXPORT_SYMBOL_GPL(gpr_alloc_port); 115 + 116 + static int pkt_router_send_svc_pkt(struct pkt_router_svc *svc, struct gpr_pkt *pkt) 117 + { 118 + struct packet_router *pr = svc->pr; 119 + struct gpr_hdr *hdr; 120 + unsigned long flags; 121 + int ret; 122 + 123 + hdr = &pkt->hdr; 124 + 125 + spin_lock_irqsave(&svc->lock, flags); 126 + ret = rpmsg_trysend(pr->ch, pkt, hdr->pkt_size); 127 + spin_unlock_irqrestore(&svc->lock, flags); 128 + 129 + return ret ? ret : hdr->pkt_size; 130 + } 131 + 132 + int gpr_send_pkt(struct apr_device *gdev, struct gpr_pkt *pkt) 133 + { 134 + return pkt_router_send_svc_pkt(&gdev->svc, pkt); 135 + } 136 + EXPORT_SYMBOL_GPL(gpr_send_pkt); 137 + 138 + int gpr_send_port_pkt(gpr_port_t *port, struct gpr_pkt *pkt) 139 + { 140 + return pkt_router_send_svc_pkt(port, pkt); 141 + } 142 + EXPORT_SYMBOL_GPL(gpr_send_port_pkt); 76 143 77 144 static void apr_dev_release(struct device *dev) 78 145 { ··· 161 74 static int apr_callback(struct rpmsg_device *rpdev, void *buf, 162 75 int len, void *priv, u32 addr) 163 76 { 164 - struct apr *apr = dev_get_drvdata(&rpdev->dev); 77 + struct packet_router *apr = dev_get_drvdata(&rpdev->dev); 165 78 struct apr_rx_buf *abuf; 166 79 unsigned long flags; 167 80 ··· 187 100 return 0; 188 101 } 189 102 190 - 191 - static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) 103 + static int apr_do_rx_callback(struct packet_router *apr, struct apr_rx_buf *abuf) 192 104 { 193 105 uint16_t hdr_size, msg_type, ver, svc_id; 194 - struct apr_device *svc = NULL; 106 + struct pkt_router_svc *svc; 107 + struct apr_device *adev; 195 108 struct apr_driver *adrv = NULL; 196 109 struct apr_resp_pkt resp; 197 110 struct apr_hdr *hdr; ··· 232 145 svc_id = hdr->dest_svc; 233 146 spin_lock_irqsave(&apr->svcs_lock, flags); 234 147 svc = idr_find(&apr->svcs_idr, svc_id); 235 - if (svc && svc->dev.driver) 236 - adrv = to_apr_driver(svc->dev.driver); 148 + if (svc && svc->dev->driver) { 149 + adev = svc_to_apr_device(svc); 150 + adrv = to_apr_driver(adev->dev.driver); 151 + } 237 152 spin_unlock_irqrestore(&apr->svcs_lock, flags); 238 153 239 - if (!adrv) { 240 - dev_err(apr->dev, "APR: service is not registered\n"); 154 + if (!adrv || !adev) { 155 + dev_err(apr->dev, "APR: service is not registered (%d)\n", 156 + svc_id); 241 157 return -EINVAL; 242 158 } 243 159 ··· 254 164 if (resp.payload_size > 0) 255 165 resp.payload = buf + hdr_size; 256 166 257 - adrv->callback(svc, &resp); 167 + adrv->callback(adev, &resp); 168 + 169 + return 0; 170 + } 171 + 172 + static int gpr_do_rx_callback(struct packet_router *gpr, struct apr_rx_buf *abuf) 173 + { 174 + uint16_t hdr_size, ver; 175 + struct pkt_router_svc *svc = NULL; 176 + struct gpr_resp_pkt resp; 177 + struct gpr_hdr *hdr; 178 + unsigned long flags; 179 + void *buf = abuf->buf; 180 + int len = abuf->len; 181 + 182 + hdr = buf; 183 + ver = hdr->version; 184 + if (ver > GPR_PKT_VER + 1) 185 + return -EINVAL; 186 + 187 + hdr_size = hdr->hdr_size; 188 + if (hdr_size < GPR_PKT_HEADER_WORD_SIZE) { 189 + dev_err(gpr->dev, "GPR: Wrong hdr size:%d\n", hdr_size); 190 + return -EINVAL; 191 + } 192 + 193 + if (hdr->pkt_size < GPR_PKT_HEADER_BYTE_SIZE || hdr->pkt_size != len) { 194 + dev_err(gpr->dev, "GPR: Wrong packet size\n"); 195 + return -EINVAL; 196 + } 197 + 198 + resp.hdr = *hdr; 199 + resp.payload_size = hdr->pkt_size - (hdr_size * 4); 200 + 201 + /* 202 + * NOTE: hdr_size is not same as GPR_HDR_SIZE as remote can include 203 + * optional headers in to gpr_hdr which should be ignored 204 + */ 205 + if (resp.payload_size > 0) 206 + resp.payload = buf + (hdr_size * 4); 207 + 208 + 209 + spin_lock_irqsave(&gpr->svcs_lock, flags); 210 + svc = idr_find(&gpr->svcs_idr, hdr->dest_port); 211 + spin_unlock_irqrestore(&gpr->svcs_lock, flags); 212 + 213 + if (!svc) { 214 + dev_err(gpr->dev, "GPR: Port(%x) is not registered\n", 215 + hdr->dest_port); 216 + return -EINVAL; 217 + } 218 + 219 + if (svc->callback) 220 + svc->callback(&resp, svc->priv, 0); 258 221 259 222 return 0; 260 223 } 261 224 262 225 static void apr_rxwq(struct work_struct *work) 263 226 { 264 - struct apr *apr = container_of(work, struct apr, rx_work); 227 + struct packet_router *apr = container_of(work, struct packet_router, rx_work); 265 228 struct apr_rx_buf *abuf, *b; 266 229 unsigned long flags; 267 230 268 231 if (!list_empty(&apr->rx_list)) { 269 232 list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { 270 - apr_do_rx_callback(apr, abuf); 233 + switch (apr->type) { 234 + case PR_TYPE_APR: 235 + apr_do_rx_callback(apr, abuf); 236 + break; 237 + case PR_TYPE_GPR: 238 + gpr_do_rx_callback(apr, abuf); 239 + break; 240 + default: 241 + break; 242 + } 271 243 spin_lock_irqsave(&apr->rx_lock, flags); 272 244 list_del(&abuf->node); 273 245 spin_unlock_irqrestore(&apr->rx_lock, flags); ··· 353 201 354 202 while (id->domain_id != 0 || id->svc_id != 0) { 355 203 if (id->domain_id == adev->domain_id && 356 - id->svc_id == adev->svc_id) 204 + id->svc_id == adev->svc.id) 357 205 return 1; 358 206 id++; 359 207 } ··· 365 213 { 366 214 struct apr_device *adev = to_apr_device(dev); 367 215 struct apr_driver *adrv = to_apr_driver(dev->driver); 216 + int ret; 368 217 369 - return adrv->probe(adev); 218 + ret = adrv->probe(adev); 219 + if (!ret) 220 + adev->svc.callback = adrv->gpr_callback; 221 + 222 + return ret; 370 223 } 371 224 372 225 static void apr_device_remove(struct device *dev) 373 226 { 374 227 struct apr_device *adev = to_apr_device(dev); 375 228 struct apr_driver *adrv; 376 - struct apr *apr = dev_get_drvdata(adev->dev.parent); 229 + struct packet_router *apr = dev_get_drvdata(adev->dev.parent); 377 230 378 231 if (dev->driver) { 379 232 adrv = to_apr_driver(dev->driver); 380 233 if (adrv->remove) 381 234 adrv->remove(adev); 382 235 spin_lock(&apr->svcs_lock); 383 - idr_remove(&apr->svcs_idr, adev->svc_id); 236 + idr_remove(&apr->svcs_idr, adev->svc.id); 384 237 spin_unlock(&apr->svcs_lock); 385 238 } 386 239 } ··· 412 255 EXPORT_SYMBOL_GPL(aprbus); 413 256 414 257 static int apr_add_device(struct device *dev, struct device_node *np, 415 - const struct apr_device_id *id) 258 + u32 svc_id, u32 domain_id) 416 259 { 417 - struct apr *apr = dev_get_drvdata(dev); 260 + struct packet_router *apr = dev_get_drvdata(dev); 418 261 struct apr_device *adev = NULL; 262 + struct pkt_router_svc *svc; 419 263 int ret; 420 264 421 265 adev = kzalloc(sizeof(*adev), GFP_KERNEL); 422 266 if (!adev) 423 267 return -ENOMEM; 424 268 425 - spin_lock_init(&adev->lock); 269 + adev->svc_id = svc_id; 270 + svc = &adev->svc; 426 271 427 - adev->svc_id = id->svc_id; 428 - adev->domain_id = id->domain_id; 429 - adev->version = id->svc_version; 272 + svc->id = svc_id; 273 + svc->pr = apr; 274 + svc->priv = adev; 275 + svc->dev = dev; 276 + spin_lock_init(&svc->lock); 277 + 278 + adev->domain_id = domain_id; 279 + 430 280 if (np) 431 281 snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); 432 - else 433 - strscpy(adev->name, id->name, APR_NAME_SIZE); 434 282 435 - dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, 436 - id->domain_id, id->svc_id); 283 + switch (apr->type) { 284 + case PR_TYPE_APR: 285 + dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, 286 + domain_id, svc_id); 287 + break; 288 + case PR_TYPE_GPR: 289 + dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name, 290 + domain_id, svc_id); 291 + break; 292 + default: 293 + break; 294 + } 437 295 438 296 adev->dev.bus = &aprbus; 439 297 adev->dev.parent = dev; ··· 457 285 adev->dev.driver = NULL; 458 286 459 287 spin_lock(&apr->svcs_lock); 460 - idr_alloc(&apr->svcs_idr, adev, id->svc_id, 461 - id->svc_id + 1, GFP_ATOMIC); 288 + idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); 462 289 spin_unlock(&apr->svcs_lock); 463 290 464 291 of_property_read_string_index(np, "qcom,protection-domain", 465 292 1, &adev->service_path); 466 293 467 - dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev)); 294 + dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev)); 468 295 469 296 ret = device_register(&adev->dev); 470 297 if (ret) { ··· 477 306 static int of_apr_add_pd_lookups(struct device *dev) 478 307 { 479 308 const char *service_name, *service_path; 480 - struct apr *apr = dev_get_drvdata(dev); 309 + struct packet_router *apr = dev_get_drvdata(dev); 481 310 struct device_node *node; 482 311 struct pdr_service *pds; 483 312 int ret; ··· 507 336 508 337 static void of_register_apr_devices(struct device *dev, const char *svc_path) 509 338 { 510 - struct apr *apr = dev_get_drvdata(dev); 339 + struct packet_router *apr = dev_get_drvdata(dev); 511 340 struct device_node *node; 512 341 const char *service_path; 513 342 int ret; 514 343 515 344 for_each_child_of_node(dev->of_node, node) { 516 - struct apr_device_id id = { {0} }; 345 + u32 svc_id; 346 + u32 domain_id; 517 347 518 348 /* 519 349 * This function is called with svc_path NULL during ··· 544 372 continue; 545 373 } 546 374 547 - if (of_property_read_u32(node, "reg", &id.svc_id)) 375 + if (of_property_read_u32(node, "reg", &svc_id)) 548 376 continue; 549 377 550 - id.domain_id = apr->dest_domain_id; 378 + domain_id = apr->dest_domain_id; 551 379 552 - if (apr_add_device(dev, node, &id)) 553 - dev_err(dev, "Failed to add apr %d svc\n", id.svc_id); 380 + if (apr_add_device(dev, node, svc_id, domain_id)) 381 + dev_err(dev, "Failed to add apr %d svc\n", svc_id); 554 382 } 555 383 } 556 384 ··· 570 398 571 399 static void apr_pd_status(int state, char *svc_path, void *priv) 572 400 { 573 - struct apr *apr = (struct apr *)priv; 401 + struct packet_router *apr = (struct packet_router *)priv; 574 402 575 403 switch (state) { 576 404 case SERVREG_SERVICE_STATE_UP: ··· 585 413 static int apr_probe(struct rpmsg_device *rpdev) 586 414 { 587 415 struct device *dev = &rpdev->dev; 588 - struct apr *apr; 416 + struct packet_router *apr; 589 417 int ret; 590 418 591 419 apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL); 592 420 if (!apr) 593 421 return -ENOMEM; 594 422 595 - ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", &apr->dest_domain_id); 423 + ret = of_property_read_u32(dev->of_node, "qcom,domain", &apr->dest_domain_id); 424 + 425 + if (of_device_is_compatible(dev->of_node, "qcom,gpr")) { 426 + apr->type = PR_TYPE_GPR; 427 + } else { 428 + if (ret) /* try deprecated apr-domain property */ 429 + ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", 430 + &apr->dest_domain_id); 431 + apr->type = PR_TYPE_APR; 432 + } 433 + 596 434 if (ret) { 597 - dev_err(dev, "APR Domain ID not specified in DT\n"); 435 + dev_err(dev, "Domain ID not specified in DT\n"); 598 436 return ret; 599 437 } 600 438 ··· 647 465 648 466 static void apr_remove(struct rpmsg_device *rpdev) 649 467 { 650 - struct apr *apr = dev_get_drvdata(&rpdev->dev); 468 + struct packet_router *apr = dev_get_drvdata(&rpdev->dev); 651 469 652 470 pdr_handle_release(apr->pdr); 653 471 device_for_each_child(&rpdev->dev, NULL, apr_remove_device); ··· 684 502 } 685 503 EXPORT_SYMBOL_GPL(apr_driver_unregister); 686 504 687 - static const struct of_device_id apr_of_match[] = { 505 + static const struct of_device_id pkt_router_of_match[] = { 688 506 { .compatible = "qcom,apr"}, 689 507 { .compatible = "qcom,apr-v2"}, 508 + { .compatible = "qcom,gpr"}, 690 509 {} 691 510 }; 692 - MODULE_DEVICE_TABLE(of, apr_of_match); 511 + MODULE_DEVICE_TABLE(of, pkt_router_of_match); 693 512 694 - static struct rpmsg_driver apr_driver = { 513 + static struct rpmsg_driver packet_router_driver = { 695 514 .probe = apr_probe, 696 515 .remove = apr_remove, 697 516 .callback = apr_callback, 698 517 .drv = { 699 518 .name = "qcom,apr", 700 - .of_match_table = apr_of_match, 519 + .of_match_table = pkt_router_of_match, 701 520 }, 702 521 }; 703 522 ··· 708 525 709 526 ret = bus_register(&aprbus); 710 527 if (!ret) 711 - ret = register_rpmsg_driver(&apr_driver); 528 + ret = register_rpmsg_driver(&packet_router_driver); 712 529 else 713 530 bus_unregister(&aprbus); 714 531 ··· 718 535 static void __exit apr_exit(void) 719 536 { 720 537 bus_unregister(&aprbus); 721 - unregister_rpmsg_driver(&apr_driver); 538 + unregister_rpmsg_driver(&packet_router_driver); 722 539 } 723 540 724 541 subsys_initcall(apr_init);
+19
include/dt-bindings/soc/qcom,gpr.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ 2 + 3 + #ifndef __DT_BINDINGS_QCOM_GPR_H 4 + #define __DT_BINDINGS_QCOM_GPR_H 5 + 6 + /* DOMAINS */ 7 + 8 + #define GPR_DOMAIN_ID_MODEM 1 9 + #define GPR_DOMAIN_ID_ADSP 2 10 + #define GPR_DOMAIN_ID_APPS 3 11 + 12 + /* Static Services */ 13 + 14 + #define GPR_APM_MODULE_IID 1 15 + #define GPR_PRM_MODULE_IID 2 16 + #define GPR_AMDB_MODULE_IID 3 17 + #define GPR_VCPM_MODULE_IID 4 18 + 19 + #endif /* __DT_BINDINGS_QCOM_GPR_H */
+69 -1
include/linux/soc/qcom/apr.h
··· 7 7 #include <linux/device.h> 8 8 #include <linux/mod_devicetable.h> 9 9 #include <dt-bindings/soc/qcom,apr.h> 10 + #include <dt-bindings/soc/qcom,gpr.h> 10 11 11 12 extern struct bus_type aprbus; 12 13 ··· 76 75 int payload_size; 77 76 }; 78 77 78 + struct gpr_hdr { 79 + uint32_t version:4; 80 + uint32_t hdr_size:4; 81 + uint32_t pkt_size:24; 82 + uint32_t dest_domain:8; 83 + uint32_t src_domain:8; 84 + uint32_t reserved:16; 85 + uint32_t src_port; 86 + uint32_t dest_port; 87 + uint32_t token; 88 + uint32_t opcode; 89 + } __packed; 90 + 91 + struct gpr_pkt { 92 + struct gpr_hdr hdr; 93 + uint32_t payload[]; 94 + }; 95 + 96 + struct gpr_resp_pkt { 97 + struct gpr_hdr hdr; 98 + void *payload; 99 + int payload_size; 100 + }; 101 + 102 + #define GPR_HDR_SIZE sizeof(struct gpr_hdr) 103 + #define GPR_PKT_VER 0x0 104 + #define GPR_PKT_HEADER_WORD_SIZE ((sizeof(struct gpr_pkt) + 3) >> 2) 105 + #define GPR_PKT_HEADER_BYTE_SIZE (GPR_PKT_HEADER_WORD_SIZE << 2) 106 + 107 + #define GPR_BASIC_RSP_RESULT 0x02001005 108 + 109 + struct gpr_ibasic_rsp_result_t { 110 + uint32_t opcode; 111 + uint32_t status; 112 + }; 113 + 114 + #define GPR_BASIC_EVT_ACCEPTED 0x02001006 115 + 116 + struct gpr_ibasic_rsp_accepted_t { 117 + uint32_t opcode; 118 + }; 119 + 79 120 /* Bits 0 to 15 -- Minor version, Bits 16 to 31 -- Major version */ 80 121 #define APR_SVC_MAJOR_VERSION(v) ((v >> 16) & 0xFF) 81 122 #define APR_SVC_MINOR_VERSION(v) (v & 0xFF) 123 + 124 + typedef int (*gpr_port_cb) (struct gpr_resp_pkt *d, void *priv, int op); 125 + struct packet_router; 126 + struct pkt_router_svc { 127 + struct device *dev; 128 + gpr_port_cb callback; 129 + struct packet_router *pr; 130 + spinlock_t lock; 131 + int id; 132 + void *priv; 133 + }; 134 + 135 + typedef struct pkt_router_svc gpr_port_t; 82 136 83 137 struct apr_device { 84 138 struct device dev; ··· 142 86 uint32_t version; 143 87 char name[APR_NAME_SIZE]; 144 88 const char *service_path; 145 - spinlock_t lock; 89 + struct pkt_router_svc svc; 146 90 struct list_head node; 147 91 }; 148 92 93 + typedef struct apr_device gpr_device_t; 94 + 149 95 #define to_apr_device(d) container_of(d, struct apr_device, dev) 96 + #define svc_to_apr_device(d) container_of(d, struct apr_device, svc) 150 97 151 98 struct apr_driver { 152 99 int (*probe)(struct apr_device *sl); 153 100 int (*remove)(struct apr_device *sl); 154 101 int (*callback)(struct apr_device *a, 155 102 struct apr_resp_pkt *d); 103 + int (*gpr_callback)(struct gpr_resp_pkt *d, void *data, int op); 156 104 struct device_driver driver; 157 105 const struct apr_device_id *id_table; 158 106 }; 159 107 108 + typedef struct apr_driver gpr_driver_t; 160 109 #define to_apr_driver(d) container_of(d, struct apr_driver, driver) 161 110 162 111 /* ··· 184 123 #define module_apr_driver(__apr_driver) \ 185 124 module_driver(__apr_driver, apr_driver_register, \ 186 125 apr_driver_unregister) 126 + #define module_gpr_driver(__gpr_driver) module_apr_driver(__gpr_driver) 187 127 188 128 int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt); 129 + 130 + gpr_port_t *gpr_alloc_port(gpr_device_t *gdev, struct device *dev, 131 + gpr_port_cb cb, void *priv); 132 + void gpr_free_port(gpr_port_t *port); 133 + int gpr_send_port_pkt(gpr_port_t *port, struct gpr_pkt *pkt); 134 + int gpr_send_pkt(gpr_device_t *gdev, struct gpr_pkt *pkt); 189 135 190 136 #endif /* __QCOM_APR_H_ */