soc: ti: pruss: Add pruss_{request,release}_mem_region() API
authorAndrew F. Davis <afd@ti.com>
Fri, 14 Apr 2023 04:55:40 +0000 (10:25 +0530)
committerNishanth Menon <nm@ti.com>
Wed, 17 May 2023 14:15:39 +0000 (09:15 -0500)
Add two new API - pruss_request_mem_region() & pruss_release_mem_region(),
to the PRUSS platform driver to allow client drivers to acquire and release
the common memory resources present within a PRU-ICSS subsystem. This
allows the client drivers to directly manipulate the respective memories,
as per their design contract with the associated firmware.

Co-developed-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Andrew F. Davis <afd@ti.com>
Co-developed-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>
Signed-off-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>
Reviewed-by: Roger Quadros <rogerq@kernel.org>
Acked-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Link: https://lore.kernel.org/r/20230414045542.3249939-3-danishanwar@ti.com
Signed-off-by: Nishanth Menon <nm@ti.com>
drivers/soc/ti/pruss.c
include/linux/pruss_driver.h

index f836660dac64742165df4862db8b6e00ab989cfe..df5eb4d959f82f10acd1d294d9ccf77e9e3b8844 100644 (file)
@@ -92,6 +92,82 @@ void pruss_put(struct pruss *pruss)
 }
 EXPORT_SYMBOL_GPL(pruss_put);
 
+/**
+ * pruss_request_mem_region() - request a memory resource
+ * @pruss: the pruss instance
+ * @mem_id: the memory resource id
+ * @region: pointer to memory region structure to be filled in
+ *
+ * This function allows a client driver to request a memory resource,
+ * and if successful, will let the client driver own the particular
+ * memory region until released using the pruss_release_mem_region()
+ * API.
+ *
+ * Return: 0 if requested memory region is available (in such case pointer to
+ * memory region is returned via @region), an error otherwise
+ */
+int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
+                            struct pruss_mem_region *region)
+{
+       if (!pruss || !region || mem_id >= PRUSS_MEM_MAX)
+               return -EINVAL;
+
+       mutex_lock(&pruss->lock);
+
+       if (pruss->mem_in_use[mem_id]) {
+               mutex_unlock(&pruss->lock);
+               return -EBUSY;
+       }
+
+       *region = pruss->mem_regions[mem_id];
+       pruss->mem_in_use[mem_id] = region;
+
+       mutex_unlock(&pruss->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pruss_request_mem_region);
+
+/**
+ * pruss_release_mem_region() - release a memory resource
+ * @pruss: the pruss instance
+ * @region: the memory region to release
+ *
+ * This function is the complimentary function to
+ * pruss_request_mem_region(), and allows the client drivers to
+ * release back a memory resource.
+ *
+ * Return: 0 on success, an error code otherwise
+ */
+int pruss_release_mem_region(struct pruss *pruss,
+                            struct pruss_mem_region *region)
+{
+       int id;
+
+       if (!pruss || !region)
+               return -EINVAL;
+
+       mutex_lock(&pruss->lock);
+
+       /* find out the memory region being released */
+       for (id = 0; id < PRUSS_MEM_MAX; id++) {
+               if (pruss->mem_in_use[id] == region)
+                       break;
+       }
+
+       if (id == PRUSS_MEM_MAX) {
+               mutex_unlock(&pruss->lock);
+               return -EINVAL;
+       }
+
+       pruss->mem_in_use[id] = NULL;
+
+       mutex_unlock(&pruss->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pruss_release_mem_region);
+
 static void pruss_of_free_clk_provider(void *data)
 {
        struct device_node *clk_mux_np = data;
@@ -298,6 +374,7 @@ static int pruss_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        pruss->dev = dev;
+       mutex_init(&pruss->lock);
 
        child = of_get_child_by_name(np, "memories");
        if (!child) {
index cb40c2b31045a5d46da2a79007dea3282db5bb41..c8f2e53b911b95022de563c00478b7759af4ee3f 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _PRUSS_DRIVER_H_
 #define _PRUSS_DRIVER_H_
 
+#include <linux/mutex.h>
 #include <linux/remoteproc/pruss.h>
 #include <linux/types.h>
 #include <linux/err.h>
@@ -41,6 +42,8 @@ struct pruss_mem_region {
  * @cfg_base: base iomap for CFG region
  * @cfg_regmap: regmap for config region
  * @mem_regions: data for each of the PRUSS memory regions
+ * @mem_in_use: to indicate if memory resource is in use
+ * @lock: mutex to serialize access to resources
  * @core_clk_mux: clk handle for PRUSS CORE_CLK_MUX
  * @iep_clk_mux: clk handle for PRUSS IEP_CLK_MUX
  */
@@ -49,6 +52,8 @@ struct pruss {
        void __iomem *cfg_base;
        struct regmap *cfg_regmap;
        struct pruss_mem_region mem_regions[PRUSS_MEM_MAX];
+       struct pruss_mem_region *mem_in_use[PRUSS_MEM_MAX];
+       struct mutex lock; /* PRU resource lock */
        struct clk *core_clk_mux;
        struct clk *iep_clk_mux;
 };
@@ -57,6 +62,10 @@ struct pruss {
 
 struct pruss *pruss_get(struct rproc *rproc);
 void pruss_put(struct pruss *pruss);
+int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
+                            struct pruss_mem_region *region);
+int pruss_release_mem_region(struct pruss *pruss,
+                            struct pruss_mem_region *region);
 
 #else
 
@@ -67,6 +76,19 @@ static inline struct pruss *pruss_get(struct rproc *rproc)
 
 static inline void pruss_put(struct pruss *pruss) { }
 
+static inline int pruss_request_mem_region(struct pruss *pruss,
+                                          enum pruss_mem mem_id,
+                                          struct pruss_mem_region *region)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int pruss_release_mem_region(struct pruss *pruss,
+                                          struct pruss_mem_region *region)
+{
+       return -EOPNOTSUPP;
+}
+
 #endif /* CONFIG_TI_PRUSS */
 
 #endif /* _PRUSS_DRIVER_H_ */