forked from mirrors/linux
		
	soc: driver updates for 6.14
These are changes to SoC specific drivers and DT bindings that don't have
 a separate subsystem tree, or that get grouped here for simplicity.
 Nothing out of the ordinary for the 6.14 release here:
 
  - Most of the updates are for Qualcomm specific drivers, adding support
    for additional SoCs in the exssting drivers, and support for wrapped
    encryption key access in the SCM firmware.
 
  - The Arm SCMI firmware code gains support for having multiple
    instances of firmware running, and better module auto loading.
 
  - A few minor updates for litex, samsung, ti, tegra, mediatek, imx and
    renesas platforms.
 
  - Reset controller updates for amlogic, to add support for the A1 soc
    and clean up the existing code.
 
  - Memory controller updates for ti davinci aemif, refactoring the code
    and adding a few interfaces to other drivers.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmeTgqUACgkQYKtH/8kJ
 Uif73w/6A005eeovEmXLEUBMThlMpOLGeE5YL6arspQ2jvF93uh4vbJXn70xWn76
 pV/1yzeu87E078mHBxcoQX0tb2Lt0xoueDBQ+jODxCcrr+6+0gPEPOq/VK7SBFH8
 h1WrCeFjxmks3kyh0/8rQ4FebPClhkNT32RbQpbu+oP6n3uoKOvFgh5WxG29+hV/
 6+lmzuMr7vWMnQ8KqPCX4tKPERkGE/68Gtq08SCH79K35dTVpMu6HadzURDssKdj
 /SJW9rJhSZGOoYFHdOU5f2n1jRt2/Vg7snzujGFCY0pV7BW9tU/XzPV8YKU4wVx3
 m0dlLCGDAN4I23TfhDJTDoEQXGU1dd4ISLf5LrbksQX9mfyZJB0hl0c9rCESuZkG
 1Rt6CCgMNjSNDrqnoM2KDSwSF9mcczea6R/NDvYcU1jbX4gHZK91OuzD6AjI8OLm
 1GcT8tmGPsUQElQYiSC+4rtsXBDg433p9WAnKLVH7xQ62mYzA2LQ6tvl2Cjua09z
 LFNv5YD2oHNo3nI3zHFu+h/TKFJ+Tnq958mH575K54HgFfsGIv/eVvm3rXY3Tb8a
 i+I41wHkGc5xuvTGgu3ZlwqC/a9cXo8jUoHPlp+c27U4VDUEkrlzRkIUaPgDZzBe
 4DUCk8LTC+l0PKcOcdr5wwBArn0c4DDC+8rPnb27ZQoW0kC0GI8=
 =oeUS
 -----END PGP SIGNATURE-----
Merge tag 'soc-drivers-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull SoC driver updates from Arnd Bergmann:
 "These are changes to SoC specific drivers and DT bindings that don't
  have a separate subsystem tree, or that get grouped here for
  simplicity.
  Nothing out of the ordinary for the 6.14 release here:
   - Most of the updates are for Qualcomm specific drivers, adding
     support for additional SoCs in the exssting drivers, and support
     for wrapped encryption key access in the SCM firmware.
   - The Arm SCMI firmware code gains support for having multiple
     instances of firmware running, and better module auto loading.
   - A few minor updates for litex, samsung, ti, tegra, mediatek, imx
     and renesas platforms.
   - Reset controller updates for amlogic, to add support for the A1 soc
     and clean up the existing code.
   - Memory controller updates for ti davinci aemif, refactoring the
     code and adding a few interfaces to other drivers"
* tag 'soc-drivers-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (58 commits)
  drivers/soc/litex: Use devm_register_restart_handler()
  reset: amlogic: aux: drop aux registration helper
  reset: amlogic: aux: get regmap through parent device
  reset: amlogic: add support for A1 SoC in auxiliary reset driver
  dt-bindings: reset: add bindings for A1 SoC audio reset controller
  soc/tegra: fuse: Update Tegra234 nvmem keepout list
  soc/tegra: Fix spelling error in tegra234_lookup_slave_timeout()
  soc/tegra: cbb: Drop unnecessary debugfs error handling
  firmware: qcom: scm: add calls for wrapped key support
  soc: qcom: pd_mapper: Add SM7225 compatible
  dt-bindings: firmware: qcom,scm: Document ipq5424 SCM
  soc: qcom: llcc: Update configuration data for IPQ5424
  dt-bindings: cache: qcom,llcc: Add IPQ5424 compatible
  soc: mediatek: mtk-devapc: Fix leaking IO map on driver remove
  soc: mediatek: mtk-devapc: Fix leaking IO map on error paths
  firmware: qcom: scm: smc: Narrow 'mempool' variable scope
  firmware: qcom: scm: smc: Handle missing SCM device
  firmware: qcom: scm: Cleanup global '__scm' on probe failures
  firmware: qcom: scm: Fix missing read barrier in qcom_scm_get_tzmem_pool()
  firmware: qcom: scm: Fix missing read barrier in qcom_scm_is_available()
  ...
			
			
This commit is contained in:
		
						commit
						f2ad904e92
					
				
					 47 changed files with 877 additions and 375 deletions
				
			
		|  | @ -20,6 +20,7 @@ description: | | ||||||
| properties: | properties: | ||||||
|   compatible: |   compatible: | ||||||
|     enum: |     enum: | ||||||
|  |       - qcom,ipq5424-llcc | ||||||
|       - qcom,qcs615-llcc |       - qcom,qcs615-llcc | ||||||
|       - qcom,qcs8300-llcc |       - qcom,qcs8300-llcc | ||||||
|       - qcom,qdu1000-llcc |       - qcom,qdu1000-llcc | ||||||
|  | @ -42,11 +43,11 @@ properties: | ||||||
|       - qcom,x1e80100-llcc |       - qcom,x1e80100-llcc | ||||||
| 
 | 
 | ||||||
|   reg: |   reg: | ||||||
|     minItems: 2 |     minItems: 1 | ||||||
|     maxItems: 10 |     maxItems: 10 | ||||||
| 
 | 
 | ||||||
|   reg-names: |   reg-names: | ||||||
|     minItems: 2 |     minItems: 1 | ||||||
|     maxItems: 10 |     maxItems: 10 | ||||||
| 
 | 
 | ||||||
|   interrupts: |   interrupts: | ||||||
|  | @ -66,6 +67,21 @@ required: | ||||||
|   - reg-names |   - reg-names | ||||||
| 
 | 
 | ||||||
| allOf: | allOf: | ||||||
|  |   - if: | ||||||
|  |       properties: | ||||||
|  |         compatible: | ||||||
|  |           contains: | ||||||
|  |             enum: | ||||||
|  |               - qcom,ipq5424-llcc | ||||||
|  |     then: | ||||||
|  |       properties: | ||||||
|  |         reg: | ||||||
|  |           items: | ||||||
|  |             - description: LLCC0 base register region | ||||||
|  |         reg-names: | ||||||
|  |           items: | ||||||
|  |             - const: llcc0_base | ||||||
|  | 
 | ||||||
|   - if: |   - if: | ||||||
|       properties: |       properties: | ||||||
|         compatible: |         compatible: | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ properties: | ||||||
|           - qcom,scm-ipq4019 |           - qcom,scm-ipq4019 | ||||||
|           - qcom,scm-ipq5018 |           - qcom,scm-ipq5018 | ||||||
|           - qcom,scm-ipq5332 |           - qcom,scm-ipq5332 | ||||||
|  |           - qcom,scm-ipq5424 | ||||||
|           - qcom,scm-ipq6018 |           - qcom,scm-ipq6018 | ||||||
|           - qcom,scm-ipq806x |           - qcom,scm-ipq806x | ||||||
|           - qcom,scm-ipq8074 |           - qcom,scm-ipq8074 | ||||||
|  | @ -42,6 +43,7 @@ properties: | ||||||
|           - qcom,scm-msm8996 |           - qcom,scm-msm8996 | ||||||
|           - qcom,scm-msm8998 |           - qcom,scm-msm8998 | ||||||
|           - qcom,scm-qcm2290 |           - qcom,scm-qcm2290 | ||||||
|  |           - qcom,scm-qcs615 | ||||||
|           - qcom,scm-qcs8300 |           - qcom,scm-qcs8300 | ||||||
|           - qcom,scm-qdu1000 |           - qcom,scm-qdu1000 | ||||||
|           - qcom,scm-sa8255p |           - qcom,scm-sa8255p | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ properties: | ||||||
|       - items: |       - items: | ||||||
|           - enum: |           - enum: | ||||||
|               - qcom,qcm2290-cpu-bwmon |               - qcom,qcm2290-cpu-bwmon | ||||||
|  |               - qcom,qcs615-cpu-bwmon | ||||||
|               - qcom,qcs8300-cpu-bwmon |               - qcom,qcs8300-cpu-bwmon | ||||||
|               - qcom,sa8775p-cpu-bwmon |               - qcom,sa8775p-cpu-bwmon | ||||||
|               - qcom,sc7180-cpu-bwmon |               - qcom,sc7180-cpu-bwmon | ||||||
|  | @ -41,6 +42,7 @@ properties: | ||||||
|           - const: qcom,sdm845-bwmon    # BWMON v4, unified register space |           - const: qcom,sdm845-bwmon    # BWMON v4, unified register space | ||||||
|       - items: |       - items: | ||||||
|           - enum: |           - enum: | ||||||
|  |               - qcom,qcs615-llcc-bwmon | ||||||
|               - qcom,qcs8300-llcc-bwmon |               - qcom,qcs8300-llcc-bwmon | ||||||
|               - qcom,sa8775p-llcc-bwmon |               - qcom,sa8775p-llcc-bwmon | ||||||
|               - qcom,sc7180-llcc-bwmon |               - qcom,sc7180-llcc-bwmon | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ properties: | ||||||
|   compatible: |   compatible: | ||||||
|     items: |     items: | ||||||
|       - enum: |       - enum: | ||||||
|  |           - qcom,qcs615-aoss-qmp | ||||||
|           - qcom,qcs8300-aoss-qmp |           - qcom,qcs8300-aoss-qmp | ||||||
|           - qcom,qdu1000-aoss-qmp |           - qcom,qdu1000-aoss-qmp | ||||||
|           - qcom,sa8255p-aoss-qmp |           - qcom,sa8255p-aoss-qmp | ||||||
|  |  | ||||||
|  | @ -64,6 +64,7 @@ properties: | ||||||
| 
 | 
 | ||||||
