summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-08-03 19:30:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-03 19:30:59 -0700
commit822ef14e9dc73079c646d33aa77e2ac42361b39e (patch)
tree34a8f741f64ef1e617575204db81aa6484df55ac /drivers/soc
parent6ce076f4159fcf7436cce1299b05eabe200592f4 (diff)
parentd76cfc7c3ad23a79eaf348a1b483e89f8ac3041a (diff)
Merge tag 'arm-drivers-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann: "A couple of subsystems have their own subsystem maintainers but choose to have the code merged through the soc tree as upstream, as the code tends to be used across multiple SoCs or has SoC specific drivers itself: - memory controllers: Krzysztof Kozlowski takes ownership of the drivers/memory subsystem and its drivers, starting out with a set of cleanup patches. A larger driver for the Tegra memory controller that was accidentally missed for v5.8 is now added. - reset controllers: Only minor updates to drivers/reset this time - firmware: The "turris mox" firmware driver gains support for signed firmware blobs The tegra firmware driver gets extended to export some debug information Various updates to i.MX firmware drivers, mostly cosmetic - ARM SCMI/SCPI: A new mechanism for platform notifications is added, among a number of minor changes. - optee: Probing of the TEE bus is rewritten to better support detection of devices that depend on the tee-supplicant user space. A new firmware based trusted platform module (fTPM) driver is added based on OP-TEE - SoC attributes: A new driver is added to provide a generic soc_device for identifying a machine through the SMCCC ARCH_SOC_ID firmware interface rather than by probing SoC family specific registers. The series also contains some cleanups to the common soc_device code. There are also a number of updates to SoC specific drivers, the main ones are: - Mediatek cmdq driver gains a few in-kernel interfaces - Minor updates to Qualcomm RPMh, socinfo, rpm drivers, mostly adding support for additional SoC variants - The Qualcomm GENI core code gains interconnect path voting and performance level support, and integrating this into a number of device drivers. - A new driver for Samsung Exynos5800 voltage coupler for - Renesas RZ/G2H (R8A774E1) SoC support gets added to a couple of SoC specific device drivers - Updates to the TI K3 Ring Accelerator driver" * tag 'arm-drivers-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (164 commits) soc: qcom: geni: Fix unused label warning soc: qcom: smd-rpm: Fix kerneldoc memory: jz4780_nemc: Only request IO memory the driver will use soc: qcom: pdr: Reorder the PD state indication ack MAINTAINERS: Add Git repository for memory controller drivers memory: brcmstb_dpfe: Fix language typo memory: samsung: exynos5422-dmc: Correct white space issues memory: samsung: exynos-srom: Correct alignment memory: pl172: Enclose macro argument usage in parenthesis memory: of: Correct kerneldoc memory: omap-gpmc: Fix language typo memory: omap-gpmc: Correct white space issues memory: omap-gpmc: Use 'unsigned int' for consistency memory: omap-gpmc: Enclose macro argument usage in parenthesis memory: omap-gpmc: Correct kerneldoc memory: mvebu-devbus: Align with open parenthesis memory: mvebu-devbus: Add missing braces to all arms of if statement memory: bt1-l2-ctl: Add blank lines after declarations soc: TI knav_qmss: make symbol 'knav_acc_range_ops' static firmware: ti_sci: Replace HTTP links with HTTPS ones ...
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/imx/Kconfig10
-rw-r--r--drivers/soc/imx/Makefile1
-rw-r--r--drivers/soc/imx/soc-imx-scu.c187
-rw-r--r--drivers/soc/mediatek/mtk-cmdq-helper.c46
-rw-r--r--drivers/soc/qcom/Kconfig2
-rw-r--r--drivers/soc/qcom/pdr_interface.c4
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c165
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c19
-rw-r--r--drivers/soc/qcom/rpmh.c4
-rw-r--r--drivers/soc/qcom/smd-rpm.c5
-rw-r--r--drivers/soc/qcom/socinfo.c65
-rw-r--r--drivers/soc/renesas/Kconfig11
-rw-r--r--drivers/soc/renesas/Makefile1
-rw-r--r--drivers/soc/renesas/r8a774e1-sysc.c43
-rw-r--r--drivers/soc/renesas/rcar-rst.c1
-rw-r--r--drivers/soc/renesas/rcar-sysc.c3
-rw-r--r--drivers/soc/renesas/rcar-sysc.h1
-rw-r--r--drivers/soc/renesas/renesas-soc.c8
-rw-r--r--drivers/soc/samsung/Kconfig3
-rw-r--r--drivers/soc/samsung/Makefile1
-rw-r--r--drivers/soc/samsung/exynos-regulator-coupler.c221
-rw-r--r--drivers/soc/tegra/fuse/tegra-apbmisc.c2
-rw-r--r--drivers/soc/ti/k3-ringacc.c200
-rw-r--r--drivers/soc/ti/knav_qmss_acc.c2
-rw-r--r--drivers/soc/ux500/ux500-soc-id.c22
-rw-r--r--drivers/soc/versatile/soc-integrator.c48
-rw-r--r--drivers/soc/versatile/soc-realview.c48
27 files changed, 782 insertions, 341 deletions
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
index d515d2cc20ed..a9370f4aacca 100644
--- a/drivers/soc/imx/Kconfig
+++ b/drivers/soc/imx/Kconfig
@@ -8,20 +8,12 @@ config IMX_GPCV2_PM_DOMAINS
select PM_GENERIC_DOMAINS
default y if SOC_IMX7D
-config IMX_SCU_SOC
- bool "i.MX System Controller Unit SoC info support"
- depends on IMX_SCU
- select SOC_BUS
- help
- If you say yes here you get support for the NXP i.MX System
- Controller Unit SoC info module, it will provide the SoC info
- like SoC family, ID and revision etc.
-
config SOC_IMX8M
bool "i.MX8M SoC family support"
depends on ARCH_MXC || COMPILE_TEST
default ARCH_MXC && ARM64
select SOC_BUS
+ select ARM_GIC_V3 if ARCH_MXC
help
If you say yes here you get support for the NXP i.MX8M family
support, it will provide the SoC info like SoC family,
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
index 446143241fe7..078dc918f4f3 100644
--- a/drivers/soc/imx/Makefile
+++ b/drivers/soc/imx/Makefile
@@ -5,4 +5,3 @@ endif
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
-obj-$(CONFIG_IMX_SCU_SOC) += soc-imx-scu.o
diff --git a/drivers/soc/imx/soc-imx-scu.c b/drivers/soc/imx/soc-imx-scu.c
deleted file mode 100644
index 20d37eaeb5f2..000000000000
--- a/drivers/soc/imx/soc-imx-scu.c
+++ /dev/null
@@ -1,187 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright 2019 NXP.
- */
-
-#include <dt-bindings/firmware/imx/rsrc.h>
-#include <linux/firmware/imx/sci.h>
-#include <linux/slab.h>
-#include <linux/sys_soc.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-
-#define IMX_SCU_SOC_DRIVER_NAME "imx-scu-soc"
-
-static struct imx_sc_ipc *soc_ipc_handle;
-
-struct imx_sc_msg_misc_get_soc_id {
- struct imx_sc_rpc_msg hdr;
- union {
- struct {
- u32 control;
- u16 resource;
- } __packed req;
- struct {
- u32 id;
- } resp;
- } data;
-} __packed __aligned(4);
-
-struct imx_sc_msg_misc_get_soc_uid {
- struct imx_sc_rpc_msg hdr;
- u32 uid_low;
- u32 uid_high;
-} __packed;
-
-static int imx_scu_soc_uid(u64 *soc_uid)
-{
- struct imx_sc_msg_misc_get_soc_uid msg;
- struct imx_sc_rpc_msg *hdr = &msg.hdr;
- int ret;
-
- hdr->ver = IMX_SC_RPC_VERSION;
- hdr->svc = IMX_SC_RPC_SVC_MISC;
- hdr->func = IMX_SC_MISC_FUNC_UNIQUE_ID;
- hdr->size = 1;
-
- ret = imx_scu_call_rpc(soc_ipc_handle, &msg, true);
- if (ret) {
- pr_err("%s: get soc uid failed, ret %d\n", __func__, ret);
- return ret;
- }
-
- *soc_uid = msg.uid_high;
- *soc_uid <<= 32;
- *soc_uid |= msg.uid_low;
-
- return 0;
-}
-
-static int imx_scu_soc_id(void)
-{
- struct imx_sc_msg_misc_get_soc_id msg;
- struct imx_sc_rpc_msg *hdr = &msg.hdr;
- int ret;
-
- hdr->ver = IMX_SC_RPC_VERSION;
- hdr->svc = IMX_SC_RPC_SVC_MISC;
- hdr->func = IMX_SC_MISC_FUNC_GET_CONTROL;
- hdr->size = 3;
-
- msg.data.req.control = IMX_SC_C_ID;
- msg.data.req.resource = IMX_SC_R_SYSTEM;
-
- ret = imx_scu_call_rpc(soc_ipc_handle, &msg, true);
- if (ret) {
- pr_err("%s: get soc info failed, ret %d\n", __func__, ret);
- return ret;
- }
-
- return msg.data.resp.id;
-}
-
-static int imx_scu_soc_probe(struct platform_device *pdev)
-{
- struct soc_device_attribute *soc_dev_attr;
- struct soc_device *soc_dev;
- int id, ret;
- u64 uid = 0;
- u32 val;
-
- ret = imx_scu_get_handle(&soc_ipc_handle);
- if (ret)
- return ret;
-
- soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr),
- GFP_KERNEL);
- if (!soc_dev_attr)
- return -ENOMEM;
-
- soc_dev_attr->family = "Freescale i.MX";
-
- ret = of_property_read_string(of_root,
- "model",
- &soc_dev_attr->machine);
- if (ret)
- return ret;
-
- id = imx_scu_soc_id();
- if (id < 0)
- return -EINVAL;
-
- ret = imx_scu_soc_uid(&uid);
- if (ret < 0)
- return -EINVAL;
-
- /* format soc_id value passed from SCU firmware */
- val = id & 0x1f;
- soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "0x%x", val);
- if (!soc_dev_attr->soc_id)
- return -ENOMEM;
-
- /* format revision value passed from SCU firmware */
- val = (id >> 5) & 0xf;
- val = (((val >> 2) + 1) << 4) | (val & 0x3);
- soc_dev_attr->revision = kasprintf(GFP_KERNEL,
- "%d.%d",
- (val >> 4) & 0xf,
- val & 0xf);
- if (!soc_dev_attr->revision) {
- ret = -ENOMEM;
- goto free_soc_id;
- }
-
- soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", uid);
- if (!soc_dev_attr->serial_number) {
- ret = -ENOMEM;
- goto free_revision;
- }
-
- soc_dev = soc_device_register(soc_dev_attr);
- if (IS_ERR(soc_dev)) {
- ret = PTR_ERR(soc_dev);
- goto free_serial_number;
- }
-
- return 0;
-
-free_serial_number:
- kfree(soc_dev_attr->serial_number);
-free_revision:
- kfree(soc_dev_attr->revision);
-free_soc_id:
- kfree(soc_dev_attr->soc_id);
- return ret;
-}
-
-static struct platform_driver imx_scu_soc_driver = {
- .driver = {
- .name = IMX_SCU_SOC_DRIVER_NAME,
- },
- .probe = imx_scu_soc_probe,
-};
-
-static int __init imx_scu_soc_init(void)
-{
- struct platform_device *pdev;
- struct device_node *np;
- int ret;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx-scu");
- if (!np)
- return -ENODEV;
-
- of_node_put(np);
-
- ret = platform_driver_register(&imx_scu_soc_driver);
- if (ret)
- return ret;
-
- pdev = platform_device_register_simple(IMX_SCU_SOC_DRIVER_NAME,
- -1, NULL, 0);
- if (IS_ERR(pdev))
- platform_driver_unregister(&imx_scu_soc_driver);
-
- return PTR_ERR_OR_ZERO(pdev);
-}
-device_initcall(imx_scu_soc_init);
diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
index 87ee9f767b7a..dc644cfb6419 100644
--- a/drivers/soc/mediatek/mtk-cmdq-helper.c
+++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
@@ -12,6 +12,7 @@
#define CMDQ_WRITE_ENABLE_MASK BIT(0)
#define CMDQ_POLL_ENABLE_MASK BIT(0)
#define CMDQ_EOC_IRQ_EN BIT(0)
+#define CMDQ_REG_TYPE 1
struct cmdq_instruction {
union {
@@ -21,8 +22,17 @@ struct cmdq_instruction {
union {
u16 offset;
u16 event;
+ u16 reg_dst;
+ };
+ union {
+ u8 subsys;
+ struct {
+ u8 sop:5;
+ u8 arg_c_t:1;
+ u8 src_t:1;
+ u8 dst_t:1;
+ };
};
- u8 subsys;
u8 op;
};
@@ -243,6 +253,21 @@ int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
}
EXPORT_SYMBOL(cmdq_pkt_clear_event);
+int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event)
+{
+ struct cmdq_instruction inst = {};
+
+ if (event >= CMDQ_MAX_EVENT)
+ return -EINVAL;
+
+ inst.op = CMDQ_CODE_WFE;
+ inst.value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE;
+ inst.event = event;
+
+ return cmdq_pkt_append_command(pkt, inst);
+}
+EXPORT_SYMBOL(cmdq_pkt_set_event);
+
int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys,
u16 offset, u32 value)
{
@@ -278,7 +303,19 @@ int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
}
EXPORT_SYMBOL(cmdq_pkt_poll_mask);
-static int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
+int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
+{
+ struct cmdq_instruction inst = {};
+
+ inst.op = CMDQ_CODE_LOGIC;
+ inst.dst_t = CMDQ_REG_TYPE;
+ inst.reg_dst = reg_idx;
+ inst.value = value;
+ return cmdq_pkt_append_command(pkt, inst);
+}
+EXPORT_SYMBOL(cmdq_pkt_assign);
+
+int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
{
struct cmdq_instruction inst = { {0} };
int err;
@@ -297,6 +334,7 @@ static int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
return err;
}
+EXPORT_SYMBOL(cmdq_pkt_finalize);
static void cmdq_pkt_flush_async_cb(struct cmdq_cb_data data)
{
@@ -331,10 +369,6 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb,
unsigned long flags = 0;
struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
- err = cmdq_pkt_finalize(pkt);
- if (err < 0)
- return err;
-
pkt->cb.cb = cb;
pkt->cb.data = data;
pkt->async_cb.cb = cmdq_pkt_flush_async_cb;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 07bb261a63d2..899f8c066797 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -89,7 +89,7 @@ config QCOM_RMTFS_MEM
config QCOM_RPMH
bool "Qualcomm RPM-Hardened (RPMH) Communication"
- depends on ARCH_QCOM && ARM64 || COMPILE_TEST
+ depends on ARCH_QCOM || COMPILE_TEST
help
Support for communication with the hardened-RPM blocks in
Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an
diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
index bdcf16f88a97..4c9225f15c4e 100644
--- a/drivers/soc/qcom/pdr_interface.c
+++ b/drivers/soc/qcom/pdr_interface.c
@@ -278,13 +278,15 @@ static void pdr_indack_work(struct work_struct *work)
list_for_each_entry_safe(ind, tmp, &pdr->indack_list, node) {
pds = ind->pds;
- pdr_send_indack_msg(pdr, pds, ind->transaction_id);
mutex_lock(&pdr->status_lock);
pds->state = ind->curr_state;
pdr->status(pds->state, pds->service_path, pdr->priv);
mutex_unlock(&pdr->status_lock);
+ /* Ack the indication after clients release the PD resources */
+ pdr_send_indack_msg(pdr, pds, ind->transaction_id);
+
mutex_lock(&pdr->list_lock);
list_del(&ind->node);
mutex_unlock(&pdr->list_lock);
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index 7d622ea1274e..d0e4f520cff8 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -3,6 +3,7 @@
#include <linux/acpi.h>
#include <linux/clk.h>
+#include <linux/console.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
@@ -90,8 +91,14 @@ struct geni_wrapper {
struct device *dev;
void __iomem *base;
struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
+ struct geni_icc_path to_core;
};
+static const char * const icc_path_names[] = {"qup-core", "qup-config",
+ "qup-memory"};
+
+static struct geni_wrapper *earlycon_wrapper;
+
#define QUP_HW_VER_REG 0x4
/* Common SE registers */
@@ -720,11 +727,132 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
}
EXPORT_SYMBOL(geni_se_rx_dma_unprep);
+int geni_icc_get(struct geni_se *se, const char *icc_ddr)
+{
+ int i, err;
+ const char *icc_names[] = {"qup-core", "qup-config", icc_ddr};
+
+ for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
+ if (!icc_names[i])
+ continue;
+
+ se->icc_paths[i].path = devm_of_icc_get(se->dev, icc_names[i]);
+ if (IS_ERR(se->icc_paths[i].path))
+ goto err;
+ }
+
+ return 0;
+
+err:
+ err = PTR_ERR(se->icc_paths[i].path);
+ if (err != -EPROBE_DEFER)
+ dev_err_ratelimited(se->dev, "Failed to get ICC path '%s': %d\n",
+ icc_names[i], err);
+ return err;
+
+}
+EXPORT_SYMBOL(geni_icc_get);
+
+int geni_icc_set_bw(struct geni_se *se)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
+ ret = icc_set_bw(se->icc_paths[i].path,
+ se->icc_paths[i].avg_bw, se->icc_paths[i].avg_bw);
+ if (ret) {
+ dev_err_ratelimited(se->dev, "ICC BW voting failed on path '%s': %d\n",
+ icc_path_names[i], ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(geni_icc_set_bw);
+
+void geni_icc_set_tag(struct geni_se *se, u32 tag)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++)
+ icc_set_tag(se->icc_paths[i].path, tag);
+}
+EXPORT_SYMBOL(geni_icc_set_tag);
+
+/* To do: Replace this by icc_bulk_enable once it's implemented in ICC core */
+int geni_icc_enable(struct geni_se *se)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
+ ret = icc_enable(se->icc_paths[i].path);
+ if (ret) {
+ dev_err_ratelimited(se->dev, "ICC enable failed on path '%s': %d\n",
+ icc_path_names[i], ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(geni_icc_enable);
+
+int geni_icc_disable(struct geni_se *se)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
+ ret = icc_disable(se->icc_paths[i].path);
+ if (ret) {
+ dev_err_ratelimited(se->dev, "ICC disable failed on path '%s': %d\n",
+ icc_path_names[i], ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(geni_icc_disable);
+
+void geni_remove_earlycon_icc_vote(void)
+{
+ struct platform_device *pdev;
+ struct geni_wrapper *wrapper;
+ struct device_node *parent;
+ struct device_node *child;
+
+ if (!earlycon_wrapper)
+ return;
+
+ wrapper = earlycon_wrapper;
+ parent = of_get_next_parent(wrapper->dev->of_node);
+ for_each_child_of_node(parent, child) {
+ if (!of_device_is_compatible(child, "qcom,geni-se-qup"))
+ continue;
+
+ pdev = of_find_device_by_node(child);
+ if (!pdev)
+ continue;
+
+ wrapper = platform_get_drvdata(pdev);
+ icc_put(wrapper->to_core.path);
+ wrapper->to_core.path = NULL;
+
+ }
+ of_node_put(parent);
+
+ earlycon_wrapper = NULL;
+}
+EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);
+
static int geni_se_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct geni_wrapper *wrapper;
+ struct console __maybe_unused *bcon;
+ bool __maybe_unused has_earlycon = false;
int ret;
wrapper = devm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL);
@@ -747,6 +875,43 @@ static int geni_se_probe(struct platform_device *pdev)
}
}
+#ifdef CONFIG_SERIAL_EARLYCON
+ for_each_console(bcon) {
+ if (!strcmp(bcon->name, "qcom_geni")) {
+ has_earlycon = true;
+ break;
+ }
+ }
+ if (!has_earlycon)
+ goto exit;
+
+ wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
+ if (IS_ERR(wrapper->to_core.path))
+ return PTR_ERR(wrapper->to_core.path);
+ /*
+ * Put minmal BW request on core clocks on behalf of early console.
+ * The vote will be removed earlycon exit function.
+ *
+ * Note: We are putting vote on each QUP wrapper instead only to which
+ * earlycon is connected because QUP core clock of different wrapper
+ * share same voltage domain. If core1 is put to 0, then core2 will
+ * also run at 0, if not voted. Default ICC vote will be removed ASA
+ * we touch any of the core clock.
+ * core1 = core2 = max(core1, core2)
+ */
+ ret = icc_set_bw(wrapper->to_core.path, GENI_DEFAULT_BW,
+ GENI_DEFAULT_BW);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: ICC BW voting failed for core: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (of_get_compatible_child(pdev->dev.of_node, "qcom,geni-debug-uart"))
+ earlycon_wrapper = wrapper;
+ of_node_put(pdev->dev.of_node);
+exit:
+#endif
dev_set_drvdata(dev, wrapper);
dev_dbg(dev, "GENI SE Driver probed\n");
return devm_of_platform_populate(dev);
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 076fd27f3081..ae6675782581 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -175,13 +175,21 @@ static void write_tcs_reg(const struct rsc_drv *drv, int reg, int tcs_id,
static void write_tcs_reg_sync(const struct rsc_drv *drv, int reg, int tcs_id,
u32 data)
{
- u32 new_data;
+ int i;
writel(data, tcs_reg_addr(drv, reg, tcs_id));
- if (readl_poll_timeout_atomic(tcs_reg_addr(drv, reg, tcs_id), new_data,
- new_data == data, 1, USEC_PER_SEC))
- pr_err("%s: error writing %#x to %d:%#x\n", drv->name,
- data, tcs_id, reg);
+
+ /*
+ * Wait until we read back the same value. Use a counter rather than
+ * ktime for timeout since this may be called after timekeeping stops.
+ */
+ for (i = 0; i < USEC_PER_SEC; i++) {
+ if (readl(tcs_reg_addr(drv, reg, tcs_id)) == data)
+ return;
+ udelay(1);
+ }
+ pr_err("%s: error writing %#x to %d:%#x\n", drv->name,
+ data, tcs_id, reg);
}
/**
@@ -1023,6 +1031,7 @@ static struct platform_driver rpmh_driver = {
.driver = {
.name = "rpmh",
.of_match_table = rpmh_drv_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index f2b5b46ccd1f..b61e183ede69 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -497,7 +497,7 @@ exit:
*
* Invalidate the sleep and wake values in batch_cache.
*/
-int rpmh_invalidate(const struct device *dev)
+void rpmh_invalidate(const struct device *dev)
{
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
struct batch_cache_req *req, *tmp;
@@ -509,7 +509,5 @@ int rpmh_invalidate(const struct device *dev)
INIT_LIST_HEAD(&ctrlr->batch_cache);
ctrlr->dirty = true;
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
-
- return 0;
}
EXPORT_SYMBOL(rpmh_invalidate);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 005dd30c58fa..b93218cb50b5 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -20,6 +20,7 @@
* struct qcom_smd_rpm - state of the rpm device driver
* @rpm_channel: reference to the smd channel
* @icc: interconnect proxy device
+ * @dev: rpm device
* @ack: completion for acks
* @lock: mutual exclusion around the send/complete pair
* @ack_status: result of the rpm request
@@ -86,6 +87,7 @@ struct qcom_rpm_message {
/**
* qcom_rpm_smd_write - write @buf to @type:@id
* @rpm: rpm handle
+ * @state: active/sleep state flags
* @type: resource type
* @id: resource identifier
* @buf: the data to be written
@@ -230,9 +232,12 @@ static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev)
static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-apq8084" },
+ { .compatible = "qcom,rpm-ipq6018" },
{ .compatible = "qcom,rpm-msm8916" },
+ { .compatible = "qcom,rpm-msm8936" },
{ .compatible = "qcom,rpm-msm8974" },
{ .compatible = "qcom,rpm-msm8976" },
+ { .compatible = "qcom,rpm-msm8994" },
{ .compatible = "qcom,rpm-msm8996" },
{ .compatible = "qcom,rpm-msm8998" },
{ .compatible = "qcom,rpm-sdm660" },
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 5983c6ffb078..e19102f46302 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -24,6 +24,7 @@
#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
+#define SMEM_SOCINFO_CHIP_ID_LENGTH 32
/*
* SMEM item id, used to acquire handles to respective
@@ -121,6 +122,16 @@ struct socinfo {
__le32 chip_family;
__le32 raw_device_family;
__le32 raw_device_num;
+ /* Version 13 */
+ __le32 nproduct_id;
+ char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH];
+ /* Version 14 */
+ __le32 num_clusters;
+ __le32 ncluster_array_offset;
+ __le32 num_defective_parts;
+ __le32 ndefective_parts_array_offset;
+ /* Version 15 */
+ __le32 nmodem_supported;
};
#ifdef CONFIG_DEBUG_FS
@@ -135,6 +146,12 @@ struct socinfo_params {
u32 raw_ver;
u32 hw_plat;
u32 fmt;
+ u32 nproduct_id;
+ u32 num_clusters;
+ u32 ncluster_array_offset;
+ u32 num_defective_parts;
+ u32 ndefective_parts_array_offset;
+ u32 nmodem_supported;
};
struct smem_image_version {
@@ -202,8 +219,10 @@ static const struct soc_id soc_id[] = {
{ 310, "MSM8996AU" },
{ 311, "APQ8096AU" },
{ 312, "APQ8096SG" },
+ { 318, "SDM630" },
{ 321, "SDM845" },
{ 341, "SDA845" },
+ { 356, "SM8250" },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
@@ -256,7 +275,10 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p)
if (model < 0)
return -EINVAL;
- seq_printf(seq, "%s\n", pmic_models[model]);
+ if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model])
+ seq_printf(seq, "%s\n", pmic_models[model]);
+ else
+ seq_printf(seq, "unknown (%d)\n", model);
return 0;
}
@@ -272,9 +294,19 @@ static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p)
return 0;
}
+static int qcom_show_chip_id(struct seq_file *seq, void *p)
+{
+ struct socinfo *socinfo = seq->private;
+
+ seq_printf(seq, "%s\n", socinfo->chip_id);
+
+ return 0;
+}
+
QCOM_OPEN(build_id, qcom_show_build_id);
QCOM_OPEN(pmic_model, qcom_show_pmic_model);
QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision);
+QCOM_OPEN(chip_id, qcom_show_chip_id);
#define DEFINE_IMAGE_OPS(type) \
static int show_image_##type(struct seq_file *seq, void *p) \
@@ -312,7 +344,38 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt);
+ debugfs_create_x32("info_fmt", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.fmt);
+
switch (qcom_socinfo->info.fmt) {
+ case SOCINFO_VERSION(0, 15):
+ qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported);
+
+ debugfs_create_u32("nmodem_supported", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.nmodem_supported);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 14):
+ qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters);
+ qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset);
+ qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts);
+ qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset);
+
+ debugfs_create_u32("num_clusters", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.num_clusters);
+ debugfs_create_u32("ncluster_array_offset", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.ncluster_array_offset);
+ debugfs_create_u32("num_defective_parts", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.num_defective_parts);
+ debugfs_create_u32("ndefective_parts_array_offset", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.ndefective_parts_array_offset);
+ /* Fall through */
+ case SOCINFO_VERSION(0, 13):
+ qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id);
+
+ debugfs_create_u32("nproduct_id", 0400, qcom_socinfo->dbg_root,
+ &qcom_socinfo->info.nproduct_id);
+ DEBUGFS_ADD(info, chip_id);
+ /* Fall through */
case SOCINFO_VERSION(0, 12):
qcom_socinfo->info.chip_family =
__le32_to_cpu(info->chip_family);
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 53cd8d2d0cd2..30984659df90 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -201,6 +201,13 @@ config ARCH_R8A774C0
help
This enables support for the Renesas RZ/G2E SoC.
+config ARCH_R8A774E1
+ bool "Renesas RZ/G2H SoC Platform"
+ select ARCH_RCAR_GEN3
+ select SYSC_R8A774E1
+ help
+ This enables support for the Renesas RZ/G2H SoC.
+
config ARCH_R8A77950
bool "Renesas R-Car H3 ES1.x SoC Platform"
select ARCH_RCAR_GEN3
@@ -296,6 +303,10 @@ config SYSC_R8A774C0
bool "RZ/G2E System Controller support" if COMPILE_TEST
select SYSC_RCAR
+config SYSC_R8A774E1
+ bool "RZ/G2H System Controller support" if COMPILE_TEST
+ select SYSC_RCAR
+
config SYSC_R8A7779
bool "R-Car H1 System Controller support" if COMPILE_TEST
select SYSC_RCAR
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index 08296d78e2ad..10a399fc486a 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_SYSC_R8A77470) += r8a77470-sysc.o
obj-$(CONFIG_SYSC_R8A774A1) += r8a774a1-sysc.o
obj-$(CONFIG_SYSC_R8A774B1) += r8a774b1-sysc.o
obj-$(CONFIG_SYSC_R8A774C0) += r8a774c0-sysc.o
+obj-$(CONFIG_SYSC_R8A774E1) += r8a774e1-sysc.o
obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o
obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o
obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o
diff --git a/drivers/soc/renesas/r8a774e1-sysc.c b/drivers/soc/renesas/r8a774e1-sysc.c
new file mode 100644
index 000000000000..18449f746455
--- /dev/null
+++ b/drivers/soc/renesas/r8a774e1-sysc.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2H System Controller
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ *
+ * Based on Renesas R-Car H3 System Controller
+ * Copyright (C) 2016-2017 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a774e1-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a774e1_areas[] __initconst = {
+ { "always-on", 0, 0, R8A774E1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+ { "ca57-scu", 0x1c0, 0, R8A774E1_PD_CA57_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
+ { "ca57-cpu0", 0x80, 0, R8A774E1_PD_CA57_CPU0, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+ { "ca57-cpu1", 0x80, 1, R8A774E1_PD_CA57_CPU1, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+ { "ca57-cpu2", 0x80, 2, R8A774E1_PD_CA57_CPU2, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+ { "ca57-cpu3", 0x80, 3, R8A774E1_PD_CA57_CPU3, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+ { "ca53-scu", 0x140, 0, R8A774E1_PD_CA53_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
+ { "ca53-cpu0", 0x200, 0, R8A774E1_PD_CA53_CPU0, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+ { "ca53-cpu1", 0x200, 1, R8A774E1_PD_CA53_CPU1, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+ { "ca53-cpu2", 0x200, 2, R8A774E1_PD_CA53_CPU2, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+ { "ca53-cpu3", 0x200, 3, R8A774E1_PD_CA53_CPU3, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+ { "a3vp", 0x340, 0, R8A774E1_PD_A3VP, R8A774E1_PD_ALWAYS_ON },
+ { "a3vc", 0x380, 0, R8A774E1_PD_A3VC, R8A774E1_PD_ALWAYS_ON },
+ { "a2vc1", 0x3c0, 1, R8A774E1_PD_A2VC1, R8A774E1_PD_A3VC },
+ { "3dg-a", 0x100, 0, R8A774E1_PD_3DG_A, R8A774E1_PD_ALWAYS_ON },
+ { "3dg-b", 0x100, 1, R8A774E1_PD_3DG_B, R8A774E1_PD_3DG_A },
+ { "3dg-c", 0x100, 2, R8A774E1_PD_3DG_C, R8A774E1_PD_3DG_B },
+ { "3dg-d", 0x100, 3, R8A774E1_PD_3DG_D, R8A774E1_PD_3DG_C },
+ { "3dg-e", 0x100, 4, R8A774E1_PD_3DG_E, R8A774E1_PD_3DG_D },
+};
+
+const struct rcar_sysc_info r8a774e1_sysc_info __initconst = {
+ .areas = r8a774e1_areas,
+ .num_areas = ARRAY_SIZE(r8a774e1_areas),
+ .extmask_offs = 0x2f8,
+ .extmask_val = BIT(0),
+};
diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c
index a2b2b1768768..a932015ce9c1 100644
--- a/drivers/soc/renesas/rcar-rst.c
+++ b/drivers/soc/renesas/rcar-rst.c
@@ -48,6 +48,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
{ .compatible = "renesas,r8a774a1-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a774b1-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a774c0-rst", .data = &rcar_rst_gen3 },
+ { .compatible = "renesas,r8a774e1-rst", .data = &rcar_rst_gen3 },
/* R-Car Gen1 */
{ .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
{ .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index 04ea87a188f1..9b235fc90027 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -296,6 +296,9 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A774C0
{ .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info },
#endif
+#ifdef CONFIG_SYSC_R8A774E1
+ { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info },
+#endif
#ifdef CONFIG_SYSC_R8A7779
{ .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
#endif
diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h
index e417f26fe155..8d861c1cfdf7 100644
--- a/drivers/soc/renesas/rcar-sysc.h
+++ b/drivers/soc/renesas/rcar-sysc.h
@@ -56,6 +56,7 @@ extern const struct rcar_sysc_info r8a77470_sysc_info;
extern const struct rcar_sysc_info r8a774a1_sysc_info;
extern const struct rcar_sysc_info r8a774b1_sysc_info;
extern const struct rcar_sysc_info r8a774c0_sysc_info;
+extern const struct rcar_sysc_info r8a774e1_sysc_info;
extern const struct rcar_sysc_info r8a7779_sysc_info;
extern const struct rcar_sysc_info r8a7790_sysc_info;
extern const struct rcar_sysc_info r8a7791_sysc_info;
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index 35dba8b8814e..f815a6a8b88b 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -126,6 +126,11 @@ static const struct renesas_soc soc_rz_g2e __initconst __maybe_unused = {
.id = 0x57,
};
+static const struct renesas_soc soc_rz_g2h __initconst __maybe_unused = {
+ .family = &fam_rzg2,
+ .id = 0x4f,
+};
+
static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = {
.family = &fam_rcar_gen1,
};
@@ -238,6 +243,9 @@ static const struct of_device_id renesas_socs[] __initconst = {
#ifdef CONFIG_ARCH_R8A774C0
{ .compatible = "renesas,r8a774c0", .data = &soc_rz_g2e },
#endif
+#ifdef CONFIG_ARCH_R8A774E1
+ { .compatible = "renesas,r8a774e1", .data = &soc_rz_g2h },
+#endif
#ifdef CONFIG_ARCH_R8A7778
{ .compatible = "renesas,r8a7778", .data = &soc_rcar_m1a },
#endif
diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index c7a2003687c7..264185664594 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -37,4 +37,7 @@ config EXYNOS_PM_DOMAINS
bool "Exynos PM domains" if COMPILE_TEST
depends on PM_GENERIC_DOMAINS || COMPILE_TEST
+config EXYNOS_REGULATOR_COUPLER
+ bool "Exynos SoC Regulator Coupler" if COMPILE_TEST
+ depends on ARCH_EXYNOS || COMPILE_TEST
endif
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index edd1d6ea064d..ecc3a32f6406 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
exynos5250-pmu.o exynos5420-pmu.o
obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
+obj-$(CONFIG_EXYNOS_REGULATOR_COUPLER) += exynos-regulator-coupler.o
diff --git a/drivers/soc/samsung/exynos-regulator-coupler.c b/drivers/soc/samsung/exynos-regulator-coupler.c
new file mode 100644
index 000000000000..61a156b44a48
--- /dev/null
+++ b/drivers/soc/samsung/exynos-regulator-coupler.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ * Author: Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * Simplified generic voltage coupler from regulator core.c
+ * The main difference is that it keeps current regulator voltage
+ * if consumers didn't apply their constraints yet.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/regulator/coupler.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
+ int *current_uV,
+ int *min_uV, int *max_uV,
+ suspend_state_t state)
+{
+ struct coupling_desc *c_desc = &rdev->coupling_desc;
+ struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
+ struct regulation_constraints *constraints = rdev->constraints;
+ int desired_min_uV = 0, desired_max_uV = INT_MAX;
+ int max_current_uV = 0, min_current_uV = INT_MAX;
+ int highest_min_uV = 0, target_uV, possible_uV;
+ int i, ret, max_spread, n_coupled = c_desc->n_coupled;
+ bool done;
+
+ *current_uV = -1;
+
+ /* Find highest min desired voltage */
+ for (i = 0; i < n_coupled; i++) {
+ int tmp_min = 0;
+ int tmp_max = INT_MAX;
+
+ lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
+
+ ret = regulator_check_consumers(c_rdevs[i],
+ &tmp_min,
+ &tmp_max, state);
+ if (ret < 0)
+ return ret;
+
+ if (tmp_min == 0) {
+ ret = regulator_get_voltage_rdev(c_rdevs[i]);
+ if (ret < 0)
+ return ret;
+ tmp_min = ret;
+ }
+
+ /* apply constraints */
+ ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max);
+ if (ret < 0)
+ return ret;
+
+ highest_min_uV = max(highest_min_uV, tmp_min);
+
+ if (i == 0) {
+ desired_min_uV = tmp_min;
+ desired_max_uV = tmp_max;
+ }
+ }
+
+ max_spread = constraints->max_spread[0];
+
+ /*
+ * Let target_uV be equal to the desired one if possible.
+ * If not, set it to minimum voltage, allowed by other coupled
+ * regulators.
+ */
+ target_uV = max(desired_min_uV, highest_min_uV - max_spread);
+
+ /*
+ * Find min and max voltages, which currently aren't violating
+ * max_spread.
+ */
+ for (i = 1; i < n_coupled; i++) {
+ int tmp_act;
+
+ tmp_act = regulator_get_voltage_rdev(c_rdevs[i]);
+ if (tmp_act < 0)
+ return tmp_act;
+
+ min_current_uV = min(tmp_act, min_current_uV);
+ max_current_uV = max(tmp_act, max_current_uV);
+ }
+
+ /*
+ * Correct target voltage, so as it currently isn't
+ * violating max_spread
+ */
+ possible_uV = max(target_uV, max_current_uV - max_spread);
+ possible_uV = min(possible_uV, min_current_uV + max_spread);
+
+ if (possible_uV > desired_max_uV)
+ return -EINVAL;
+
+ done = (possible_uV == target_uV);
+ desired_min_uV = possible_uV;
+
+ /* Set current_uV if wasn't done earlier in the code and if necessary */
+ if (*current_uV == -1) {
+ ret = regulator_get_voltage_rdev(rdev);
+ if (ret < 0)
+ return ret;
+ *current_uV = ret;
+ }
+
+ *min_uV = desired_min_uV;
+ *max_uV = desired_max_uV;
+
+ return done;
+}
+
+static int exynos_coupler_balance_voltage(struct regulator_coupler *coupler,
+ struct regulator_dev *rdev,
+ suspend_state_t state)
+{
+ struct regulator_dev **c_rdevs;
+ struct regulator_dev *best_rdev;
+ struct coupling_desc *c_desc = &rdev->coupling_desc;
+ int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
+ unsigned int delta, best_delta;
+ unsigned long c_rdev_done = 0;
+ bool best_c_rdev_done;
+
+ c_rdevs = c_desc->coupled_rdevs;
+ n_coupled = c_desc->n_coupled;
+
+ /*
+ * Find the best possible voltage change on each loop. Leave the loop
+ * if there isn't any possible change.
+ */
+ do {
+ best_c_rdev_done = false;
+ best_delta = 0;
+ best_min_uV = 0;
+ best_max_uV = 0;
+ best_c_rdev = 0;
+ best_rdev = NULL;
+
+ /*
+ * Find highest difference between optimal voltage
+ * and current voltage.
+ */
+ for (i = 0; i < n_coupled; i++) {
+ /*
+ * optimal_uV is the best voltage that can be set for
+ * i-th regulator at the moment without violating
+ * max_spread constraint in order to balance
+ * the coupled voltages.
+ */
+ int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
+
+ if (test_bit(i, &c_rdev_done))
+ continue;
+
+ ret = regulator_get_optimal_voltage(c_rdevs[i],
+ &current_uV,
+ &optimal_uV,
+ &optimal_max_uV,
+ state);
+ if (ret < 0)
+ goto out;
+
+ delta = abs(optimal_uV - current_uV);
+
+ if (delta && best_delta <= delta) {
+ best_c_rdev_done = ret;
+ best_delta = delta;
+ best_rdev = c_rdevs[i];
+ best_min_uV = optimal_uV;
+ best_max_uV = optimal_max_uV;
+ best_c_rdev = i;
+ }
+ }
+
+ /* Nothing to change, return successfully */
+ if (!best_rdev) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
+ best_max_uV, state);
+
+ if (ret < 0)
+ goto out;
+
+ if (best_c_rdev_done)
+ set_bit(best_c_rdev, &c_rdev_done);
+
+ } while (n_coupled > 1);
+
+out:
+ return ret;
+}
+
+static int exynos_coupler_attach(struct regulator_coupler *coupler,
+ struct regulator_dev *rdev)
+{
+ return 0;
+}
+
+static struct regulator_coupler exynos_coupler = {
+ .attach_regulator = exynos_coupler_attach,
+ .balance_voltage = exynos_coupler_balance_voltage,
+};
+
+static int __init exynos_coupler_init(void)
+{
+ if (!of_machine_is_compatible("samsung,exynos5800"))
+ return 0;
+
+ return regulator_coupler_register(&exynos_coupler);
+}
+arch_initcall(exynos_coupler_init);
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index 3cdd69d1bd4d..8e416ad91ee2 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -27,7 +27,7 @@ static u32 chipid;
u32 tegra_read_chipid(void)
{
- WARN(!chipid, "Tegra ABP MISC not yet available\n");
+ WARN(!chipid, "Tegra APB MISC not yet available\n");
return chipid;
}
diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c
index 5fb2ee2ac978..6dcc21dde0cb 100644
--- a/drivers/soc/ti/k3-ringacc.c
+++ b/drivers/soc/ti/k3-ringacc.c
@@ -109,6 +109,21 @@ struct k3_ring_ops {
};
/**
+ * struct k3_ring_state - Internal state tracking structure
+ *
+ * @free: Number of free entries
+ * @occ: Occupancy
+ * @windex: Write index
+ * @rindex: Read index
+ */
+struct k3_ring_state {
+ u32 free;
+ u32 occ;
+ u32 windex;
+ u32 rindex;
+};
+
+/**
* struct k3_ring - RA Ring descriptor
*
* @rt: Ring control/status registers
@@ -121,10 +136,6 @@ struct k3_ring_ops {
* @elm_size: Size of the ring element
* @mode: Ring mode
* @flags: flags
- * @free: Number of free elements
- * @occ: Ring occupancy
- * @windex: Write index (only for @K3_RINGACC_RING_MODE_RING)
- * @rindex: Read index (only for @K3_RINGACC_RING_MODE_RING)
* @ring_id: Ring Id
* @parent: Pointer on struct @k3_ringacc
* @use_count: Use count for shared rings
@@ -143,16 +154,17 @@ struct k3_ring {
u32 flags;
#define K3_RING_FLAG_BUSY BIT(1)
#define K3_RING_FLAG_SHARED BIT(2)
- u32 free;
- u32 occ;
- u32 windex;
- u32 rindex;
+ struct k3_ring_state state;
u32 ring_id;
struct k3_ringacc *parent;
u32 use_count;
int proxy_id;
};
+struct k3_ringacc_ops {
+ int (*init)(struct platform_device *pdev, struct k3_ringacc *ringacc);
+};
+
/**
* struct k3_ringacc - Rings accelerator descriptor
*
@@ -171,6 +183,7 @@ struct k3_ring {
* @tisci: pointer ti-sci handle
* @tisci_ring_ops: ti-sci rings ops
* @tisci_dev_id: ti-sci device id
+ * @ops: SoC specific ringacc operation
*/
struct k3_ringacc {
struct device *dev;
@@ -191,6 +204,8 @@ struct k3_ringacc {
const struct ti_sci_handle *tisci;
const struct ti_sci_rm_ringacc_ops *tisci_ring_ops;
u32 tisci_dev_id;
+
+ const struct k3_ringacc_ops *ops;
};
static long k3_ringacc_ring_get_fifo_pos(struct k3_ring *ring)
@@ -245,6 +260,7 @@ static void k3_ringacc_ring_dump(struct k3_ring *ring)
&ring->ring_mem_dma);
dev_dbg(dev, "dump elmsize %d, size %d, mode %d, proxy_id %d\n",
ring->elm_size, ring->size, ring->mode, ring->proxy_id);
+ dev_dbg(dev, "dump flags %08X\n", ring->flags);
dev_dbg(dev, "dump ring_rt_regs: db%08x\n", readl(&ring->rt->db));
dev_dbg(dev, "dump occ%08x\n", readl(&ring->rt->occ));
@@ -313,6 +329,30 @@ error:
}
EXPORT_SYMBOL_GPL(k3_ringacc_request_ring);
+int k3_ringacc_request_rings_pair(struct k3_ringacc *ringacc,
+ int fwd_id, int compl_id,
+ struct k3_ring **fwd_ring,
+ struct k3_ring **compl_ring)
+{
+ int ret = 0;
+
+ if (!fwd_ring || !compl_ring)
+ return -EINVAL;
+
+ *fwd_ring = k3_ringacc_request_ring(ringacc, fwd_id, 0);
+ if (!(*fwd_ring))
+ return -ENODEV;
+
+ *compl_ring = k3_ringacc_request_ring(ringacc, compl_id, 0);
+ if (!(*compl_ring)) {
+ k3_ringacc_ring_free(*fwd_ring);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(k3_ringacc_request_rings_pair);
+
static void k3_ringacc_ring_reset_sci(struct k3_ring *ring)
{
struct k3_ringacc *ringacc = ring->parent;
@@ -339,10 +379,7 @@ void k3_ringacc_ring_reset(struct k3_ring *ring)
if (!ring || !(ring->flags & K3_RING_FLAG_BUSY))
return;
- ring->occ = 0;
- ring->free = 0;
- ring->rindex = 0;
- ring->windex = 0;
+ memset(&ring->state, 0, sizeof(ring->state));
k3_ringacc_ring_reset_sci(ring);
}
@@ -556,11 +593,13 @@ static int k3_ringacc_ring_cfg_sci(struct k3_ring *ring)
int k3_ringacc_ring_cfg(struct k3_ring *ring, struct k3_ring_cfg *cfg)
{
- struct k3_ringacc *ringacc = ring->parent;
+ struct k3_ringacc *ringacc;
int ret = 0;
if (!ring || !cfg)
return -EINVAL;
+ ringacc = ring->parent;
+
if (cfg->elm_size > K3_RINGACC_RING_ELSIZE_256 ||
cfg->mode >= K3_RINGACC_RING_MODE_INVALID ||
cfg->size & ~K3_RINGACC_CFG_RING_SIZE_ELCNT_MASK ||
@@ -590,10 +629,7 @@ int k3_ringacc_ring_cfg(struct k3_ring *ring, struct k3_ring_cfg *cfg)
ring->size = cfg->size;
ring->elm_size = cfg->elm_size;
ring->mode = cfg->mode;
- ring->occ = 0;
- ring->free = 0;
- ring->rindex = 0;
- ring->windex = 0;
+ memset(&ring->state, 0, sizeof(ring->state));
if (ring->proxy_id != K3_RINGACC_PROXY_NOT_USED)
ring->proxy = ringacc->proxy_target_base +
@@ -613,7 +649,7 @@ int k3_ringacc_ring_cfg(struct k3_ring *ring, struct k3_ring_cfg *cfg)
ring->ops = NULL;
ret = -EINVAL;
goto err_free_proxy;
- };
+ }
ring->ring_mem_virt = dma_alloc_coherent(ringacc->dev,
ring->size * (4 << ring->elm_size),
@@ -664,10 +700,10 @@ u32 k3_ringacc_ring_get_free(struct k3_ring *ring)
if (!ring || !(ring->flags & K3_RING_FLAG_BUSY))
return -EINVAL;
- if (!ring->free)
- ring->free = ring->size - readl(&ring->rt->occ);
+ if (!ring->state.free)
+ ring->state.free = ring->size - readl(&ring->rt->occ);
- return ring->free;
+ return ring->state.free;
}
EXPORT_SYMBOL_GPL(k3_ringacc_ring_get_free);
@@ -738,7 +774,7 @@ static int k3_ringacc_ring_access_proxy(struct k3_ring *ring, void *elem,
"proxy:memcpy_fromio(x): --> ptr(%p), mode:%d\n", ptr,
access_mode);
memcpy_fromio(elem, ptr, (4 << ring->elm_size));
- ring->occ--;
+ ring->state.occ--;
break;
case K3_RINGACC_ACCESS_MODE_PUSH_TAIL:
case K3_RINGACC_ACCESS_MODE_PUSH_HEAD:
@@ -746,14 +782,14 @@ static int k3_ringacc_ring_access_proxy(struct k3_ring *ring, void *elem,
"proxy:memcpy_toio(x): --> ptr(%p), mode:%d\n", ptr,
access_mode);
memcpy_toio(ptr, elem, (4 << ring->elm_size));
- ring->free--;
+ ring->state.free--;
break;
default:
return -EINVAL;
}
- dev_dbg(ring->parent->dev, "proxy: free%d occ%d\n", ring->free,
- ring->occ);
+ dev_dbg(ring->parent->dev, "proxy: free%d occ%d\n", ring->state.free,
+ ring->state.occ);
return 0;
}
@@ -808,7 +844,7 @@ static int k3_ringacc_ring_access_io(struct k3_ring *ring, void *elem,
"memcpy_fromio(x): --> ptr(%p), mode:%d\n", ptr,
access_mode);
memcpy_fromio(elem, ptr, (4 << ring->elm_size));
- ring->occ--;
+ ring->state.occ--;
break;
case K3_RINGACC_ACCESS_MODE_PUSH_TAIL:
case K3_RINGACC_ACCESS_MODE_PUSH_HEAD:
@@ -816,14 +852,15 @@ static int k3_ringacc_ring_access_io(struct k3_ring *ring, void *elem,
"memcpy_toio(x): --> ptr(%p), mode:%d\n", ptr,
access_mode);
memcpy_toio(ptr, elem, (4 << ring->elm_size));
- ring->free--;
+ ring->state.free--;
break;
default:
return -EINVAL;
}
- dev_dbg(ring->parent->dev, "free%d index%d occ%d index%d\n", ring->free,
- ring->windex, ring->occ, ring->rindex);
+ dev_dbg(ring->parent->dev, "free%d index%d occ%d index%d\n",
+ ring->state.free, ring->state.windex, ring->state.occ,
+ ring->state.rindex);
return 0;
}
@@ -855,16 +892,16 @@ static int k3_ringacc_ring_push_mem(struct k3_ring *ring, void *elem)
{
void *elem_ptr;
- elem_ptr = k3_ringacc_get_elm_addr(ring, ring->windex);
+ elem_ptr = k3_ringacc_get_elm_addr(ring, ring->state.windex);
memcpy(elem_ptr, elem, (4 << ring->elm_size));
- ring->windex = (ring->windex + 1) % ring->size;
- ring->free--;
+ ring->state.windex = (ring->state.windex + 1) % ring->size;
+ ring->state.free--;
writel(1, &ring->rt->db);
dev_dbg(ring->parent->dev, "ring_push_mem: free%d index%d\n",
- ring->free, ring->windex);
+ ring->state.free, ring->state.windex);
return 0;
}
@@ -873,16 +910,16 @@ static int k3_ringacc_ring_pop_mem(struct k3_ring *ring, void *elem)
{
void *elem_ptr;
- elem_ptr = k3_ringacc_get_elm_addr(ring, ring->rindex);
+ elem_ptr = k3_ringacc_get_elm_addr(ring, ring->state.rindex);
memcpy(elem, elem_ptr, (4 << ring->elm_size));
- ring->rindex = (ring->rindex + 1) % ring->size;
- ring->occ--;
+ ring->state.rindex = (ring->state.rindex + 1) % ring->size;
+ ring->state.occ--;
writel(-1, &ring->rt->db);
dev_dbg(ring->parent->dev, "ring_pop_mem: occ%d index%d pos_ptr%p\n",
- ring->occ, ring->rindex, elem_ptr);
+ ring->state.occ, ring->state.rindex, elem_ptr);
return 0;
}
@@ -893,8 +930,8 @@ int k3_ringacc_ring_push(struct k3_ring *ring, void *elem)
if (!ring || !(ring->flags & K3_RING_FLAG_BUSY))
return -EINVAL;
- dev_dbg(ring->parent->dev, "ring_push: free%d index%d\n", ring->free,
- ring->windex);
+ dev_dbg(ring->parent->dev, "ring_push: free%d index%d\n",
+ ring->state.free, ring->state.windex);
if (k3_ringacc_ring_is_full(ring))
return -ENOMEM;
@@ -914,7 +951,7 @@ int k3_ringacc_ring_push_head(struct k3_ring *ring, void *elem)
return -EINVAL;
dev_dbg(ring->parent->dev, "ring_push_head: free%d index%d\n",
- ring->free, ring->windex);
+ ring->state.free, ring->state.windex);
if (k3_ringacc_ring_is_full(ring))
return -ENOMEM;
@@ -933,13 +970,13 @@ int k3_ringacc_ring_pop(struct k3_ring *ring, void *elem)
if (!ring || !(ring->flags & K3_RING_FLAG_BUSY))
return -EINVAL;
- if (!ring->occ)
- ring->occ = k3_ringacc_ring_get_occ(ring);
+ if (!ring->state.occ)
+ ring->state.occ = k3_ringacc_ring_get_occ(ring);
- dev_dbg(ring->parent->dev, "ring_pop: occ%d index%d\n", ring->occ,
- ring->rindex);
+ dev_dbg(ring->parent->dev, "ring_pop: occ%d index%d\n", ring->state.occ,
+ ring->state.rindex);
- if (!ring->occ)
+ if (!ring->state.occ)
return -ENODATA;
if (ring->ops && ring->ops->pop_head)
@@ -956,13 +993,13 @@ int k3_ringacc_ring_pop_tail(struct k3_ring *ring, void *elem)
if (!ring || !(ring->flags & K3_RING_FLAG_BUSY))
return -EINVAL;
- if (!ring->occ)
- ring->occ = k3_ringacc_ring_get_occ(ring);
+ if (!ring->state.occ)
+ ring->state.occ = k3_ringacc_ring_get_occ(ring);
- dev_dbg(ring->parent->dev, "ring_pop_tail: occ%d index%d\n", ring->occ,
- ring->rindex);
+ dev_dbg(ring->parent->dev, "ring_pop_tail: occ%d index%d\n",
+ ring->state.occ, ring->state.rindex);
- if (!ring->occ)
+ if (!ring->state.occ)
return -ENODATA;
if (ring->ops && ring->ops->pop_tail)
@@ -1047,21 +1084,14 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc)
ringacc->rm_gp_range);
}
-static int k3_ringacc_probe(struct platform_device *pdev)
+static int k3_ringacc_init(struct platform_device *pdev,
+ struct k3_ringacc *ringacc)
{
- struct k3_ringacc *ringacc;
void __iomem *base_fifo, *base_rt;
struct device *dev = &pdev->dev;
struct resource *res;
int ret, i;
- ringacc = devm_kzalloc(dev, sizeof(*ringacc), GFP_KERNEL);
- if (!ringacc)
- return -ENOMEM;
-
- ringacc->dev = dev;
- mutex_init(&ringacc->req_lock);
-
dev->msi_domain = of_msi_get_domain(dev, dev->of_node,
DOMAIN_BUS_TI_SCI_INTA_MSI);
if (!dev->msi_domain) {
@@ -1120,14 +1150,9 @@ static int k3_ringacc_probe(struct platform_device *pdev)
ringacc->rings[i].ring_id = i;
ringacc->rings[i].proxy_id = K3_RINGACC_PROXY_NOT_USED;
}
- dev_set_drvdata(dev, ringacc);
ringacc->tisci_ring_ops = &ringacc->tisci->ops.rm_ring_ops;
- mutex_lock(&k3_ringacc_list_lock);
- list_add_tail(&ringacc->list, &k3_ringacc_list);
- mutex_unlock(&k3_ringacc_list_lock);
-
dev_info(dev, "Ring Accelerator probed rings:%u, gp-rings[%u,%u] sci-dev-id:%u\n",
ringacc->num_rings,
ringacc->rm_gp_range->desc[0].start,
@@ -1137,15 +1162,60 @@ static int k3_ringacc_probe(struct platform_device *pdev)
ringacc->dma_ring_reset_quirk ? "enabled" : "disabled");
dev_info(dev, "RA Proxy rev. %08x, num_proxies:%u\n",
readl(&ringacc->proxy_gcfg->revision), ringacc->num_proxies);
+
return 0;
}
+struct ringacc_match_data {
+ struct k3_ringacc_ops ops;
+};
+
+static struct ringacc_match_data k3_ringacc_data = {
+ .ops = {
+ .init = k3_ringacc_init,
+ },
+};
+
/* Match table for of_platform binding */
static const struct of_device_id k3_ringacc_of_match[] = {
- { .compatible = "ti,am654-navss-ringacc", },
+ { .compatible = "ti,am654-navss-ringacc", .data = &k3_ringacc_data, },
{},
};
+static int k3_ringacc_probe(struct platform_device *pdev)
+{
+ const struct ringacc_match_data *match_data;
+ const struct of_device_id *match;
+ struct device *dev = &pdev->dev;
+ struct k3_ringacc *ringacc;
+ int ret;
+
+ match = of_match_node(k3_ringacc_of_match, dev->of_node);
+ if (!match)
+ return -ENODEV;
+ match_data = match->data;
+
+ ringacc = devm_kzalloc(dev, sizeof(*ringacc), GFP_KERNEL);
+ if (!ringacc)
+ return -ENOMEM;
+
+ ringacc->dev = dev;
+ mutex_init(&ringacc->req_lock);
+ ringacc->ops = &match_data->ops;
+
+ ret = ringacc->ops->init(pdev, ringacc);
+ if (ret)
+ return ret;
+
+ dev_set_drvdata(dev, ringacc);
+
+ mutex_lock(&k3_ringacc_list_lock);
+ list_add_tail(&ringacc->list, &k3_ringacc_list);
+ mutex_unlock(&k3_ringacc_list_lock);
+
+ return 0;
+}
+
static struct platform_driver k3_ringacc_driver = {
.probe = k3_ringacc_probe,
.driver = {
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c
index 1762d89fc05d..fde66e28e046 100644
--- a/drivers/soc/ti/knav_qmss_acc.c
+++ b/drivers/soc/ti/knav_qmss_acc.c
@@ -450,7 +450,7 @@ static int knav_acc_free_range(struct knav_range_info *range)
return 0;
}
-struct knav_range_ops knav_acc_range_ops = {
+static struct knav_range_ops knav_acc_range_ops = {
.set_notify = knav_acc_set_notify,
.init_queue = knav_acc_init_queue,
.open_queue = knav_acc_open_queue,
diff --git a/drivers/soc/ux500/ux500-soc-id.c b/drivers/soc/ux500/ux500-soc-id.c
index d64feeb51a40..a9472e0e5d61 100644
--- a/drivers/soc/ux500/ux500-soc-id.c
+++ b/drivers/soc/ux500/ux500-soc-id.c
@@ -146,9 +146,8 @@ static const char * __init ux500_get_revision(void)
return kasprintf(GFP_KERNEL, "%s", "Unknown");
}
-static ssize_t ux500_get_process(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+process_show(struct device *dev, struct device_attribute *attr, char *buf)
{
if (dbx500_id.process == 0x00)
return sprintf(buf, "Standard\n");
@@ -156,6 +155,15 @@ static ssize_t ux500_get_process(struct device *dev,
return sprintf(buf, "%02xnm\n", dbx500_id.process);
}
+static DEVICE_ATTR_RO(process);
+
+static struct attribute *ux500_soc_attrs[] = {
+ &dev_attr_process.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(ux500_soc);
+
static const char *db8500_read_soc_id(struct device_node *backupram)
{
void __iomem *base;
@@ -184,14 +192,11 @@ static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr,
soc_dev_attr->machine = ux500_get_machine();
soc_dev_attr->family = ux500_get_family();
soc_dev_attr->revision = ux500_get_revision();
+ soc_dev_attr->custom_attr_group = ux500_soc_groups[0];
}
-static const struct device_attribute ux500_soc_attr =
- __ATTR(process, S_IRUGO, ux500_get_process, NULL);
-
static int __init ux500_soc_device_init(void)
{
- struct device *parent;
struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr;
struct device_node *backupram;
@@ -217,9 +222,6 @@ static int __init ux500_soc_device_init(void)
return PTR_ERR(soc_dev);
}
- parent = soc_device_to_device(soc_dev);
- device_create_file(parent, &ux500_soc_attr);
-
return 0;
}
subsys_initcall(ux500_soc_device_init);
diff --git a/drivers/soc/versatile/soc-integrator.c b/drivers/soc/versatile/soc-integrator.c
index ae13fa2aa582..7dcf77ccd31e 100644
--- a/drivers/soc/versatile/soc-integrator.c
+++ b/drivers/soc/versatile/soc-integrator.c
@@ -56,45 +56,47 @@ static const char *integrator_fpga_str(u32 id)
}
}
-static ssize_t integrator_get_manf(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+manufacturer_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%02x\n", integrator_coreid >> 24);
}
-static struct device_attribute integrator_manf_attr =
- __ATTR(manufacturer, S_IRUGO, integrator_get_manf, NULL);
+static DEVICE_ATTR_RO(manufacturer);
-static ssize_t integrator_get_arch(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+arch_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", integrator_arch_str(integrator_coreid));
}
-static struct device_attribute integrator_arch_attr =
- __ATTR(arch, S_IRUGO, integrator_get_arch, NULL);
+static DEVICE_ATTR_RO(arch);
-static ssize_t integrator_get_fpga(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+fpga_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", integrator_fpga_str(integrator_coreid));
}
-static struct device_attribute integrator_fpga_attr =
- __ATTR(fpga, S_IRUGO, integrator_get_fpga, NULL);
+static DEVICE_ATTR_RO(fpga);
-static ssize_t integrator_get_build(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+build_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%02x\n", (integrator_coreid >> 4) & 0xFF);
}
-static struct device_attribute integrator_build_attr =
- __ATTR(build, S_IRUGO, integrator_get_build, NULL);
+static DEVICE_ATTR_RO(build);
+
+static struct attribute *integrator_attrs[] = {
+ &dev_attr_manufacturer.attr,
+ &dev_attr_arch.attr,
+ &dev_attr_fpga.attr,
+ &dev_attr_build.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(integrator);
static int __init integrator_soc_init(void)
{
@@ -127,6 +129,7 @@ static int __init integrator_soc_init(void)
soc_dev_attr->soc_id = "Integrator";
soc_dev_attr->machine = "Integrator";
soc_dev_attr->family = "Versatile";
+ soc_dev_attr->custom_attr_group = integrator_groups[0];
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr);
@@ -134,11 +137,6 @@ static int __init integrator_soc_init(void)
}
dev = soc_device_to_device(soc_dev);
- device_create_file(dev, &integrator_manf_attr);
- device_create_file(dev, &integrator_arch_attr);
- device_create_file(dev, &integrator_fpga_attr);
- device_create_file(dev, &integrator_build_attr);
-
dev_info(dev, "Detected ARM core module:\n");
dev_info(dev, " Manufacturer: %02x\n", (val >> 24));
dev_info(dev, " Architecture: %s\n", integrator_arch_str(val));
diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c
index 9471353dd8c3..c6876d232d8f 100644
--- a/drivers/soc/versatile/soc-realview.c
+++ b/drivers/soc/versatile/soc-realview.c
@@ -39,45 +39,47 @@ static const char *realview_arch_str(u32 id)
}
}
-static ssize_t realview_get_manf(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+manufacturer_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%02x\n", realview_coreid >> 24);
}
-static struct device_attribute realview_manf_attr =
- __ATTR(manufacturer, S_IRUGO, realview_get_manf, NULL);
+static DEVICE_ATTR_RO(manufacturer);
-static ssize_t realview_get_board(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+board_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "HBI-%03x\n", ((realview_coreid >> 16) & 0xfff));
}
-static struct device_attribute realview_board_attr =
- __ATTR(board, S_IRUGO, realview_get_board, NULL);
+static DEVICE_ATTR_RO(board);
-static ssize_t realview_get_arch(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+fpga_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", realview_arch_str(realview_coreid));
}
-static struct device_attribute realview_arch_attr =
- __ATTR(fpga, S_IRUGO, realview_get_arch, NULL);
+static DEVICE_ATTR_RO(fpga);
-static ssize_t realview_get_build(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t
+build_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%02x\n", (realview_coreid & 0xFF));
}
-static struct device_attribute realview_build_attr =
- __ATTR(build, S_IRUGO, realview_get_build, NULL);
+static DEVICE_ATTR_RO(build);
+
+static struct attribute *realview_attrs[] = {
+ &dev_attr_manufacturer.attr,
+ &dev_attr_board.attr,
+ &dev_attr_fpga.attr,
+ &dev_attr_build.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(realview);
static int realview_soc_probe(struct platform_device *pdev)
{
@@ -102,6 +104,7 @@ static int realview_soc_probe(struct platform_device *pdev)
soc_dev_attr->machine = "RealView";
soc_dev_attr->family = "Versatile";
+ soc_dev_attr->custom_attr_group = realview_groups[0];
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr);
@@ -112,11 +115,6 @@ static int realview_soc_probe(struct platform_device *pdev)
if (ret)
return -ENODEV;
- device_create_file(soc_device_to_device(soc_dev), &realview_manf_attr);
- device_create_file(soc_device_to_device(soc_dev), &realview_board_attr);
- device_create_file(soc_device_to_device(soc_dev), &realview_arch_attr);
- device_create_file(soc_device_to_device(soc_dev), &realview_build_attr);
-
dev_info(&pdev->dev, "RealView Syscon Core ID: 0x%08x, HBI-%03x\n",
realview_coreid,
((realview_coreid >> 16) & 0xfff));