1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

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:
Linus Torvalds 2025-01-24 14:56:59 -08:00
commit f2ad904e92
47 changed files with 877 additions and 375 deletions

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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>

View file

@ -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)); \

View file

@ -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)

View file

@ -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);

View file

@ -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);

View file

@ -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",

View file

@ -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");

View file

@ -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");

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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;
} }
} }

View file

@ -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

View file

@ -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");

View file

@ -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
View 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");

View file

@ -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);

View file

@ -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 = {

View file

@ -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

View file

@ -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 @@ err:
} }
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},

View file

@ -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) |

View file

@ -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,

View file

@ -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, },
{}, {},
}; };

View file

@ -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",
}; };

View file

@ -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);

View file

@ -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));

View file

@ -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

View file

@ -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)

View file

@ -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);

View file

@ -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.

View file

@ -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 }
}; };

View file

@ -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);
} }

View file

@ -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
/* /*

View 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 */

View file

@ -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);

View 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

View file

@ -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,

View file

@ -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,

View file

@ -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 */

View file

@ -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__ */