|   samsung,mode: |   samsung,mode: | ||||||
|     $ref: /schemas/types.yaml#/definitions/uint32 |     $ref: /schemas/types.yaml#/definitions/uint32 | ||||||
|  |     enum: [0, 1, 2, 3] | ||||||
|     description: |     description: | ||||||
|       Selects USI function (which serial protocol to use). Refer to |       Selects USI function (which serial protocol to use). Refer to | ||||||
|       <include/dt-bindings/soc/samsung,exynos-usi.h> for valid USI mode values. |       <include/dt-bindings/soc/samsung,exynos-usi.h> for valid USI mode values. | ||||||
|  |  | ||||||
|  | @ -21,6 +21,10 @@ properties: | ||||||
|               - samsung,exynos3-sysreg |               - samsung,exynos3-sysreg | ||||||
|               - samsung,exynos4-sysreg |               - samsung,exynos4-sysreg | ||||||
|               - samsung,exynos5-sysreg |               - samsung,exynos5-sysreg | ||||||
|  |               - samsung,exynos8895-fsys0-sysreg | ||||||
|  |               - samsung,exynos8895-fsys1-sysreg | ||||||
|  |               - samsung,exynos8895-peric0-sysreg | ||||||
|  |               - samsung,exynos8895-peric1-sysreg | ||||||
|               - samsung,exynosautov920-peric0-sysreg |               - samsung,exynosautov920-peric0-sysreg | ||||||
|               - samsung,exynosautov920-peric1-sysreg |               - samsung,exynosautov920-peric1-sysreg | ||||||
|               - tesla,fsd-cam-sysreg |               - tesla,fsd-cam-sysreg | ||||||
|  | @ -79,6 +83,10 @@ allOf: | ||||||
|               - samsung,exynos850-cmgp-sysreg |               - samsung,exynos850-cmgp-sysreg | ||||||
|               - samsung,exynos850-peri-sysreg |               - samsung,exynos850-peri-sysreg | ||||||
|               - samsung,exynos850-sysreg |               - samsung,exynos850-sysreg | ||||||
|  |               - samsung,exynos8895-fsys0-sysreg | ||||||
|  |               - samsung,exynos8895-fsys1-sysreg | ||||||
|  |               - samsung,exynos8895-peric0-sysreg | ||||||
|  |               - samsung,exynos8895-peric1-sysreg | ||||||
|     then: |     then: | ||||||
|       required: |       required: | ||||||
|         - clocks |         - clocks | ||||||
|  |  | ||||||
|  | @ -23661,6 +23661,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git | ||||||
| F:	Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml | F:	Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml | ||||||
| F:	drivers/pmdomain/ti/omap_prm.c | F:	drivers/pmdomain/ti/omap_prm.c | ||||||
| F:	drivers/soc/ti/* | F:	drivers/soc/ti/* | ||||||
|  | F:	include/linux/pruss_driver.h | ||||||
| 
 | 
 | ||||||
| TI LM49xxx FAMILY ASoC CODEC DRIVERS | TI LM49xxx FAMILY ASoC CODEC DRIVERS | ||||||
| M:	M R Swami Reddy <mr.swami.reddy@ti.com> | M:	M R Swami Reddy <mr.swami.reddy@ti.com> | ||||||
|  |  | ||||||
|  | @ -442,7 +442,7 @@ struct scmi_transport_core_operations { | ||||||
|  */ |  */ | ||||||
| struct scmi_transport { | struct scmi_transport { | ||||||
| 	struct device *supplier; | 	struct device *supplier; | ||||||
| 	struct scmi_desc *desc; | 	struct scmi_desc desc; | ||||||
| 	struct scmi_transport_core_operations **core_ops; | 	struct scmi_transport_core_operations **core_ops; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -468,7 +468,7 @@ static int __tag##_probe(struct platform_device *pdev)			       \ | ||||||
| 	device_set_of_node_from_dev(&spdev->dev, dev);			       \ | 	device_set_of_node_from_dev(&spdev->dev, dev);			       \ | ||||||
| 									       \ | 									       \ | ||||||
| 	strans.supplier = dev;						       \ | 	strans.supplier = dev;						       \ | ||||||
| 	strans.desc = &(__desc);					       \ | 	memcpy(&strans.desc, &(__desc), sizeof(strans.desc));		       \ | ||||||
| 	strans.core_ops = &(__core_ops);				       \ | 	strans.core_ops = &(__core_ops);				       \ | ||||||
| 									       \ | 									       \ | ||||||
| 	ret = platform_device_add_data(spdev, &strans, sizeof(strans));	       \ | 	ret = platform_device_add_data(spdev, &strans, sizeof(strans));	       \ | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ | ||||||
| #include <linux/io.h> | #include <linux/io.h> | ||||||
| #include <linux/io-64-nonatomic-hi-lo.h> | #include <linux/io-64-nonatomic-hi-lo.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
|  | #include <linux/kmod.h> | ||||||
| #include <linux/ktime.h> | #include <linux/ktime.h> | ||||||
| #include <linux/hashtable.h> | #include <linux/hashtable.h> | ||||||
| #include <linux/list.h> | #include <linux/list.h> | ||||||
|  | @ -43,6 +44,8 @@ | ||||||
| #define CREATE_TRACE_POINTS | #define CREATE_TRACE_POINTS | ||||||
| #include <trace/events/scmi.h> | #include <trace/events/scmi.h> | ||||||
| 
 | 
 | ||||||
|  | #define SCMI_VENDOR_MODULE_ALIAS_FMT	"scmi-protocol-0x%02x-%s" | ||||||
|  | 
 | ||||||
| static DEFINE_IDA(scmi_id); | static DEFINE_IDA(scmi_id); | ||||||
| 
 | 
 | ||||||
| static DEFINE_XARRAY(scmi_protocols); | static DEFINE_XARRAY(scmi_protocols); | ||||||
|  | @ -275,6 +278,44 @@ scmi_vendor_protocol_lookup(int protocol_id, char *vendor_id, | ||||||
| 	return proto; | 	return proto; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const struct scmi_protocol * | ||||||
|  | scmi_vendor_protocol_get(int protocol_id, struct scmi_revision_info *version) | ||||||
|  | { | ||||||
|  | 	const struct scmi_protocol *proto; | ||||||
|  | 
 | ||||||
|  | 	proto = scmi_vendor_protocol_lookup(protocol_id, version->vendor_id, | ||||||
|  | 					    version->sub_vendor_id, | ||||||
|  | 					    version->impl_ver); | ||||||
|  | 	if (!proto) { | ||||||
|  | 		int ret; | ||||||
|  | 
 | ||||||
|  | 		pr_debug("Looking for '" SCMI_VENDOR_MODULE_ALIAS_FMT "'\n", | ||||||
|  | 			 protocol_id, version->vendor_id); | ||||||
|  | 
 | ||||||
|  | 		/* Note that vendor_id is mandatory for vendor protocols */ | ||||||
|  | 		ret = request_module(SCMI_VENDOR_MODULE_ALIAS_FMT, | ||||||
|  | 				     protocol_id, version->vendor_id); | ||||||
|  | 		if (ret) { | ||||||
|  | 			pr_warn("Problem loading module for protocol 0x%x\n", | ||||||
|  | 				protocol_id); | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* Lookup again, once modules loaded */ | ||||||
|  | 		proto = scmi_vendor_protocol_lookup(protocol_id, | ||||||
|  | 						    version->vendor_id, | ||||||
|  | 						    version->sub_vendor_id, | ||||||
|  | 						    version->impl_ver); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (proto) | ||||||
|  | 		pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n", | ||||||
|  | 			protocol_id, proto->vendor_id ?: "", | ||||||
|  | 			proto->sub_vendor_id ?: "", proto->impl_ver); | ||||||
|  | 
 | ||||||
|  | 	return proto; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const struct scmi_protocol * | static const struct scmi_protocol * | ||||||
| scmi_protocol_get(int protocol_id, struct scmi_revision_info *version) | scmi_protocol_get(int protocol_id, struct scmi_revision_info *version) | ||||||
| { | { | ||||||
|  | @ -283,10 +324,8 @@ scmi_protocol_get(int protocol_id, struct scmi_revision_info *version) | ||||||
| 	if (protocol_id < SCMI_PROTOCOL_VENDOR_BASE) | 	if (protocol_id < SCMI_PROTOCOL_VENDOR_BASE) | ||||||
| 		proto = xa_load(&scmi_protocols, protocol_id); | 		proto = xa_load(&scmi_protocols, protocol_id); | ||||||
| 	else | 	else | ||||||
| 		proto = scmi_vendor_protocol_lookup(protocol_id, | 		proto = scmi_vendor_protocol_get(protocol_id, version); | ||||||
| 						    version->vendor_id, | 
 | ||||||
| 						    version->sub_vendor_id, |  | ||||||
| 						    version->impl_ver); |  | ||||||
| 	if (!proto || !try_module_get(proto->owner)) { | 	if (!proto || !try_module_get(proto->owner)) { | ||||||
| 		pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id); | 		pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id); | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  | @ -294,11 +333,6 @@ scmi_protocol_get(int protocol_id, struct scmi_revision_info *version) | ||||||
| 
 | 
 | ||||||
| 	pr_debug("Found SCMI Protocol 0x%x\n", protocol_id); | 	pr_debug("Found SCMI Protocol 0x%x\n", protocol_id); | ||||||
| 
 | 
 | ||||||
| 	if (protocol_id >= SCMI_PROTOCOL_VENDOR_BASE) |  | ||||||
| 		pr_info("Loaded SCMI Vendor Protocol 0x%x - %s %s %X\n", |  | ||||||
| 			protocol_id, proto->vendor_id ?: "", |  | ||||||
| 			proto->sub_vendor_id ?: "", proto->impl_ver); |  | ||||||
| 
 |  | ||||||
| 	return proto; | 	return proto; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -366,7 +400,9 @@ int scmi_protocol_register(const struct scmi_protocol *proto) | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	pr_debug("Registered SCMI Protocol 0x%x\n", proto->id); | 	pr_debug("Registered SCMI Protocol 0x%x - %s  %s  0x%08X\n", | ||||||
|  | 		 proto->id, proto->vendor_id, proto->sub_vendor_id, | ||||||
|  | 		 proto->impl_ver); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -3028,7 +3064,7 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	trans = dev_get_platdata(dev); | 	trans = dev_get_platdata(dev); | ||||||
| 	if (!trans || !trans->desc || !trans->supplier || !trans->core_ops) | 	if (!trans || !trans->supplier || !trans->core_ops) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!device_link_add(dev, trans->supplier, DL_FLAG_AUTOREMOVE_CONSUMER)) { | 	if (!device_link_add(dev, trans->supplier, DL_FLAG_AUTOREMOVE_CONSUMER)) { | ||||||
|  | @ -3043,33 +3079,33 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev) | ||||||
| 	dev_info(dev, "Using %s\n", dev_driver_string(trans->supplier)); | 	dev_info(dev, "Using %s\n", dev_driver_string(trans->supplier)); | ||||||
| 
 | 
 | ||||||
| 	ret = of_property_read_u32(dev->of_node, "arm,max-rx-timeout-ms", | 	ret = of_property_read_u32(dev->of_node, "arm,max-rx-timeout-ms", | ||||||
| 				   &trans->desc->max_rx_timeout_ms); | 				   &trans->desc.max_rx_timeout_ms); | ||||||
| 	if (ret && ret != -EINVAL) | 	if (ret && ret != -EINVAL) | ||||||
| 		dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n"); | 		dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n"); | ||||||
| 
 | 
 | ||||||
| 	ret = of_property_read_u32(dev->of_node, "arm,max-msg-size", | 	ret = of_property_read_u32(dev->of_node, "arm,max-msg-size", | ||||||
| 				   &trans->desc->max_msg_size); | 				   &trans->desc.max_msg_size); | ||||||
| 	if (ret && ret != -EINVAL) | 	if (ret && ret != -EINVAL) | ||||||
| 		dev_err(dev, "Malformed arm,max-msg-size DT property.\n"); | 		dev_err(dev, "Malformed arm,max-msg-size DT property.\n"); | ||||||
| 
 | 
 | ||||||
| 	ret = of_property_read_u32(dev->of_node, "arm,max-msg", | 	ret = of_property_read_u32(dev->of_node, "arm,max-msg", | ||||||
| 				   &trans->desc->max_msg); | 				   &trans->desc.max_msg); | ||||||
| 	if (ret && ret != -EINVAL) | 	if (ret && ret != -EINVAL) | ||||||
| 		dev_err(dev, "Malformed arm,max-msg DT property.\n"); | 		dev_err(dev, "Malformed arm,max-msg DT property.\n"); | ||||||
| 
 | 
 | ||||||
| 	dev_info(dev, | 	dev_info(dev, | ||||||
| 		 "SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n", | 		 "SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n", | ||||||
| 		 trans->desc->max_rx_timeout_ms, trans->desc->max_msg_size, | 		 trans->desc.max_rx_timeout_ms, trans->desc.max_msg_size, | ||||||
| 		 trans->desc->max_msg); | 		 trans->desc.max_msg); | ||||||
| 
 | 
 | ||||||
| 	/* System wide atomic threshold for atomic ops .. if any */ | 	/* System wide atomic threshold for atomic ops .. if any */ | ||||||
| 	if (!of_property_read_u32(dev->of_node, "atomic-threshold-us", | 	if (!of_property_read_u32(dev->of_node, "atomic-threshold-us", | ||||||
| 				  &trans->desc->atomic_threshold)) | 				  &trans->desc.atomic_threshold)) | ||||||
| 		dev_info(dev, | 		dev_info(dev, | ||||||
| 			 "SCMI System wide atomic threshold set to %u us\n", | 			 "SCMI System wide atomic threshold set to %u us\n", | ||||||
| 			 trans->desc->atomic_threshold); | 			 trans->desc.atomic_threshold); | ||||||
| 
 | 
 | ||||||
| 	return trans->desc; | 	return &trans->desc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int scmi_probe(struct platform_device *pdev) | static int scmi_probe(struct platform_device *pdev) | ||||||
|  |  | ||||||
|  | @ -378,6 +378,7 @@ static const struct of_device_id scmi_of_match[] = { | ||||||
| 	{ .compatible = "arm,scmi" }, | 	{ .compatible = "arm,scmi" }, | ||||||
| 	{ /* Sentinel */ }, | 	{ /* Sentinel */ }, | ||||||
| }; | }; | ||||||
|  | MODULE_DEVICE_TABLE(of, scmi_of_match); | ||||||
| 
 | 
 | ||||||
| DEFINE_SCMI_TRANSPORT_DRIVER(scmi_mailbox, scmi_mailbox_driver, | DEFINE_SCMI_TRANSPORT_DRIVER(scmi_mailbox, scmi_mailbox_driver, | ||||||
| 			     scmi_mailbox_desc, scmi_of_match, core); | 			     scmi_mailbox_desc, scmi_of_match, core); | ||||||
|  |  | ||||||
|  | @ -301,6 +301,7 @@ static const struct of_device_id scmi_of_match[] = { | ||||||
| 	{ .compatible = "qcom,scmi-smc" }, | 	{ .compatible = "qcom,scmi-smc" }, | ||||||
| 	{ /* Sentinel */ }, | 	{ /* Sentinel */ }, | ||||||
| }; | }; | ||||||
|  | MODULE_DEVICE_TABLE(of, scmi_of_match); | ||||||
| 
 | 
 | ||||||
| DEFINE_SCMI_TRANSPORT_DRIVER(scmi_smc, scmi_smc_driver, scmi_smc_desc, | DEFINE_SCMI_TRANSPORT_DRIVER(scmi_smc, scmi_smc_driver, scmi_smc_desc, | ||||||
| 			     scmi_of_match, core); | 			     scmi_of_match, core); | ||||||
|  |  | ||||||
|  | @ -921,6 +921,7 @@ static const struct virtio_device_id id_table[] = { | ||||||
| 	{ VIRTIO_ID_SCMI, VIRTIO_DEV_ANY_ID }, | 	{ VIRTIO_ID_SCMI, VIRTIO_DEV_ANY_ID }, | ||||||
| 	{ 0 } | 	{ 0 } | ||||||
| }; | }; | ||||||
|  | MODULE_DEVICE_TABLE(virtio, id_table); | ||||||
| 
 | 
 | ||||||
| static struct virtio_driver virtio_scmi_driver = { | static struct virtio_driver virtio_scmi_driver = { | ||||||
| 	.driver.name = "scmi-virtio", | 	.driver.name = "scmi-virtio", | ||||||
|  |  | ||||||
|  | @ -374,10 +374,11 @@ static const struct scmi_protocol scmi_imx_bbm = { | ||||||
| 	.ops = &scmi_imx_bbm_proto_ops, | 	.ops = &scmi_imx_bbm_proto_ops, | ||||||
| 	.events = &scmi_imx_bbm_protocol_events, | 	.events = &scmi_imx_bbm_protocol_events, | ||||||
| 	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, | 	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, | ||||||
| 	.vendor_id = "NXP", | 	.vendor_id = SCMI_IMX_VENDOR, | ||||||
| 	.sub_vendor_id = "IMX", | 	.sub_vendor_id = SCMI_IMX_SUBVENDOR, | ||||||
| }; | }; | ||||||
| module_scmi_protocol(scmi_imx_bbm); | module_scmi_protocol(scmi_imx_bbm); | ||||||
| 
 | 
 | ||||||
|  | MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_BBM) "-" SCMI_IMX_VENDOR); | ||||||
| MODULE_DESCRIPTION("i.MX SCMI BBM driver"); | MODULE_DESCRIPTION("i.MX SCMI BBM driver"); | ||||||
| MODULE_LICENSE("GPL"); | MODULE_LICENSE("GPL"); | ||||||
|  |  | ||||||
|  | @ -309,10 +309,11 @@ static const struct scmi_protocol scmi_imx_misc = { | ||||||
| 	.ops = &scmi_imx_misc_proto_ops, | 	.ops = &scmi_imx_misc_proto_ops, | ||||||
| 	.events = &scmi_imx_misc_protocol_events, | 	.events = &scmi_imx_misc_protocol_events, | ||||||
| 	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, | 	.supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, | ||||||
| 	.vendor_id = "NXP", | 	.vendor_id = SCMI_IMX_VENDOR, | ||||||
| 	.sub_vendor_id = "IMX", | 	.sub_vendor_id = SCMI_IMX_SUBVENDOR, | ||||||
| }; | }; | ||||||
| module_scmi_protocol(scmi_imx_misc); | module_scmi_protocol(scmi_imx_misc); | ||||||
| 
 | 
 | ||||||
|  | MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_IMX_MISC) "-" SCMI_IMX_VENDOR); | ||||||
| MODULE_DESCRIPTION("i.MX SCMI MISC driver"); | MODULE_DESCRIPTION("i.MX SCMI MISC driver"); | ||||||
| MODULE_LICENSE("GPL"); | MODULE_LICENSE("GPL"); | ||||||
|  |  | ||||||
|  | @ -152,7 +152,6 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, | ||||||
| 		   enum qcom_scm_convention qcom_convention, | 		   enum qcom_scm_convention qcom_convention, | ||||||
| 		   struct qcom_scm_res *res, bool atomic) | 		   struct qcom_scm_res *res, bool atomic) | ||||||
| { | { | ||||||
| 	struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool(); |  | ||||||
| 	int arglen = desc->arginfo & 0xf; | 	int arglen = desc->arginfo & 0xf; | ||||||
| 	int i, ret; | 	int i, ret; | ||||||
| 	void *args_virt __free(qcom_tzmem) = NULL; | 	void *args_virt __free(qcom_tzmem) = NULL; | ||||||
|  | @ -173,6 +172,11 @@ int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, | ||||||
| 		smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i]; | 		smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i]; | ||||||
| 
 | 
 | ||||||
| 	if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) { | 	if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) { | ||||||
|  | 		struct qcom_tzmem_pool *mempool = qcom_scm_get_tzmem_pool(); | ||||||
|  | 
 | ||||||
|  | 		if (!mempool) | ||||||
|  | 			return -EINVAL; | ||||||
|  | 
 | ||||||
| 		args_virt = qcom_tzmem_alloc(mempool, | 		args_virt = qcom_tzmem_alloc(mempool, | ||||||
| 					     SCM_SMC_N_EXT_ARGS * sizeof(u64), | 					     SCM_SMC_N_EXT_ARGS * sizeof(u64), | ||||||
| 					     flag); | 					     flag); | ||||||
|  |  | ||||||
|  | @ -217,7 +217,10 @@ static DEFINE_SPINLOCK(scm_query_lock); | ||||||
| 
 | 
 | ||||||
| struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void) | struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void) | ||||||
| { | { | ||||||
| 	return __scm ? __scm->mempool : NULL; | 	if (!qcom_scm_is_available()) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	return __scm->mempool; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static enum qcom_scm_convention __get_convention(void) | static enum qcom_scm_convention __get_convention(void) | ||||||
|  | @ -1279,6 +1282,220 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key); | EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key); | ||||||
| 
 | 
 | ||||||
