[PATCH v7 7/7] cros_ec: differentiate SCP from EC by feature bit.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Since a SCP and EC would both exist on a system, and use the cros_ec_dev
driver, we need to differentiate between them for the userspace, or they
would both be registered at /dev/cros_ec, causing a conflict.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - No change.

Changes from v4:
 - No change.

Changes from v3:
 - No change.

Changes from v2:
 - No change.

Changes from v1:
 - New patch extracted from Patch 5.
---
 drivers/mfd/cros_ec_dev.c| 10 ++
 include/linux/mfd/cros_ec.h  |  1 +
 include/linux/mfd/cros_ec_commands.h |  2 ++
 3 files changed, 13 insertions(+)

diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index d275deaecb12..da2f2145d31d 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -418,6 +418,16 @@ static int ec_device_probe(struct platform_device *pdev)
device_initialize(>class_dev);
cdev_init(>cdev, );
 
+   /* check whether this is actually a SCP rather than an EC */
+   if (cros_ec_check_features(ec, EC_FEATURE_SCP)) {
+   dev_info(dev, "SCP detected.\n");
+   /*
+* Help userspace differentiating ECs from SCP,
+* regardless of the probing order.
+*/
+   ec_platform->ec_name = CROS_EC_DEV_SCP_NAME;
+   }
+
/*
 * Add the class device
 * Link to the character device for creating the /dev entry
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 8f2a8918bfa3..a971399bad82 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -24,6 +24,7 @@
 
 #define CROS_EC_DEV_NAME "cros_ec"
 #define CROS_EC_DEV_PD_NAME "cros_pd"
+#define CROS_EC_DEV_SCP_NAME "cros_scp"
 
 /*
  * The EC is unresponsive for a time after a reboot command.  Add a
diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index fc91082d4c35..3e5da6e93b2f 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -856,6 +856,8 @@ enum ec_feature_code {
EC_FEATURE_RTC = 27,
/* EC supports CEC commands */
EC_FEATURE_CEC = 35,
+   /* The MCU exposes a SCP */
+   EC_FEATURE_SCP = 39,
 };
 
 #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
-- 
2.21.0.392.gf8f6787159e-goog



[PATCH v7 5/7] dt-bindings: Add binding for cros-ec-rpmsg.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Add a DT binding documentation for ChromeOS EC driver over rpmsg.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - New patch.
---
 Documentation/devicetree/bindings/mfd/cros-ec.txt | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/cros-ec.txt 
b/Documentation/devicetree/bindings/mfd/cros-ec.txt
index 6245c9b1a68b..4860eabd0f72 100644
--- a/Documentation/devicetree/bindings/mfd/cros-ec.txt
+++ b/Documentation/devicetree/bindings/mfd/cros-ec.txt
@@ -3,7 +3,7 @@ ChromeOS Embedded Controller
 Google's ChromeOS EC is a Cortex-M device which talks to the AP and
 implements various function such as keyboard and battery charging.
 
-The EC can be connect through various means (I2C, SPI, LPC) and the
+The EC can be connect through various means (I2C, SPI, LPC, RPMSG) and the
 compatible string used depends on the interface. Each connection method has
 its own driver which connects to the top level interface-agnostic EC driver.
 Other Linux driver (such as cros-ec-keyb for the matrix keyboard) connect to
@@ -17,6 +17,9 @@ Required properties (SPI):
 - compatible: "google,cros-ec-spi"
 - reg: SPI chip select
 
+Required properties (RPMSG):
+- compatible: "google,cros-ec-rpmsg"
+
 Optional properties (SPI):
 - google,cros-ec-spi-pre-delay: Some implementations of the EC need a little
   time to wake up from sleep before they can receive SPI transfers at a high
-- 
2.21.0.392.gf8f6787159e-goog



[PATCH v7 6/7] platform/chrome: cros_ec: add EC host command support using rpmsg.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Add EC host command support through rpmsg.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - Make data for response aligned to 4 bytes.

Changes from v5:
 - Change commit title.
 - Add documents for some structs, and fix all warning from
   scripts/kernel-doc.
 - Miscellaneous fixes based on feedback.

Changes from v4:
 - Change from work queue to completion.
 - Change from matching using rpmsg id to device tree compatible, to
   support EC subdevices.

Changes from v3:
 - Add host event support by adding an extra bytes at the start of IPC
   message to indicate the type of the message (host event or host
   command), since there's no additional irq that can be used for host
   event.

Changes from v2:
 - Wait for ipi ack instead of depends on the behavior in mtk-rpmsg.

Changes from v1:
 - Code format fix based on feedback for cros_ec_rpmsg.c.
 - Extract feature detection for SCP into separate patch (Patch 6).
---
 drivers/platform/chrome/Kconfig |   9 +
 drivers/platform/chrome/Makefile|   1 +
 drivers/platform/chrome/cros_ec_rpmsg.c | 265 
 3 files changed, 275 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_rpmsg.c

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 9186d81a51cc..5c48aa6da2f8 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_I2C
  a checksum. Failing accesses will be retried three times to
  improve reliability.
 
+config CROS_EC_RPMSG
+   tristate "ChromeOS Embedded Controller (rpmsg)"
+   depends on MFD_CROS_EC && RPMSG && OF
+   help
+ If you say Y here, you get support for talking to the ChromeOS EC
+ through rpmsg. This uses a simple byte-level protocol with a
+ checksum. Also since there's no addition EC-to-host interrupt, this
+ use a byte in message to distinguish host event from host command.
+
 config CROS_EC_SPI
tristate "ChromeOS Embedded Controller (SPI)"
depends on MFD_CROS_EC && SPI
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 1e2f0029b597..4b69d795720d 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_LAPTOP)   += chromeos_laptop.o
 obj-$(CONFIG_CHROMEOS_PSTORE)  += chromeos_pstore.o
 obj-$(CONFIG_CHROMEOS_TBMC)+= chromeos_tbmc.o
 obj-$(CONFIG_CROS_EC_I2C)  += cros_ec_i2c.o
+obj-$(CONFIG_CROS_EC_RPMSG)+= cros_ec_rpmsg.o
 obj-$(CONFIG_CROS_EC_SPI)  += cros_ec_spi.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
 cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c 
b/drivers/platform/chrome/cros_ec_rpmsg.c
new file mode 100644
index ..2ecae806cfc5
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_rpmsg.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2018 Google LLC.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define EC_MSG_TIMEOUT_MS 200
+#define HOST_COMMAND_MARK 1
+#define HOST_EVENT_MARK 2
+
+/**
+ * struct cros_ec_rpmsg_response - rpmsg message format from from EC.
+ *
+ * @type:  The type of message, should be either HOST_COMMAND_MARK or
+ * HOST_EVENT_MARK, representing that the message is a response to
+ * host command, or a host event.
+ * @data:  ec_host_response for host command.
+ */
+struct cros_ec_rpmsg_response {
+   u8 type;
+   u8 data[] __aligned(4);
+};
+
+/**
+ * struct cros_ec_rpmsg - information about a EC over rpmsg.
+ *
+ * @rpdev: rpmsg device we are connected to
+ * @xfer_ack:  completion for host command transfer.
+ * @host_event_work:   Work struct for pending host event.
+ */
+struct cros_ec_rpmsg {
+   struct rpmsg_device *rpdev;
+   struct completion xfer_ack;
+   struct work_struct host_event_work;
+};
+
+/**
+ * cros_ec_cmd_xfer_rpmsg - Transfer a message over rpmsg and receive the reply
+ *
+ * @ec_dev: ChromeOS EC device
+ * @ec_msg: Message to transfer
+ *
+ * This is only used for old EC proto version, and is not supported for this
+ * driver.
+ *
+ * Return: number of bytes of the reply on success or negative error code.
+ */
+static int cros_ec_cmd_xfer_rpmsg(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *ec_msg)
+{
+   return -EINVAL;
+}
+
+/**
+ * cros_ec_pkt_xfer_rpmsg - Transfer a packet over rpmsg and receive the reply
+ *
+ * @ec_dev: ChromeOS EC device
+ * @ec_msg: Message to transfer
+ *
+ * Return: number of bytes of the reply on success or negative error code.
+ */
+static int cros_ec_pkt_xfer_rpmsg(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *ec_msg)

[PATCH v7 4/7] rpmsg: add rpmsg support for mt8183 SCP.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Add a simple rpmsg support for mt8183 SCP, that use IPI / IPC directly.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - Decouple mtk_rpmsg from mtk_scp by putting all necessary informations
   (name service IPI id, register/unregister/send functions) into a
   struct, and pass it to the mtk_rpmsg_create_rproc_subdev function.

Changes from v5:
 - CONFIG_MTK_SCP now selects CONFIG_RPMSG_MTK_SCP, and the dummy
   implementation for mtk_rpmsg_{create,destroy}_rproc_subdev when
   CONFIG_RPMSG_MTK_SCP is not defined is removed.

