--- /dev/null
+/* individual sequence descriptor for SHUB control - init, reset, release */
+struct pmucal_seq shub_init[] = {
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "QCH_CON_CM4_SHUB_QCH", 0x11000000,
+ 0x3018, (0x7 << 0), (0x4 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "RESET_SUBCPU_SHUB_OPTION", 0x11860000,
+ 0x3D28, (0x1 << 15), (0x1 << 15), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "RESET_SU:BCPU_SHUB_STATUS", 0x11860000,
+ 0x3D24, (0x1 << 0), (0x0 << 0), 0x11860000, 0x3D24,
+ (0x1 << 0), (0x0 << 0)),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "QCH_CON_CM4_SHUB_QCH", 0x11000000,
+ 0x3018, (0x7 << 0), (0x6 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "QCH_CON_CM4_SHUB_QCH", 0x11000000,
+ 0x3018, (0x7 << 0), (0x2 << 0), 0, 0, 0xffffffff, 0),
+};
+
+struct pmucal_seq shub_standbywfi_status[] = {
+ PMUCAL_SEQ_DESC(PMUCAL_READ, "RESET_SUBCPU_SHUB_STATUS", 0x11860000,
+ 0x3D24, (0x1 << 28), 0, 0, 0, 0xffffffff, 0),
+};
+
+struct pmucal_seq shub_reset_assert[] = {
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "RESET_SUBCPU_SHUB_CONFIGURATION",
+ 0x11860000, 0x3D20, (0x1 << 0), (0x0 << 0), 0, 0,
+ 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "RESET_SUBCPU_SHUB_STATUS", 0x11860000,
+ 0x3D24, (0x1 << 0), (0x0 << 0), 0x11860000, 0x3D24,
+ (0x1 << 0), (0x0 << 0)),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "TOP_BUS_SHUB_OPTION", 0x11860000, 0x2C68,
+ (0x3 << 0), (0x3 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "TOP_BUS_SHUB_CONFIGURATION", 0x11860000,
+ 0x2C60, (0x7 << 0), (0x6 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "TOP_BUS_SHUB_STATUS", 0x11860000, 0x2C64,
+ (0x7 << 0), (0x6 << 0), 0x11860000, 0x2C64, (0x7 << 0),
+ (0x6 << 0)),
+
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "TOP_PWR_SHUB_CONFIGURATION", 0x11860000,
+ 0x2CE0, (0x3 << 0), (0x0 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "TOP_PWR_SHUB_STATUS", 0x11860000, 0x2CE4,
+ (0x3 << 0), (0x0 << 0), 0x11860000, 0x2CE4, (0x3 << 0),
+ (0x0 << 0)),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "LOGIC_RESET_SHUB_CONFIGURATION",
+ 0x11860000, 0x2D80, (0x3 << 0), (0x0 << 0), 0, 0,
+ 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "LOGIC_RESET_SHUB_STATUS", 0x11860000,
+ 0x2D84, (0x3 << 0), (0x0 << 0), 0x11860000, 0x2D64,
+ (0x3 << 0), (0x0 << 0)),
+
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "RESET_CMU_SHUB_CONFIGURATION",
+ 0x11860000, 0x2A60, (0x3 << 0), (0x0 << 0), 0, 0,
+ 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "RESET_CMU_SHUB_STATUS", 0x11860000,
+ 0x2A64, (0x3 << 0), (0x0 << 0), 0x11860000, 0x2A64,
+ (0x3 << 0), (0x0 << 0)),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "TOP_BUS_SHUB_CONFIGURATION", 0x11860000,
+ 0x2C60, (0x7 << 0), (0x0 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "TOP_BUS_SHUB_STATUS", 0x11860000, 0x2C64,
+ (0x7 << 0), (0x0 << 0), 0x11860000, 0x2C64, (0x7 << 0),
+ (0x0 << 0)),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "TOP_BUS_SHUB_OPTION", 0x11860000, 0x2C68,
+ (0x3 << 0), (0x0 << 0), 0, 0, 0xffffffff, 0),
+};
+
+struct pmucal_seq shub_reset_release_config[] = {
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "RESET_CMU_SHUB_CONFIGURATION",
+ 0x11860000, 0x2A60, (0x3 << 0), (0x3 << 0), 0, 0,
+ 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "RESET_CMU_SHUB_STATUS", 0x11860000,
+ 0x2A64, (0x3 << 0), (0x3 << 0), 0x11860000, 0x2A64,
+ (0x3 << 0), (0x3 << 0)),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "LOGIC_RESET_SHUB_CONFIGURATION",
+ 0x11860000, 0x2D80, (0x3 << 0), (0x3 << 0), 0, 0,
+ 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "LOGIC_RESET_SHUB_STATUS", 0x11860000,
+ 0x2D84, (0x3 << 0), (0x3 << 0), 0x11860000, 0x2D84,
+ (0x3 << 0), (0x3 << 0)),
+
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "TOP_PWR_SHUB_CONFIGURATION", 0x11860000,
+ 0x2CE0, (0x3 << 0), (0x3 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "TOP_PWR_SHUB_STATUS", 0x11860000, 0x2CE4,
+ (0x3 << 0), (0x3 << 0), 0x11860000, 0x2CE4, (0x3 << 0),
+ (0x3 << 0)),
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "TOP_BUS_SHUB_CONFIGURATION", 0x11860000,
+ 0x2C60, (0x7 << 0), (0x7 << 0), 0, 0, 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_WAIT, "TOP_BUS_SHUB_STATUS", 0x11860000, 0x2C64,
+ (0x7 << 0), (0x7 << 0), 0x11860000, 0x2C64, (0x7 << 0),
+ (0x7 << 0)),
+};
+
+struct pmucal_seq shub_reset_release[] = {
+ PMUCAL_SEQ_DESC(PMUCAL_WRITE, "RESET_SUBCPU_SHUB_CONFIGURATION",
+ 0x11860000, 0x3D20, (0x1 << 0), (0x1 << 0), 0, 0,
+ 0xffffffff, 0),
+ PMUCAL_SEQ_DESC(PMUCAL_READ, "RESET_SUBCPU_SHUB_STATUS", 0x11860000,
+ 0x3D24, (0xF << 0), (0xF << 0), 0, 0, 0xffffffff, 0)
+};
+
+struct pmucal_shub pmucal_shub_list = {
+ .init = shub_init,
+ .status = shub_standbywfi_status,
+ .reset_assert = shub_reset_assert,
+ .reset_release_config = shub_reset_release_config,
+ .reset_release = shub_reset_release,
+ .num_init = ARRAY_SIZE(shub_init),
+ .num_status = ARRAY_SIZE(shub_standbywfi_status),
+ .num_reset_assert = ARRAY_SIZE(shub_reset_assert),
+ .num_reset_release_config = ARRAY_SIZE(shub_reset_release_config),
+ .num_reset_release = ARRAY_SIZE(shub_reset_release),
+};
+
+unsigned int pmucal_shub_list_size = 1;
reg = __raw_readl(seq->base_va + seq->offset);
#endif
reg &= seq->mask;
+
if (reg == seq->value)
return true;
else
if (timeout > 1000) {
u32 reg;
reg = __raw_readl(seq->base_va + seq->offset);
- pr_err("%s %s:timed out during wait. (value:0x%x, seq_idx = %d)\n",
- PMUCAL_PREFIX, __func__, reg, pmucal_rae_seq_idx);
+ pr_err("%s %s:timed out during wait. (value:0x%x,intended: 0x%x, seq_idx = %d)\n",
+ PMUCAL_PREFIX, __func__, reg, seq->value, pmucal_rae_seq_idx);
return -ETIMEDOUT;
}
}
-
return 0;
}
}
#endif
+/**
+ * pmucal_rae_handle_shub_seq - handles a sequence array based on each element's access_type.
+ * exposed to PMUCAL common logics.
+ *
+ * @seq: Sequence array to be handled.
+ * @seq_size: Array size of seq.
+ *
+ * Returns 0 on success. Otherwise, negative error code.
+ */
+
+#ifdef CONFIG_SHUB_PMUCAL
+static unsigned int pmucal_rae_shub_seq_idx;
+
+int pmucal_rae_handle_shub_seq(struct pmucal_seq *seq, unsigned int seq_size)
+{
+ int ret, i;
+ u32 reg;
+
+ for (i = 0; i < seq_size; i++) {
+ pmucal_rae_shub_seq_idx = i;
+ pr_info("%s: shub reset sequence %d pa: 0x%llx / va: 0x%llx\n",
+ __func__, i,
+ (unsigned long long int)seq[i].base_pa + seq[i].offset,
+ (unsigned long long int)seq[i].base_va + seq[i].offset);
+ switch (seq[i].access_type) {
+ case PMUCAL_READ:
+ pmucal_rae_read(&seq[i]);
+ pr_info("%s%s %s = 0x%08x\n", PMUCAL_PREFIX, "raw_read", seq[i].sfr_name,
+ __raw_readl(seq[i].base_va + seq[i].offset));
+ break;
+ case PMUCAL_WRITE:
+ reg = __raw_readl(seq[i].base_va + seq[i].offset);
+ reg = (reg & ~seq[i].mask) | seq[i].value;
+ pr_info("%s%s %s = 0x%08x\n", PMUCAL_PREFIX,
+ "raw_write ", seq[i].sfr_name, reg);
+ pmucal_rae_write(&seq[i]);
+ pr_info("%s%s %s = 0x%08x\n", PMUCAL_PREFIX, "raw_read(check)",
+ seq[i].sfr_name, __raw_readl(seq[i].base_va + seq[i].offset));
+ break;
+ case PMUCAL_COND_READ:
+ if (pmucal_rae_check_condition(&seq[i]))
+ pmucal_rae_read(&seq[i]);
+ break;
+ case PMUCAL_COND_WRITE:
+ if (pmucal_rae_check_condition(&seq[i]))
+ pmucal_rae_write(&seq[i]);
+ break;
+ case PMUCAL_WAIT:
+ ret = pmucal_rae_wait(&seq[i]);
+ if (ret)
+ return ret;
+ pr_info("%s%s\t%s = 0x%08x\n", PMUCAL_PREFIX, "raw_read(wait)",
+ seq[i].sfr_name,
+ __raw_readl(seq[i].base_va + seq[i].offset) & seq[i].mask);
+ break;
+ case PMUCAL_DELAY:
+ udelay(seq[i].value);
+ break;
+ default:
+ pr_err("%s %s:invalid PMUCAL access type\n", PMUCAL_PREFIX, __func__);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+#endif
+
/**
* pmucal_rae_init - Init function of PMUCAL Register Access Engine.
* exposed to PWRCAL interface.
--- /dev/null
+#include "pmucal_shub.h"
+#include "pmucal_rae.h"
+
+/**
+ * pmucal_shub_init - init shub.
+ * exposed to PWRCAL interface.
+
+ * Returns 0 on success. Otherwise, negative error code.
+ */
+int pmucal_shub_init(void)
+{
+ pr_info("%s%s()\n", PMUCAL_PREFIX, __func__);
+
+ return 0;
+}
+
+/**
+ * pmucal_shub_standbywfi_status - get shub standbywfi status.
+ * exposed to PWRCAL interface.
+
+ * Returns 1 when the shub is in wfi, 0 when not.
+ * Otherwise, negative error code.
+ */
+int pmucal_shub_standbywfi_status(void)
+{
+ pr_info("%s%s()\n", PMUCAL_PREFIX, __func__);
+
+ if (!pmucal_shub_list.status) {
+ pr_err("%s there is no sequence element for shub-status.\n",
+ PMUCAL_PREFIX);
+ return -ENOENT;
+ }
+
+ pmucal_rae_handle_shub_seq(pmucal_shub_list.status,
+ pmucal_shub_list.num_status);
+
+ pr_err("shub_status: 0x%X\n", pmucal_shub_list.status->value);
+
+ if (pmucal_shub_list.status->value == 0x1)
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * pmucal_shub_reset_assert - reset assert shub.
+ * exposed to PWRCAL interface.
+ *
+ * Returns 0 on success. Otherwise, negative error code.
+ */
+int pmucal_shub_reset_assert(void)
+{
+ int ret;
+
+ if (!pmucal_shub_list.reset_assert) {
+ pr_err("%s there is no sequence element for shub-reset_assert.\n",
+ PMUCAL_PREFIX);
+ return -ENOENT;
+ }
+
+ ret = pmucal_rae_handle_shub_seq(pmucal_shub_list.reset_assert,
+ pmucal_shub_list.num_reset_assert);
+ if (ret) {
+ pr_err("%s %s: error on handling shub-reset_assert sequence.\n",
+ PMUCAL_PREFIX, __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * pmucal_shub_reset_release_config - reset_release_config shub except SHUB CPU reset
+ * exposed to PWRCAL interface.
+ *
+ * Returns 0 on success. Otherwise, negative error code.
+ */
+int pmucal_shub_reset_release_config(void)
+{
+ int ret;
+
+ if (!pmucal_shub_list.reset_release_config) {
+ pr_err("%s there is no sequence element for shub-reset_release_config.\n",
+ PMUCAL_PREFIX);
+ return -ENOENT;
+ }
+
+ ret = pmucal_rae_handle_shub_seq(pmucal_shub_list.reset_release_config,
+ pmucal_shub_list.num_reset_release_config);
+ if (ret) {
+ pr_err("%s %s: error on handling shub-reset_release_config sequence.\n",
+ PMUCAL_PREFIX, __func__);
+ return ret;
+ }
+ return 0;
+}
+int pmucal_shub_reset_release(void)
+{
+ int ret;
+
+ if (!pmucal_shub_list.reset_release) {
+ pr_err("%s there is no sequence element for shub-reset_release.\n",
+ PMUCAL_PREFIX);
+ return -ENOENT;
+ }
+
+ ret = pmucal_rae_handle_shub_seq(pmucal_shub_list.reset_release,
+ pmucal_shub_list.num_reset_release);
+ if (ret) {
+ pr_err("%s %s: error on handling shub-reset_release sequence.\n",
+ PMUCAL_PREFIX, __func__);
+ return ret;
+ }
+
+ return 0;
+
+}
+int pmucal_is_shub_regs(int reg)
+{
+ int i;
+ int is_shub_regs = 0;
+
+ for (i = 0; i < pmucal_shub_list.num_init; i++) {
+ if (reg == pmucal_shub_list.init[i].base_pa + pmucal_shub_list.init[i].offset) {
+ is_shub_regs = 1;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < pmucal_shub_list.num_reset_assert; i++) {
+ if (reg == pmucal_shub_list.reset_assert[i].base_pa + pmucal_shub_list.reset_assert[i].offset) {
+ is_shub_regs = 1;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < pmucal_shub_list.num_reset_release; i++) {
+ if (reg == pmucal_shub_list.reset_release[i].base_pa + pmucal_shub_list.reset_release[i].offset) {
+ is_shub_regs = 1;
+ goto out;
+ }
+ }
+
+out:
+ return is_shub_regs;
+}
+
+/**
+ * pmucal_cp_initialize - Initialize function of PMUCAL SHUB common logic.
+ * exposed to PWRCAL interface.
+ *
+ * Returns 0 on success. Otherwise, negative error code.
+ */
+int __init pmucal_shub_initialize(void)
+{
+ int ret = 0;
+
+ pr_info("%s%s()\n", PMUCAL_PREFIX, __func__);
+
+ if (!pmucal_shub_list_size) {
+ pr_err("%s %s: there is no shub list. aborting init...\n",
+ PMUCAL_PREFIX, __func__);
+ return -ENOENT;
+ }
+
+ /* convert physical base address to virtual addr */
+ ret = pmucal_rae_phy2virt(pmucal_shub_list.init,
+ pmucal_shub_list.num_init);
+ if (ret) {
+ pr_err("%s %s: error on PA2VA conversion. aborting init...\n",
+ PMUCAL_PREFIX, __func__);
+ goto out;
+ }
+
+ ret = pmucal_rae_phy2virt(pmucal_shub_list.status,
+ pmucal_shub_list.num_status);
+ if (ret) {
+ pr_err("%s %s: error on PA2VA conversion. aborting status...\n",
+ PMUCAL_PREFIX, __func__);
+ goto out;
+ }
+
+ ret = pmucal_rae_phy2virt(pmucal_shub_list.reset_assert,
+ pmucal_shub_list.num_reset_assert);
+
+//investigating virtual address of assrtion
+
+ pr_info("%s %p\n", PMUCAL_PREFIX, pmucal_shub_list.reset_assert[0].base_va);
+
+ if (ret) {
+ pr_err("%s %s: error on PA2VA conversion. aborting reset_assert...\n",
+ PMUCAL_PREFIX, __func__);
+ goto out;
+ }
+
+ ret = pmucal_rae_phy2virt(pmucal_shub_list.reset_release_config,
+ pmucal_shub_list.num_reset_release_config);
+ if (ret) {
+ pr_err("%s %s: error on PA2VA conversion. aborting reset_release_config...\n",
+ PMUCAL_PREFIX, __func__);
+ goto out;
+ }
+
+ ret = pmucal_rae_phy2virt(pmucal_shub_list.reset_release,
+ pmucal_shub_list.num_reset_release);
+ if (ret) {
+ pr_err("%s %s: error on PA2VA conversion. aborting reset_release...\n",
+ PMUCAL_PREFIX, __func__);
+ goto out;
+ }
+out:
+ return ret;
+}