|  | bool qcom_scm_has_wrapped_key_support(void) | ||||||
|  | { | ||||||
|  | 	return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, | ||||||
|  | 					    QCOM_SCM_ES_DERIVE_SW_SECRET) && | ||||||
|  | 	       __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, | ||||||
|  | 					    QCOM_SCM_ES_GENERATE_ICE_KEY) && | ||||||
|  | 	       __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, | ||||||
|  | 					    QCOM_SCM_ES_PREPARE_ICE_KEY) && | ||||||
|  | 	       __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES, | ||||||
|  | 					    QCOM_SCM_ES_IMPORT_ICE_KEY); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * qcom_scm_derive_sw_secret() - Derive software secret from wrapped key | ||||||
|  |  * @eph_key: an ephemerally-wrapped key | ||||||
|  |  * @eph_key_size: size of @eph_key in bytes | ||||||
|  |  * @sw_secret: output buffer for the software secret | ||||||
|  |  * @sw_secret_size: size of the software secret to derive in bytes | ||||||
|  |  * | ||||||
|  |  * Derive a software secret from an ephemerally-wrapped key for software crypto | ||||||
|  |  * operations.  This is done by calling into the secure execution environment, | ||||||
|  |  * which then calls into the hardware to unwrap and derive the secret. | ||||||
|  |  * | ||||||
|  |  * For more information on sw_secret, see the "Hardware-wrapped keys" section of | ||||||
|  |  * Documentation/block/inline-encryption.rst. | ||||||
|  |  * | ||||||
|  |  * Return: 0 on success; -errno on failure. | ||||||
|  |  */ | ||||||
|  | int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size, | ||||||
|  | 			      u8 *sw_secret, size_t sw_secret_size) | ||||||
|  | { | ||||||
|  | 	struct qcom_scm_desc desc = { | ||||||
|  | 		.svc = QCOM_SCM_SVC_ES, | ||||||
|  | 		.cmd = QCOM_SCM_ES_DERIVE_SW_SECRET, | ||||||
|  | 		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, | ||||||
|  | 					 QCOM_SCM_RW, QCOM_SCM_VAL), | ||||||
|  | 		.owner = ARM_SMCCC_OWNER_SIP, | ||||||
|  | 	}; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	void *eph_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, | ||||||
|  | 								eph_key_size, | ||||||
|  | 								GFP_KERNEL); | ||||||
|  | 	if (!eph_key_buf) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	void *sw_secret_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, | ||||||
|  | 								  sw_secret_size, | ||||||
|  | 								  GFP_KERNEL); | ||||||
|  | 	if (!sw_secret_buf) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	memcpy(eph_key_buf, eph_key, eph_key_size); | ||||||
|  | 	desc.args[0] = qcom_tzmem_to_phys(eph_key_buf); | ||||||
|  | 	desc.args[1] = eph_key_size; | ||||||
|  | 	desc.args[2] = qcom_tzmem_to_phys(sw_secret_buf); | ||||||
|  | 	desc.args[3] = sw_secret_size; | ||||||
|  | 
 | ||||||
|  | 	ret = qcom_scm_call(__scm->dev, &desc, NULL); | ||||||
|  | 	if (!ret) | ||||||
|  | 		memcpy(sw_secret, sw_secret_buf, sw_secret_size); | ||||||
|  | 
 | ||||||
|  | 	memzero_explicit(eph_key_buf, eph_key_size); | ||||||
|  | 	memzero_explicit(sw_secret_buf, sw_secret_size); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * qcom_scm_generate_ice_key() - Generate a wrapped key for storage encryption | ||||||
|  |  * @lt_key: output buffer for the long-term wrapped key | ||||||
|  |  * @lt_key_size: size of @lt_key in bytes.  Must be the exact wrapped key size | ||||||
|  |  *		 used by the SoC. | ||||||
|  |  * | ||||||
|  |  * Generate a key using the built-in HW module in the SoC.  The resulting key is | ||||||
|  |  * returned wrapped with the platform-specific Key Encryption Key. | ||||||
|  |  * | ||||||
|  |  * Return: 0 on success; -errno on failure. | ||||||
|  |  */ | ||||||
|  | int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size) | ||||||
|  | { | ||||||
|  | 	struct qcom_scm_desc desc = { | ||||||
|  | 		.svc = QCOM_SCM_SVC_ES, | ||||||
|  | 		.cmd =  QCOM_SCM_ES_GENERATE_ICE_KEY, | ||||||
|  | 		.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL), | ||||||
|  | 		.owner = ARM_SMCCC_OWNER_SIP, | ||||||
|  | 	}; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, | ||||||
|  | 							       lt_key_size, | ||||||
|  | 							       GFP_KERNEL); | ||||||
|  | 	if (!lt_key_buf) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	desc.args[0] = qcom_tzmem_to_phys(lt_key_buf); | ||||||
|  | 	desc.args[1] = lt_key_size; | ||||||
|  | 
 | ||||||
|  | 	ret = qcom_scm_call(__scm->dev, &desc, NULL); | ||||||
|  | 	if (!ret) | ||||||
|  | 		memcpy(lt_key, lt_key_buf, lt_key_size); | ||||||
|  | 
 | ||||||
|  | 	memzero_explicit(lt_key_buf, lt_key_size); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * qcom_scm_prepare_ice_key() - Re-wrap a key with the per-boot ephemeral key | ||||||
|  |  * @lt_key: a long-term wrapped key | ||||||
|  |  * @lt_key_size: size of @lt_key in bytes | ||||||
|  |  * @eph_key: output buffer for the ephemerally-wrapped key | ||||||
|  |  * @eph_key_size: size of @eph_key in bytes.  Must be the exact wrapped key size | ||||||
|  |  *		  used by the SoC. | ||||||
|  |  * | ||||||
|  |  * Given a long-term wrapped key, re-wrap it with the per-boot ephemeral key for | ||||||
|  |  * added protection.  The resulting key will only be valid for the current boot. | ||||||
|  |  * | ||||||
|  |  * Return: 0 on success; -errno on failure. | ||||||
|  |  */ | ||||||
|  | int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size, | ||||||
|  | 			     u8 *eph_key, size_t eph_key_size) | ||||||
|  | { | ||||||
|  | 	struct qcom_scm_desc desc = { | ||||||
|  | 		.svc = QCOM_SCM_SVC_ES, | ||||||
|  | 		.cmd =  QCOM_SCM_ES_PREPARE_ICE_KEY, | ||||||
|  | 		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, QCOM_SCM_VAL, | ||||||
|  | 					 QCOM_SCM_RW, QCOM_SCM_VAL), | ||||||
|  | 		.owner = ARM_SMCCC_OWNER_SIP, | ||||||
|  | 	}; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, | ||||||
|  | 							       lt_key_size, | ||||||
|  | 							       GFP_KERNEL); | ||||||
|  | 	if (!lt_key_buf) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	void *eph_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, | ||||||
|  | 								eph_key_size, | ||||||
|  | 								GFP_KERNEL); | ||||||
|  | 	if (!eph_key_buf) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	memcpy(lt_key_buf, lt_key, lt_key_size); | ||||||
|  | 	desc.args[0] = qcom_tzmem_to_phys(lt_key_buf); | ||||||
|  | 	desc.args[1] = lt_key_size; | ||||||
|  | 	desc.args[2] = qcom_tzmem_to_phys(eph_key_buf); | ||||||
|  | 	desc.args[3] = eph_key_size; | ||||||
|  | 
 | ||||||
|  | 	ret = qcom_scm_call(__scm->dev, &desc, NULL); | ||||||
|  | 	if (!ret) | ||||||
|  | 		memcpy(eph_key, eph_key_buf, eph_key_size); | ||||||
|  | 
 | ||||||
|  | 	memzero_explicit(lt_key_buf, lt_key_size); | ||||||
|  | 	memzero_explicit(eph_key_buf, eph_key_size); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * qcom_scm_import_ice_key() - Import key for storage encryption | ||||||
|  |  * @raw_key: the raw key to import | ||||||
|  |  * @raw_key_size: size of @raw_key in bytes | ||||||
|  |  * @lt_key: output buffer for the long-term wrapped key | ||||||
|  |  * @lt_key_size: size of @lt_key in bytes.  Must be the exact wrapped key size | ||||||
|  |  *		 used by the SoC. | ||||||
|  |  * | ||||||
|  |  * Import a raw key and return a long-term wrapped key.  Uses the SoC's HWKM to | ||||||
|  |  * wrap the raw key using the platform-specific Key Encryption Key. | ||||||
|  |  * | ||||||
|  |  * Return: 0 on success; -errno on failure. | ||||||
|  |  */ | ||||||
|  | int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size, | ||||||
|  | 			    u8 *lt_key, size_t lt_key_size) | ||||||
|  | { | ||||||
|  | 	struct qcom_scm_desc desc = { | ||||||
|  | 		.svc = QCOM_SCM_SVC_ES, | ||||||
|  | 		.cmd =  QCOM_SCM_ES_IMPORT_ICE_KEY, | ||||||
|  | 		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, QCOM_SCM_VAL, | ||||||
|  | 					 QCOM_SCM_RW, QCOM_SCM_VAL), | ||||||
|  | 		.owner = ARM_SMCCC_OWNER_SIP, | ||||||
|  | 	}; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	void *raw_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, | ||||||
|  | 								raw_key_size, | ||||||
|  | 								GFP_KERNEL); | ||||||
|  | 	if (!raw_key_buf) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	void *lt_key_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, | ||||||
|  | 							       lt_key_size, | ||||||
|  | 							       GFP_KERNEL); | ||||||
|  | 	if (!lt_key_buf) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	memcpy(raw_key_buf, raw_key, raw_key_size); | ||||||
|  | 	desc.args[0] = qcom_tzmem_to_phys(raw_key_buf); | ||||||
|  | 	desc.args[1] = raw_key_size; | ||||||
|  | 	desc.args[2] = qcom_tzmem_to_phys(lt_key_buf); | ||||||
|  | 	desc.args[3] = lt_key_size; | ||||||
|  | 
 | ||||||
|  | 	ret = qcom_scm_call(__scm->dev, &desc, NULL); | ||||||
|  | 	if (!ret) | ||||||
|  | 		memcpy(lt_key, lt_key_buf, lt_key_size); | ||||||
|  | 
 | ||||||