Changes from v4:
 - Match and fill the device tree node to the created rpmsg subdevice,
   so the rpmsg subdevice can utilize the properties and subnodes on
   device tree (This is similar to what drivers/rpmsg/qcom_smd.c does).

Changes from v3:
 - Change from unprepare to stop, to stop the rpmsg driver before the
   rproc is stopped, avoiding problem that some rpmsg would fail after
   rproc is stopped.
 - Add missing spin_lock_init, and use destroy_ept instead of kref_put.

Changes from v2:
 - Unregiser IPI handler on unprepare.
 - Lock the channel list on operations.
 - Move SCP_IPI_NS_SERVICE to 0xFF.

Changes from v1:
 - Do cleanup properly in mtk_rpmsg.c, which also removes the problem of
   short-lived work items.
 - Fix several issues checkpatch found.
---
 drivers/remoteproc/Kconfig|   1 +
 drivers/remoteproc/mtk_common.h   |   2 +
 drivers/remoteproc/mtk_scp.c  |  38 ++-
 drivers/remoteproc/mtk_scp_ipi.c  |   1 +
 drivers/rpmsg/Kconfig |   9 +
 drivers/rpmsg/Makefile|   1 +
 drivers/rpmsg/mtk_rpmsg.c | 396 ++
 include/linux/platform_data/mtk_scp.h |   4 +-
 include/linux/rpmsg/mtk_rpmsg.h   |  30 ++
 9 files changed, 477 insertions(+), 5 deletions(-)
 create mode 100644 drivers/rpmsg/mtk_rpmsg.c
 create mode 100644 include/linux/rpmsg/mtk_rpmsg.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 92bd20d6b9cd..01182936f4fa 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -25,6 +25,7 @@ config IMX_REMOTEPROC
 config MTK_SCP
tristate "Mediatek SCP support"
depends on ARCH_MEDIATEK
+   select RPMSG_MTK_SCP
help
  Say y here to support Mediatek's System Companion Processor (SCP) via
  the remote processor framework.
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
index 7504ae1bc0ef..19a907810271 100644
--- a/drivers/remoteproc/mtk_common.h
+++ b/drivers/remoteproc/mtk_common.h
@@ -54,6 +54,8 @@ struct mtk_scp {
void __iomem *cpu_addr;
phys_addr_t phys_addr;
size_t dram_size;
+
+   struct rproc_subdev *rpmsg_subdev;
 };
 
 /**
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index ca45cb729bd3..2c4847fcae10 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "mtk_common.h"
 #include "remoteproc_internal.h"
@@ -472,6 +473,31 @@ static int scp_map_memory_region(struct mtk_scp *scp)
return 0;
 }
 
+static struct mtk_rpmsg_info mtk_scp_rpmsg_info = {
+   .send_ipi = scp_ipi_send,
+   .register_ipi = scp_ipi_register,
+   .unregister_ipi = scp_ipi_unregister,
+   .ns_ipi_id = SCP_IPI_NS_SERVICE,
+};
+
+static void scp_add_rpmsg_subdev(struct mtk_scp *scp)
+{
+   scp->rpmsg_subdev =
+   mtk_rpmsg_create_rproc_subdev(to_platform_device(scp->dev),
+ _scp_rpmsg_info);
+   if (scp->rpmsg_subdev)
+   rproc_add_subdev(scp->rproc, scp->rpmsg_subdev);
+}
+
+static void scp_remove_rpmsg_subdev(struct mtk_scp *scp)
+{
+   if (scp->rpmsg_subdev) {
+   rproc_remove_subdev(scp->rproc, scp->rpmsg_subdev);
+   mtk_rpmsg_destroy_rproc_subdev(scp->rpmsg_subdev);
+   scp->rpmsg_subdev = NULL;
+   }
+}
+
 static int scp_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -553,22 +579,25 @@ static int scp_probe(struct platform_device *pdev)
init_waitqueue_head(>run.wq);
init_waitqueue_head(>ack_wq);
 
+   scp_add_rpmsg_subdev(scp);
+
ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), NULL,
scp_irq_handler, IRQF_ONESHOT,
pdev->name, scp);
 
if (ret) {
dev_err(dev, "failed to request irq\n");
-   goto destroy_mutex;
+   goto remove_subdev;
}
 
ret = rproc_add(rproc);
if (ret)
-   goto destroy_mutex;
+   goto remove_subdev;
 
-   return ret;
+   return 0;
 
-destroy_mutex:
+remove_subdev:
+   scp_remove_rpmsg_subdev(scp);
mutex_destroy(>lock);
 free_rproc:
rproc_free(rproc);
@@ -580,6 +609,7 @@ static 

[PATCH v7 1/7] dt-bindings: Add a binding for Mediatek SCP

2019-03-26 Thread Peter Shih
From: Erin Lo 

Add a DT binding documentation of SCP for the
MT8183 SoC from Mediatek.

Signed-off-by: Erin Lo 
Signed-off-by: Pi-Hsun Shih 
Reviewed-by: Rob Herring 
---
Changes from v6:
 - No change.

Changes from v5:
 - Remove dependency on CONFIG_RPMSG_MTK_SCP.

Changes from v4:
 - Add detail of more properties.
 - Document the usage of mtk,rpmsg-name in subnode from the new design.

Changes from v3:
 - No change.

Changes from v2:
 - No change. I realized that for this patch series, there's no need to
   add anything under the mt8183-scp node (neither the mt8183-rpmsg or
   the cros-ec-rpmsg) for them to work, since mt8183-rpmsg is added
   directly as a rproc_subdev by code, and cros-ec-rpmsg is dynamically
   created by SCP name service.

Changes from v1:
 - No change.
---
 .../bindings/remoteproc/mtk,scp.txt   | 36 +++
 1 file changed, 36 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/mtk,scp.txt

diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt 
b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt
new file mode 100644
index ..3ba668bab14b
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt
@@ -0,0 +1,36 @@
+Mediatek SCP Bindings
+
+
+This binding provides support for ARM Cortex M4 Co-processor found on some
+Mediatek SoCs.
+
+Required properties:
+- compatible   Should be "mediatek,mt8183-scp"
+- reg  Should contain the address ranges for the two memory
+   regions, SRAM and CFG.
+- reg-namesContains the corresponding names for the two memory
+   regions. These should be named "sram" & "cfg".
+- clocks   Clock for co-processor (See: 
../clock/clock-bindings.txt)
+- clock-names  Contains the corresponding name for the clock. This
+   should be named "main".
+
+Subnodes
+
+
+Subnodes of the SCP represent rpmsg devices. The names of the devices are not
+important. The properties of these nodes are defined by the individual bindings
+for the rpmsg devices - but must contain the following property:
+
+- mtk,rpmsg-name   Contains the name for the rpmsg device. Used to match
+   the subnode to rpmsg device announced by SCP.
+
+Example:
+
+   scp: scp@1050 {
+   compatible = "mediatek,mt8183-scp";
+   reg = <0 0x1050 0 0x8>,
+ <0 0x105c 0 0x5000>;
+   reg-names = "sram", "cfg";
+   clocks = < CLK_INFRA_SCPSYS>;
+   clock-names = "main";
+   };
-- 
2.21.0.392.gf8f6787159e-goog



[PATCH v7 3/7] remoteproc: mt8183: add reserved memory manager API

2019-03-26 Thread Peter Shih
From: Erin Lo 

Add memory table mapping API for other driver to lookup
reserved physical and virtual memory

Signed-off-by: Erin Lo 
Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - No change.

Changes from v4:
 - New patch.
---
 drivers/remoteproc/mtk_scp.c  | 111 ++
 include/linux/platform_data/mtk_scp.h |  20 +
 2 files changed, 131 insertions(+)

diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index a84d69ae6c53..ca45cb729bd3 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -331,6 +331,113 @@ void *scp_mapping_dm_addr(struct platform_device *pdev, 
u32 mem_addr)
 }
 EXPORT_SYMBOL_GPL(scp_mapping_dm_addr);
 
+#if SCP_RESERVED_MEM
+phys_addr_t scp_mem_base_phys;
+phys_addr_t scp_mem_base_virt;
+phys_addr_t scp_mem_size;
+
+static struct scp_reserve_mblock scp_reserve_mblock[] = {
+   {
+   .num = SCP_ISP_MEM_ID,
+   .start_phys = 0x0,
+   .start_virt = 0x0,
+   .size = 0x140,  /*20MB*/
+   },
+};
+
+static int scp_reserve_mem_init(struct mtk_scp *scp)
+{
+   enum scp_reserve_mem_id_t id;
+   phys_addr_t accumlate_memory_size = 0;
+
+   scp_mem_base_phys = (phys_addr_t) (scp->phys_addr + MAX_CODE_SIZE);
+   scp_mem_size = (phys_addr_t) (scp->dram_size - MAX_CODE_SIZE);
+
+   dev_info(scp->dev,
+"phys:0x%llx - 0x%llx (0x%llx)\n",
+scp_mem_base_phys,
+scp_mem_base_phys + scp_mem_size,
+scp_mem_size);
+   accumlate_memory_size = 0;
+   for (id = 0; id < SCP_NUMS_MEM_ID; id++) {
+   scp_reserve_mblock[id].start_phys =
+   scp_mem_base_phys + accumlate_memory_size;
+   accumlate_memory_size += scp_reserve_mblock[id].size;
+   dev_info(scp->dev,
+"[reserve_mem:%d]: phys:0x%llx - 0x%llx (0x%llx)\n",
+id, scp_reserve_mblock[id].start_phys,
+scp_reserve_mblock[id].start_phys +
+scp_reserve_mblock[id].size,
+scp_reserve_mblock[id].size);
+   }
+   return 0;
+}
+
+static int scp_reserve_memory_ioremap(struct mtk_scp *scp)
+{
+   enum scp_reserve_mem_id_t id;
+   phys_addr_t accumlate_memory_size = 0;
+
+   scp_mem_base_virt = (phys_addr_t)(size_t)ioremap_wc(scp_mem_base_phys,
+   scp_mem_size);
+
+   dev_info(scp->dev,
+"virt:0x%llx - 0x%llx (0x%llx)\n",
+   (phys_addr_t)scp_mem_base_virt,
+   (phys_addr_t)scp_mem_base_virt + (phys_addr_t)scp_mem_size,
+   scp_mem_size);
+   for (id = 0; id < SCP_NUMS_MEM_ID; id++) {
+   scp_reserve_mblock[id].start_virt =
+   scp_mem_base_virt + accumlate_memory_size;
+   accumlate_memory_size += scp_reserve_mblock[id].size;
+   }
+   /* the reserved memory should be larger then expected memory
+* or scp_reserve_mblock does not match dts
+*/
+   WARN_ON(accumlate_memory_size > scp_mem_size);
+#ifdef DEBUG
+   for (id = 0; id < NUMS_MEM_ID; id++) {
+   dev_info(scp->dev,
+"[mem_reserve-%d] 
phys:0x%llx,virt:0x%llx,size:0x%llx\n",
+id,
+scp_get_reserve_mem_phys(id),
+scp_get_reserve_mem_virt(id),
+scp_get_reserve_mem_size(id));
+   }
+#endif
+   return 0;
+}
+phys_addr_t scp_get_reserve_mem_phys(enum scp_reserve_mem_id_t id)
+{
+   if (id >= SCP_NUMS_MEM_ID) {
+   pr_err("[SCP] no reserve memory for %d", id);
+   return 0;
+   } else
+   return scp_reserve_mblock[id].start_phys;
+}
+EXPORT_SYMBOL_GPL(scp_get_reserve_mem_phys);
+
+phys_addr_t scp_get_reserve_mem_virt(enum scp_reserve_mem_id_t id)
+{
+   if (id >= SCP_NUMS_MEM_ID) {
+   pr_err("[SCP] no reserve memory for %d", id);
+   return 0;
+   } else
+   return scp_reserve_mblock[id].start_virt;
+}
+EXPORT_SYMBOL_GPL(scp_get_reserve_mem_virt);
+
+phys_addr_t scp_get_reserve_mem_size(enum scp_reserve_mem_id_t id)
+{
+   if (id >= SCP_NUMS_MEM_ID) {
+   pr_err("[SCP] no reserve memory for %d", id);
+   return 0;
+   } else
+   return scp_reserve_mblock[id].size;
+}
+EXPORT_SYMBOL_GPL(scp_get_reserve_mem_size);
+#endif
+
 static int scp_map_memory_region(struct mtk_scp *scp)
 {
struct device_node *node;
@@ -358,6 +465,10 @@ static int scp_map_memory_region(struct mtk_scp *scp)
return -EBUSY;
}
 
+#if SCP_RESERVED_MEM
+   scp_reserve_mem_init(scp);
+   scp_reserve_memory_ioremap(scp);
+#endif
return 0;
 }
 
diff --git 

[PATCH v7 2/7] remoteproc/mediatek: add SCP support for mt8183

2019-03-26 Thread Peter Shih
From: Erin Lo 

Provide a basic driver to control Cortex M4 co-processor

Signed-off-by: Erin Lo 
Signed-off-by: Nicolas Boichat 
Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - Changed some space to tab.

Changes from v4:
 - Rename most function from mtk_scp_* to scp_*.
 - Change the irq to threaded handler.
 - Load ELF file instead of plain binary file as firmware by default
   (Squashed patch 6 in v4 into this patch).

Changes from v3:
 - Fix some issue found by checkpatch.
 - Make writes aligned in scp_ipi_send.

Changes from v2:
 - Squash patch 3 from v2 (separate the ipi interface) into this patch.
 - Remove unused name argument from scp_ipi_register.
 - Add scp_ipi_unregister for proper cleanup.
 - Move IPI ids in sync with firmware.
 - Add mb() in proper place, and correctly clear the run->signaled.

Changes from v1:
 - Extract functions and rename variables in mtk_scp.c.
---
 drivers/remoteproc/Kconfig|   9 +
 drivers/remoteproc/Makefile   |   1 +
 drivers/remoteproc/mtk_common.h   |  75 
 drivers/remoteproc/mtk_scp.c  | 496 ++
 drivers/remoteproc/mtk_scp_ipi.c  | 162 +
 include/linux/platform_data/mtk_scp.h | 135 +++
 6 files changed, 878 insertions(+)
 create mode 100644 drivers/remoteproc/mtk_common.h
 create mode 100644 drivers/remoteproc/mtk_scp.c
 create mode 100644 drivers/remoteproc/mtk_scp_ipi.c
 create mode 100644 include/linux/platform_data/mtk_scp.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index f0abd2608044..92bd20d6b9cd 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -22,6 +22,15 @@ config IMX_REMOTEPROC
 
  It's safe to say N here.
 
+config MTK_SCP
+   tristate "Mediatek SCP support"
+   depends on ARCH_MEDIATEK
+   help
+ Say y here to support Mediatek's System Companion Processor (SCP) via
+ the remote processor framework.
+
+ It's safe to say N here.
+
 config OMAP_REMOTEPROC
tristate "OMAP remoteproc support"
depends on ARCH_OMAP4 || SOC_OMAP5
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index ce5d061e92be..16b3e5e7a81c 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -10,6 +10,7 @@ remoteproc-y  += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
 remoteproc-y   += remoteproc_elf_loader.o
 obj-$(CONFIG_IMX_REMOTEPROC)   += imx_rproc.o
+obj-$(CONFIG_MTK_SCP)  += mtk_scp.o mtk_scp_ipi.o
 obj-$(CONFIG_OMAP_REMOTEPROC)  += omap_remoteproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
new file mode 100644
index ..7504ae1bc0ef
--- /dev/null
+++ b/drivers/remoteproc/mtk_common.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#ifndef __RPROC_MTK_COMMON_H
+#define __RPROC_MTK_COMMON_H
+
+#include 
+#include 
+#include 
+#include 
+
+#define MT8183_SW_RSTN 0x0
+#define MT8183_SW_RSTN_BIT BIT(0)
+#define MT8183_SCP_TO_HOST 0x1C
+#define MT8183_SCP_IPC_INT_BIT BIT(0)
+#define MT8183_SCP_WDT_INT_BIT BIT(8)
+#define MT8183_HOST_TO_SCP 0x28
+#define MT8183_HOST_IPC_INT_BITBIT(0)
+#define MT8183_SCP_SRAM_PDN0x402C
+
+#define SCP_FW_VER_LEN 32
+
+struct scp_run {
+   u32 signaled;
+   s8 fw_ver[SCP_FW_VER_LEN];
+   u32 dec_capability;
+   u32 enc_capability;
+   wait_queue_head_t wq;
+};
+
+struct scp_ipi_desc {
+   scp_ipi_handler_t handler;
+   void *priv;
+};
+
+struct mtk_scp {
+   struct device *dev;
+   struct rproc *rproc;
+   struct clk *clk;
+   void __iomem *reg_base;
+   void __iomem *sram_base;
+   size_t sram_size;
+
+   struct share_obj *recv_buf;
+   struct share_obj *send_buf;
+   struct scp_run run;
+   struct mutex lock; /* for protecting mtk_scp data structure */
+   struct scp_ipi_desc ipi_desc[SCP_IPI_MAX];
+   bool ipi_id_ack[SCP_IPI_MAX];
+   wait_queue_head_t ack_wq;
+
+   void __iomem *cpu_addr;
+   phys_addr_t phys_addr;
+   size_t dram_size;
+};
+
+/**
+ * struct share_obj - SRAM buffer shared with
+ *   AP and SCP
+ *
+ * @id:IPI id
+ * @len:   share buffer length
+ * @share_buf: share buffer data
+ */
+struct share_obj {
+   s32 id;
+   u32 len;
+   u8 share_buf[288];
+};
+
+void scp_memcpy_aligned(void *dst, const void *src, unsigned int len);
+
+#endif
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
new file mode 100644
index ..a84d69ae6c53
--- /dev/null
+++ 

Re: [PATCH] thermal: mtk: Allocate enough space for mtk_thermal.

2019-01-29 Thread Peter Shih
Adding Michael Kao to cc list.

On Wed, Jan 9, 2019 at 1:57 PM Pi-Hsun Shih  wrote:
>
> The mtk_thermal struct contains a 'struct mtk_thermal_bank banks[];',
> but the allocation only allocates sizeof(struct mtk_thermal) bytes,
> which cause out of bound access with the ->banks[] member. Change it to
> a fixed size array instead.
>
> Signed-off-by: Pi-Hsun Shih 
> ---
>  drivers/thermal/mtk_thermal.c | 7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> index 0691f260f6eabe..ea11edb3fcced6 100644
> --- a/drivers/thermal/mtk_thermal.c
> +++ b/drivers/thermal/mtk_thermal.c
> @@ -159,6 +159,9 @@
>  #define MT7622_NUM_SENSORS_PER_ZONE1
>  #define MT7622_TS1 0
>
> +/* The maximum number of banks */
> +#define MAX_NUM_ZONES  8
> +
>  struct mtk_thermal;
>
>  struct thermal_bank_cfg {
> @@ -178,7 +181,7 @@ struct mtk_thermal_data {
> const int *sensor_mux_values;
> const int *msr;
> const int *adcpnp;
> -   struct thermal_bank_cfg bank_data[];
> +   struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];
>  };
>
>  struct mtk_thermal {
> @@ -197,7 +200,7 @@ struct mtk_thermal {
> s32 vts[MT8173_NUM_SENSORS];
>
> const struct mtk_thermal_data *conf;
> -   struct mtk_thermal_bank banks[];
> +   struct mtk_thermal_bank banks[MAX_NUM_ZONES];
>  };
>
>  /* MT8173 thermal sensor data */
> --
> 2.20.1.97.g81188d93c3-goog
>


Re: [RFC v2 3/6] remoteproc: move IPI interface into separate file.

2019-01-20 Thread Peter Shih
On Sat, Jan 19, 2019 at 5:04 AM Nicolas Boichat  wrote:
>
> Hi,
>
> On Mon, Jan 7, 2019 at 9:26 PM Pi-Hsun Shih  wrote:
> >
> > Move the IPI interface into a separate file mtk_scp_ipi.c, so the things
> > that use the interface only can depend on the module only.
> >
> > Signed-off-by: Pi-Hsun Shih 
> > ---
> > Changes from v1:
> >  - Resolved conflict because of change in Patch 2.
> > ---
> >  drivers/remoteproc/Makefile  |   2 +-
> >  drivers/remoteproc/mtk_common.h  |  73 +++
> >  drivers/remoteproc/mtk_scp.c | 154 +--
>
> The fact that you remove a bunch of stuff from mtk_scp.c makes me
> think that we should probably reorganize the patches. The series here
> shows the history of how we developed this, but for upstreaming
> purpose, we want independent, small-ish patches.
>
> Maybe 2/6 should contain just basic mtk_scp code with no IPI. 3/6 IPI
> only, and _maybe_ 4/6 rpmsg should be folded into 3/6?
>
> Thanks,
>

I think it's hard to have mtk_scp code without IPI, since the
initialization itself depends on IPI.

I'll fold 3/6 into 2/6 in v3.

> >  drivers/remoteproc/mtk_scp_ipi.c | 108 ++
> >  4 files changed, 183 insertions(+), 154 deletions(-)
> >  create mode 100644 drivers/remoteproc/mtk_common.h
> >  create mode 100644 drivers/remoteproc/mtk_scp_ipi.c
> >
> > diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
> > index 98e3498dbbe0e2..16b3e5e7a81c8e 100644
> > --- a/drivers/remoteproc/Makefile
> > +++ b/drivers/remoteproc/Makefile
> > @@ -10,7 +10,7 @@ remoteproc-y  += 
> > remoteproc_sysfs.o
> >  remoteproc-y   += remoteproc_virtio.o
> >  remoteproc-y   += remoteproc_elf_loader.o
> >  obj-$(CONFIG_IMX_REMOTEPROC)   += imx_rproc.o
> > -obj-$(CONFIG_MTK_SCP)  += mtk_scp.o
> > +obj-$(CONFIG_MTK_SCP)  += mtk_scp.o mtk_scp_ipi.o
> >  obj-$(CONFIG_OMAP_REMOTEPROC)  += omap_remoteproc.o
> >  obj-$(CONFIG_WKUP_M3_RPROC)+= wkup_m3_rproc.o
> >  obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
> > diff --git a/drivers/remoteproc/mtk_common.h 
> > b/drivers/remoteproc/mtk_common.h
> > new file mode 100644
> > index 00..e97287a4eb25cc
> > --- /dev/null
> > +++ b/drivers/remoteproc/mtk_common.h
> > @@ -0,0 +1,73 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2018 MediaTek Inc.
> > +
> > +#ifndef __RPROC_MTK_COMMON_H
> > +#define __RPROC_MTK_COMMON_H
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define MT8183_SW_RSTN 0x0
> > +#define MT8183_SW_RSTN_BIT BIT(0)
> > +#define MT8183_SCP_TO_HOST 0x1C
> > +#define MT8183_SCP_IPC_INT_BIT BIT(0)
> > +#define MT8183_SCP_WDT_INT_BIT BIT(8)
> > +#define MT8183_HOST_TO_SCP 0x28
> > +#define MT8183_HOST_IPC_INT_BITBIT(0)
> > +#define MT8183_SCP_SRAM_PDN0x402C
> > +
> > +#define SCP_FW_VER_LEN 32
> > +
> > +struct scp_run {
> > +   u32 signaled;
> > +   s8 fw_ver[SCP_FW_VER_LEN];
> > +   u32 dec_capability;
> > +   u32 enc_capability;
> > +   wait_queue_head_t wq;
> > +};
> > +
> > +struct scp_ipi_desc {
> > +   scp_ipi_handler_t handler;
> > +   const char *name;
> > +   void *priv;
> > +};
> > +
> > +struct mtk_scp {
> > +   struct device *dev;
> > +   struct rproc *rproc;
> > +   struct clk *clk;
> > +   void __iomem *reg_base;
> > +   void __iomem *sram_base;
> > +   size_t sram_size;
> > +
> > +   struct share_obj *recv_buf;
> > +   struct share_obj *send_buf;
> > +   struct scp_run run;
> > +   struct mutex scp_mutex; /* for protecting mtk_scp data structure */
> > +   struct scp_ipi_desc ipi_desc[SCP_IPI_MAX];
> > +   bool ipi_id_ack[SCP_IPI_MAX];
> > +   wait_queue_head_t ack_wq;
> > +
> > +   void __iomem *cpu_addr;
> > +   phys_addr_t phys_addr;
> > +   size_t dram_size;
> > +};
> > +
> > +/**
> > + * struct share_obj - SRAM buffer shared with
> > + *   AP and SCP
> > + *
> > + * @id:IPI id
> > + * @len:   share buffer length
> > + * @share_buf: share buffer data
> > + */
> > +struct share_obj {
> > +   s32 id;
> > +   u32 len;
> > +   u8 share_buf[288];
> > +};
> > +
> > +#endif
> > diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
> > index 6e2e17a227d018..3e84c696523436 100644
> > --- a/drivers/remoteproc/mtk_scp.c
> > +++ b/drivers/remoteproc/mtk_scp.c
> > @@ -13,163 +13,11 @@
> >  #include 
> >  #include 
> >
> > +#include "mtk_common.h"
> >  #include "remoteproc_internal.h"
> >
> > -#define MT8183_SW_RSTN 0x0
> > -#define MT8183_SW_RSTN_BIT BIT(0)
> > -#define MT8183_SCP_TO_HOST 0x1C
> > -#define MT8183_SCP_IPC_INT_BIT BIT(0)
> > -#define 

Re: [RFC v2 1/6] dt-bindings: Add a binding for Mediatek SCP

2019-01-15 Thread Peter Shih
On Wed, Jan 16, 2019 at 4:34 AM Rob Herring  wrote:
>
> On Tue, Jan 08, 2019 at 01:26:01PM +0800, Pi-Hsun Shih wrote:
> > From: Erin Lo 
> >
> > Add a DT binding documentation of SCP for the
> > MT8183 SoC from Mediatek.
> >
> > Signed-off-by: Erin Lo 
> > ---
> > Changes from v1:
> >  - no change
>
> No answer to my question on v1?
>

Sorry I missed the last mail.

Yes there would be additional optional properties. For the current patch
series, the "cros-ec-rpmsg" entry would not be listed in the device tree, but
there would be a "mediatek,mt8183-rpmsg" under this node.

Would update this in v3.

> > ---
> >  .../devicetree/bindings/remoteproc/mtk,scp.txt | 10 ++
> >  1 file changed, 10 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/remoteproc/mtk,scp.txt
> >
> > diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt 
> > b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt
> > new file mode 100644
> > index 00..b07e5c4ca9af1d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt
> > @@ -0,0 +1,10 @@
> > +Mediatek SCP Bindings
> > +
> > +
> > +This binding provides support for ARM Cortex M4 Co-processor found on some
> > +Mediatek SoCs.
> > +
> > +Required properties:
> > +- compatible Should be "mediatek,mt8183-scp"
> > +- clocks Clock for co-processor (See: 
> > ../clock/clock-bindings.txt)
> > +
> > --
> > 2.20.1.97.g81188d93c3-goog
> >


Re: [RFC,5/5] mfd: cros_ec: add EC host command support using rpmsg.

2019-01-06 Thread Peter Shih
On Fri, Jan 4, 2019 at 7:39 PM Enric Balletbo Serra  wrote:
>
> Hi Peter,
>
> Missatge de Peter Shih  del dia dv., 4 de gen.
> 2019 a les 8:58:
> >
> > Thanks for the review.
> > I would leave some formatting comment to v2, and reply others first.
> >
> > On Fri, Jan 4, 2019 at 12:05 AM Enric Balletbo Serra
> >  wrote:
> > >
> > > Hi,
> > >
> > > Many thanks for sending this. Please, add Guenter and me for next
> > > versions, we are interested in it, thanks :)
> > >
> > > Missatge de Pi-Hsun Shih  del dia dc., 26 de des.
> > > 2018 a les 8:57:
> > > >
> > > > Add EC host command support through rpmsg.
> > > >
> > > > Signed-off-by: Pi-Hsun Shih 
> > > > ---
> > > >  drivers/mfd/cros_ec_dev.c   |   9 ++
> > > >  drivers/platform/chrome/Kconfig |   8 ++
> > > >  drivers/platform/chrome/Makefile|   1 +
> > > >  drivers/platform/chrome/cros_ec_rpmsg.c | 164 
> > > >  include/linux/mfd/cros_ec.h |   1 +
> > > >  include/linux/mfd/cros_ec_commands.h|   2 +
> > > >  6 files changed, 185 insertions(+)
> > > >  create mode 100644 drivers/platform/chrome/cros_ec_rpmsg.c
> > > >
> > > > diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
> > > > index 2d0fee488c5aa8..67983853413d07 100644
> > > > --- a/drivers/mfd/cros_ec_dev.c
> > > > +++ b/drivers/mfd/cros_ec_dev.c
> > > > @@ -414,6 +414,15 @@ static int ec_device_probe(struct platform_device 
> > > > *pdev)
> > > > device_initialize(>class_dev);
> > > > cdev_init(>cdev, );
> > > >
> > > > +   if (cros_ec_check_features(ec, EC_FEATURE_SCP)) {
> > > > +   dev_info(dev, "SCP detected.\n");
> > > > +   /*
> > > > +* Help userspace differentiating ECs from SCP,
> > > > +* regardless of the probing order.
> > > > +*/
> > > > +   ec_platform->ec_name = CROS_EC_DEV_SCP_NAME;
> > > > +   }
> > > > +
> > >
> > > Why userspace should know that this is an SCP? From the userspace
> > > point of view shouldn't be this transparent, we don't do distinctions
> > > when the transport layer is i2c, spi or lpc, and I think that the
> > > cros_ec_rpmsg driver is a cros-ec transport layer, like these. So, I
> > > think that this is not needed.
> > >
> >
> > Since both the EC and the SCP talk in EC host command format here, and they 
> > can
> > both exist on the same system, if we don't do the distinction, both of them
> > would be registered as /dev/cros_ec, and cause an error.
> >
>
> Interesting, so this system will have two cros-ec, one connected via
> spi or i2c to the soc and another one using the M4 within the M8183?
>
> Actually, on some systems, we have chained EC's (ie cros_ec and
> cros_pd). The way we actually handle the name to access the different
> ECs is create a mfd cell with their specific platform data, I am
> wondering if we can do the same here (see drivers/mfd/cros_ec.c)
>

