Skip to contentSkip to conversation

soc/qcom: add OCMEM driver

PATCH In review Rob Clark 3 participants 4 messages Oct 12, 2015 – Oct 23, 2015

Subsystems (2)
lore
Share & tools
lore

Rob Clark

author
#0 lore raw

PATCH 1/1 soc/qcom: add OCMEM driver

The OCMEM driver handles allocation and configuration of the On Chip MEMory that is present on some snapdragon devices.

Devices which have OCMEM do not have GMEM inside the gpu core, so the gpu must instead use OCMEM to be functional. Since currently the gpu is the only OCMEM user with an upstream driver, this is just a minimal implementation sufficient for statically allocating to the gpu it's chunk of OCMEM.

v2: minor updates from review comments (use devm_ioremap_resource(), devm_clk_get() doesn't return NULL, etc..)

---
 drivers/soc/qcom/Kconfig     |   6 +
 drivers/soc/qcom/Makefile    |   1 +
 drivers/soc/qcom/ocmem.c     | 401 +++++++++++++++++++++++++++++++++++++++++++
 drivers/soc/qcom/ocmem.xml.h | 106 ++++++++++++
 include/soc/qcom/ocmem.h     |  40 +++++
 5 files changed, 554 insertions(+)
 create mode 100644 drivers/soc/qcom/ocmem.c
 create mode 100644 drivers/soc/qcom/ocmem.xml.h
 create mode 100644 include/soc/qcom/ocmem.h
drivers/soc/qcom/Kconfig +6 -0
index 266060b..b485043 100644
@@ -74,3 +74,9 @@ config QCOM_WCNSS_CTRL
 	help
 	  Client driver for the WCNSS_CTRL SMD channel, used to download nv
 	  firmware to a newly booted WCNSS chip.
+
+config QCOM_OCMEM
+	tristate "Qualcomm OCMEM driver"
+	depends on QCOM_SMD
+	help
+	  Allocator for OCMEM (On Chip MEMory).
drivers/soc/qcom/Makefile +1 -0
index fdd664e..940bb35 100644
@@ -7,3 +7,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o
 obj-$(CONFIG_QCOM_SMSM)	+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_OCMEM)	+= ocmem.o
drivers/soc/qcom/ocmem.c new file +401 -0

401 lines not on this page · raw message

drivers/soc/qcom/ocmem.xml.h new file +106 -0

106 lines not on this page · raw message

include/soc/qcom/ocmem.h new file +40 -0
new file mode 100644
index 0000000..47f6548
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 Red Hat
+ * Author: Rob Clark <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OCMEM_H__
+#define __OCMEM_H__
+
+enum ocmem_client {
+	/* GMEM clients */
+	OCMEM_GRAPHICS = 0x0,
+	/*
+	 * TODO add more once ocmem_allocate() is clever enough to
+	 * deal with multiple clients.
+	 */
+	OCMEM_CLIENT_MAX,
+};
+
+struct ocmem_buf {
+	unsigned long offset;
+	unsigned long addr;
+	unsigned long len;
+};
+
+struct ocmem_buf *ocmem_allocate(enum ocmem_client client, unsigned long size);
+void ocmem_free(enum ocmem_client client, struct ocmem_buf *buf);
+
+#endif /* __OCMEM_H__ */
Signature · 1 line
2.5.0
#1 lore raw

Hi Rob,

Quoted 29 lines · Rob Clark

The OCMEM driver handles allocation and configuration of the On Chip MEMory that is present on some snapdragon devices.

Devices which have OCMEM do not have GMEM inside the gpu core, so the gpu must instead use OCMEM to be functional. Since currently the gpu is the only OCMEM user with an upstream driver, this is just a minimal implementation sufficient for statically allocating to the gpu it's chunk of OCMEM.