|  | 	memzero_explicit(raw_key_buf, raw_key_size); | ||||||
|  | 	memzero_explicit(lt_key_buf, lt_key_size); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. |  * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. | ||||||
|  * |  * | ||||||
|  | @ -1768,18 +1985,23 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send); | ||||||
|  + any potential issues with this, only allow validated machines for now. |  + any potential issues with this, only allow validated machines for now. | ||||||
|  */ |  */ | ||||||
| static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { | static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { | ||||||
|  | 	{ .compatible = "asus,vivobook-s15" }, | ||||||
| 	{ .compatible = "dell,xps13-9345" }, | 	{ .compatible = "dell,xps13-9345" }, | ||||||
|  | 	{ .compatible = "hp,omnibook-x14" }, | ||||||
|  | 	{ .compatible = "huawei,gaokun3" }, | ||||||
| 	{ .compatible = "lenovo,flex-5g" }, | 	{ .compatible = "lenovo,flex-5g" }, | ||||||
| 	{ .compatible = "lenovo,thinkpad-t14s" }, | 	{ .compatible = "lenovo,thinkpad-t14s" }, | ||||||
| 	{ .compatible = "lenovo,thinkpad-x13s", }, | 	{ .compatible = "lenovo,thinkpad-x13s", }, | ||||||
| 	{ .compatible = "lenovo,yoga-slim7x" }, | 	{ .compatible = "lenovo,yoga-slim7x" }, | ||||||
| 	{ .compatible = "microsoft,arcata", }, | 	{ .compatible = "microsoft,arcata", }, | ||||||
|  | 	{ .compatible = "microsoft,blackrock" }, | ||||||
| 	{ .compatible = "microsoft,romulus13", }, | 	{ .compatible = "microsoft,romulus13", }, | ||||||
| 	{ .compatible = "microsoft,romulus15", }, | 	{ .compatible = "microsoft,romulus15", }, | ||||||
| 	{ .compatible = "qcom,sc8180x-primus" }, | 	{ .compatible = "qcom,sc8180x-primus" }, | ||||||
| 	{ .compatible = "qcom,x1e001de-devkit" }, | 	{ .compatible = "qcom,x1e001de-devkit" }, | ||||||
| 	{ .compatible = "qcom,x1e80100-crd" }, | 	{ .compatible = "qcom,x1e80100-crd" }, | ||||||
| 	{ .compatible = "qcom,x1e80100-qcp" }, | 	{ .compatible = "qcom,x1e80100-qcp" }, | ||||||
|  | 	{ .compatible = "qcom,x1p42100-crd" }, | ||||||
| 	{ } | 	{ } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -1867,7 +2089,8 @@ static int qcom_scm_qseecom_init(struct qcom_scm *scm) | ||||||
|  */ |  */ | ||||||
| bool qcom_scm_is_available(void) | bool qcom_scm_is_available(void) | ||||||
| { | { | ||||||
| 	return !!READ_ONCE(__scm); | 	/* Paired with smp_store_release() in qcom_scm_probe */ | ||||||
|  | 	return !!smp_load_acquire(&__scm); | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(qcom_scm_is_available); | EXPORT_SYMBOL_GPL(qcom_scm_is_available); | ||||||
| 
 | 
 | ||||||
|  | @ -2024,18 +2247,22 @@ static int qcom_scm_probe(struct platform_device *pdev) | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	/* Let all above stores be available after this */ | 	/* Paired with smp_load_acquire() in qcom_scm_is_available(). */ | ||||||
| 	smp_store_release(&__scm, scm); | 	smp_store_release(&__scm, scm); | ||||||
| 
 | 
 | ||||||
| 	irq = platform_get_irq_optional(pdev, 0); | 	irq = platform_get_irq_optional(pdev, 0); | ||||||
| 	if (irq < 0) { | 	if (irq < 0) { | ||||||
| 		if (irq != -ENXIO) | 		if (irq != -ENXIO) { | ||||||
| 			return irq; | 			ret = irq; | ||||||
|  | 			goto err; | ||||||
|  | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler, | 		ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler, | ||||||
| 						IRQF_ONESHOT, "qcom-scm", __scm); | 						IRQF_ONESHOT, "qcom-scm", __scm); | ||||||
| 		if (ret < 0) | 		if (ret < 0) { | ||||||
| 			return dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n"); | 			dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n"); | ||||||
|  | 			goto err; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	__get_convention(); | 	__get_convention(); | ||||||
|  | @ -2054,14 +2281,18 @@ static int qcom_scm_probe(struct platform_device *pdev) | ||||||
| 		qcom_scm_disable_sdi(); | 		qcom_scm_disable_sdi(); | ||||||
| 
 | 
 | ||||||
| 	ret = of_reserved_mem_device_init(__scm->dev); | 	ret = of_reserved_mem_device_init(__scm->dev); | ||||||
| 	if (ret && ret != -ENODEV) | 	if (ret && ret != -ENODEV) { | ||||||
| 		return dev_err_probe(__scm->dev, ret, | 		dev_err_probe(__scm->dev, ret, | ||||||
| 				     "Failed to setup the reserved memory region for TZ mem\n"); | 			      "Failed to setup the reserved memory region for TZ mem\n"); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = qcom_tzmem_enable(__scm->dev); | 	ret = qcom_tzmem_enable(__scm->dev); | ||||||
| 	if (ret) | 	if (ret) { | ||||||
| 		return dev_err_probe(__scm->dev, ret, | 		dev_err_probe(__scm->dev, ret, | ||||||
| 				     "Failed to enable the TrustZone memory allocator\n"); | 			      "Failed to enable the TrustZone memory allocator\n"); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	memset(&pool_config, 0, sizeof(pool_config)); | 	memset(&pool_config, 0, sizeof(pool_config)); | ||||||
| 	pool_config.initial_size = 0; | 	pool_config.initial_size = 0; | ||||||
|  | @ -2069,9 +2300,11 @@ static int qcom_scm_probe(struct platform_device *pdev) | ||||||
| 	pool_config.max_size = SZ_256K; | 	pool_config.max_size = SZ_256K; | ||||||
| 
 | 
 | ||||||
| 	__scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config); | 	__scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config); | ||||||
| 	if (IS_ERR(__scm->mempool)) | 	if (IS_ERR(__scm->mempool)) { | ||||||
| 		return dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool), | 		dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool), | ||||||
| 				     "Failed to create the SCM memory pool\n"); | 			      "Failed to create the SCM memory pool\n"); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Initialize the QSEECOM interface. | 	 * Initialize the QSEECOM interface. | ||||||
|  | @ -2087,6 +2320,12 @@ static int qcom_scm_probe(struct platform_device *pdev) | ||||||
| 	WARN(ret < 0, "failed to initialize qseecom: %d\n", ret); | 	WARN(ret < 0, "failed to initialize qseecom: %d\n", ret); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | 
 | ||||||
|  | err: | ||||||
|  | 	/* Paired with smp_load_acquire() in qcom_scm_is_available(). */ | ||||||
|  | 	smp_store_release(&__scm, NULL); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void qcom_scm_shutdown(struct platform_device *pdev) | static void qcom_scm_shutdown(struct platform_device *pdev) | ||||||
|  |  | ||||||
|  | @ -128,6 +128,10 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void); | ||||||
| #define QCOM_SCM_SVC_ES			0x10	/* Enterprise Security */ | #define QCOM_SCM_SVC_ES			0x10	/* Enterprise Security */ | ||||||
| #define QCOM_SCM_ES_INVALIDATE_ICE_KEY	0x03 | #define QCOM_SCM_ES_INVALIDATE_ICE_KEY	0x03 | ||||||
| #define QCOM_SCM_ES_CONFIG_SET_ICE_KEY	0x04 | #define QCOM_SCM_ES_CONFIG_SET_ICE_KEY	0x04 | ||||||
|  | #define QCOM_SCM_ES_DERIVE_SW_SECRET	0x07 | ||||||
|  | #define QCOM_SCM_ES_GENERATE_ICE_KEY	0x08 | ||||||
|  | #define QCOM_SCM_ES_PREPARE_ICE_KEY	0x09 | ||||||
|  | #define QCOM_SCM_ES_IMPORT_ICE_KEY	0x0a | ||||||
| 
 | 
 | ||||||
| #define QCOM_SCM_SVC_HDCP		0x11 | #define QCOM_SCM_SVC_HDCP		0x11 | ||||||
| #define QCOM_SCM_HDCP_INVOKE		0x01 | #define QCOM_SCM_HDCP_INVOKE		0x01 | ||||||
|  |  | ||||||
|  | @ -358,17 +358,6 @@ static unsigned int gpmc_ps_to_ticks(unsigned int time_ps) | ||||||
| 	return (time_ps + tick_ps - 1) / tick_ps; | 	return (time_ps + tick_ps - 1) / tick_ps; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static unsigned int gpmc_clk_ticks_to_ns(unsigned int ticks, int cs, |  | ||||||
| 					 enum gpmc_clk_domain cd) |  | ||||||
| { |  | ||||||
| 	return ticks * gpmc_get_clk_period(cs, cd) / 1000; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| unsigned int gpmc_ticks_to_ns(unsigned int ticks) |  | ||||||
| { |  | ||||||
| 	return gpmc_clk_ticks_to_ns(ticks, /* any CS */ 0, GPMC_CD_FCLK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned int gpmc_ticks_to_ps(unsigned int ticks) | static unsigned int gpmc_ticks_to_ps(unsigned int ticks) | ||||||
| { | { | ||||||
| 	return ticks * gpmc_get_fclk_period(); | 	return ticks * gpmc_get_fclk_period(); | ||||||
|  | @ -415,6 +404,13 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_OMAP_GPMC_DEBUG | #ifdef CONFIG_OMAP_GPMC_DEBUG | ||||||
|  | 
 | ||||||
|  | static unsigned int gpmc_clk_ticks_to_ns(unsigned int ticks, int cs, | ||||||
|  | 					 enum gpmc_clk_domain cd) | ||||||
|  | { | ||||||
|  | 	return ticks * gpmc_get_clk_period(cs, cd) / 1000; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * get_gpmc_timing_reg - read a timing parameter and print DTS settings for it. |  * get_gpmc_timing_reg - read a timing parameter and print DTS settings for it. | ||||||
|  * @cs:      Chip Select Region |  * @cs:      Chip Select Region | ||||||
|  | @ -1295,21 +1291,6 @@ int gpmc_omap_onenand_set_timings(struct device *dev, int cs, int freq, | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(gpmc_omap_onenand_set_timings); | EXPORT_SYMBOL_GPL(gpmc_omap_onenand_set_timings); | ||||||
| 
 | 
 | ||||||
| int gpmc_get_client_irq(unsigned int irq_config) |  | ||||||
| { |  | ||||||
| 	if (!gpmc_irq_domain) { |  | ||||||
| 		pr_warn("%s called before GPMC IRQ domain available\n", |  | ||||||
| 			__func__); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* we restrict this to NAND IRQs only */ |  | ||||||
| 	if (irq_config >= GPMC_NR_NAND_IRQS) |  | ||||||
| 		return 0; |  | ||||||
| 
 |  | ||||||
| 	return irq_create_mapping(gpmc_irq_domain, irq_config); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int gpmc_irq_endis(unsigned long hwirq, bool endis) | static int gpmc_irq_endis(unsigned long hwirq, bool endis) | ||||||
| { | { | ||||||
| 	u32 regval; | 	u32 regval; | ||||||
|  |  | ||||||
|  | @ -474,14 +474,15 @@ tegra_emc_find_node_by_ram_code(struct tegra_emc *emc) | ||||||
| 
 | 
 | ||||||
| 	ram_code = tegra_read_ram_code(); | 	ram_code = tegra_read_ram_code(); | ||||||
| 
 | 
 | ||||||
| 	for (np = of_find_node_by_name(dev->of_node, "emc-tables"); np; | 	for_each_child_of_node(dev->of_node, np) { | ||||||
| 	     np = of_find_node_by_name(np, "emc-tables")) { | 		if (!of_node_name_eq(np, "emc-tables")) | ||||||
|  | 			continue; | ||||||
| 		err = of_property_read_u32(np, "nvidia,ram-code", &value); | 		err = of_property_read_u32(np, "nvidia,ram-code", &value); | ||||||
| 		if (err || value != ram_code) { | 		if (err || value != ram_code) { | ||||||
| 			struct device_node *lpddr2_np; | 			struct device_node *lpddr2_np; | ||||||
| 			bool cfg_mismatches = false; | 			bool cfg_mismatches = false; | ||||||
| 
 | 
 | ||||||
| 			lpddr2_np = of_find_node_by_name(np, "lpddr2"); | 			lpddr2_np = of_get_child_by_name(np, "lpddr2"); | ||||||
| 			if (lpddr2_np) { | 			if (lpddr2_np) { | ||||||
| 				const struct lpddr2_info *info; | 				const struct lpddr2_info *info; | ||||||
| 
 | 
 | ||||||
|  | @ -518,7 +519,6 @@ tegra_emc_find_node_by_ram_code(struct tegra_emc *emc) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (cfg_mismatches) { | 			if (cfg_mismatches) { | ||||||
| 				of_node_put(np); |  | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -13,7 +13,9 @@ | ||||||
| #include <linux/err.h> | #include <linux/err.h> | ||||||
| #include <linux/io.h> | #include <linux/io.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
|  | #include <linux/memory/ti-aemif.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
|  | #include <linux/mutex.h> | ||||||
| #include <linux/of.h> | #include <linux/of.h> | ||||||
| #include <linux/of_platform.h> | #include <linux/of_platform.h> | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
|  | @ -69,39 +71,27 @@ | ||||||
| #define ACR_SSTROBE_MASK	BIT(31) | #define ACR_SSTROBE_MASK	BIT(31) | ||||||
| #define ASIZE_16BIT	1 | #define ASIZE_16BIT	1 | ||||||
| 
 | 
 | ||||||
| #define CONFIG_MASK	(TA(TA_MAX) | \ | #define TIMINGS_MASK	(TA(TA_MAX) | \ | ||||||
| 				RHOLD(RHOLD_MAX) | \ | 			RHOLD(RHOLD_MAX) | \ | ||||||
| 				RSTROBE(RSTROBE_MAX) |	\ | 			RSTROBE(RSTROBE_MAX) |	\ | ||||||
| 				RSETUP(RSETUP_MAX) | \ | 			RSETUP(RSETUP_MAX) | \ | ||||||
| 				WHOLD(WHOLD_MAX) | \ | 			WHOLD(WHOLD_MAX) | \ | ||||||
| 				WSTROBE(WSTROBE_MAX) | \ | 			WSTROBE(WSTROBE_MAX) | \ | ||||||
| 				WSETUP(WSETUP_MAX) | \ | 			WSETUP(WSETUP_MAX)) | ||||||
| 				EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | \ | 
 | ||||||
| 				ASIZE_MAX) | #define CONFIG_MASK	(EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | ASIZE_MAX) | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * struct aemif_cs_data: structure to hold cs parameters |  * struct aemif_cs_data: structure to hold CS parameters | ||||||
|  |  * @timings: timings configuration | ||||||
|  * @cs: chip-select number |  * @cs: chip-select number | ||||||
|  * @wstrobe: write strobe width, ns |  | ||||||
|  * @rstrobe: read strobe width, ns |  | ||||||
|  * @wsetup: write setup width, ns |  | ||||||
|  * @whold: write hold width, ns |  | ||||||
|  * @rsetup: read setup width, ns |  | ||||||
|  * @rhold: read hold width, ns |  | ||||||
|  * @ta: minimum turn around time, ns |  | ||||||
|  * @enable_ss: enable/disable select strobe mode |  * @enable_ss: enable/disable select strobe mode | ||||||
|  * @enable_ew: enable/disable extended wait mode |  * @enable_ew: enable/disable extended wait mode | ||||||
|  * @asize: width of the asynchronous device's data bus |  * @asize: width of the asynchronous device's data bus | ||||||
|  */ |  */ | ||||||
| struct aemif_cs_data { | struct aemif_cs_data { | ||||||
|  | 	struct aemif_cs_timings timings; | ||||||
| 	u8	cs; | 	u8	cs; | ||||||
| 	u16	wstrobe; |  | ||||||
| 	u16	rstrobe; |  | ||||||
| 	u8	wsetup; |  | ||||||
| 	u8	whold; |  | ||||||
| 	u8	rsetup; |  | ||||||
| 	u8	rhold; |  | ||||||
| 	u8	ta; |  | ||||||
| 	u8	enable_ss; | 	u8	enable_ss; | ||||||
| 	u8	enable_ew; | 	u8	enable_ew; | ||||||
| 	u8	asize; | 	u8	asize; | ||||||
|  | @ -115,6 +105,7 @@ struct aemif_cs_data { | ||||||
|  * @num_cs: number of assigned chip-selects |  * @num_cs: number of assigned chip-selects | ||||||
|  * @cs_offset: start number of cs nodes |  * @cs_offset: start number of cs nodes | ||||||
|  * @cs_data: array of chip-select settings |  * @cs_data: array of chip-select settings | ||||||
|  |  * @config_cs_lock: lock used to access CS configuration | ||||||
|  */ |  */ | ||||||
| struct aemif_device { | struct aemif_device { | ||||||
| 	void __iomem *base; | 	void __iomem *base; | ||||||
|  | @ -123,20 +114,94 @@ struct aemif_device { | ||||||
| 	u8 num_cs; | 	u8 num_cs; | ||||||
| 	int cs_offset; | 	int cs_offset; | ||||||
| 	struct aemif_cs_data cs_data[NUM_CS]; | 	struct aemif_cs_data cs_data[NUM_CS]; | ||||||
|  | 	struct mutex config_cs_lock; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * aemif_check_cs_timings() - Check the validity of a CS timing configuration. | ||||||
|  |  * @timings: timings configuration | ||||||
|  |  * | ||||||
|  |  * @return: 0 if the timing configuration is valid, negative error number otherwise. | ||||||
|  |  */ | ||||||
|  | int aemif_check_cs_timings(struct aemif_cs_timings *timings) | ||||||
|  | { | ||||||
|  | 	if (timings->ta > TA_MAX) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (timings->rhold > RHOLD_MAX) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (timings->rstrobe > RSTROBE_MAX) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (timings->rsetup > RSETUP_MAX) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (timings->whold > WHOLD_MAX) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (timings->wstrobe > WSTROBE_MAX) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (timings->wsetup > WSETUP_MAX) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(aemif_check_cs_timings); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * aemif_set_cs_timings() - Set the timing configuration of a given chip select. | ||||||
|  |  * @aemif: aemif device to configure | ||||||
|  |  * @cs: index of the chip select to configure | ||||||
|  |  * @timings: timings configuration to set | ||||||
|  |  * | ||||||
|  |  * @return: 0 on success, else negative errno. | ||||||
|  |  */ | ||||||
|  | int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, | ||||||
|  | 			 struct aemif_cs_timings *timings) | ||||||
|  | { | ||||||
|  | 	unsigned int offset; | ||||||
|  | 	u32 val, set; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	if (!timings || !aemif) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (cs > aemif->num_cs) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	ret = aemif_check_cs_timings(timings); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	set = TA(timings->ta) | RHOLD(timings->rhold) | RSTROBE(timings->rstrobe) | | ||||||
|  | 	      RSETUP(timings->rsetup) | WHOLD(timings->whold) | | ||||||
|  | 	      WSTROBE(timings->wstrobe) | WSETUP(timings->wsetup); | ||||||
|  | 
 | ||||||
|  | 	offset = A1CR_OFFSET + cs * 4; | ||||||
|  | 
 | ||||||
|  | 	mutex_lock(&aemif->config_cs_lock); | ||||||
|  | 	val = readl(aemif->base + offset); | ||||||
|  | 	val &= ~TIMINGS_MASK; | ||||||
|  | 	val |= set; | ||||||
|  | 	writel(val, aemif->base + offset); | ||||||
|  | 	mutex_unlock(&aemif->config_cs_lock); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(aemif_set_cs_timings); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * aemif_calc_rate - calculate timing data. |  * aemif_calc_rate - calculate timing data. | ||||||
|  * @pdev: platform device to calculate for |  * @pdev: platform device to calculate for | ||||||
|  * @wanted: The cycle time needed in nanoseconds. |  * @wanted: The cycle time needed in nanoseconds. | ||||||
|  * @clk: The input clock rate in kHz. |  * @clk: The input clock rate in kHz. | ||||||
|  * @max: The maximum divider value that can be programmed. |  | ||||||
|  * |  * | ||||||
|  * On success, returns the calculated timing value minus 1 for easy |  * @return: the calculated timing value minus 1 for easy | ||||||
|  * programming into AEMIF timing registers, else negative errno. |  * programming into AEMIF timing registers. | ||||||
|  */ |  */ | ||||||
| static int aemif_calc_rate(struct platform_device *pdev, int wanted, | static u32 aemif_calc_rate(struct platform_device *pdev, int wanted, unsigned long clk) | ||||||
| 			   unsigned long clk, int max) |  | ||||||
| { | { | ||||||
| 	int result; | 	int result; | ||||||
| 
 | 
 | ||||||
|  | @ -149,10 +214,6 @@ static int aemif_calc_rate(struct platform_device *pdev, int wanted, | ||||||
| 	if (result < 0) | 	if (result < 0) | ||||||
| 		result = 0; | 		result = 0; | ||||||
| 
 | 
 | ||||||
| 	/* ... But configuring tighter timings is not an option. */ |  | ||||||
| 	else if (result > max) |  | ||||||
| 		result = -EINVAL; |  | ||||||
| 
 |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -174,48 +235,25 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum) | ||||||
| { | { | ||||||
| 	struct aemif_device *aemif = platform_get_drvdata(pdev); | 	struct aemif_device *aemif = platform_get_drvdata(pdev); | ||||||
| 	struct aemif_cs_data *data = &aemif->cs_data[csnum]; | 	struct aemif_cs_data *data = &aemif->cs_data[csnum]; | ||||||
| 	int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; |  | ||||||
| 	unsigned long clk_rate = aemif->clk_rate; |  | ||||||
| 	unsigned offset; | 	unsigned offset; | ||||||
| 	u32 set, val; | 	u32 set, val; | ||||||
| 
 | 
 | ||||||
| 	offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; | 	offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; | ||||||
| 
 | 
 | ||||||
| 	ta	= aemif_calc_rate(pdev, data->ta, clk_rate, TA_MAX); | 	set = (data->asize & ACR_ASIZE_MASK); | ||||||
| 	rhold	= aemif_calc_rate(pdev, data->rhold, clk_rate, RHOLD_MAX); |  | ||||||
| 	rstrobe	= aemif_calc_rate(pdev, data->rstrobe, clk_rate, RSTROBE_MAX); |  | ||||||
| 	rsetup	= aemif_calc_rate(pdev, data->rsetup, clk_rate, RSETUP_MAX); |  | ||||||
| 	whold	= aemif_calc_rate(pdev, data->whold, clk_rate, WHOLD_MAX); |  | ||||||
| 	wstrobe	= aemif_calc_rate(pdev, data->wstrobe, clk_rate, WSTROBE_MAX); |  | ||||||
| 	wsetup	= aemif_calc_rate(pdev, data->wsetup, clk_rate, WSETUP_MAX); |  | ||||||
| 
 |  | ||||||
| 	if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 || |  | ||||||
| 	    whold < 0 || wstrobe < 0 || wsetup < 0) { |  | ||||||
| 		dev_err(&pdev->dev, "%s: cannot get suitable timings\n", |  | ||||||
| 			__func__); |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) | |  | ||||||
| 		WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup); |  | ||||||
| 
 |  | ||||||
| 	set |= (data->asize & ACR_ASIZE_MASK); |  | ||||||
| 	if (data->enable_ew) | 	if (data->enable_ew) | ||||||
| 		set |= ACR_EW_MASK; | 		set |= ACR_EW_MASK; | ||||||
| 	if (data->enable_ss) | 	if (data->enable_ss) | ||||||
| 		set |= ACR_SSTROBE_MASK; | 		set |= ACR_SSTROBE_MASK; | ||||||
| 
 | 
 | ||||||
|  | 	mutex_lock(&aemif->config_cs_lock); | ||||||
| 	val = readl(aemif->base + offset); | 	val = readl(aemif->base + offset); | ||||||
| 	val &= ~CONFIG_MASK; | 	val &= ~CONFIG_MASK; | ||||||
| 	val |= set; | 	val |= set; | ||||||
| 	writel(val, aemif->base + offset); | 	writel(val, aemif->base + offset); | ||||||
|  | 	mutex_unlock(&aemif->config_cs_lock); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return aemif_set_cs_timings(aemif, data->cs - aemif->cs_offset, &data->timings); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline int aemif_cycles_to_nsec(int val, unsigned long clk_rate) |  | ||||||
| { |  | ||||||
| 	return ((val + 1) * NSEC_PER_MSEC) / clk_rate; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -231,19 +269,18 @@ static void aemif_get_hw_params(struct platform_device *pdev, int csnum) | ||||||
| { | { | ||||||
| 	struct aemif_device *aemif = platform_get_drvdata(pdev); | 	struct aemif_device *aemif = platform_get_drvdata(pdev); | ||||||
| 	struct aemif_cs_data *data = &aemif->cs_data[csnum]; | 	struct aemif_cs_data *data = &aemif->cs_data[csnum]; | ||||||
| 	unsigned long clk_rate = aemif->clk_rate; |  | ||||||
| 	u32 val, offset; | 	u32 val, offset; | ||||||
| 
 | 
 | ||||||
| 	offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; | 	offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; | ||||||
| 	val = readl(aemif->base + offset); | 	val = readl(aemif->base + offset); | ||||||
| 
 | 
 | ||||||
| 	data->ta = aemif_cycles_to_nsec(TA_VAL(val), clk_rate); | 	data->timings.ta = TA_VAL(val); | ||||||
| 	data->rhold = aemif_cycles_to_nsec(RHOLD_VAL(val), clk_rate); | 	data->timings.rhold = RHOLD_VAL(val); | ||||||
| 	data->rstrobe = aemif_cycles_to_nsec(RSTROBE_VAL(val), clk_rate); | 	data->timings.rstrobe = RSTROBE_VAL(val); | ||||||
| 	data->rsetup = aemif_cycles_to_nsec(RSETUP_VAL(val), clk_rate); | 	data->timings.rsetup = RSETUP_VAL(val); | ||||||
| 	data->whold = aemif_cycles_to_nsec(WHOLD_VAL(val), clk_rate); | 	data->timings.whold = WHOLD_VAL(val); | ||||||
| 	data->wstrobe = aemif_cycles_to_nsec(WSTROBE_VAL(val), clk_rate); | 	data->timings.wstrobe = WSTROBE_VAL(val); | ||||||
| 	data->wsetup = aemif_cycles_to_nsec(WSETUP_VAL(val), clk_rate); | 	data->timings.wsetup = WSETUP_VAL(val); | ||||||
| 	data->enable_ew = EW_VAL(val); | 	data->enable_ew = EW_VAL(val); | ||||||
| 	data->enable_ss = SSTROBE_VAL(val); | 	data->enable_ss = SSTROBE_VAL(val); | ||||||
| 	data->asize = val & ASIZE_MAX; | 	data->asize = val & ASIZE_MAX; | ||||||
|  | @ -261,6 +298,7 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, | ||||||
| 				      struct device_node *np) | 				      struct device_node *np) | ||||||
| { | { | ||||||
| 	struct aemif_device *aemif = platform_get_drvdata(pdev); | 	struct aemif_device *aemif = platform_get_drvdata(pdev); | ||||||
|  | 	unsigned long clk_rate = aemif->clk_rate; | ||||||
| 	struct aemif_cs_data *data; | 	struct aemif_cs_data *data; | ||||||
| 	u32 cs; | 	u32 cs; | ||||||
| 	u32 val; | 	u32 val; | ||||||
|  | @ -288,32 +326,33 @@ static int of_aemif_parse_abus_config(struct platform_device *pdev, | ||||||
| 
 | 
 | ||||||
| 	/* override the values from device node */ | 	/* override the values from device node */ | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) | 	if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) | ||||||
| 		data->ta = val; | 		data->timings.ta = aemif_calc_rate(pdev, val, clk_rate); | ||||||
| 
 | 
 | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) | 	if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) | ||||||
| 		data->rhold = val; | 		data->timings.rhold = aemif_calc_rate(pdev, val, clk_rate); | ||||||
| 
 | 
 | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) | 	if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) | ||||||
| 		data->rstrobe = val; | 		data->timings.rstrobe = aemif_calc_rate(pdev, val, clk_rate); | ||||||
| 
 | 
 | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) | 	if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) | ||||||
| 		data->rsetup = val; | 		data->timings.rsetup = aemif_calc_rate(pdev, val, clk_rate); | ||||||
| 
 | 
 | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) | 	if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) | ||||||
| 		data->whold = val; | 		data->timings.whold = aemif_calc_rate(pdev, val, clk_rate); | ||||||
| 
 | 
 | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) | 	if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) | ||||||
| 		data->wstrobe = val; | 		data->timings.wstrobe = aemif_calc_rate(pdev, val, clk_rate); | ||||||
| 
 | 
 | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) | 	if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) | ||||||
| 		data->wsetup = val; | 		data->timings.wsetup = aemif_calc_rate(pdev, val, clk_rate); | ||||||
| 
 | 
 | ||||||
| 	if (!of_property_read_u32(np, "ti,cs-bus-width", &val)) | 	if (!of_property_read_u32(np, "ti,cs-bus-width", &val)) | ||||||
| 		if (val == 16) | 		if (val == 16) | ||||||
| 			data->asize = 1; | 			data->asize = 1; | ||||||
| 	data->enable_ew = of_property_read_bool(np, "ti,cs-extended-wait-mode"); | 	data->enable_ew = of_property_read_bool(np, "ti,cs-extended-wait-mode"); | ||||||
| 	data->enable_ss = of_property_read_bool(np, "ti,cs-select-strobe-mode"); | 	data->enable_ss = of_property_read_bool(np, "ti,cs-select-strobe-mode"); | ||||||
| 	return 0; | 
 | ||||||
|  | 	return aemif_check_cs_timings(&data->timings); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct of_device_id aemif_of_match[] = { | static const struct of_device_id aemif_of_match[] = { | ||||||
|  | @ -351,6 +390,7 @@ static int aemif_probe(struct platform_device *pdev) | ||||||
| 	if (IS_ERR(aemif->base)) | 	if (IS_ERR(aemif->base)) | ||||||
| 		return PTR_ERR(aemif->base); | 		return PTR_ERR(aemif->base); | ||||||
| 
 | 
 | ||||||
|  | 	mutex_init(&aemif->config_cs_lock); | ||||||
| 	if (np) { | 	if (np) { | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * For every controller device node, there is a cs device node | 		 * For every controller device node, there is a cs device node | ||||||
|  |  | ||||||
|  | @ -11,20 +11,20 @@ | ||||||
| #include <linux/auxiliary_bus.h> | #include <linux/auxiliary_bus.h> | ||||||
| #include <linux/regmap.h> | #include <linux/regmap.h> | ||||||
| #include <linux/reset-controller.h> | #include <linux/reset-controller.h> | ||||||
| #include <linux/slab.h> |  | ||||||
| 
 | 
 | ||||||
| #include "reset-meson.h" | #include "reset-meson.h" | ||||||
| #include <soc/amlogic/reset-meson-aux.h> |  | ||||||
| 
 | 
 | ||||||
| static DEFINE_IDA(meson_rst_aux_ida); | static const struct meson_reset_param meson_a1_audio_param = { | ||||||
| 
 | 	.reset_ops	= &meson_reset_toggle_ops, | ||||||
| struct meson_reset_adev { | 	.reset_num	= 32, | ||||||
| 	struct auxiliary_device adev; | 	.level_offset	= 0x28, | ||||||
| 	struct regmap *map; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define to_meson_reset_adev(_adev) \ | static const struct meson_reset_param meson_a1_audio_vad_param = { | ||||||
| 	container_of((_adev), struct meson_reset_adev, adev) | 	.reset_ops	= &meson_reset_toggle_ops, | ||||||
|  | 	.reset_num	= 6, | ||||||
|  | 	.level_offset	= 0x8, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| static const struct meson_reset_param meson_g12a_audio_param = { | static const struct meson_reset_param meson_g12a_audio_param = { | ||||||
| 	.reset_ops	= &meson_reset_toggle_ops, | 	.reset_ops	= &meson_reset_toggle_ops, | ||||||
|  | @ -40,6 +40,12 @@ static const struct meson_reset_param meson_sm1_audio_param = { | ||||||
| 
 | 
 | ||||||
| static const struct auxiliary_device_id meson_reset_aux_ids[] = { | static const struct auxiliary_device_id meson_reset_aux_ids[] = { | ||||||
| 	{ | 	{ | ||||||
|  | 		.name = "a1-audio-clkc.rst-a1", | ||||||
|  | 		.driver_data = (kernel_ulong_t)&meson_a1_audio_param, | ||||||
|  | 	}, { | ||||||
|  | 		.name = "a1-audio-clkc.rst-a1-vad", | ||||||
|  | 		.driver_data = (kernel_ulong_t)&meson_a1_audio_vad_param, | ||||||
|  | 	}, { | ||||||
| 		.name = "axg-audio-clkc.rst-g12a", | 		.name = "axg-audio-clkc.rst-g12a", | ||||||
| 		.driver_data = (kernel_ulong_t)&meson_g12a_audio_param, | 		.driver_data = (kernel_ulong_t)&meson_g12a_audio_param, | ||||||
| 	}, { | 	}, { | ||||||
|  | @ -54,10 +60,13 @@ static int meson_reset_aux_probe(struct auxiliary_device *adev, | ||||||
| { | { | ||||||
| 	const struct meson_reset_param *param = | 	const struct meson_reset_param *param = | ||||||
| 		(const struct meson_reset_param *)(id->driver_data); | 		(const struct meson_reset_param *)(id->driver_data); | ||||||
| 	struct meson_reset_adev *raux = | 	struct regmap *map; | ||||||
| 		to_meson_reset_adev(adev); |  | ||||||
| 
 | 
 | ||||||
| 	return meson_reset_controller_register(&adev->dev, raux->map, param); | 	map = dev_get_regmap(adev->dev.parent, NULL); | ||||||
|  | 	if (!map) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	return meson_reset_controller_register(&adev->dev, map, param); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct auxiliary_driver meson_reset_aux_driver = { | static struct auxiliary_driver meson_reset_aux_driver = { | ||||||
|  | @ -66,70 +75,6 @@ static struct auxiliary_driver meson_reset_aux_driver = { | ||||||
| }; | }; | ||||||
| module_auxiliary_driver(meson_reset_aux_driver); | module_auxiliary_driver(meson_reset_aux_driver); | ||||||
| 
 | 
 | ||||||
| static void meson_rst_aux_release(struct device *dev) |  | ||||||
| { |  | ||||||
| 	struct auxiliary_device *adev = to_auxiliary_dev(dev); |  | ||||||
| 	struct meson_reset_adev *raux = |  | ||||||
| 		to_meson_reset_adev(adev); |  | ||||||
| 
 |  | ||||||
| 	ida_free(&meson_rst_aux_ida, adev->id); |  | ||||||
| 	kfree(raux); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void meson_rst_aux_unregister_adev(void *_adev) |  | ||||||
| { |  | ||||||
| 	struct auxiliary_device *adev = _adev; |  | ||||||
| 
 |  | ||||||
| 	auxiliary_device_delete(adev); |  | ||||||
| 	auxiliary_device_uninit(adev); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int devm_meson_rst_aux_register(struct device *dev, |  | ||||||
| 				struct regmap *map, |  | ||||||
| 				const char *adev_name) |  | ||||||
| { |  | ||||||
| 	struct meson_reset_adev *raux; |  | ||||||
| 	struct auxiliary_device *adev; |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	raux = kzalloc(sizeof(*raux), GFP_KERNEL); |  | ||||||
| 	if (!raux) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL); |  | ||||||
| 	if (ret < 0) |  | ||||||
| 		goto raux_free; |  | ||||||
| 
 |  | ||||||
| 	raux->map = map; |  | ||||||
| 
 |  | ||||||
| 	adev = &raux->adev; |  | ||||||
| 	adev->id = ret; |  | ||||||
| 	adev->name = adev_name; |  | ||||||
| 	adev->dev.parent = dev; |  | ||||||
| 	adev->dev.release = meson_rst_aux_release; |  | ||||||
| 	device_set_of_node_from_dev(&adev->dev, dev); |  | ||||||
| 
 |  | ||||||
| 	ret = auxiliary_device_init(adev); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto ida_free; |  | ||||||
| 
 |  | ||||||
| 	ret = __auxiliary_device_add(adev, dev->driver->name); |  | ||||||
| 	if (ret) { |  | ||||||
| 		auxiliary_device_uninit(adev); |  | ||||||
| 		return ret; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev, |  | ||||||
| 					adev); |  | ||||||
| 
 |  | ||||||
| ida_free: |  | ||||||
| 	ida_free(&meson_rst_aux_ida, adev->id); |  | ||||||
| raux_free: |  | ||||||
| 	kfree(raux); |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register); |  | ||||||
| 
 |  | ||||||
| MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver"); | MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver"); | ||||||
| MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); | MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); | ||||||
| MODULE_LICENSE("Dual BSD/GPL"); | MODULE_LICENSE("Dual BSD/GPL"); | ||||||
|  |  | ||||||
|  | @ -3,4 +3,4 @@ ifeq ($(CONFIG_ARM),y) | ||||||
| obj-$(CONFIG_ARCH_MXC) += soc-imx.o | obj-$(CONFIG_ARCH_MXC) += soc-imx.o | ||||||
| endif | endif | ||||||
| obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o | obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o | ||||||
| obj-$(CONFIG_SOC_IMX9) += imx93-src.o | obj-$(CONFIG_SOC_IMX9) += imx93-src.o soc-imx9.o | ||||||
|  |  | ||||||
							
								
								
									
										128
									
								
								drivers/soc/imx/soc-imx9.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								drivers/soc/imx/soc-imx9.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,128 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+
 | ||||||
|  | /*
 | ||||||
|  |  * Copyright 2024 NXP | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <linux/arm-smccc.h> | ||||||
|  | #include <linux/init.h> | ||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/of.h> | ||||||
|  | #include <linux/platform_device.h> | ||||||
|  | #include <linux/slab.h> | ||||||
|  | #include <linux/sys_soc.h> | ||||||
|  | 
 | ||||||
|  | #define IMX_SIP_GET_SOC_INFO	0xc2000006 | ||||||
|  | #define SOC_ID(x)		(((x) & 0xFFFF) >> 8) | ||||||
|  | #define SOC_REV_MAJOR(x)	((((x) >> 28) & 0xF) - 0x9) | ||||||
|  | #define SOC_REV_MINOR(x)	(((x) >> 24) & 0xF) | ||||||
|  | 
 | ||||||
|  | static int imx9_soc_probe(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	struct soc_device_attribute *attr; | ||||||
|  | 	struct arm_smccc_res res; | ||||||
|  | 	struct soc_device *sdev; | ||||||
|  | 	u32 soc_id, rev_major, rev_minor; | ||||||
|  | 	u64 uid127_64, uid63_0; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	attr = kzalloc(sizeof(*attr), GFP_KERNEL); | ||||||
|  | 	if (!attr) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	err = of_property_read_string(of_root, "model", &attr->machine); | ||||||
|  | 	if (err) { | ||||||
|  | 		pr_err("%s: missing model property: %d\n", __func__, err); | ||||||
|  | 		goto attr; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX"); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Retrieve the soc id, rev & uid info: | ||||||
|  | 	 * res.a1[31:16]: soc revision; | ||||||
|  | 	 * res.a1[15:0]: soc id; | ||||||
|  | 	 * res.a2: uid[127:64]; | ||||||
|  | 	 * res.a3: uid[63:0]; | ||||||
|  | 	 */ | ||||||
|  | 	arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res); | ||||||
|  | 	if (res.a0 != SMCCC_RET_SUCCESS) { | ||||||
|  | 		pr_err("%s: SMC failed: 0x%lx\n", __func__, res.a0); | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto family; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	soc_id = SOC_ID(res.a1); | ||||||
|  | 	rev_major = SOC_REV_MAJOR(res.a1); | ||||||
|  | 	rev_minor = SOC_REV_MINOR(res.a1); | ||||||
|  | 
 | ||||||
|  | 	attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id); | ||||||
|  | 	attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor); | ||||||
|  | 
 | ||||||
|  | 	uid127_64 = res.a2; | ||||||
|  | 	uid63_0 = res.a3; | ||||||
|  | 	attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0); | ||||||
|  | 
 | ||||||
|  | 	sdev = soc_device_register(attr); | ||||||
|  | 	if (IS_ERR(sdev)) { | ||||||
|  | 		err = PTR_ERR(sdev); | ||||||
|  | 		pr_err("%s failed to register SoC as a device: %d\n", __func__, err); | ||||||
|  | 		goto serial_number; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | serial_number: | ||||||
|  | 	kfree(attr->serial_number); | ||||||
|  | 	kfree(attr->revision); | ||||||
|  | 	kfree(attr->soc_id); | ||||||
|  | family: | ||||||
|  | 	kfree(attr->family); | ||||||
|  | attr: | ||||||
|  | 	kfree(attr); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static __maybe_unused const struct of_device_id imx9_soc_match[] = { | ||||||
|  | 	{ .compatible = "fsl,imx93", }, | ||||||
|  | 	{ .compatible = "fsl,imx95", }, | ||||||
|  | 	{ } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define IMX_SOC_DRIVER	"imx9-soc" | ||||||
|  | 
 | ||||||
|  | static struct platform_driver imx9_soc_driver = { | ||||||
|  | 	.probe = imx9_soc_probe, | ||||||
|  | 	.driver = { | ||||||
|  | 		.name = IMX_SOC_DRIVER, | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int __init imx9_soc_init(void) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	struct platform_device *pdev; | ||||||
|  | 
 | ||||||
|  | 	/* No match means it is not an i.MX 9 series SoC, do nothing. */ | ||||||
|  | 	if (!of_match_node(imx9_soc_match, of_root)) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	ret = platform_driver_register(&imx9_soc_driver); | ||||||
|  | 	if (ret) { | ||||||
|  | 		pr_err("failed to register imx9_soc platform driver: %d\n", ret); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pdev = platform_device_register_simple(IMX_SOC_DRIVER, -1, NULL, 0); | ||||||
|  | 	if (IS_ERR(pdev)) { | ||||||
|  | 		pr_err("failed to register imx9_soc platform device: %ld\n", PTR_ERR(pdev)); | ||||||
|  | 		platform_driver_unregister(&imx9_soc_driver); | ||||||
|  | 		return PTR_ERR(pdev); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | device_initcall(imx9_soc_init); | ||||||
|  | 
 | ||||||
|  | MODULE_AUTHOR("NXP"); | ||||||
|  | MODULE_DESCRIPTION("NXP i.MX9 SoC"); | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
|  | @ -69,14 +69,11 @@ static int litex_check_csr_access(void __iomem *reg_addr) | ||||||
| 
 | 
 | ||||||
| struct litex_soc_ctrl_device { | struct litex_soc_ctrl_device { | ||||||
| 	void __iomem *base; | 	void __iomem *base; | ||||||
| 	struct notifier_block reset_nb; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int litex_reset_handler(struct notifier_block *this, unsigned long mode, | static int litex_reset_handler(struct sys_off_data *data) | ||||||
| 			       void *cmd) |  | ||||||
| { | { | ||||||
| 	struct litex_soc_ctrl_device *soc_ctrl_dev = | 	struct litex_soc_ctrl_device *soc_ctrl_dev = data->cb_data; | ||||||
| 		container_of(this, struct litex_soc_ctrl_device, reset_nb); |  | ||||||
| 
 | 
 | ||||||
| 	litex_write32(soc_ctrl_dev->base + RESET_REG_OFF, RESET_REG_VALUE); | 	litex_write32(soc_ctrl_dev->base + RESET_REG_OFF, RESET_REG_VALUE); | ||||||
| 	return NOTIFY_DONE; | 	return NOTIFY_DONE; | ||||||
|  | @ -105,11 +102,9 @@ static int litex_soc_ctrl_probe(struct platform_device *pdev) | ||||||
| 	if (error) | 	if (error) | ||||||
| 		return error; | 		return error; | ||||||
| 
 | 
 | ||||||
| 	platform_set_drvdata(pdev, soc_ctrl_dev); | 	error = devm_register_restart_handler(&pdev->dev, | ||||||
| 
 | 					      litex_reset_handler, | ||||||
| 	soc_ctrl_dev->reset_nb.notifier_call = litex_reset_handler; | 					      soc_ctrl_dev); | ||||||
| 	soc_ctrl_dev->reset_nb.priority = 128; |  | ||||||
| 	error = register_restart_handler(&soc_ctrl_dev->reset_nb); |  | ||||||
| 	if (error) { | 	if (error) { | ||||||
| 		dev_warn(&pdev->dev, "cannot register restart handler: %d\n", | 		dev_warn(&pdev->dev, "cannot register restart handler: %d\n", | ||||||
| 			 error); | 			 error); | ||||||
|  | @ -118,20 +113,12 @@ static int litex_soc_ctrl_probe(struct platform_device *pdev) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void litex_soc_ctrl_remove(struct platform_device *pdev) |  | ||||||
| { |  | ||||||
| 	struct litex_soc_ctrl_device *soc_ctrl_dev = platform_get_drvdata(pdev); |  | ||||||
| 
 |  | ||||||
| 	unregister_restart_handler(&soc_ctrl_dev->reset_nb); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct platform_driver litex_soc_ctrl_driver = { | static struct platform_driver litex_soc_ctrl_driver = { | ||||||
| 	.driver = { | 	.driver = { | ||||||
| 		.name = "litex-soc-controller", | 		.name = "litex-soc-controller", | ||||||
| 		.of_match_table = litex_soc_ctrl_of_match, | 		.of_match_table = litex_soc_ctrl_of_match, | ||||||
| 	}, | 	}, | ||||||
| 	.probe = litex_soc_ctrl_probe, | 	.probe = litex_soc_ctrl_probe, | ||||||
| 	.remove = litex_soc_ctrl_remove, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| module_platform_driver(litex_soc_ctrl_driver); | module_platform_driver(litex_soc_ctrl_driver); | ||||||
|  |  | ||||||
|  | @ -273,23 +273,31 @@ static int mtk_devapc_probe(struct platform_device *pdev) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	devapc_irq = irq_of_parse_and_map(node, 0); | 	devapc_irq = irq_of_parse_and_map(node, 0); | ||||||
| 	if (!devapc_irq) | 	if (!devapc_irq) { | ||||||
| 		return -EINVAL; | 		ret = -EINVAL; | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock"); | 	ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock"); | ||||||
| 	if (IS_ERR(ctx->infra_clk)) | 	if (IS_ERR(ctx->infra_clk)) { | ||||||
| 		return -EINVAL; | 		ret = -EINVAL; | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq, | 	ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq, | ||||||
| 			       IRQF_TRIGGER_NONE, "devapc", ctx); | 			       IRQF_TRIGGER_NONE, "devapc", ctx); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	platform_set_drvdata(pdev, ctx); | 	platform_set_drvdata(pdev, ctx); | ||||||
| 
 | 
 | ||||||
| 	start_devapc(ctx); | 	start_devapc(ctx); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | 
 | ||||||
|  | err: | ||||||
|  | 	iounmap(ctx->infra_base); | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void mtk_devapc_remove(struct platform_device *pdev) | static void mtk_devapc_remove(struct platform_device *pdev) | ||||||
|  | @ -297,6 +305,7 @@ static void mtk_devapc_remove(struct platform_device *pdev) | ||||||
| 	struct mtk_devapc_context *ctx = platform_get_drvdata(pdev); | 	struct mtk_devapc_context *ctx = platform_get_drvdata(pdev); | ||||||
| 
 | 
 | ||||||
| 	stop_devapc(ctx); | 	stop_devapc(ctx); | ||||||
|  | 	iounmap(ctx->infra_base); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct platform_driver mtk_devapc_driver = { | static struct platform_driver mtk_devapc_driver = { | ||||||
|  |  | ||||||
|  | @ -139,7 +139,7 @@ config QCOM_RAMP_CTRL | ||||||
| 
 | 
 | ||||||
| config QCOM_RMTFS_MEM | config QCOM_RMTFS_MEM | ||||||
| 	tristate "Qualcomm Remote Filesystem memory driver" | 	tristate "Qualcomm Remote Filesystem memory driver" | ||||||
| 	depends on ARCH_QCOM | 	depends on ARCH_QCOM || COMPILE_TEST | ||||||
| 	select QCOM_SCM | 	select QCOM_SCM | ||||||
| 	help | 	help | ||||||
| 	  The Qualcomm remote filesystem memory driver is used for allocating | 	  The Qualcomm remote filesystem memory driver is used for allocating | ||||||
|  |  | ||||||
|  | @ -142,6 +142,7 @@ struct qcom_llcc_config { | ||||||
| 	bool skip_llcc_cfg; | 	bool skip_llcc_cfg; | ||||||
| 	bool no_edac; | 	bool no_edac; | ||||||
| 	bool irq_configured; | 	bool irq_configured; | ||||||
|  | 	bool no_broadcast_register; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct qcom_sct_config { | struct qcom_sct_config { | ||||||
|  | @ -154,6 +155,38 @@ enum llcc_reg_offset { | ||||||
| 	LLCC_COMMON_STATUS0, | 	LLCC_COMMON_STATUS0, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const struct llcc_slice_config ipq5424_data[] =  { | ||||||
|  | 	{ | ||||||
|  | 		.usecase_id = LLCC_CPUSS, | ||||||
|  | 		.slice_id = 1, | ||||||
|  | 		.max_cap = 768, | ||||||
|  | 		.priority = 1, | ||||||
|  | 		.bonus_ways = 0xFFFF, | ||||||
|  | 		.retain_on_pc = true, | ||||||
|  | 		.activate_on_init = true, | ||||||
|  | 		.write_scid_cacheable_en = true, | ||||||
|  | 		.stale_en = true, | ||||||
|  | 		.stale_cap_en = true, | ||||||
|  | 		.alloc_oneway_en = true, | ||||||
|  | 		.ovcap_en = true, | ||||||
|  | 		.ovcap_prio = true, | ||||||
|  | 		.vict_prio = true, | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		.usecase_id = LLCC_VIDSC0, | ||||||
|  | 		.slice_id = 2, | ||||||
|  | 		.max_cap = 256, | ||||||
|  | 		.priority = 2, | ||||||
|  | 		.fixed_size = true, | ||||||
|  | 		.bonus_ways = 0xF000, | ||||||
|  | 		.retain_on_pc = true, | ||||||
|  | 		.activate_on_init = true, | ||||||
|  | 		.write_scid_cacheable_en = true, | ||||||
|  | 		.stale_en = true, | ||||||
|  | 		.stale_cap_en = true, | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static const struct llcc_slice_config sa8775p_data[] =  { | static const struct llcc_slice_config sa8775p_data[] =  { | ||||||
| 	{ | 	{ | ||||||
| 		.usecase_id = LLCC_CPUSS, | 		.usecase_id = LLCC_CPUSS, | ||||||
|  | @ -3004,6 +3037,7 @@ static const struct llcc_slice_config x1e80100_data[] = { | ||||||
| 		.fixed_size = true, | 		.fixed_size = true, | ||||||
| 		.bonus_ways = 0xfff, | 		.bonus_ways = 0xfff, | ||||||
| 		.cache_mode = 0, | 		.cache_mode = 0, | ||||||
|  | 		.activate_on_init = true, | ||||||
| 	}, { | 	}, { | ||||||
| 		.usecase_id = LLCC_CAMEXP0, | 		.usecase_id = LLCC_CAMEXP0, | ||||||
| 		.slice_id = 4, | 		.slice_id = 4, | ||||||
|  | @ -3185,6 +3219,16 @@ static const struct qcom_llcc_config qdu1000_cfg[] = { | ||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const struct qcom_llcc_config ipq5424_cfg[] = { | ||||||
|  | 	{ | ||||||
|  | 		.sct_data       = ipq5424_data, | ||||||
|  | 		.size           = ARRAY_SIZE(ipq5424_data), | ||||||
|  | 		.reg_offset     = llcc_v2_1_reg_offset, | ||||||
|  | 		.edac_reg_offset = &llcc_v2_1_edac_reg_offset, | ||||||
|  | 		.no_broadcast_register = true, | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static const struct qcom_llcc_config sa8775p_cfg[] = { | static const struct qcom_llcc_config sa8775p_cfg[] = { | ||||||
| 	{ | 	{ | ||||||
| 		.sct_data	= sa8775p_data, | 		.sct_data	= sa8775p_data, | ||||||
|  | @ -3360,6 +3404,11 @@ static const struct qcom_sct_config qdu1000_cfgs = { | ||||||
| 	.num_config	= ARRAY_SIZE(qdu1000_cfg), | 	.num_config	= ARRAY_SIZE(qdu1000_cfg), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const struct qcom_sct_config ipq5424_cfgs = { | ||||||
|  | 	.llcc_config	= ipq5424_cfg, | ||||||
|  | 	.num_config	= ARRAY_SIZE(ipq5424_cfg), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static const struct qcom_sct_config sa8775p_cfgs = { | static const struct qcom_sct_config sa8775p_cfgs = { | ||||||
| 	.llcc_config	= sa8775p_cfg, | 	.llcc_config	= sa8775p_cfg, | ||||||
| 	.num_config	= ARRAY_SIZE(sa8775p_cfg), | 	.num_config	= ARRAY_SIZE(sa8775p_cfg), | ||||||
|  | @ -3957,8 +4006,12 @@ static int qcom_llcc_probe(struct platform_device *pdev) | ||||||
| 
 | 
 | ||||||
| 	drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base"); | 	drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base"); | ||||||
| 	if (IS_ERR(drv_data->bcast_regmap)) { | 	if (IS_ERR(drv_data->bcast_regmap)) { | ||||||
| 		ret = PTR_ERR(drv_data->bcast_regmap); | 		if (cfg->no_broadcast_register) { | ||||||
| 		goto err; | 			drv_data->bcast_regmap = regmap; | ||||||
|  | 		} else { | ||||||
|  | 			ret = PTR_ERR(drv_data->bcast_regmap); | ||||||
|  | 			goto err; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Extract version of the IP */ | 	/* Extract version of the IP */ | ||||||
|  | @ -4029,6 +4082,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct of_device_id qcom_llcc_of_match[] = { | static const struct of_device_id qcom_llcc_of_match[] = { | ||||||
|  | 	{ .compatible = "qcom,ipq5424-llcc", .data = &ipq5424_cfgs}, | ||||||
| 	{ .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs}, | 	{ .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs}, | ||||||
| 	{ .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs}, | 	{ .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs}, | ||||||
| 	{ .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs}, | 	{ .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs}, | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
|  * Copyright (c) 2022, Linaro Ltd |  * Copyright (c) 2022, Linaro Ltd | ||||||
|  */ |  */ | ||||||
| #include <linux/auxiliary_bus.h> | #include <linux/auxiliary_bus.h> | ||||||
|  | #include <linux/cleanup.h> | ||||||
| #include <linux/delay.h> | #include <linux/delay.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/of.h> | #include <linux/of.h> | ||||||
|  | @ -100,15 +101,13 @@ void pmic_glink_client_register(struct pmic_glink_client *client) | ||||||
| 	struct pmic_glink *pg = client->pg; | 	struct pmic_glink *pg = client->pg; | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&pg->state_lock); | 	guard(mutex)(&pg->state_lock); | ||||||
| 	spin_lock_irqsave(&pg->client_lock, flags); | 	spin_lock_irqsave(&pg->client_lock, flags); | ||||||
| 
 | 
 | ||||||
| 	list_add(&client->node, &pg->clients); | 	list_add(&client->node, &pg->clients); | ||||||
| 	client->pdr_notify(client->priv, pg->client_state); | 	client->pdr_notify(client->priv, pg->client_state); | ||||||
| 
 | 
 | ||||||
| 	spin_unlock_irqrestore(&pg->client_lock, flags); | 	spin_unlock_irqrestore(&pg->client_lock, flags); | ||||||
| 	mutex_unlock(&pg->state_lock); |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(pmic_glink_client_register); | EXPORT_SYMBOL_GPL(pmic_glink_client_register); | ||||||
| 
 | 
 | ||||||
|  | @ -119,26 +118,25 @@ int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len) | ||||||
| 	unsigned long start; | 	unsigned long start; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&pg->state_lock); | 	guard(mutex)(&pg->state_lock); | ||||||
| 	if (!pg->ept) { | 	if (!pg->ept) { | ||||||
| 		ret = -ECONNRESET; | 		return -ECONNRESET; | ||||||
| 	} else { | 	} | ||||||
| 		start = jiffies; | 
 | ||||||
| 		for (;;) { | 	start = jiffies; | ||||||
| 			ret = rpmsg_send(pg->ept, data, len); | 	for (;;) { | ||||||
| 			if (ret != -EAGAIN) | 		ret = rpmsg_send(pg->ept, data, len); | ||||||
| 				break; | 		if (ret != -EAGAIN) | ||||||
| 
 | 			break; | ||||||
| 			if (timeout_reached) { | 
 | ||||||
| 				ret = -ETIMEDOUT; | 		if (timeout_reached) { | ||||||
| 				break; | 			ret = -ETIMEDOUT; | ||||||
| 			} | 			break; | ||||||
| 
 | 		} | ||||||
| 			usleep_range(1000, 5000); | 
 | ||||||
| 			timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT); | 		usleep_range(1000, 5000); | ||||||
| 		} | 		timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT); | ||||||
| 	} | 	} | ||||||
| 	mutex_unlock(&pg->state_lock); |  | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | @ -227,51 +225,42 @@ static void pmic_glink_pdr_callback(int state, char *svc_path, void *priv) | ||||||
| { | { | ||||||
| 	struct pmic_glink *pg = priv; | 	struct pmic_glink *pg = priv; | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&pg->state_lock); | 	guard(mutex)(&pg->state_lock); | ||||||
| 	pg->pdr_state = state; | 	pg->pdr_state = state; | ||||||
| 
 | 
 | ||||||
| 	pmic_glink_state_notify_clients(pg); | 	pmic_glink_state_notify_clients(pg); | ||||||
| 	mutex_unlock(&pg->state_lock); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev) | static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev) | ||||||
| { | { | ||||||
| 	struct pmic_glink *pg = __pmic_glink; | 	struct pmic_glink *pg = __pmic_glink; | ||||||
| 	int ret = 0; |  | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&__pmic_glink_lock); | 	guard(mutex)(&__pmic_glink_lock); | ||||||
| 	if (!pg) { | 	pg = __pmic_glink; | ||||||
| 		ret = dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n"); | 	if (!pg) | ||||||
| 		goto out_unlock; | 		return dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n"); | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	dev_set_drvdata(&rpdev->dev, pg); | 	dev_set_drvdata(&rpdev->dev, pg); | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&pg->state_lock); | 	guard(mutex)(&pg->state_lock); | ||||||
| 	pg->ept = rpdev->ept; | 	pg->ept = rpdev->ept; | ||||||
| 	pmic_glink_state_notify_clients(pg); | 	pmic_glink_state_notify_clients(pg); | ||||||
| 	mutex_unlock(&pg->state_lock); |  | ||||||
| 
 | 
 | ||||||
| out_unlock: | 	return 0; | ||||||
| 	mutex_unlock(&__pmic_glink_lock); |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void pmic_glink_rpmsg_remove(struct rpmsg_device *rpdev) | static void pmic_glink_rpmsg_remove(struct rpmsg_device *rpdev) | ||||||
| { | { | ||||||
| 	struct pmic_glink *pg; | 	struct pmic_glink *pg; | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&__pmic_glink_lock); | 	guard(mutex)(&__pmic_glink_lock); | ||||||
| 	pg = __pmic_glink; | 	pg = __pmic_glink; | ||||||
| 	if (!pg) | 	if (!pg) | ||||||
| 		goto out_unlock; | 		return; | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&pg->state_lock); | 	guard(mutex)(&pg->state_lock); | ||||||
| 	pg->ept = NULL; | 	pg->ept = NULL; | ||||||
| 	pmic_glink_state_notify_clients(pg); | 	pmic_glink_state_notify_clients(pg); | ||||||
| 	mutex_unlock(&pg->state_lock); |  | ||||||
| out_unlock: |  | ||||||
| 	mutex_unlock(&__pmic_glink_lock); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct rpmsg_device_id pmic_glink_rpmsg_id_match[] = { | static const struct rpmsg_device_id pmic_glink_rpmsg_id_match[] = { | ||||||
|  | @ -378,9 +367,8 @@ static void pmic_glink_remove(struct platform_device *pdev) | ||||||
| 	if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) | 	if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) | ||||||
| 		pmic_glink_del_aux_device(pg, &pg->ucsi_aux); | 		pmic_glink_del_aux_device(pg, &pg->ucsi_aux); | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&__pmic_glink_lock); | 	guard(mutex)(&__pmic_glink_lock); | ||||||
| 	__pmic_glink = NULL; | 	__pmic_glink = NULL; | ||||||
| 	mutex_unlock(&__pmic_glink_lock); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const unsigned long pmic_glink_sc8280xp_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | | static const unsigned long pmic_glink_sc8280xp_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
|  */ |  */ | ||||||
| #include <linux/auxiliary_bus.h> | #include <linux/auxiliary_bus.h> | ||||||
| #include <linux/bitfield.h> | #include <linux/bitfield.h> | ||||||
|  | #include <linux/cleanup.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/of.h> | #include <linux/of.h> | ||||||
| #include <linux/of_device.h> | #include <linux/of_device.h> | ||||||
|  | @ -114,7 +115,7 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm | ||||||
| 	 * The USBC_CMD_WRITE_REQ ack doesn't identify the request, so wait for | 	 * The USBC_CMD_WRITE_REQ ack doesn't identify the request, so wait for | ||||||
| 	 * one ack at a time. | 	 * one ack at a time. | ||||||
| 	 */ | 	 */ | ||||||
| 	mutex_lock(&altmode->lock); | 	guard(mutex)(&altmode->lock); | ||||||
| 
 | 
 | ||||||
| 	req.hdr.owner = cpu_to_le32(altmode->owner_id); | 	req.hdr.owner = cpu_to_le32(altmode->owner_id); | ||||||
| 	req.hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP); | 	req.hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP); | ||||||
|  | @ -125,18 +126,16 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm | ||||||
| 	ret = pmic_glink_send(altmode->client, &req, sizeof(req)); | 	ret = pmic_glink_send(altmode->client, &req, sizeof(req)); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		dev_err(altmode->dev, "failed to send altmode request: %#x (%d)\n", cmd, ret); | 		dev_err(altmode->dev, "failed to send altmode request: %#x (%d)\n", cmd, ret); | ||||||
| 		goto out_unlock; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	left = wait_for_completion_timeout(&altmode->pan_ack, 5 * HZ); | 	left = wait_for_completion_timeout(&altmode->pan_ack, 5 * HZ); | ||||||
| 	if (!left) { | 	if (!left) { | ||||||
| 		dev_err(altmode->dev, "timeout waiting for altmode request ack for: %#x\n", cmd); | 		dev_err(altmode->dev, "timeout waiting for altmode request ack for: %#x\n", cmd); | ||||||
| 		ret = -ETIMEDOUT; | 		return -ETIMEDOUT; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| out_unlock: | 	return 0; | ||||||
| 	mutex_unlock(&altmode->lock); |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode, | static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode, | ||||||
|  |  | ||||||
|  | @ -553,6 +553,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { | ||||||
| 	{ .compatible = "qcom,sm4250", .data = sm6115_domains, }, | 	{ .compatible = "qcom,sm4250", .data = sm6115_domains, }, | ||||||
| 	{ .compatible = "qcom,sm6115", .data = sm6115_domains, }, | 	{ .compatible = "qcom,sm6115", .data = sm6115_domains, }, | ||||||
| 	{ .compatible = "qcom,sm6350", .data = sm6350_domains, }, | 	{ .compatible = "qcom,sm6350", .data = sm6350_domains, }, | ||||||
|  | 	{ .compatible = "qcom,sm7225", .data = sm6350_domains, }, | ||||||
| 	{ .compatible = "qcom,sm7325", .data = sc7280_domains, }, | 	{ .compatible = "qcom,sm7325", .data = sc7280_domains, }, | ||||||
| 	{ .compatible = "qcom,sm8150", .data = sm8150_domains, }, | 	{ .compatible = "qcom,sm8150", .data = sm8150_domains, }, | ||||||
| 	{ .compatible = "qcom,sm8250", .data = sm8250_domains, }, | 	{ .compatible = "qcom,sm8250", .data = sm8250_domains, }, | ||||||
|  | @ -561,6 +562,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { | ||||||
| 	{ .compatible = "qcom,sm8550", .data = sm8550_domains, }, | 	{ .compatible = "qcom,sm8550", .data = sm8550_domains, }, | ||||||
| 	{ .compatible = "qcom,sm8650", .data = sm8550_domains, }, | 	{ .compatible = "qcom,sm8650", .data = sm8550_domains, }, | ||||||
| 	{ .compatible = "qcom,x1e80100", .data = x1e80100_domains, }, | 	{ .compatible = "qcom,x1e80100", .data = x1e80100_domains, }, | ||||||
|  | 	{ .compatible = "qcom,x1p42100", .data = x1e80100_domains, }, | ||||||
| 	{}, | 	{}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -125,7 +125,7 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct class rmtfs_class = { | static const struct class rmtfs_class = { | ||||||
| 	.name           = "rmtfs", | 	.name           = "rmtfs", | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -112,7 +112,8 @@ struct qcom_smem_state *qcom_smem_state_get(struct device *dev, | ||||||
| 
 | 
 | ||||||
| 	if (args.args_count != 1) { | 	if (args.args_count != 1) { | ||||||
| 		dev_err(dev, "invalid #qcom,smem-state-cells\n"); | 		dev_err(dev, "invalid #qcom,smem-state-cells\n"); | ||||||
| 		return ERR_PTR(-EINVAL); | 		state = ERR_PTR(-EINVAL); | ||||||
|  | 		goto put; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	state = of_node_to_state(args.np); | 	state = of_node_to_state(args.np); | ||||||
|  |  | ||||||
|  | @ -451,6 +451,7 @@ static const struct soc_id soc_id[] = { | ||||||
| 	{ qcom_board_id(QCS9100) }, | 	{ qcom_board_id(QCS9100) }, | ||||||
| 	{ qcom_board_id(QCS8300) }, | 	{ qcom_board_id(QCS8300) }, | ||||||
| 	{ qcom_board_id(QCS8275) }, | 	{ qcom_board_id(QCS8275) }, | ||||||
|  | 	{ qcom_board_id(QCS9075) }, | ||||||
| 	{ qcom_board_id(QCS615) }, | 	{ qcom_board_id(QCS615) }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -796,7 +797,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev) | ||||||
| 	if (!qs->attr.soc_id || !qs->attr.revision) | 	if (!qs->attr.soc_id || !qs->attr.revision) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	if (offsetof(struct socinfo, serial_num) <= item_size) { | 	if (offsetofend(struct socinfo, serial_num) <= item_size) { | ||||||
| 		qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL, | 		qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL, | ||||||
| 							"%u", | 							"%u", | ||||||
| 							le32_to_cpu(info->serial_num)); | 							le32_to_cpu(info->serial_num)); | ||||||
|  |  | ||||||
|  | @ -345,6 +345,11 @@ config ARCH_R9A09G011 | ||||||
| 	help | 	help | ||||||
| 	  This enables support for the Renesas RZ/V2M SoC. | 	  This enables support for the Renesas RZ/V2M SoC. | ||||||
| 
 | 
 | ||||||
|  | config ARCH_R9A09G047 | ||||||
|  | 	bool "ARM64 Platform support for RZ/G3E" | ||||||
|  | 	help | ||||||
|  | 	  This enables support for the Renesas RZ/G3E SoC variants. | ||||||
|  | 
 | ||||||
| config ARCH_R9A09G057 | config ARCH_R9A09G057 | ||||||
| 	bool "ARM64 Platform support for RZ/V2H(P)" | 	bool "ARM64 Platform support for RZ/V2H(P)" | ||||||
| 	select RENESAS_RZV2H_ICU | 	select RENESAS_RZV2H_ICU | ||||||
|  |  | ||||||
|  | @ -126,7 +126,7 @@ static int tensor_set_bits_atomic(void *ctx, unsigned int offset, u32 val, | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			return ret; | 			return ret; | ||||||
| 	} | 	} | ||||||
| 	return ret; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool tensor_is_atomic(unsigned int reg) | static bool tensor_is_atomic(unsigned int reg) | ||||||
|  |  | ||||||
|  | @ -69,19 +69,12 @@ static int tegra_cbb_err_show(struct seq_file *file, void *data) | ||||||
| } | } | ||||||
| DEFINE_SHOW_ATTRIBUTE(tegra_cbb_err); | DEFINE_SHOW_ATTRIBUTE(tegra_cbb_err); | ||||||
| 
 | 
 | ||||||
| static int tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb) | static void tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb) | ||||||
| { | { | ||||||
| 	static struct dentry *root; | 	static struct dentry *root; | ||||||
| 
 | 
 | ||||||
| 	if (!root) { | 	if (!root) | ||||||
| 		root = debugfs_create_file("tegra_cbb_err", 0444, NULL, cbb, &tegra_cbb_err_fops); | 		root = debugfs_create_file("tegra_cbb_err", 0444, NULL, cbb, &tegra_cbb_err_fops); | ||||||
| 		if (IS_ERR_OR_NULL(root)) { |  | ||||||
| 			pr_err("%s(): could not create debugfs node\n", __func__); |  | ||||||
| 			return PTR_ERR(root); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void tegra_cbb_stall_enable(struct tegra_cbb *cbb) | void tegra_cbb_stall_enable(struct tegra_cbb *cbb) | ||||||
|  | @ -148,13 +141,8 @@ int tegra_cbb_register(struct tegra_cbb *cbb) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (IS_ENABLED(CONFIG_DEBUG_FS)) { | 	if (IS_ENABLED(CONFIG_DEBUG_FS)) | ||||||
| 		ret = tegra_cbb_err_debugfs_init(cbb); | 		tegra_cbb_err_debugfs_init(cbb); | ||||||
| 		if (ret) { |  | ||||||
| 			dev_err(cbb->dev, "failed to create debugfs\n"); |  | ||||||
| 			return ret; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	/* register interrupt handler for errors due to different initiators */ | 	/* register interrupt handler for errors due to different initiators */ | ||||||
| 	ret = cbb->ops->interrupt_enable(cbb); | 	ret = cbb->ops->interrupt_enable(cbb); | ||||||
|  |  | ||||||
|  | @ -277,7 +277,7 @@ static void tegra234_lookup_slave_timeout(struct seq_file *file, struct tegra234 | ||||||
| 	 *    which timed out. | 	 *    which timed out. | ||||||
| 	 *	a) Get block number from the index of set bit in | 	 *	a) Get block number from the index of set bit in | ||||||
| 	 *	   <FABRIC>_SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register. | 	 *	   <FABRIC>_SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register. | ||||||
| 	 *	b) Get address of register repective to block number i.e. | 	 *	b) Get address of register respective to block number i.e. | ||||||
| 	 *	   <FABRIC>_SN_AXI2APB_<>_BLOCK<index-set-bit>_TMO_0. | 	 *	   <FABRIC>_SN_AXI2APB_<>_BLOCK<index-set-bit>_TMO_0. | ||||||
| 	 *	c) Read the register in above step to get client_id which | 	 *	c) Read the register in above step to get client_id which | ||||||
| 	 *	   timed out as per the set bits. | 	 *	   timed out as per the set bits. | ||||||
|  |  | ||||||
|  | @ -647,15 +647,20 @@ static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct nvmem_keepout tegra234_fuse_keepouts[] = { | static const struct nvmem_keepout tegra234_fuse_keepouts[] = { | ||||||
| 	{ .start = 0x01c, .end = 0x0c8 }, | 	{ .start = 0x01c, .end = 0x064 }, | ||||||
| 	{ .start = 0x12c, .end = 0x184 }, | 	{ .start = 0x084, .end = 0x0a0 }, | ||||||
|  | 	{ .start = 0x0a4, .end = 0x0c8 }, | ||||||
|  | 	{ .start = 0x12c, .end = 0x164 }, | ||||||
|  | 	{ .start = 0x16c, .end = 0x184 }, | ||||||
| 	{ .start = 0x190, .end = 0x198 }, | 	{ .start = 0x190, .end = 0x198 }, | ||||||
| 	{ .start = 0x1a0, .end = 0x204 }, | 	{ .start = 0x1a0, .end = 0x204 }, | ||||||
| 	{ .start = 0x21c, .end = 0x250 }, | 	{ .start = 0x21c, .end = 0x2f0 }, | ||||||
| 	{ .start = 0x25c, .end = 0x2f0 }, |  | ||||||
| 	{ .start = 0x310, .end = 0x3d8 }, | 	{ .start = 0x310, .end = 0x3d8 }, | ||||||
| 	{ .start = 0x400, .end = 0x4f0 }, | 	{ .start = 0x400, .end = 0x420 }, | ||||||
| 	{ .start = 0x4f8, .end = 0x7e8 }, | 	{ .start = 0x444, .end = 0x490 }, | ||||||
|  | 	{ .start = 0x4bc, .end = 0x4f0 }, | ||||||
|  | 	{ .start = 0x4f8, .end = 0x54c }, | ||||||
|  | 	{ .start = 0x57c, .end = 0x7e8 }, | ||||||
| 	{ .start = 0x8d0, .end = 0x8d8 }, | 	{ .start = 0x8d0, .end = 0x8d8 }, | ||||||
| 	{ .start = 0xacc, .end = 0xf00 } | 	{ .start = 0xacc, .end = 0xf00 } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -1272,8 +1272,9 @@ static void optee_msg_get_os_revision(optee_invoke_fn *invoke_fn) | ||||||
| 		  &res.smccc); | 		  &res.smccc); | ||||||
| 
 | 
 | ||||||
| 	if (res.result.build_id) | 	if (res.result.build_id) | ||||||
| 		pr_info("revision %lu.%lu (%08lx)", res.result.major, | 		pr_info("revision %lu.%lu (%0*lx)", res.result.major, | ||||||
| 			res.result.minor, res.result.build_id); | 			res.result.minor, (int)sizeof(res.result.build_id) * 2, | ||||||
|  | 			res.result.build_id); | ||||||
| 	else | 	else | ||||||
| 		pr_info("revision %lu.%lu", res.result.major, res.result.minor); | 		pr_info("revision %lu.%lu", res.result.major, res.result.minor); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -284,6 +284,7 @@ | ||||||
| #define QCOM_ID_QCS9100			667 | #define QCOM_ID_QCS9100			667 | ||||||
| #define QCOM_ID_QCS8300			674 | #define QCOM_ID_QCS8300			674 | ||||||
| #define QCOM_ID_QCS8275			675 | #define QCOM_ID_QCS8275			675 | ||||||
|  | #define QCOM_ID_QCS9075			676 | ||||||
| #define QCOM_ID_QCS615			680 | #define QCOM_ID_QCS615			680 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								include/dt-bindings/reset/amlogic,meson-a1-audio-reset.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								include/dt-bindings/reset/amlogic,meson-a1-audio-reset.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2024, SaluteDevices. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Author: Jan Dakinevich <jan.dakinevich@salutedevices.com> | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H | ||||||
|  | #define _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H | ||||||
|  | 
 | ||||||
|  | #define AUD_RESET_DDRARB	0 | ||||||
|  | #define AUD_RESET_TDMIN_A	1 | ||||||
|  | #define AUD_RESET_TDMIN_B	2 | ||||||
|  | #define AUD_RESET_TDMIN_LB	3 | ||||||
|  | #define AUD_RESET_LOOPBACK	4 | ||||||
|  | #define AUD_RESET_TDMOUT_A	5 | ||||||
|  | #define AUD_RESET_TDMOUT_B	6 | ||||||
|  | #define AUD_RESET_FRDDR_A	7 | ||||||
|  | #define AUD_RESET_FRDDR_B	8 | ||||||
|  | #define AUD_RESET_TODDR_A	9 | ||||||
|  | #define AUD_RESET_TODDR_B	10 | ||||||
|  | #define AUD_RESET_SPDIFIN	11 | ||||||
|  | #define AUD_RESET_RESAMPLE	12 | ||||||
|  | #define AUD_RESET_EQDRC		13 | ||||||
|  | #define AUD_RESET_LOCKER	14 | ||||||
|  | #define AUD_RESET_TOACODEC	30 | ||||||
|  | #define AUD_RESET_CLKTREE	31 | ||||||
|  | 
 | ||||||
|  | #define AUD_VAD_RESET_DDRARB	0 | ||||||
|  | #define AUD_VAD_RESET_PDM	1 | ||||||
|  | #define AUD_VAD_RESET_TDMIN_VAD	2 | ||||||
|  | #define AUD_VAD_RESET_TODDR_VAD	3 | ||||||
|  | #define AUD_VAD_RESET_TOVAD	4 | ||||||
|  | #define AUD_VAD_RESET_CLKTREE	5 | ||||||
|  | 
 | ||||||
|  | #endif /* _DT_BINDINGS_AMLOGIC_MESON_A1_AUDIO_RESET_H */ | ||||||
|  | @ -105,6 +105,14 @@ bool qcom_scm_ice_available(void); | ||||||
| int qcom_scm_ice_invalidate_key(u32 index); | int qcom_scm_ice_invalidate_key(u32 index); | ||||||
| int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, | int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, | ||||||
| 			 enum qcom_scm_ice_cipher cipher, u32 data_unit_size); | 			 enum qcom_scm_ice_cipher cipher, u32 data_unit_size); | ||||||
|  | bool qcom_scm_has_wrapped_key_support(void); | ||||||
|  | int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size, | ||||||
|  | 			      u8 *sw_secret, size_t sw_secret_size); | ||||||
|  | int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size); | ||||||
|  | int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size, | ||||||
|  | 			     u8 *eph_key, size_t eph_key_size); | ||||||
|  | int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size, | ||||||
|  | 			    u8 *lt_key, size_t lt_key_size); | ||||||
| 
 | 
 | ||||||
| bool qcom_scm_hdcp_available(void); | bool qcom_scm_hdcp_available(void); | ||||||
| int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); | int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); | ||||||
|  |  | ||||||
							
								
								
									
										32
									
								
								include/linux/memory/ti-aemif.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								include/linux/memory/ti-aemif.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | ||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
|  | 
 | ||||||
|  | #ifndef __MEMORY_TI_AEMIF_H | ||||||
|  | #define __MEMORY_TI_AEMIF_H | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct aemif_cs_timings: structure to hold CS timing configuration | ||||||
|  |  * values are expressed in number of clock cycles - 1 | ||||||
|  |  * @ta: minimum turn around time | ||||||
|  |  * @rhold: read hold width | ||||||
|  |  * @rstrobe: read strobe width | ||||||
|  |  * @rsetup: read setup width | ||||||
|  |  * @whold: write hold width | ||||||
|  |  * @wstrobe: write strobe width | ||||||
|  |  * @wsetup: write setup width | ||||||
|  |  */ | ||||||
|  | struct aemif_cs_timings { | ||||||
|  | 	u32	ta; | ||||||
|  | 	u32	rhold; | ||||||
|  | 	u32	rstrobe; | ||||||
|  | 	u32	rsetup; | ||||||
|  | 	u32	whold; | ||||||
|  | 	u32	wstrobe; | ||||||
|  | 	u32	wsetup; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct aemif_device; | ||||||
|  | 
 | ||||||
|  | int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings); | ||||||
|  | int aemif_check_cs_timings(struct aemif_cs_timings *timings); | ||||||
|  | 
 | ||||||
|  | #endif // __MEMORY_TI_AEMIF_H
 | ||||||
|  | @ -66,10 +66,6 @@ extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, | ||||||
| 
 | 
 | ||||||
| struct device_node; | struct device_node; | ||||||
| 
 | 
 | ||||||
| extern int gpmc_get_client_irq(unsigned irq_config); |  | ||||||
| 
 |  | ||||||
| extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); |  | ||||||
| 
 |  | ||||||
| extern void gpmc_cs_write_reg(int cs, int idx, u32 val); | extern void gpmc_cs_write_reg(int cs, int idx, u32 val); | ||||||
| extern int gpmc_calc_divider(unsigned int sync_clk); | extern int gpmc_calc_divider(unsigned int sync_clk); | ||||||
| extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, | extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, | ||||||
|  |  | ||||||
|  | @ -13,10 +13,11 @@ | ||||||
| #include <linux/notifier.h> | #include <linux/notifier.h> | ||||||
| #include <linux/types.h> | #include <linux/types.h> | ||||||
| 
 | 
 | ||||||
| enum scmi_nxp_protocol { | #define	SCMI_PROTOCOL_IMX_BBM	0x81 | ||||||
| 	SCMI_PROTOCOL_IMX_BBM = 0x81, | #define	SCMI_PROTOCOL_IMX_MISC	0x84 | ||||||
| 	SCMI_PROTOCOL_IMX_MISC = 0x84, | 
 | ||||||
| }; | #define SCMI_IMX_VENDOR		"NXP" | ||||||
|  | #define SCMI_IMX_SUBVENDOR	"IMX" | ||||||
| 
 | 
 | ||||||
| struct scmi_imx_bbm_proto_ops { | struct scmi_imx_bbm_proto_ops { | ||||||
| 	int (*rtc_time_set)(const struct scmi_protocol_handle *ph, u32 id, | 	int (*rtc_time_set)(const struct scmi_protocol_handle *ph, u32 id, | ||||||
|  |  | ||||||
|  | @ -1,23 +0,0 @@ | ||||||
| /* SPDX-License-Identifier: GPL-2.0 */ |  | ||||||
| #ifndef __SOC_RESET_MESON_AUX_H |  | ||||||
| #define __SOC_RESET_MESON_AUX_H |  | ||||||
| 
 |  | ||||||
| #include <linux/err.h> |  | ||||||
| 
 |  | ||||||
| struct device; |  | ||||||
| struct regmap; |  | ||||||
| 
 |  | ||||||
| #if IS_ENABLED(CONFIG_RESET_MESON_AUX) |  | ||||||
| int devm_meson_rst_aux_register(struct device *dev, |  | ||||||
| 				struct regmap *map, |  | ||||||
| 				const char *adev_name); |  | ||||||
| #else |  | ||||||
| static inline int devm_meson_rst_aux_register(struct device *dev, |  | ||||||
| 					      struct regmap *map, |  | ||||||
| 					      const char *adev_name) |  | ||||||
| { |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif /* __SOC_RESET_MESON_AUX_H */ |  | ||||||
|  | @ -6,6 +6,9 @@ | ||||||
| #ifndef __SOC_QCOM_TCS_H__ | #ifndef __SOC_QCOM_TCS_H__ | ||||||
| #define __SOC_QCOM_TCS_H__ | #define __SOC_QCOM_TCS_H__ | ||||||
| 
 | 
 | ||||||
|  | #include <linux/bitfield.h> | ||||||
|  | #include <linux/bits.h> | ||||||
|  | 
 | ||||||
| #define MAX_RPMH_PAYLOAD	16 | #define MAX_RPMH_PAYLOAD	16 | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -60,22 +63,17 @@ struct tcs_request { | ||||||
| 	struct tcs_cmd *cmds; | 	struct tcs_cmd *cmds; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define BCM_TCS_CMD_COMMIT_SHFT		30 | #define BCM_TCS_CMD_COMMIT_MASK		BIT(30) | ||||||
| #define BCM_TCS_CMD_COMMIT_MASK		0x40000000 | #define BCM_TCS_CMD_VALID_MASK		BIT(29) | ||||||
| #define BCM_TCS_CMD_VALID_SHFT		29 | #define BCM_TCS_CMD_VOTE_MASK		GENMASK(13, 0) | ||||||
| #define BCM_TCS_CMD_VALID_MASK		0x20000000 | #define BCM_TCS_CMD_VOTE_Y_MASK		GENMASK(13, 0) | ||||||
| #define BCM_TCS_CMD_VOTE_X_SHFT		14 | #define BCM_TCS_CMD_VOTE_X_MASK		GENMASK(27, 14) | ||||||
| #define BCM_TCS_CMD_VOTE_MASK		0x3fff |  | ||||||
| #define BCM_TCS_CMD_VOTE_Y_SHFT		0 |  | ||||||
| #define BCM_TCS_CMD_VOTE_Y_MASK		0xfffc000 |  | ||||||
| 
 | 
 | ||||||
| /* Construct a Bus Clock Manager (BCM) specific TCS command */ | /* Construct a Bus Clock Manager (BCM) specific TCS command */ | ||||||
| #define BCM_TCS_CMD(commit, valid, vote_x, vote_y)		\ | #define BCM_TCS_CMD(commit, valid, vote_x, vote_y)		\ | ||||||
| 	(((commit) << BCM_TCS_CMD_COMMIT_SHFT) |		\ | 	(u32_encode_bits(commit, BCM_TCS_CMD_COMMIT_MASK) |	\ | ||||||
| 	((valid) << BCM_TCS_CMD_VALID_SHFT) |			\ | 	u32_encode_bits(valid, BCM_TCS_CMD_VALID_MASK) |	\ | ||||||
| 	((cpu_to_le32(vote_x) &					\ | 	u32_encode_bits(vote_x, BCM_TCS_CMD_VOTE_X_MASK) |	\ | ||||||
| 	BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_X_SHFT) |	\ | 	u32_encode_bits(vote_y, BCM_TCS_CMD_VOTE_Y_MASK)) | ||||||
| 	((cpu_to_le32(vote_y) &					\ |  | ||||||
| 	BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_Y_SHFT)) |  | ||||||
| 
 | 
 | ||||||
| #endif /* __SOC_QCOM_TCS_H__ */ | #endif /* __SOC_QCOM_TCS_H__ */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds