All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Дмитрий Санковский" <dsankouski@gmail.com>
To: u-boot@lists.denx.de, Ramon Fried <rfried.dev@gmail.com>
Subject: Subject: [PATCH 2/6 v2] spmi: msm: add arbiter version 5 support
Date: Tue, 31 Aug 2021 11:43:48 +0300	[thread overview]
Message-ID: <CABTCjFAHk261JLdw63KoDs5D=k5DAjYnmdX+eu2Y8qnQP2t8qQ@mail.gmail.com> (raw)

From b65826c49fee93dd7ded11a848814d8fa79fdb2e Mon Sep 17 00:00:00 2001
From: Dzmitry Sankouski <dsankouski@gmail.com>
Date: Sat, 28 Aug 2021 13:53:42 +0300
Subject: [PATCH 2/6 v2] spmi: msm: add arbiter version 5 support

Currently driver supports only version 1 and 2.
Version 5 has slightly different registers structure

Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
Cc: Ramon Fried <rfried.dev@gmail.com>
---
Changes for v2:
- change string formats in debug statements

 MAINTAINERS             |   1 +
 drivers/spmi/spmi-msm.c | 156 +++++++++++++++++++++++++++-------------
 2 files changed, 107 insertions(+), 50 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 52ddc99cda..6b8b0783d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -392,6 +392,7 @@ F: drivers/phy/msm8916-usbh-phy.c
 F: drivers/serial/serial_msm.c
 F: drivers/serial/serial_msm_geni.c
 F: drivers/smem/msm_smem.c
+F: drivers/spmi/spmi-msm.c
 F: drivers/usb/host/ehci-msm.c

 ARM STI
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index 5a335e50aa..c5bc55bc6f 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -19,39 +19,63 @@
 DECLARE_GLOBAL_DATA_PTR;

 /* PMIC Arbiter configuration registers */
-#define PMIC_ARB_VERSION 0x0000
-#define PMIC_ARB_VERSION_V2_MIN 0x20010000
-
-#define ARB_CHANNEL_OFFSET(n) (0x4 * (n))
-#define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000)
-
-#define SPMI_REG_CMD0 0x0
-#define SPMI_REG_CONFIG 0x4
-#define SPMI_REG_STATUS 0x8
-#define SPMI_REG_WDATA 0x10
-#define SPMI_REG_RDATA 0x18
-
-#define SPMI_CMD_OPCODE_SHIFT 27
-#define SPMI_CMD_SLAVE_ID_SHIFT 20
-#define SPMI_CMD_ADDR_SHIFT 12
-#define SPMI_CMD_ADDR_OFFSET_SHIFT 4
-#define SPMI_CMD_BYTE_CNT_SHIFT 0
-
-#define SPMI_CMD_EXT_REG_WRITE_LONG 0x00
-#define SPMI_CMD_EXT_REG_READ_LONG 0x01
-
-#define SPMI_STATUS_DONE 0x1
+#define PMIC_ARB_VERSION 0x0000
+#define PMIC_ARB_VERSION_V2_MIN 0x20010000
+#define PMIC_ARB_VERSION_V3_MIN 0x30000000
+#define PMIC_ARB_VERSION_V5_MIN 0x50000000
+
+#define APID_MAP_OFFSET_V1_V2_V3 (0x800)
+#define APID_MAP_OFFSET_V5 (0x900)
+#define ARB_CHANNEL_OFFSET(n) (0x4 * (n))
+#define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000)
+#define SPMI_V5_OBS_CH_OFFSET(chnl) ((chnl) * 0x80)
+#define SPMI_V5_RW_CH_OFFSET(chnl) ((chnl) * 0x10000)
+
+#define SPMI_REG_CMD0 0x0
+#define SPMI_REG_CONFIG 0x4
+#define SPMI_REG_STATUS 0x8
+#define SPMI_REG_WDATA 0x10
+#define SPMI_REG_RDATA 0x18
+
+#define SPMI_CMD_OPCODE_SHIFT 27
+#define SPMI_CMD_SLAVE_ID_SHIFT 20
+#define SPMI_CMD_ADDR_SHIFT 12
+#define SPMI_CMD_ADDR_OFFSET_SHIFT 4
+#define SPMI_CMD_BYTE_CNT_SHIFT 0
+
+#define SPMI_CMD_EXT_REG_WRITE_LONG 0x00
+#define SPMI_CMD_EXT_REG_READ_LONG 0x01
+
+#define SPMI_STATUS_DONE 0x1
+
+#define SPMI_MAX_CHANNELS 128
+#define SPMI_MAX_SLAVES 16
+#define SPMI_MAX_PERIPH 256
+
+enum arb_ver {
+ V1 = 1,
+ V2,
+ V3,
+ V5 = 5
+};