Yes there's two cros-ec as described (one throught spi / i2c to a EC, one
through rpmsg to the M4 within M8183).

I think that what transport layer used (rpmsg / spi / i2c) is independent to
what the cros-ec actually is (a normal EC, or a SCP), so we probably still need
some feature detection to check what the cros-ec is. It seems to be hard to do
that on cros_ec_register in drivers/mfd/cros_ec.c using different mfd cell,
since it knows nothing about the EC features.

Or should I just don't do feature detection, but write the information in the
device tree instead? (Via some "dev-name" property probably?)

> > This change is actually independent to the rpmsg change (EC through all
> > transport layer can report that they have feature EC_FEATURE_SCP, and would
> > then be seen from userspace as /dev/cros_scp), I'll move this to another 
> > patch
> > in v2.
> >
> > > > /*
> > > >  * Add the class device
> > > >  * Link to the character device for creating the /dev entry
> > > > diff --git a/drivers/platform/chrome/Kconfig 
> > > > b/drivers/platform/chrome/Kconfig
> > > > index 16b1615958aa2d..b03d68eb732177 100644
> > > > --- a/drivers/platform/chrome/Kconfig
> > > > +++ b/drivers/platform/chrome/

Re: [RFC,5/5] mfd: cros_ec: add EC host command support using rpmsg.

2019-01-03 Thread Peter Shih
Thanks for the review.
I would leave some formatting comment to v2, and reply others first.

On Fri, Jan 4, 2019 at 12:05 AM Enric Balletbo Serra
 wrote:
>
> Hi,
>
> Many thanks for sending this. Please, add Guenter and me for next
> versions, we are interested in it, thanks :)
>
> Missatge de Pi-Hsun Shih  del dia dc., 26 de des.
> 2018 a les 8:57:
> >
> > Add EC host command support through rpmsg.
> >
> > Signed-off-by: Pi-Hsun Shih 
> > ---
> >  drivers/mfd/cros_ec_dev.c   |   9 ++
> >  drivers/platform/chrome/Kconfig |   8 ++
> >  drivers/platform/chrome/Makefile|   1 +
> >  drivers/platform/chrome/cros_ec_rpmsg.c | 164 
> >  include/linux/mfd/cros_ec.h |   1 +
> >  include/linux/mfd/cros_ec_commands.h|   2 +
> >  6 files changed, 185 insertions(+)
> >  create mode 100644 drivers/platform/chrome/cros_ec_rpmsg.c
> >
> > diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
> > index 2d0fee488c5aa8..67983853413d07 100644
> > --- a/drivers/mfd/cros_ec_dev.c
> > +++ b/drivers/mfd/cros_ec_dev.c
> > @@ -414,6 +414,15 @@ static int ec_device_probe(struct platform_device 
> > *pdev)
> > device_initialize(>class_dev);
> > cdev_init(>cdev, );
> >
> > +   if (cros_ec_check_features(ec, EC_FEATURE_SCP)) {
> > +   dev_info(dev, "SCP detected.\n");
> > +   /*
> > +* Help userspace differentiating ECs from SCP,
> > +* regardless of the probing order.
> > +*/
> > +   ec_platform->ec_name = CROS_EC_DEV_SCP_NAME;
> > +   }
> > +
>
> Why userspace should know that this is an SCP? From the userspace
> point of view shouldn't be this transparent, we don't do distinctions
> when the transport layer is i2c, spi or lpc, and I think that the
> cros_ec_rpmsg driver is a cros-ec transport layer, like these. So, I
> think that this is not needed.
>

Since both the EC and the SCP talk in EC host command format here, and they can
both exist on the same system, if we don't do the distinction, both of them
would be registered as /dev/cros_ec, and cause an error.

This change is actually independent to the rpmsg change (EC through all
transport layer can report that they have feature EC_FEATURE_SCP, and would
then be seen from userspace as /dev/cros_scp), I'll move this to another patch
in v2.