v2: minor updates from review comments (use devm_ioremap_resource(), devm_clk_get() doesn't return NULL, etc..)

---
 drivers/soc/qcom/Kconfig     |   6 +
 drivers/soc/qcom/Makefile    |   1 +
 drivers/soc/qcom/ocmem.c     | 401 +++++++++++++++++++++++++++++++++++++++++++
 drivers/soc/qcom/ocmem.xml.h | 106 ++++++++++++
 include/soc/qcom/ocmem.h     |  40 +++++
 5 files changed, 554 insertions(+)
 create mode 100644 drivers/soc/qcom/ocmem.c
 create mode 100644 drivers/soc/qcom/ocmem.xml.h
 create mode 100644 include/soc/qcom/ocmem.h
drivers/soc/qcom/Kconfig +0 -0
index 266060b..b485043 100644

drivers/soc/qcom/Kconfig config QCOM_WCNSS_CTRL · line 80

Quoted 7 lines
drivers/soc/qcom/Kconfig +4 -0
@@ -74,3 +74,9 @@ config QCOM_WCNSS_CTRL
 	help
 	  Client driver for the WCNSS_CTRL SMD channel, used to download nv
 	  firmware to a newly booted WCNSS chip.
+
+config QCOM_OCMEM
+	tristate "Qualcomm OCMEM driver"
+	depends on QCOM_SMD

Why this driver depends on SMD, I cannot see where smd is used here.

Maybe depends on ARCH_QCOM should be sufficient?

Quoted 31 lines
drivers/soc/qcom/Kconfig +2 -0
+	help
+	  Allocator for OCMEM (On Chip MEMory).
drivers/soc/qcom/Makefile +1 -0
index fdd664e..940bb35 100644
@@ -7,3 +7,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o
 obj-$(CONFIG_QCOM_SMSM)	+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_OCMEM)	+= ocmem.o
drivers/soc/qcom/ocmem.c new file +14 -0
new file mode 100644
index 0000000..506a072
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2015 Red Hat
+ * Author: Rob Clark <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with

drivers/soc/qcom/ocmem.c line 24

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/qcom_scm.h>

Do we need to update the Kconfig to enable/depend on scm driver?

Quoted 5 lines
drivers/soc/qcom/ocmem.c new file +5 -0
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <soc/qcom/ocmem.h>

drivers/soc/qcom/ocmem.c line 39

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+#include "ocmem.xml.h"
+
+enum region_mode {
+	WIDE_MODE = 0x0,
+	THIN_MODE,
+	MODE_DEFAULT = WIDE_MODE,
+};
+
+struct ocmem_region {
+	unsigned psgsc_ctrl;

this is not used

Quoted 8 lines
drivers/soc/qcom/ocmem.c new file +8 -0
+	bool interleaved;
+	enum region_mode mode;
+	unsigned int num_macros;
+	enum ocmem_macro_state macro_state[4];
+	unsigned long macro_size;
+	unsigned long region_size;
+};
+

<snip>

Quoted 26 lines
drivers/soc/qcom/ocmem.c new file +26 -0
+
+static const struct of_device_id ocmem_dt_match[] = {
+	{ .compatible = "qcom,ocmem-msm8974", .data = &ocmem_8974_config },
+	{}
+};
+
+static int ocmem_dev_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct ocmem_config *config = NULL;
+	const struct of_device_id *match;
+	struct resource *res;
+	uint32_t reg, num_banks, region_size;
+	int i, j, ret;
+
+	/* we need scm to be available: */
+	if (!qcom_scm_is_available())
+		return -EPROBE_DEFER;
+
+	match = of_match_device(ocmem_dt_match, dev);
+	if (match)
+		config = match->data;
+
+	if (!config) {
+		dev_err(dev, "unknown config: %s\n", dev->of_node->name);
+		return -ENXIO;

drivers/soc/qcom/ocmem.c line 279

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+	}
+
+	ocmem = devm_kzalloc(dev, sizeof(*ocmem), GFP_KERNEL);
+	if (!ocmem)
+		return -ENOMEM;
+
+	ocmem->dev = dev;
+	ocmem->config = config;
+
+	ocmem->core_clk = devm_clk_get(dev, "core_clk");

We have a convention to avoid _clk suffix for qcom clocks in dt nodes.

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+	if (IS_ERR(ocmem->core_clk)) {
+		dev_info(dev, "Unable to get the core clock\n");
+		return PTR_ERR(ocmem->core_clk);
+	}
+
+	ocmem->iface_clk = devm_clk_get(dev, "iface_clk");
+	if (IS_ERR(ocmem->iface_clk)) {
+		ret = PTR_ERR(ocmem->iface_clk);
+		ocmem->iface_clk = NULL;
+		/* in probe-defer case, propagate error up and try again later: */

drivers/soc/qcom/ocmem.c line 299

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+		if (ret == -EPROBE_DEFER)
+			goto fail;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"ocmem_ctrl_physical");
+	ocmem->mmio = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ocmem->mmio)) {
+		dev_err(&pdev->dev, "failed to ioremap memory resource\n");
+		ret = -EINVAL;

ret = PTR_ERR(ocmem->mmio); ?

Quoted 3 lines
drivers/soc/qcom/ocmem.c new file +3 -0
+		goto fail;
+	}
+

<snip>