-#define SPMI_MAX_CHANNELS 128
-#define SPMI_MAX_SLAVES 16
-#define SPMI_MAX_PERIPH 256
+/*
+ * PMIC arbiter version 5 uses different register offsets for read/write vs
+ * observer channels.
+ */
+enum pmic_arb_channel {
+ PMIC_ARB_CHANNEL_RW,
+ PMIC_ARB_CHANNEL_OBS,
+};

 struct msm_spmi_priv {
- phys_addr_t arb_chnl; /* ARB channel mapping base */
+ phys_addr_t arb_chnl;  /* ARB channel mapping base */
  phys_addr_t spmi_core; /* SPMI core */
- phys_addr_t spmi_obs; /* SPMI observer */
+ phys_addr_t spmi_obs;  /* SPMI observer */
  /* SPMI channel map */
  uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH];
+ /* SPMI bus arbiter version */
+ u32 arb_ver;
 };

 static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
@@ -59,6 +83,7 @@ static int msm_spmi_write(struct udevice *dev, int usid,
int pid, int off,
 {
  struct msm_spmi_priv *priv = dev_get_priv(dev);
  unsigned channel;
+ unsigned int ch_offset;
  uint32_t reg = 0;

  if (usid >= SPMI_MAX_SLAVES)
@@ -69,8 +94,8 @@ static int msm_spmi_write(struct udevice *dev, int usid,
int pid, int off,
  channel = priv->channel_map[usid][pid];

  /* Disable IRQ mode for the current channel*/
- writel(0x0, priv->spmi_core + SPMI_CH_OFFSET(channel) +
-       SPMI_REG_CONFIG);
+ writel(0x0,
+       priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);

  /* Write single byte */
  writel(val, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA);
@@ -82,6 +107,12 @@ static int msm_spmi_write(struct udevice *dev, int
usid, int pid, int off,
  reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
  reg |= 1; /* byte count */

+ if (priv->arb_ver == V5) {
+ ch_offset = SPMI_V5_RW_CH_OFFSET(channel);
+ } else {
+ ch_offset = SPMI_CH_OFFSET(channel);
+ }
+
  /* Send write command */
  writel(reg, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);

@@ -104,6 +135,7 @@ static int msm_spmi_read(struct udevice *dev, int usid,
int pid, int off)
 {
  struct msm_spmi_priv *priv = dev_get_priv(dev);
  unsigned channel;
+ unsigned int ch_offset;
  uint32_t reg = 0;

  if (usid >= SPMI_MAX_SLAVES)
@@ -113,8 +145,14 @@ static int msm_spmi_read(struct udevice *dev, int
usid, int pid, int off)

  channel = priv->channel_map[usid][pid];

+ if (priv->arb_ver == V5) {
+ ch_offset = SPMI_V5_OBS_CH_OFFSET(channel);
+ } else {
+ ch_offset = SPMI_CH_OFFSET(channel);
+ }
+
  /* Disable IRQ mode for the current channel*/
- writel(0x0, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
+ writel(0x0, priv->spmi_obs + ch_offset + SPMI_REG_CONFIG);

  /* Prepare read command */
  reg |= SPMI_CMD_EXT_REG_READ_LONG << SPMI_CMD_OPCODE_SHIFT;
@@ -124,13 +162,12 @@ static int msm_spmi_read(struct udevice *dev, int
usid, int pid, int off)
  reg |= 1; /* byte count */

  /* Request read */
- writel(reg, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
+ writel(reg, priv->spmi_obs + ch_offset + SPMI_REG_CMD0);

  /* Wait till CMD DONE status */
  reg = 0;
  while (!reg) {
- reg = readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) +
-    SPMI_REG_STATUS);
+ reg = readl(priv->spmi_obs + ch_offset + SPMI_REG_STATUS);
  }

  if (reg ^ SPMI_STATUS_DONE) {
@@ -139,8 +176,8 @@ static int msm_spmi_read(struct udevice *dev, int usid,
int pid, int off)
  }

  /* Read the data */
- return readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) +
-     SPMI_REG_RDATA) & 0xFF;
+ return readl(priv->spmi_obs + ch_offset +
+ SPMI_REG_RDATA) & 0xFF;
 }

 static struct dm_spmi_ops msm_spmi_ops = {
@@ -150,31 +187,50 @@ static struct dm_spmi_ops msm_spmi_ops = {

 static int msm_spmi_probe(struct udevice *dev)
 {
- struct udevice *parent = dev->parent;
  struct msm_spmi_priv *priv = dev_get_priv(dev);
- int node = dev_of_offset(dev);
+ u32 config_addr;
  u32 hw_ver;
- bool is_v1;
+ u32 version;
  int i;
+ int err;
+
+ config_addr = dev_read_addr_index(dev, 0);
+ priv->spmi_core = dev_read_addr_index(dev, 1);
+ priv->spmi_obs = dev_read_addr_index(dev, 2);
+
+ hw_ver = readl(config_addr + PMIC_ARB_VERSION);
+
+ if (hw_ver < PMIC_ARB_VERSION_V3_MIN) {
+ priv->arb_ver = V2;
+ version = 2;
+ priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3;
+ } else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) {
+ priv->arb_ver = V3;
+ version = 3;
+ priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3;
+ } else {
+ priv->arb_ver = V5;
+ version = 5;
+ priv->arb_chnl = config_addr + APID_MAP_OFFSET_V5;
+
+ if (err) {
+ dev_err(dev, "could not read APID->PPID mapping table, rc= %d\n", err);
+ return -1;
+ }
+ }

- priv->arb_chnl = dev_read_addr(dev);
- priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
- dev_of_offset(parent), node, "reg", 1, NULL, false);
- priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
- dev_of_offset(parent), node, "reg", 2, NULL, false);
-
- hw_ver = readl(priv->arb_chnl + PMIC_ARB_VERSION - 0x800);
- is_v1  = (hw_ver < PMIC_ARB_VERSION_V2_MIN);
-
- dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", (is_v1 ? 1 : 2), hw_ver);
+ dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", version, hw_ver);

  if (priv->arb_chnl == FDT_ADDR_T_NONE ||
     priv->spmi_core == FDT_ADDR_T_NONE ||
     priv->spmi_obs == FDT_ADDR_T_NONE)
  return -EINVAL;

+ dev_dbg(dev, "priv->arb_chnl address (%llu)\n", priv->arb_chnl);
+ dev_dbg(dev, "priv->spmi_core address (%llu)\n", priv->spmi_core);
+ dev_dbg(dev, "priv->spmi_obs address (%llu)\n", priv->spmi_obs);
  /* Scan peripherals connected to each SPMI channel */
- for (i = 0; i < SPMI_MAX_PERIPH ; i++) {
+ for (i = 0; i < SPMI_MAX_PERIPH; i++) {
  uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i));
  uint8_t slave_id = (periph & 0xf0000) >> 16;
  uint8_t pid = (periph & 0xff00) >> 8;
@@ -195,5 +251,5 @@ U_BOOT_DRIVER(msm_spmi) = {
  .of_match = msm_spmi_ids,
  .ops = &msm_spmi_ops,
  .probe = msm_spmi_probe,
- .priv_auto = sizeof(struct msm_spmi_priv),
+ .priv_auto = sizeof(struct msm_spmi_priv),
 };
-- 
2.20.1

             reply	other threads:[~2021-08-31 11:29 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-31  8:43 Дмитрий Санковский [this message]
2021-09-05 13:33 ` Subject: [PATCH 2/6 v2] spmi: msm: add arbiter version 5 support Ramon Fried

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CABTCjFAHk261JLdw63KoDs5D=k5DAjYnmdX+eu2Y8qnQP2t8qQ@mail.gmail.com' \
    --to=dsankouski@gmail.com \
    --cc=rfried.dev@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.