> > /*
> >  * Add the class device
> >  * Link to the character device for creating the /dev entry
> > diff --git a/drivers/platform/chrome/Kconfig 
> > b/drivers/platform/chrome/Kconfig
> > index 16b1615958aa2d..b03d68eb732177 100644
> > --- a/drivers/platform/chrome/Kconfig
> > +++ b/drivers/platform/chrome/Kconfig
> > @@ -72,6 +72,14 @@ config CROS_EC_SPI
> >   response time cannot be guaranteed, we support ignoring
> >   'pre-amble' bytes before the response actually starts.
> >
> > +config CROS_EC_RPMSG
> > +   tristate "ChromeOS Embedded Controller (rpmsg)"
> > +   depends on MFD_CROS_EC && RPMSG
>
> I think that this driver is DT-only, && OF ?

Would add this in v2.

>
> > +   help
> > + If you say Y here, you get support for talking to the ChromeOS EC
> > + through rpmsg. This uses a simple byte-level protocol with a
> > + checksum.
> > +
> >  config CROS_EC_LPC
> >  tristate "ChromeOS Embedded Controller (LPC)"
> >  depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
> > diff --git a/drivers/platform/chrome/Makefile 
> > b/drivers/platform/chrome/Makefile
> > index cd591bf872bbe9..3e3190af2b50f4 100644
> > --- a/drivers/platform/chrome/Makefile
> > +++ b/drivers/platform/chrome/Makefile
> > @@ -8,6 +8,7 @@ cros_ec_ctl-objs:= cros_ec_sysfs.o 
> > cros_ec_lightbar.o \
> >  obj-$(CONFIG_CROS_EC_CTL)  += cros_ec_ctl.o
> >  obj-$(CONFIG_CROS_EC_I2C)  += cros_ec_i2c.o
> >  obj-$(CONFIG_CROS_EC_SPI)  += cros_ec_spi.o
> > +obj-$(CONFIG_CROS_EC_RPMSG)+= cros_ec_rpmsg.o
> >  cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
> >  cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
> >  obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
> > diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c 
> > b/drivers/platform/chrome/cros_ec_rpmsg.c
> > new file mode 100644
> > index 00..f123ca6d1c029c
> > --- /dev/null
> > +++ b/drivers/platform/chrome/cros_ec_rpmsg.c
> > @@ -0,0 +1,164 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright 2018 Google LLC.
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +/**
> > + * cros_ec_cmd_xfer_rpmsg - Transfer a message over rpmsg and receive the 
> > reply
> > + *
> > + * This is only used for old EC proto version, and is not supported for 
> > this
> > + * driver.
> > + *
> > + * @ec_dev: ChromeOS 

[PATCH] tty: serial: 8250_mtk: always resume the device in probe.

2018-11-26 Thread Peter Shih
serial8250_register_8250_port calls uart_config_port, which calls
config_port on the port before it tries to power on the port. So we need
the port to be on before calling serial8250_register_8250_port. Change
the code to always do a runtime resume in probe before registering port,
and always do a runtime suspend in remove.

This basically reverts the change in commit 68e5fc4a255a ("tty: serial:
8250_mtk: use pm_runtime callbacks for enabling"), but still use
pm_runtime callbacks.

Fixes: 68e5fc4a255a ("tty: serial: 8250_mtk: use pm_runtime callbacks for 
enabling")
Signed-off-by: Peter Shih 
---
 drivers/tty/serial/8250/8250_mtk.c | 16 +++-
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c 
b/drivers/tty/serial/8250/8250_mtk.c
index dd5e1cede2b58..c3f933d10295e 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -213,17 +213,17 @@ static int mtk8250_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, data);
 
-   pm_runtime_enable(>dev);
-   if (!pm_runtime_enabled(>dev)) {
-   err = mtk8250_runtime_resume(>dev);
-   if (err)
-   return err;
-   }
+   err = mtk8250_runtime_resume(>dev);
+   if (err)
+   return err;
 
data->line = serial8250_register_8250_port();
if (data->line < 0)
return data->line;
 
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 }
 
@@ -234,13 +234,11 @@ static int mtk8250_remove(struct platform_device *pdev)
pm_runtime_get_sync(>dev);
 
serial8250_unregister_port(data->line);
+   mtk8250_runtime_suspend(>dev);
 
pm_runtime_disable(>dev);
pm_runtime_put_noidle(>dev);
 
-   if (!pm_runtime_status_suspended(>dev))
-   mtk8250_runtime_suspend(>dev);
-
return 0;
 }
 
-- 
2.20.0.rc0.387.gc7a69e6b6c-goog



[PATCH] tty: serial: 8250_mtk: always resume the device in probe.

2018-11-26 Thread Peter Shih
serial8250_register_8250_port calls uart_config_port, which calls
config_port on the port before it tries to power on the port. So we need
the port to be on before calling serial8250_register_8250_port. Change
the code to always do a runtime resume in probe before registering port,
and always do a runtime suspend in remove.

This basically reverts the change in commit 68e5fc4a255a ("tty: serial:
8250_mtk: use pm_runtime callbacks for enabling"), but still use
pm_runtime callbacks.

Fixes: 68e5fc4a255a ("tty: serial: 8250_mtk: use pm_runtime callbacks for 
enabling")
Signed-off-by: Peter Shih 
---
 drivers/tty/serial/8250/8250_mtk.c | 16 +++-
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_mtk.c 
b/drivers/tty/serial/8250/8250_mtk.c
index dd5e1cede2b58..c3f933d10295e 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -213,17 +213,17 @@ static int mtk8250_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, data);
 
-   pm_runtime_enable(>dev);
-   if (!pm_runtime_enabled(>dev)) {
-   err = mtk8250_runtime_resume(>dev);
-   if (err)
-   return err;
-   }
+   err = mtk8250_runtime_resume(>dev);
+   if (err)
+   return err;
 
data->line = serial8250_register_8250_port();
if (data->line < 0)
return data->line;
 
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 }
 
@@ -234,13 +234,11 @@ static int mtk8250_remove(struct platform_device *pdev)
pm_runtime_get_sync(>dev);
 
serial8250_unregister_port(data->line);
+   mtk8250_runtime_suspend(>dev);
 
pm_runtime_disable(>dev);
pm_runtime_put_noidle(>dev);
 
-   if (!pm_runtime_status_suspended(>dev))
-   mtk8250_runtime_suspend(>dev);
-
return 0;
 }
 
-- 
2.20.0.rc0.387.gc7a69e6b6c-goog



[PATCH v3] spi: mediatek: Don't modify spi_transfer when transfer.

2018-09-19 Thread Peter Shih
Mediatek SPI driver modifies some fields (tx_buf, rx_buf, len, tx_dma,
rx_dma) of the spi_transfer* passed in when doing transfer_one and in
interrupt handler. This is somewhat unexpected, and there are some
caller (e.g. Cr50 spi driver) that reuse the spi_transfer for multiple
messages. Add a field to record how many bytes have been transferred,
and calculate the right len / buffer based on it instead.

Signed-off-by: Pi-Hsun Shih 
---
 drivers/spi/spi-mt65xx.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 86bf45667a040..3dc31627c6558 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -98,6 +98,7 @@ struct mtk_spi {
struct clk *parent_clk, *sel_clk, *spi_clk;
struct spi_transfer *cur_transfer;
u32 xfer_len;
+   u32 num_xfered;
struct scatterlist *tx_sgl, *rx_sgl;
u32 tx_sgl_len, rx_sgl_len;
const struct mtk_spi_compatible *dev_comp;
@@ -385,6 +386,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 
mdata->cur_transfer = xfer;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
+   mdata->num_xfered = 0;
mtk_spi_prepare_transfer(master, xfer);
mtk_spi_setup_packet(master);
 
@@ -415,6 +417,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
mdata->tx_sgl_len = 0;
mdata->rx_sgl_len = 0;
mdata->cur_transfer = xfer;
+   mdata->num_xfered = 0;
 
mtk_spi_prepare_transfer(master, xfer);
 
@@ -482,7 +485,7 @@ static int mtk_spi_setup(struct spi_device *spi)
 
 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 {
-   u32 cmd, reg_val, cnt, remainder;
+   u32 cmd, reg_val, cnt, remainder, len;
struct spi_master *master = dev_id;
struct mtk_spi *mdata = spi_master_get_devdata(master);
struct spi_transfer *trans = mdata->cur_transfer;
@@ -497,36 +500,38 @@ static irqreturn_t mtk_spi_interrupt(int irq, void 
*dev_id)
if (trans->rx_buf) {
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
-trans->rx_buf, cnt);
+trans->rx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
-   memcpy(trans->rx_buf + (cnt * 4),
-   _val, remainder);
+   memcpy(trans->rx_buf +
+   mdata->num_xfered +
+   (cnt * 4),
+   _val,
+   remainder);
}
}
 
-   trans->len -= mdata->xfer_len;
-   if (!trans->len) {
+   mdata->num_xfered += mdata->xfer_len;
+   if (mdata->num_xfered == trans->len) {
spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
-   if (trans->tx_buf)
-   trans->tx_buf += mdata->xfer_len;
-   if (trans->rx_buf)
-   trans->rx_buf += mdata->xfer_len;
-
-   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+   len = trans->len - mdata->num_xfered;
+   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
mtk_spi_setup_packet(master);
 
-   cnt = trans->len / 4;
-   iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, 
cnt);
+   cnt = len / 4;
+   iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
+   trans->tx_buf + mdata->num_xfered, cnt);
 
-   remainder = trans->len % 4;
+   remainder = len % 4;
if (remainder > 0) {
reg_val = 0;
-   memcpy(_val, trans->tx_buf + (cnt * 4), remainder);
+   memcpy(_val,
+   trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+   remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
 
-- 
2.19.0.rc2.392.g5ba43deb5a-goog



[PATCH v3] spi: mediatek: Don't modify spi_transfer when transfer.

2018-09-19 Thread Peter Shih
Mediatek SPI driver modifies some fields (tx_buf, rx_buf, len, tx_dma,
rx_dma) of the spi_transfer* passed in when doing transfer_one and in
interrupt handler. This is somewhat unexpected, and there are some
caller (e.g. Cr50 spi driver) that reuse the spi_transfer for multiple
messages. Add a field to record how many bytes have been transferred,
and calculate the right len / buffer based on it instead.

Signed-off-by: Pi-Hsun Shih 
---
 drivers/spi/spi-mt65xx.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 86bf45667a040..3dc31627c6558 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -98,6 +98,7 @@ struct mtk_spi {
struct clk *parent_clk, *sel_clk, *spi_clk;
struct spi_transfer *cur_transfer;
u32 xfer_len;
+   u32 num_xfered;
struct scatterlist *tx_sgl, *rx_sgl;
u32 tx_sgl_len, rx_sgl_len;
const struct mtk_spi_compatible *dev_comp;
@@ -385,6 +386,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 
mdata->cur_transfer = xfer;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
+   mdata->num_xfered = 0;
mtk_spi_prepare_transfer(master, xfer);
mtk_spi_setup_packet(master);
 
@@ -415,6 +417,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
mdata->tx_sgl_len = 0;
mdata->rx_sgl_len = 0;
mdata->cur_transfer = xfer;
+   mdata->num_xfered = 0;
 
mtk_spi_prepare_transfer(master, xfer);
 
@@ -482,7 +485,7 @@ static int mtk_spi_setup(struct spi_device *spi)
 
 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 {
-   u32 cmd, reg_val, cnt, remainder;
+   u32 cmd, reg_val, cnt, remainder, len;
struct spi_master *master = dev_id;
struct mtk_spi *mdata = spi_master_get_devdata(master);
struct spi_transfer *trans = mdata->cur_transfer;
@@ -497,36 +500,38 @@ static irqreturn_t mtk_spi_interrupt(int irq, void 
*dev_id)
if (trans->rx_buf) {
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
-trans->rx_buf, cnt);
+trans->rx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
-   memcpy(trans->rx_buf + (cnt * 4),
-   _val, remainder);
+   memcpy(trans->rx_buf +
+   mdata->num_xfered +
+   (cnt * 4),
+   _val,
+   remainder);
}
}
 
-   trans->len -= mdata->xfer_len;
-   if (!trans->len) {
+   mdata->num_xfered += mdata->xfer_len;
+   if (mdata->num_xfered == trans->len) {
spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
-   if (trans->tx_buf)
-   trans->tx_buf += mdata->xfer_len;
-   if (trans->rx_buf)
-   trans->rx_buf += mdata->xfer_len;
-
-   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+   len = trans->len - mdata->num_xfered;
+   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
mtk_spi_setup_packet(master);
 
-   cnt = trans->len / 4;
-   iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, 
cnt);
+   cnt = len / 4;
+   iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
+   trans->tx_buf + mdata->num_xfered, cnt);
 
-   remainder = trans->len % 4;
+   remainder = len % 4;
if (remainder > 0) {
reg_val = 0;
-   memcpy(_val, trans->tx_buf + (cnt * 4), remainder);
+   memcpy(_val,
+   trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+   remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
 
-- 
2.19.0.rc2.392.g5ba43deb5a-goog



[PATCH v2] spi: mediatek: Don't modify spi_transfer when transfer.

2018-09-09 Thread Peter Shih
Mediatek SPI driver modifies some fields (tx_buf, rx_buf, len, tx_dma,
rx_dma) of the spi_transfer* passed in when doing transfer_one and in
interrupt handler. This is somewhat unexpected, and there are some
caller (e.g. Cr50 spi driver) that reuse the spi_transfer for multiple
messages. Add a field to record how many bytes have been transferred,
and calculate the right len / buffer based on it instead.

Signed-off-by: Pi-Hsun Shih 

Change-Id: I23e218cd964f16c0b2b26127d4a5ca6529867673
---
 drivers/spi/spi-mt65xx.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 86bf45667a040..3dc31627c6558 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -98,6 +98,7 @@ struct mtk_spi {
struct clk *parent_clk, *sel_clk, *spi_clk;
struct spi_transfer *cur_transfer;
u32 xfer_len;
+   u32 num_xfered;
struct scatterlist *tx_sgl, *rx_sgl;
u32 tx_sgl_len, rx_sgl_len;
const struct mtk_spi_compatible *dev_comp;
@@ -385,6 +386,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 
mdata->cur_transfer = xfer;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
+   mdata->num_xfered = 0;
mtk_spi_prepare_transfer(master, xfer);
mtk_spi_setup_packet(master);
 
@@ -415,6 +417,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
mdata->tx_sgl_len = 0;
mdata->rx_sgl_len = 0;
mdata->cur_transfer = xfer;
+   mdata->num_xfered = 0;
 
mtk_spi_prepare_transfer(master, xfer);
 
@@ -482,7 +485,7 @@ static int mtk_spi_setup(struct spi_device *spi)
 
 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 {
-   u32 cmd, reg_val, cnt, remainder;
+   u32 cmd, reg_val, cnt, remainder, len;
struct spi_master *master = dev_id;
struct mtk_spi *mdata = spi_master_get_devdata(master);
struct spi_transfer *trans = mdata->cur_transfer;
@@ -497,36 +500,38 @@ static irqreturn_t mtk_spi_interrupt(int irq, void 
*dev_id)
if (trans->rx_buf) {
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
-trans->rx_buf, cnt);
+trans->rx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
-   memcpy(trans->rx_buf + (cnt * 4),
-   _val, remainder);
+   memcpy(trans->rx_buf +
+   mdata->num_xfered +
+   (cnt * 4),
+   _val,
+   remainder);
}
}
 
-   trans->len -= mdata->xfer_len;
-   if (!trans->len) {
+   mdata->num_xfered += mdata->xfer_len;
+   if (mdata->num_xfered == trans->len) {
spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
-   if (trans->tx_buf)
-   trans->tx_buf += mdata->xfer_len;
-   if (trans->rx_buf)
-   trans->rx_buf += mdata->xfer_len;
-
-   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+   len = trans->len - mdata->num_xfered;
+   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
mtk_spi_setup_packet(master);
 
-   cnt = trans->len / 4;
-   iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, 
cnt);
+   cnt = len / 4;
+   iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
+   trans->tx_buf + mdata->num_xfered, cnt);
 
-   remainder = trans->len % 4;
+   remainder = len % 4;
if (remainder > 0) {
reg_val = 0;
-   memcpy(_val, trans->tx_buf + (cnt * 4), remainder);
+   memcpy(_val,
+   trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+   remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
 
-- 
2.19.0.rc2.392.g5ba43deb5a-goog



[PATCH v2] spi: mediatek: Don't modify spi_transfer when transfer.

2018-09-09 Thread Peter Shih
Mediatek SPI driver modifies some fields (tx_buf, rx_buf, len, tx_dma,
rx_dma) of the spi_transfer* passed in when doing transfer_one and in
interrupt handler. This is somewhat unexpected, and there are some
caller (e.g. Cr50 spi driver) that reuse the spi_transfer for multiple
messages. Add a field to record how many bytes have been transferred,
and calculate the right len / buffer based on it instead.

Signed-off-by: Pi-Hsun Shih 

Change-Id: I23e218cd964f16c0b2b26127d4a5ca6529867673
---
 drivers/spi/spi-mt65xx.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 86bf45667a040..3dc31627c6558 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -98,6 +98,7 @@ struct mtk_spi {
struct clk *parent_clk, *sel_clk, *spi_clk;
struct spi_transfer *cur_transfer;
u32 xfer_len;
+   u32 num_xfered;
struct scatterlist *tx_sgl, *rx_sgl;
u32 tx_sgl_len, rx_sgl_len;
const struct mtk_spi_compatible *dev_comp;
@@ -385,6 +386,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 
mdata->cur_transfer = xfer;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
+   mdata->num_xfered = 0;
mtk_spi_prepare_transfer(master, xfer);
mtk_spi_setup_packet(master);
 
@@ -415,6 +417,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
mdata->tx_sgl_len = 0;
mdata->rx_sgl_len = 0;
mdata->cur_transfer = xfer;
+   mdata->num_xfered = 0;
 
mtk_spi_prepare_transfer(master, xfer);
 
@@ -482,7 +485,7 @@ static int mtk_spi_setup(struct spi_device *spi)
 
 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 {
-   u32 cmd, reg_val, cnt, remainder;
+   u32 cmd, reg_val, cnt, remainder, len;
struct spi_master *master = dev_id;
struct mtk_spi *mdata = spi_master_get_devdata(master);
struct spi_transfer *trans = mdata->cur_transfer;
@@ -497,36 +500,38 @@ static irqreturn_t mtk_spi_interrupt(int irq, void 
*dev_id)
if (trans->rx_buf) {
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
-trans->rx_buf, cnt);
+trans->rx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
-   memcpy(trans->rx_buf + (cnt * 4),
-   _val, remainder);
+   memcpy(trans->rx_buf +
+   mdata->num_xfered +
+   (cnt * 4),
+   _val,
+   remainder);
}
}
 
-   trans->len -= mdata->xfer_len;
-   if (!trans->len) {
+   mdata->num_xfered += mdata->xfer_len;
+   if (mdata->num_xfered == trans->len) {
spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
-   if (trans->tx_buf)
-   trans->tx_buf += mdata->xfer_len;
-   if (trans->rx_buf)
-   trans->rx_buf += mdata->xfer_len;
-
-   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+   len = trans->len - mdata->num_xfered;
+   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
mtk_spi_setup_packet(master);
 
-   cnt = trans->len / 4;
-   iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, 
cnt);
+   cnt = len / 4;
+   iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
+   trans->tx_buf + mdata->num_xfered, cnt);
 
-   remainder = trans->len % 4;
+   remainder = len % 4;
if (remainder > 0) {
reg_val = 0;
-   memcpy(_val, trans->tx_buf + (cnt * 4), remainder);
+   memcpy(_val,
+   trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+   remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
 
-- 
2.19.0.rc2.392.g5ba43deb5a-goog



[PATCH] spi: mediatek: Don't modify spi_transfer when transfer.

2018-09-09 Thread Peter Shih
Mediatek SPI driver modifies some fields (tx_buf, rx_buf, len, tx_dma,
rx_dma) of the spi_transfer* passed in when doing transfer_one and in
interrupt handler. This is somewhat unexpected, and there are some
caller (e.g. Cr50 spi driver) that reuse the spi_transfer for multiple
messages. Add a field to record how many bytes have been transferred,
and calculate the right len / buffer based on it instead.

BUG=b:113973051
TEST=None

Signed-off-by: Pi-Hsun Shih 

Change-Id: I23e218cd964f16c0b2b26127d4a5ca6529867673
---
 drivers/spi/spi-mt65xx.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 86bf45667a040..3dc31627c6558 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -98,6 +98,7 @@ struct mtk_spi {
struct clk *parent_clk, *sel_clk, *spi_clk;
struct spi_transfer *cur_transfer;
u32 xfer_len;
+   u32 num_xfered;
struct scatterlist *tx_sgl, *rx_sgl;
u32 tx_sgl_len, rx_sgl_len;
const struct mtk_spi_compatible *dev_comp;
@@ -385,6 +386,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 
mdata->cur_transfer = xfer;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
+   mdata->num_xfered = 0;
mtk_spi_prepare_transfer(master, xfer);
mtk_spi_setup_packet(master);
 
@@ -415,6 +417,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
mdata->tx_sgl_len = 0;
mdata->rx_sgl_len = 0;
mdata->cur_transfer = xfer;
+   mdata->num_xfered = 0;
 
mtk_spi_prepare_transfer(master, xfer);
 
@@ -482,7 +485,7 @@ static int mtk_spi_setup(struct spi_device *spi)
 
 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 {
-   u32 cmd, reg_val, cnt, remainder;
+   u32 cmd, reg_val, cnt, remainder, len;
struct spi_master *master = dev_id;
struct mtk_spi *mdata = spi_master_get_devdata(master);
struct spi_transfer *trans = mdata->cur_transfer;
@@ -497,36 +500,38 @@ static irqreturn_t mtk_spi_interrupt(int irq, void 
*dev_id)
if (trans->rx_buf) {
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
-trans->rx_buf, cnt);
+trans->rx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
-   memcpy(trans->rx_buf + (cnt * 4),
-   _val, remainder);
+   memcpy(trans->rx_buf +
+   mdata->num_xfered +
+   (cnt * 4),
+   _val,
+   remainder);
}
}
 
-   trans->len -= mdata->xfer_len;
-   if (!trans->len) {
+   mdata->num_xfered += mdata->xfer_len;
+   if (mdata->num_xfered == trans->len) {
spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
-   if (trans->tx_buf)
-   trans->tx_buf += mdata->xfer_len;
-   if (trans->rx_buf)
-   trans->rx_buf += mdata->xfer_len;
-
-   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+   len = trans->len - mdata->num_xfered;
+   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
mtk_spi_setup_packet(master);
 
-   cnt = trans->len / 4;
-   iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, 
cnt);
+   cnt = len / 4;
+   iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
+   trans->tx_buf + mdata->num_xfered, cnt);
 
-   remainder = trans->len % 4;
+   remainder = len % 4;
if (remainder > 0) {
reg_val = 0;
-   memcpy(_val, trans->tx_buf + (cnt * 4), remainder);
+   memcpy(_val,
+   trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+   remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
 
-- 
2.19.0.rc2.392.g5ba43deb5a-goog



[PATCH] spi: mediatek: Don't modify spi_transfer when transfer.

2018-09-09 Thread Peter Shih
Mediatek SPI driver modifies some fields (tx_buf, rx_buf, len, tx_dma,
rx_dma) of the spi_transfer* passed in when doing transfer_one and in
interrupt handler. This is somewhat unexpected, and there are some
caller (e.g. Cr50 spi driver) that reuse the spi_transfer for multiple
messages. Add a field to record how many bytes have been transferred,
and calculate the right len / buffer based on it instead.

BUG=b:113973051
TEST=None

Signed-off-by: Pi-Hsun Shih 

Change-Id: I23e218cd964f16c0b2b26127d4a5ca6529867673
---
 drivers/spi/spi-mt65xx.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 86bf45667a040..3dc31627c6558 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -98,6 +98,7 @@ struct mtk_spi {
struct clk *parent_clk, *sel_clk, *spi_clk;
struct spi_transfer *cur_transfer;
u32 xfer_len;
+   u32 num_xfered;
struct scatterlist *tx_sgl, *rx_sgl;
u32 tx_sgl_len, rx_sgl_len;
const struct mtk_spi_compatible *dev_comp;
@@ -385,6 +386,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
 
mdata->cur_transfer = xfer;
mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
+   mdata->num_xfered = 0;
mtk_spi_prepare_transfer(master, xfer);
mtk_spi_setup_packet(master);
 
@@ -415,6 +417,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
mdata->tx_sgl_len = 0;
mdata->rx_sgl_len = 0;
mdata->cur_transfer = xfer;
+   mdata->num_xfered = 0;
 
mtk_spi_prepare_transfer(master, xfer);
 
@@ -482,7 +485,7 @@ static int mtk_spi_setup(struct spi_device *spi)
 
 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 {
-   u32 cmd, reg_val, cnt, remainder;
+   u32 cmd, reg_val, cnt, remainder, len;
struct spi_master *master = dev_id;
struct mtk_spi *mdata = spi_master_get_devdata(master);
struct spi_transfer *trans = mdata->cur_transfer;
@@ -497,36 +500,38 @@ static irqreturn_t mtk_spi_interrupt(int irq, void 
*dev_id)
if (trans->rx_buf) {
cnt = mdata->xfer_len / 4;
ioread32_rep(mdata->base + SPI_RX_DATA_REG,
-trans->rx_buf, cnt);
+trans->rx_buf + mdata->num_xfered, cnt);
remainder = mdata->xfer_len % 4;
if (remainder > 0) {
reg_val = readl(mdata->base + SPI_RX_DATA_REG);
-   memcpy(trans->rx_buf + (cnt * 4),
-   _val, remainder);
+   memcpy(trans->rx_buf +
+   mdata->num_xfered +
+   (cnt * 4),
+   _val,
+   remainder);
}
}
 
-   trans->len -= mdata->xfer_len;
-   if (!trans->len) {
+   mdata->num_xfered += mdata->xfer_len;
+   if (mdata->num_xfered == trans->len) {
spi_finalize_current_transfer(master);
return IRQ_HANDLED;
}
 
-   if (trans->tx_buf)
-   trans->tx_buf += mdata->xfer_len;
-   if (trans->rx_buf)
-   trans->rx_buf += mdata->xfer_len;
-
-   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
+   len = trans->len - mdata->num_xfered;
+   mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
mtk_spi_setup_packet(master);
 
-   cnt = trans->len / 4;
-   iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, 
cnt);
+   cnt = len / 4;
+   iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
+   trans->tx_buf + mdata->num_xfered, cnt);
 
-   remainder = trans->len % 4;
+   remainder = len % 4;
if (remainder > 0) {
reg_val = 0;
-   memcpy(_val, trans->tx_buf + (cnt * 4), remainder);
+   memcpy(_val,
+   trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+   remainder);
writel(reg_val, mdata->base + SPI_TX_DATA_REG);
}
 
-- 
2.19.0.rc2.392.g5ba43deb5a-goog