Quoted 5 lines
drivers/soc/qcom/ocmem.c new file +5 -0
+
+static bool ocmem_exists(void)
+{
+	struct device_driver *drv = &ocmem_driver.driver;
+	struct device *d;

drivers/soc/qcom/ocmem.c line 399

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+
+	d = bus_find_device(&platform_bus_type, NULL, drv,
+			(void *)platform_bus_type.match);
+	if (d) {
+		put_device(d);
+		return true;
+	}
+
+	return false;
+}

do you have a dt binding document? I think that ocmem dt client nodes should have a phandle to ocmem dt node and this could eliminate the need of ocmem_exist(), no ?

<snip>

Signature · 2 lines
regards,
Stan
#2 lore raw
Quoted 1 line · Stanimir Varbanov

Hi Rob,

...

Quoted 15 lines

drivers/soc/qcom/Kconfig config QCOM_WCNSS_CTRL · line 80

Quoted 12 lines
drivers/soc/qcom/Kconfig +4 -0
index 266060b..b485043 100644
@@ -74,3 +74,9 @@ config QCOM_WCNSS_CTRL
 	help
 	  Client driver for the WCNSS_CTRL SMD channel, used to download nv
 	  firmware to a newly booted WCNSS chip.
+
+config QCOM_OCMEM
+	tristate "Qualcomm OCMEM driver"
+	depends on QCOM_SMD

Why this driver depends on SMD, I cannot see where smd is used here.

Quoted 1 line

Maybe depends on ARCH_QCOM should be sufficient?

AFAIK, Stan is correct. OCMEM should only be used by GPU w/o any of the SMD stuff, so ARCH_QCOM looks better.

- Bryan

Signature · 3 lines
Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
Linux Foundation Collaborative Project
author
#3 lore raw
In reply to Stanimir Varbanov
Quoted 42 lines · Stanimir Varbanov

Hi Rob,

Quoted 29 lines · Rob Clark

The OCMEM driver handles allocation and configuration of the On Chip MEMory that is present on some snapdragon devices.

Devices which have OCMEM do not have GMEM inside the gpu core, so the gpu must instead use OCMEM to be functional. Since currently the gpu is the only OCMEM user with an upstream driver, this is just a minimal implementation sufficient for statically allocating to the gpu it's chunk of OCMEM.

v2: minor updates from review comments (use devm_ioremap_resource(), devm_clk_get() doesn't return NULL, etc..)

---
 drivers/soc/qcom/Kconfig     |   6 +
 drivers/soc/qcom/Makefile    |   1 +
 drivers/soc/qcom/ocmem.c     | 401 +++++++++++++++++++++++++++++++++++++++++++
 drivers/soc/qcom/ocmem.xml.h | 106 ++++++++++++
 include/soc/qcom/ocmem.h     |  40 +++++
 5 files changed, 554 insertions(+)
 create mode 100644 drivers/soc/qcom/ocmem.c
 create mode 100644 drivers/soc/qcom/ocmem.xml.h
 create mode 100644 include/soc/qcom/ocmem.h
drivers/soc/qcom/Kconfig +0 -0
index 266060b..b485043 100644

drivers/soc/qcom/Kconfig config QCOM_WCNSS_CTRL · line 80

Quoted 7 lines
drivers/soc/qcom/Kconfig +4 -0
@@ -74,3 +74,9 @@ config QCOM_WCNSS_CTRL
      help
        Client driver for the WCNSS_CTRL SMD channel, used to download nv
        firmware to a newly booted WCNSS chip.
+
+config QCOM_OCMEM
+     tristate "Qualcomm OCMEM driver"
+     depends on QCOM_SMD

Why this driver depends on SMD, I cannot see where smd is used here.

Quoted 1 line

Maybe depends on ARCH_QCOM should be sufficient?

yeah, that should have been "SCM".. the acronyms are too close together ;-)

Quoted 153 lines
Quoted 32 lines
drivers/soc/qcom/Kconfig +2 -0
+     help
+       Allocator for OCMEM (On Chip MEMory).
drivers/soc/qcom/Makefile +1 -0
index fdd664e..940bb35 100644
@@ -7,3 +7,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)     += smp2p.o
 obj-$(CONFIG_QCOM_SMSM)      += smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_OCMEM)     += ocmem.o
drivers/soc/qcom/ocmem.c new file +14 -0
new file mode 100644
index 0000000..506a072
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2015 Red Hat
+ * Author: Rob Clark <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with

drivers/soc/qcom/ocmem.c line 24

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/qcom_scm.h>

Do we need to update the Kconfig to enable/depend on scm driver?

Quoted 5 lines
drivers/soc/qcom/ocmem.c new file +5 -0
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <soc/qcom/ocmem.h>

drivers/soc/qcom/ocmem.c line 39

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+#include "ocmem.xml.h"
+
+enum region_mode {
+     WIDE_MODE = 0x0,
+     THIN_MODE,
+     MODE_DEFAULT = WIDE_MODE,
+};
+
+struct ocmem_region {
+     unsigned psgsc_ctrl;

this is not used

Quoted 8 lines
drivers/soc/qcom/ocmem.c new file +8 -0
+     bool interleaved;
+     enum region_mode mode;
+     unsigned int num_macros;
+     enum ocmem_macro_state macro_state[4];
+     unsigned long macro_size;
+     unsigned long region_size;
+};
+

<snip>

Quoted 26 lines
drivers/soc/qcom/ocmem.c new file +26 -0
+
+static const struct of_device_id ocmem_dt_match[] = {
+     { .compatible = "qcom,ocmem-msm8974", .data = &ocmem_8974_config },
+     {}
+};
+
+static int ocmem_dev_probe(struct platform_device *pdev)
+{
+     struct device *dev = &pdev->dev;
+     const struct ocmem_config *config = NULL;
+     const struct of_device_id *match;
+     struct resource *res;
+     uint32_t reg, num_banks, region_size;
+     int i, j, ret;
+
+     /* we need scm to be available: */
+     if (!qcom_scm_is_available())
+             return -EPROBE_DEFER;
+
+     match = of_match_device(ocmem_dt_match, dev);
+     if (match)
+             config = match->data;
+
+     if (!config) {
+             dev_err(dev, "unknown config: %s\n", dev->of_node->name);
+             return -ENXIO;

drivers/soc/qcom/ocmem.c line 279

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+     }
+
+     ocmem = devm_kzalloc(dev, sizeof(*ocmem), GFP_KERNEL);
+     if (!ocmem)
+             return -ENOMEM;
+
+     ocmem->dev = dev;
+     ocmem->config = config;
+
+     ocmem->core_clk = devm_clk_get(dev, "core_clk");

We have a convention to avoid _clk suffix for qcom clocks in dt nodes.

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+     if (IS_ERR(ocmem->core_clk)) {
+             dev_info(dev, "Unable to get the core clock\n");
+             return PTR_ERR(ocmem->core_clk);
+     }
+
+     ocmem->iface_clk = devm_clk_get(dev, "iface_clk");
+     if (IS_ERR(ocmem->iface_clk)) {
+             ret = PTR_ERR(ocmem->iface_clk);
+             ocmem->iface_clk = NULL;
+             /* in probe-defer case, propagate error up and try again later: */

drivers/soc/qcom/ocmem.c line 299

Quoted 10 lines
drivers/soc/qcom/ocmem.c new file +10 -0
+             if (ret == -EPROBE_DEFER)
+                     goto fail;
+     }
+
+     res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                     "ocmem_ctrl_physical");
+     ocmem->mmio = devm_ioremap_resource(&pdev->dev, res);
+     if (IS_ERR(ocmem->mmio)) {
+             dev_err(&pdev->dev, "failed to ioremap memory resource\n");
+             ret = -EINVAL;

ret = PTR_ERR(ocmem->mmio); ?

Quoted 3 lines
drivers/soc/qcom/ocmem.c new file +3 -0
+             goto fail;
+     }
+

<snip>

Quoted 11 lines
drivers/soc/qcom/ocmem.c new file +11 -0
+
+static bool ocmem_exists(void)
+{
+     struct device_driver *drv = &ocmem_driver.driver;
+     struct device *d;
+
+     d = bus_find_device(&platform_bus_type, NULL, drv,
+                     (void *)platform_bus_type.match);
+     if (d) {
+             put_device(d);
+             return true;
Quoted 8 lines

drivers/soc/qcom/ocmem.c line 399

Quoted 4 lines
drivers/soc/qcom/ocmem.c new file +4 -0
+     }
+
+     return false;
+}

do you have a dt binding document? I think that ocmem dt client nodes should have a phandle to ocmem dt node and this could eliminate the need of ocmem_exist(), no ?

so far just generic bindings (ie. compatible/clocks/reg) so I didn't write one.. are thinks which don't introduce any custom properties supposed to be documented?

Not sure about the phandle link.. I didn't think it influenced probe order (and if another ocmem client needed to access it from it's probe()...)

BR,
-R

Quoted 6 lines

<snip>

--
regards,
Stan