ipq806x: add hwspinlock support
This change cherry-picks the following 3 changes from linux-next: *fb7737 hwspinlock/core: add device tree support *19a0f6 hwspinlock: qcom: Add support for Qualcomm HW Mutex block *bd5717 hwspinlock: qcom: Correct msb in regmap_field We're also adding a patch to add the hardware spinlock device nodes on IPQ806x platforms (033-soc-qcom-Add-sfbp-device-to-IPQ806x-dts.patch). Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> SVN-Revision: 46655
This commit is contained in:
parent
6856535e29
commit
6b775f4517
19 changed files with 958 additions and 28 deletions
|
@ -0,0 +1,167 @@
|
||||||
|
From fb7737e949e31d8a71acee6bbb670f32dbd2a2c0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Suman Anna <s-anna@ti.com>
|
||||||
|
Date: Wed, 4 Mar 2015 20:01:14 -0600
|
||||||
|
Subject: [PATCH] hwspinlock/core: add device tree support
|
||||||
|
|
||||||
|
This patch adds a new OF-friendly API of_hwspin_lock_get_id()
|
||||||
|
for hwspinlock clients to use/request locks from a hwspinlock
|
||||||
|
device instantiated through a device-tree blob. This new API
|
||||||
|
can be used by hwspinlock clients to get the id for a specific
|
||||||
|
lock using the phandle + args specifier, so that it can be
|
||||||
|
requested using the available hwspin_lock_request_specific()
|
||||||
|
API.
|
||||||
|
|
||||||
|
Signed-off-by: Suman Anna <s-anna@ti.com>
|
||||||
|
Reviewed-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
[small comment clarification]
|
||||||
|
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
|
||||||
|
---
|
||||||
|
Documentation/hwspinlock.txt | 10 +++++
|
||||||
|
drivers/hwspinlock/hwspinlock_core.c | 79 ++++++++++++++++++++++++++++++++++++
|
||||||
|
include/linux/hwspinlock.h | 7 ++++
|
||||||
|
3 files changed, 96 insertions(+)
|
||||||
|
|
||||||
|
--- a/Documentation/hwspinlock.txt
|
||||||
|
+++ b/Documentation/hwspinlock.txt
|
||||||
|
@@ -48,6 +48,16 @@ independent, drivers.
|
||||||
|
ids for predefined purposes.
|
||||||
|
Should be called from a process context (might sleep).
|
||||||
|
|
||||||
|
+ int of_hwspin_lock_get_id(struct device_node *np, int index);
|
||||||
|
+ - retrieve the global lock id for an OF phandle-based specific lock.
|
||||||
|
+ This function provides a means for DT users of a hwspinlock module
|
||||||
|
+ to get the global lock id of a specific hwspinlock, so that it can
|
||||||
|
+ be requested using the normal hwspin_lock_request_specific() API.
|
||||||
|
+ The function returns a lock id number on success, -EPROBE_DEFER if
|
||||||
|
+ the hwspinlock device is not yet registered with the core, or other
|
||||||
|
+ error values.
|
||||||
|
+ Should be called from a process context (might sleep).
|
||||||
|
+
|
||||||
|
int hwspin_lock_free(struct hwspinlock *hwlock);
|
||||||
|
- free a previously-assigned hwspinlock; returns 0 on success, or an
|
||||||
|
appropriate error code on failure (e.g. -EINVAL if the hwspinlock
|
||||||
|
--- a/drivers/hwspinlock/hwspinlock_core.c
|
||||||
|
+++ b/drivers/hwspinlock/hwspinlock_core.c
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
#include <linux/hwspinlock.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
|
||||||
|
#include "hwspinlock_internal.h"
|
||||||
|
|
||||||
|
@@ -257,6 +258,84 @@ void __hwspin_unlock(struct hwspinlock *
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(__hwspin_unlock);
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id
|
||||||
|
+ * @bank: the hwspinlock device bank
|
||||||
|
+ * @hwlock_spec: hwlock specifier as found in the device tree
|
||||||
|
+ *
|
||||||
|
+ * This is a simple translation function, suitable for hwspinlock platform
|
||||||
|
+ * drivers that only has a lock specifier length of 1.
|
||||||
|
+ *
|
||||||
|
+ * Returns a relative index of the lock within a specified bank on success,
|
||||||
|
+ * or -EINVAL on invalid specifier cell count.
|
||||||
|
+ */
|
||||||
|
+static inline int
|
||||||
|
+of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec)
|
||||||
|
+{
|
||||||
|
+ if (WARN_ON(hwlock_spec->args_count != 1))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ return hwlock_spec->args[0];
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock
|
||||||
|
+ * @np: device node from which to request the specific hwlock
|
||||||
|
+ * @index: index of the hwlock in the list of values
|
||||||
|
+ *
|
||||||
|
+ * This function provides a means for DT users of the hwspinlock module to
|
||||||
|
+ * get the global lock id of a specific hwspinlock using the phandle of the
|
||||||
|
+ * hwspinlock device, so that it can be requested using the normal
|
||||||
|
+ * hwspin_lock_request_specific() API.
|
||||||
|
+ *
|
||||||
|
+ * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
|
||||||
|
+ * device is not yet registered, -EINVAL on invalid args specifier value or an
|
||||||
|
+ * appropriate error as returned from the OF parsing of the DT client node.
|
||||||
|
+ */
|
||||||
|
+int of_hwspin_lock_get_id(struct device_node *np, int index)
|
||||||
|
+{
|
||||||
|
+ struct of_phandle_args args;
|
||||||
|
+ struct hwspinlock *hwlock;
|
||||||
|
+ struct radix_tree_iter iter;
|
||||||
|
+ void **slot;
|
||||||
|
+ int id;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index,
|
||||||
|
+ &args);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Find the hwspinlock device: we need its base_id */
|
||||||
|
+ ret = -EPROBE_DEFER;
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ radix_tree_for_each_slot(slot, &hwspinlock_tree, &iter, 0) {
|
||||||
|
+ hwlock = radix_tree_deref_slot(slot);
|
||||||
|
+ if (unlikely(!hwlock))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (hwlock->bank->dev->of_node == args.np) {
|
||||||
|
+ ret = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ id = of_hwspin_lock_simple_xlate(&args);
|
||||||
|
+ if (id < 0 || id >= hwlock->bank->num_locks) {
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ id += hwlock->bank->base_id;
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ of_node_put(args.np);
|
||||||
|
+ return ret ? ret : id;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id);
|
||||||
|
+
|
||||||
|
static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
|
||||||
|
{
|
||||||
|
struct hwspinlock *tmp;
|
||||||
|
--- a/include/linux/hwspinlock.h
|
||||||
|
+++ b/include/linux/hwspinlock.h
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */
|
||||||
|
|
||||||
|
struct device;
|
||||||
|
+struct device_node;
|
||||||
|
struct hwspinlock;
|
||||||
|
struct hwspinlock_device;
|
||||||
|
struct hwspinlock_ops;
|
||||||
|
@@ -66,6 +67,7 @@ int hwspin_lock_unregister(struct hwspin
|
||||||
|
struct hwspinlock *hwspin_lock_request(void);
|
||||||
|
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
|
||||||
|
int hwspin_lock_free(struct hwspinlock *hwlock);
|
||||||
|
+int of_hwspin_lock_get_id(struct device_node *np, int index);
|
||||||
|
int hwspin_lock_get_id(struct hwspinlock *hwlock);
|
||||||
|
int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int,
|
||||||
|
unsigned long *);
|
||||||
|
@@ -120,6 +122,11 @@ void __hwspin_unlock(struct hwspinlock *
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline int of_hwspin_lock_get_id(struct device_node *np, int index)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
|
||||||
|
{
|
||||||
|
return 0;
|
|
@ -0,0 +1,234 @@
|
||||||
|
From 19a0f61224d2d91860fa8291ab63cb104ee86bdd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Date: Tue, 24 Mar 2015 10:11:05 -0700
|
||||||
|
Subject: [PATCH] hwspinlock: qcom: Add support for Qualcomm HW Mutex block
|
||||||
|
|
||||||
|
Add driver for Qualcomm Hardware Mutex block found in many Qualcomm
|
||||||
|
SoCs.
|
||||||
|
|
||||||
|
Based on initial effort by Kumar Gala <galak@codeaurora.org>
|
||||||
|
|
||||||
|
Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Reviewed-by: Andy Gross <agross@codeaurora.org>
|
||||||
|
Reviewed-by: Jeffrey Hugo <jhugo@codeaurora.org>
|
||||||
|
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
|
||||||
|
---
|
||||||
|
drivers/hwspinlock/Kconfig | 12 +++
|
||||||
|
drivers/hwspinlock/Makefile | 1 +
|
||||||
|
drivers/hwspinlock/qcom_hwspinlock.c | 181 +++++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 194 insertions(+)
|
||||||
|
create mode 100644 drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
|
||||||
|
--- a/drivers/hwspinlock/Kconfig
|
||||||
|
+++ b/drivers/hwspinlock/Kconfig
|
||||||
|
@@ -18,6 +18,18 @@ config HWSPINLOCK_OMAP
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
+config HWSPINLOCK_QCOM
|
||||||
|
+ tristate "Qualcomm Hardware Spinlock device"
|
||||||
|
+ depends on ARCH_QCOM
|
||||||
|
+ select HWSPINLOCK
|
||||||
|
+ select MFD_SYSCON
|
||||||
|
+ help
|
||||||
|
+ Say y here to support the Qualcomm Hardware Mutex functionality, which
|
||||||
|
+ provides a synchronisation mechanism for the various processors on
|
||||||
|
+ the SoC.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
config HSEM_U8500
|
||||||
|
tristate "STE Hardware Semaphore functionality"
|
||||||
|
depends on ARCH_U8500
|
||||||
|
--- a/drivers/hwspinlock/Makefile
|
||||||
|
+++ b/drivers/hwspinlock/Makefile
|
||||||
|
@@ -4,4 +4,5 @@
|
||||||
|
|
||||||
|
obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o
|
||||||
|
obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o
|
||||||
|
+obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o
|
||||||
|
obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
@@ -0,0 +1,181 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||||
|
+ * Copyright (c) 2015, Sony Mobile Communications AB
|
||||||
|
+ *
|
||||||
|
+ * This software is licensed under the terms of the GNU General Public
|
||||||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||||||
|
+ * may be copied, distributed, and modified under those terms.
|
||||||
|
+ *
|
||||||
|
+ * 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.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/hwspinlock.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/mfd/syscon.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/of_device.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/pm_runtime.h>
|
||||||
|
+#include <linux/regmap.h>
|
||||||
|
+
|
||||||
|
+#include "hwspinlock_internal.h"
|
||||||
|
+
|
||||||
|
+#define QCOM_MUTEX_APPS_PROC_ID 1
|
||||||
|
+#define QCOM_MUTEX_NUM_LOCKS 32
|
||||||
|
+
|
||||||
|
+static int qcom_hwspinlock_trylock(struct hwspinlock *lock)
|
||||||
|
+{
|
||||||
|
+ struct regmap_field *field = lock->priv;
|
||||||
|
+ u32 lock_owner;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_write(field, QCOM_MUTEX_APPS_PROC_ID);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_read(field, &lock_owner);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return lock_owner == QCOM_MUTEX_APPS_PROC_ID;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void qcom_hwspinlock_unlock(struct hwspinlock *lock)
|
||||||
|
+{
|
||||||
|
+ struct regmap_field *field = lock->priv;
|
||||||
|
+ u32 lock_owner;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_read(field, &lock_owner);
|
||||||
|
+ if (ret) {
|
||||||
|
+ pr_err("%s: unable to query spinlock owner\n", __func__);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (lock_owner != QCOM_MUTEX_APPS_PROC_ID) {
|
||||||
|
+ pr_err("%s: spinlock not owned by us (actual owner is %d)\n",
|
||||||
|
+ __func__, lock_owner);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_write(field, 0);
|
||||||
|
+ if (ret)
|
||||||
|
+ pr_err("%s: failed to unlock spinlock\n", __func__);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct hwspinlock_ops qcom_hwspinlock_ops = {
|
||||||
|
+ .trylock = qcom_hwspinlock_trylock,
|
||||||
|
+ .unlock = qcom_hwspinlock_unlock,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct of_device_id qcom_hwspinlock_of_match[] = {
|
||||||
|
+ { .compatible = "qcom,sfpb-mutex" },
|
||||||
|
+ { .compatible = "qcom,tcsr-mutex" },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, qcom_hwspinlock_of_match);
|
||||||
|
+
|
||||||
|
+static int qcom_hwspinlock_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct hwspinlock_device *bank;
|
||||||
|
+ struct device_node *syscon;
|
||||||
|
+ struct reg_field field;
|
||||||
|
+ struct regmap *regmap;
|
||||||
|
+ size_t array_size;
|
||||||
|
+ u32 stride;
|
||||||
|
+ u32 base;
|
||||||
|
+ int ret;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ syscon = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
|
||||||
|
+ if (!syscon) {
|
||||||
|
+ dev_err(&pdev->dev, "no syscon property\n");
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ regmap = syscon_node_to_regmap(syscon);
|
||||||
|
+ if (IS_ERR(regmap))
|
||||||
|
+ return PTR_ERR(regmap);
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1, &base);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(&pdev->dev, "no offset in syscon\n");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 2, &stride);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(&pdev->dev, "no stride syscon\n");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ array_size = QCOM_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock);
|
||||||
|
+ bank = devm_kzalloc(&pdev->dev, sizeof(*bank) + array_size, GFP_KERNEL);
|
||||||
|
+ if (!bank)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ platform_set_drvdata(pdev, bank);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < QCOM_MUTEX_NUM_LOCKS; i++) {
|
||||||
|
+ field.reg = base + i * stride;
|
||||||
|
+ field.lsb = 0;
|
||||||
|
+ field.msb = 32;
|
||||||
|
+
|
||||||
|
+ bank->lock[i].priv = devm_regmap_field_alloc(&pdev->dev,
|
||||||
|
+ regmap, field);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pm_runtime_enable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ ret = hwspin_lock_register(bank, &pdev->dev, &qcom_hwspinlock_ops,
|
||||||
|
+ 0, QCOM_MUTEX_NUM_LOCKS);
|
||||||
|
+ if (ret)
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qcom_hwspinlock_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct hwspinlock_device *bank = platform_get_drvdata(pdev);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = hwspin_lock_unregister(bank);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct platform_driver qcom_hwspinlock_driver = {
|
||||||
|
+ .probe = qcom_hwspinlock_probe,
|
||||||
|
+ .remove = qcom_hwspinlock_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "qcom_hwspinlock",
|
||||||
|
+ .of_match_table = qcom_hwspinlock_of_match,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init qcom_hwspinlock_init(void)
|
||||||
|
+{
|
||||||
|
+ return platform_driver_register(&qcom_hwspinlock_driver);
|
||||||
|
+}
|
||||||
|
+/* board init code might need to reserve hwspinlocks for predefined purposes */
|
||||||
|
+postcore_initcall(qcom_hwspinlock_init);
|
||||||
|
+
|
||||||
|
+static void __exit qcom_hwspinlock_exit(void)
|
||||||
|
+{
|
||||||
|
+ platform_driver_unregister(&qcom_hwspinlock_driver);
|
||||||
|
+}
|
||||||
|
+module_exit(qcom_hwspinlock_exit);
|
||||||
|
+
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
+MODULE_DESCRIPTION("Hardware spinlock driver for Qualcomm SoCs");
|
|
@ -0,0 +1,26 @@
|
||||||
|
From bd5717a4632cdecafe82d03de7dcb3b1876e2828 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Date: Fri, 26 Jun 2015 14:47:21 -0700
|
||||||
|
Subject: [PATCH] hwspinlock: qcom: Correct msb in regmap_field
|
||||||
|
|
||||||
|
msb of the regmap_field was mistakenly given the value 32, to set all bits
|
||||||
|
in the regmap update mask; although incorrect this worked until 921cc294,
|
||||||
|
where the mask calculation was corrected.
|
||||||
|
|
||||||
|
Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
|
||||||
|
---
|
||||||
|
drivers/hwspinlock/qcom_hwspinlock.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
+++ b/drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
@@ -123,7 +123,7 @@ static int qcom_hwspinlock_probe(struct
|
||||||
|
for (i = 0; i < QCOM_MUTEX_NUM_LOCKS; i++) {
|
||||||
|
field.reg = base + i * stride;
|
||||||
|
field.lsb = 0;
|
||||||
|
- field.msb = 32;
|
||||||
|
+ field.msb = 31;
|
||||||
|
|
||||||
|
bank->lock[i].priv = devm_regmap_field_alloc(&pdev->dev,
|
||||||
|
regmap, field);
|
|
@ -0,0 +1,34 @@
|
||||||
|
From c7c482da19a5e4ba7101198c21c2434056b0b2da Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
Date: Thu, 13 Aug 2015 09:45:26 -0700
|
||||||
|
Subject: [PATCH 1/3] ARM: qcom: add SFPB nodes to IPQ806x dts
|
||||||
|
|
||||||
|
Add one new node to the ipq806x.dtsi file to declare & register the
|
||||||
|
hardware spinlock devices. This mechanism is required to be used by
|
||||||
|
other drivers such as SMEM.
|
||||||
|
|
||||||
|
Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq8064.dtsi | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
@@ -291,5 +291,17 @@
|
||||||
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ sfpb_mutex_block: syscon@1200600 {
|
||||||
|
+ compatible = "syscon";
|
||||||
|
+ reg = <0x01200600 0x100>;
|
||||||
|
+ };
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ sfpb_mutex: sfpb-mutex {
|
||||||
|
+ compatible = "qcom,sfpb-mutex";
|
||||||
|
+ syscon = <&sfpb_mutex_block 4 4>;
|
||||||
|
+
|
||||||
|
+ #hwlock-cells = <1>;
|
||||||
|
+ };
|
||||||
|
};
|
|
@ -32,9 +32,9 @@
|
||||||
};
|
};
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -291,5 +291,90 @@
|
@@ -296,6 +296,91 @@
|
||||||
#clock-cells = <1>;
|
compatible = "syscon";
|
||||||
#reset-cells = <1>;
|
reg = <0x01200600 0x100>;
|
||||||
};
|
};
|
||||||
+
|
+
|
||||||
+ hs_phy_1: phy@100f8800 {
|
+ hs_phy_1: phy@100f8800 {
|
||||||
|
@ -122,4 +122,5 @@
|
||||||
+ };
|
+ };
|
||||||
+
|
+
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
|
@ -134,8 +134,8 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Qualcomm IPQ8064";
|
model = "Qualcomm IPQ8064";
|
||||||
@@ -306,6 +308,129 @@
|
@@ -311,6 +313,129 @@
|
||||||
#reset-cells = <1>;
|
reg = <0x01200600 0x100>;
|
||||||
};
|
};
|
||||||
|
|
||||||
+ pcie0: pci@1b500000 {
|
+ pcie0: pci@1b500000 {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -336,15 +336,21 @@
|
@@ -341,15 +341,21 @@
|
||||||
|
|
||||||
clocks = <&gcc PCIE_A_CLK>,
|
clocks = <&gcc PCIE_A_CLK>,
|
||||||
<&gcc PCIE_H_CLK>,
|
<&gcc PCIE_H_CLK>,
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@@ -377,15 +383,21 @@
|
@@ -382,15 +388,21 @@
|
||||||
|
|
||||||
clocks = <&gcc PCIE_1_A_CLK>,
|
clocks = <&gcc PCIE_1_A_CLK>,
|
||||||
<&gcc PCIE_1_H_CLK>,
|
<&gcc PCIE_1_H_CLK>,
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@@ -418,15 +430,21 @@
|
@@ -423,15 +435,21 @@
|
||||||
|
|
||||||
clocks = <&gcc PCIE_2_A_CLK>,
|
clocks = <&gcc PCIE_2_A_CLK>,
|
||||||
<&gcc PCIE_2_H_CLK>,
|
<&gcc PCIE_2_H_CLK>,
|
||||||
|
|
|
@ -13,7 +13,7 @@ Signed-off-by: Andy Gross <agross@codeaurora.org>
|
||||||
|
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -657,5 +657,25 @@
|
@@ -662,6 +662,26 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,4 +38,5 @@ Signed-off-by: Andy Gross <agross@codeaurora.org>
|
||||||
+ };
|
+ };
|
||||||
+
|
+
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
|
@ -26,7 +26,7 @@ arch/arm/boot/dts/qcom-ipq8064.dtsi | 15 +++++++++++++++
|
||||||
|
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -677,5 +677,21 @@
|
@@ -682,6 +682,22 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,4 +47,5 @@ arch/arm/boot/dts/qcom-ipq8064.dtsi | 15 +++++++++++++++
|
||||||
+ };
|
+ };
|
||||||
+
|
+
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
|
@ -117,7 +117,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
};
|
};
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -693,5 +693,91 @@
|
@@ -698,6 +698,92 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -208,4 +208,5 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
+ };
|
+ };
|
||||||
+
|
+
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
From fb7737e949e31d8a71acee6bbb670f32dbd2a2c0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Suman Anna <s-anna@ti.com>
|
||||||
|
Date: Wed, 4 Mar 2015 20:01:14 -0600
|
||||||
|
Subject: [PATCH] hwspinlock/core: add device tree support
|
||||||
|
|
||||||
|
This patch adds a new OF-friendly API of_hwspin_lock_get_id()
|
||||||
|
for hwspinlock clients to use/request locks from a hwspinlock
|
||||||
|
device instantiated through a device-tree blob. This new API
|
||||||
|
can be used by hwspinlock clients to get the id for a specific
|
||||||
|
lock using the phandle + args specifier, so that it can be
|
||||||
|
requested using the available hwspin_lock_request_specific()
|
||||||
|
API.
|
||||||
|
|
||||||
|
Signed-off-by: Suman Anna <s-anna@ti.com>
|
||||||
|
Reviewed-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
[small comment clarification]
|
||||||
|
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
|
||||||
|
---
|
||||||
|
Documentation/hwspinlock.txt | 10 +++++
|
||||||
|
drivers/hwspinlock/hwspinlock_core.c | 79 ++++++++++++++++++++++++++++++++++++
|
||||||
|
include/linux/hwspinlock.h | 7 ++++
|
||||||
|
3 files changed, 96 insertions(+)
|
||||||
|
|
||||||
|
--- a/Documentation/hwspinlock.txt
|
||||||
|
+++ b/Documentation/hwspinlock.txt
|
||||||
|
@@ -48,6 +48,16 @@ independent, drivers.
|
||||||
|
ids for predefined purposes.
|
||||||
|
Should be called from a process context (might sleep).
|
||||||
|
|
||||||
|
+ int of_hwspin_lock_get_id(struct device_node *np, int index);
|
||||||
|
+ - retrieve the global lock id for an OF phandle-based specific lock.
|
||||||
|
+ This function provides a means for DT users of a hwspinlock module
|
||||||
|
+ to get the global lock id of a specific hwspinlock, so that it can
|
||||||
|
+ be requested using the normal hwspin_lock_request_specific() API.
|
||||||
|
+ The function returns a lock id number on success, -EPROBE_DEFER if
|
||||||
|
+ the hwspinlock device is not yet registered with the core, or other
|
||||||
|
+ error values.
|
||||||
|
+ Should be called from a process context (might sleep).
|
||||||
|
+
|
||||||
|
int hwspin_lock_free(struct hwspinlock *hwlock);
|
||||||
|
- free a previously-assigned hwspinlock; returns 0 on success, or an
|
||||||
|
appropriate error code on failure (e.g. -EINVAL if the hwspinlock
|
||||||
|
--- a/drivers/hwspinlock/hwspinlock_core.c
|
||||||
|
+++ b/drivers/hwspinlock/hwspinlock_core.c
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
#include <linux/hwspinlock.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
|
||||||
|
#include "hwspinlock_internal.h"
|
||||||
|
|
||||||
|
@@ -257,6 +258,84 @@ void __hwspin_unlock(struct hwspinlock *
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(__hwspin_unlock);
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id
|
||||||
|
+ * @bank: the hwspinlock device bank
|
||||||
|
+ * @hwlock_spec: hwlock specifier as found in the device tree
|
||||||
|
+ *
|
||||||
|
+ * This is a simple translation function, suitable for hwspinlock platform
|
||||||
|
+ * drivers that only has a lock specifier length of 1.
|
||||||
|
+ *
|
||||||
|
+ * Returns a relative index of the lock within a specified bank on success,
|
||||||
|
+ * or -EINVAL on invalid specifier cell count.
|
||||||
|
+ */
|
||||||
|
+static inline int
|
||||||
|
+of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec)
|
||||||
|
+{
|
||||||
|
+ if (WARN_ON(hwlock_spec->args_count != 1))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ return hwlock_spec->args[0];
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock
|
||||||
|
+ * @np: device node from which to request the specific hwlock
|
||||||
|
+ * @index: index of the hwlock in the list of values
|
||||||
|
+ *
|
||||||
|
+ * This function provides a means for DT users of the hwspinlock module to
|
||||||
|
+ * get the global lock id of a specific hwspinlock using the phandle of the
|
||||||
|
+ * hwspinlock device, so that it can be requested using the normal
|
||||||
|
+ * hwspin_lock_request_specific() API.
|
||||||
|
+ *
|
||||||
|
+ * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
|
||||||
|
+ * device is not yet registered, -EINVAL on invalid args specifier value or an
|
||||||
|
+ * appropriate error as returned from the OF parsing of the DT client node.
|
||||||
|
+ */
|
||||||
|
+int of_hwspin_lock_get_id(struct device_node *np, int index)
|
||||||
|
+{
|
||||||
|
+ struct of_phandle_args args;
|
||||||
|
+ struct hwspinlock *hwlock;
|
||||||
|
+ struct radix_tree_iter iter;
|
||||||
|
+ void **slot;
|
||||||
|
+ int id;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index,
|
||||||
|
+ &args);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Find the hwspinlock device: we need its base_id */
|
||||||
|
+ ret = -EPROBE_DEFER;
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ radix_tree_for_each_slot(slot, &hwspinlock_tree, &iter, 0) {
|
||||||
|
+ hwlock = radix_tree_deref_slot(slot);
|
||||||
|
+ if (unlikely(!hwlock))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (hwlock->bank->dev->of_node == args.np) {
|
||||||
|
+ ret = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ id = of_hwspin_lock_simple_xlate(&args);
|
||||||
|
+ if (id < 0 || id >= hwlock->bank->num_locks) {
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ id += hwlock->bank->base_id;
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ of_node_put(args.np);
|
||||||
|
+ return ret ? ret : id;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id);
|
||||||
|
+
|
||||||
|
static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
|
||||||
|
{
|
||||||
|
struct hwspinlock *tmp;
|
||||||
|
--- a/include/linux/hwspinlock.h
|
||||||
|
+++ b/include/linux/hwspinlock.h
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */
|
||||||
|
|
||||||
|
struct device;
|
||||||
|
+struct device_node;
|
||||||
|
struct hwspinlock;
|
||||||
|
struct hwspinlock_device;
|
||||||
|
struct hwspinlock_ops;
|
||||||
|
@@ -66,6 +67,7 @@ int hwspin_lock_unregister(struct hwspin
|
||||||
|
struct hwspinlock *hwspin_lock_request(void);
|
||||||
|
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
|
||||||
|
int hwspin_lock_free(struct hwspinlock *hwlock);
|
||||||
|
+int of_hwspin_lock_get_id(struct device_node *np, int index);
|
||||||
|
int hwspin_lock_get_id(struct hwspinlock *hwlock);
|
||||||
|
int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int,
|
||||||
|
unsigned long *);
|
||||||
|
@@ -120,6 +122,11 @@ void __hwspin_unlock(struct hwspinlock *
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline int of_hwspin_lock_get_id(struct device_node *np, int index)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
|
||||||
|
{
|
||||||
|
return 0;
|
|
@ -0,0 +1,234 @@
|
||||||
|
From 19a0f61224d2d91860fa8291ab63cb104ee86bdd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Date: Tue, 24 Mar 2015 10:11:05 -0700
|
||||||
|
Subject: [PATCH] hwspinlock: qcom: Add support for Qualcomm HW Mutex block
|
||||||
|
|
||||||
|
Add driver for Qualcomm Hardware Mutex block found in many Qualcomm
|
||||||
|
SoCs.
|
||||||
|
|
||||||
|
Based on initial effort by Kumar Gala <galak@codeaurora.org>
|
||||||
|
|
||||||
|
Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Reviewed-by: Andy Gross <agross@codeaurora.org>
|
||||||
|
Reviewed-by: Jeffrey Hugo <jhugo@codeaurora.org>
|
||||||
|
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
|
||||||
|
---
|
||||||
|
drivers/hwspinlock/Kconfig | 12 +++
|
||||||
|
drivers/hwspinlock/Makefile | 1 +
|
||||||
|
drivers/hwspinlock/qcom_hwspinlock.c | 181 +++++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 194 insertions(+)
|
||||||
|
create mode 100644 drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
|
||||||
|
--- a/drivers/hwspinlock/Kconfig
|
||||||
|
+++ b/drivers/hwspinlock/Kconfig
|
||||||
|
@@ -18,6 +18,18 @@ config HWSPINLOCK_OMAP
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
+config HWSPINLOCK_QCOM
|
||||||
|
+ tristate "Qualcomm Hardware Spinlock device"
|
||||||
|
+ depends on ARCH_QCOM
|
||||||
|
+ select HWSPINLOCK
|
||||||
|
+ select MFD_SYSCON
|
||||||
|
+ help
|
||||||
|
+ Say y here to support the Qualcomm Hardware Mutex functionality, which
|
||||||
|
+ provides a synchronisation mechanism for the various processors on
|
||||||
|
+ the SoC.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
config HSEM_U8500
|
||||||
|
tristate "STE Hardware Semaphore functionality"
|
||||||
|
depends on ARCH_U8500
|
||||||
|
--- a/drivers/hwspinlock/Makefile
|
||||||
|
+++ b/drivers/hwspinlock/Makefile
|
||||||
|
@@ -4,4 +4,5 @@
|
||||||
|
|
||||||
|
obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o
|
||||||
|
obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o
|
||||||
|
+obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o
|
||||||
|
obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
@@ -0,0 +1,181 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||||
|
+ * Copyright (c) 2015, Sony Mobile Communications AB
|
||||||
|
+ *
|
||||||
|
+ * This software is licensed under the terms of the GNU General Public
|
||||||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||||||
|
+ * may be copied, distributed, and modified under those terms.
|
||||||
|
+ *
|
||||||
|
+ * 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.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/hwspinlock.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/mfd/syscon.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/of_device.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/pm_runtime.h>
|
||||||
|
+#include <linux/regmap.h>
|
||||||
|
+
|
||||||
|
+#include "hwspinlock_internal.h"
|
||||||
|
+
|
||||||
|
+#define QCOM_MUTEX_APPS_PROC_ID 1
|
||||||
|
+#define QCOM_MUTEX_NUM_LOCKS 32
|
||||||
|
+
|
||||||
|
+static int qcom_hwspinlock_trylock(struct hwspinlock *lock)
|
||||||
|
+{
|
||||||
|
+ struct regmap_field *field = lock->priv;
|
||||||
|
+ u32 lock_owner;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_write(field, QCOM_MUTEX_APPS_PROC_ID);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_read(field, &lock_owner);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return lock_owner == QCOM_MUTEX_APPS_PROC_ID;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void qcom_hwspinlock_unlock(struct hwspinlock *lock)
|
||||||
|
+{
|
||||||
|
+ struct regmap_field *field = lock->priv;
|
||||||
|
+ u32 lock_owner;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_read(field, &lock_owner);
|
||||||
|
+ if (ret) {
|
||||||
|
+ pr_err("%s: unable to query spinlock owner\n", __func__);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (lock_owner != QCOM_MUTEX_APPS_PROC_ID) {
|
||||||
|
+ pr_err("%s: spinlock not owned by us (actual owner is %d)\n",
|
||||||
|
+ __func__, lock_owner);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = regmap_field_write(field, 0);
|
||||||
|
+ if (ret)
|
||||||
|
+ pr_err("%s: failed to unlock spinlock\n", __func__);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct hwspinlock_ops qcom_hwspinlock_ops = {
|
||||||
|
+ .trylock = qcom_hwspinlock_trylock,
|
||||||
|
+ .unlock = qcom_hwspinlock_unlock,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct of_device_id qcom_hwspinlock_of_match[] = {
|
||||||
|
+ { .compatible = "qcom,sfpb-mutex" },
|
||||||
|
+ { .compatible = "qcom,tcsr-mutex" },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, qcom_hwspinlock_of_match);
|
||||||
|
+
|
||||||
|
+static int qcom_hwspinlock_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct hwspinlock_device *bank;
|
||||||
|
+ struct device_node *syscon;
|
||||||
|
+ struct reg_field field;
|
||||||
|
+ struct regmap *regmap;
|
||||||
|
+ size_t array_size;
|
||||||
|
+ u32 stride;
|
||||||
|
+ u32 base;
|
||||||
|
+ int ret;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ syscon = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
|
||||||
|
+ if (!syscon) {
|
||||||
|
+ dev_err(&pdev->dev, "no syscon property\n");
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ regmap = syscon_node_to_regmap(syscon);
|
||||||
|
+ if (IS_ERR(regmap))
|
||||||
|
+ return PTR_ERR(regmap);
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1, &base);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(&pdev->dev, "no offset in syscon\n");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 2, &stride);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(&pdev->dev, "no stride syscon\n");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ array_size = QCOM_MUTEX_NUM_LOCKS * sizeof(struct hwspinlock);
|
||||||
|
+ bank = devm_kzalloc(&pdev->dev, sizeof(*bank) + array_size, GFP_KERNEL);
|
||||||
|
+ if (!bank)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ platform_set_drvdata(pdev, bank);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < QCOM_MUTEX_NUM_LOCKS; i++) {
|
||||||
|
+ field.reg = base + i * stride;
|
||||||
|
+ field.lsb = 0;
|
||||||
|
+ field.msb = 32;
|
||||||
|
+
|
||||||
|
+ bank->lock[i].priv = devm_regmap_field_alloc(&pdev->dev,
|
||||||
|
+ regmap, field);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pm_runtime_enable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ ret = hwspin_lock_register(bank, &pdev->dev, &qcom_hwspinlock_ops,
|
||||||
|
+ 0, QCOM_MUTEX_NUM_LOCKS);
|
||||||
|
+ if (ret)
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qcom_hwspinlock_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct hwspinlock_device *bank = platform_get_drvdata(pdev);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = hwspin_lock_unregister(bank);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pm_runtime_disable(&pdev->dev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct platform_driver qcom_hwspinlock_driver = {
|
||||||
|
+ .probe = qcom_hwspinlock_probe,
|
||||||
|
+ .remove = qcom_hwspinlock_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "qcom_hwspinlock",
|
||||||
|
+ .of_match_table = qcom_hwspinlock_of_match,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init qcom_hwspinlock_init(void)
|
||||||
|
+{
|
||||||
|
+ return platform_driver_register(&qcom_hwspinlock_driver);
|
||||||
|
+}
|
||||||
|
+/* board init code might need to reserve hwspinlocks for predefined purposes */
|
||||||
|
+postcore_initcall(qcom_hwspinlock_init);
|
||||||
|
+
|
||||||
|
+static void __exit qcom_hwspinlock_exit(void)
|
||||||
|
+{
|
||||||
|
+ platform_driver_unregister(&qcom_hwspinlock_driver);
|
||||||
|
+}
|
||||||
|
+module_exit(qcom_hwspinlock_exit);
|
||||||
|
+
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
+MODULE_DESCRIPTION("Hardware spinlock driver for Qualcomm SoCs");
|
|
@ -0,0 +1,26 @@
|
||||||
|
From bd5717a4632cdecafe82d03de7dcb3b1876e2828 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Date: Fri, 26 Jun 2015 14:47:21 -0700
|
||||||
|
Subject: [PATCH] hwspinlock: qcom: Correct msb in regmap_field
|
||||||
|
|
||||||
|
msb of the regmap_field was mistakenly given the value 32, to set all bits
|
||||||
|
in the regmap update mask; although incorrect this worked until 921cc294,
|
||||||
|
where the mask calculation was corrected.
|
||||||
|
|
||||||
|
Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
|
||||||
|
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
|
||||||
|
---
|
||||||
|
drivers/hwspinlock/qcom_hwspinlock.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
+++ b/drivers/hwspinlock/qcom_hwspinlock.c
|
||||||
|
@@ -123,7 +123,7 @@ static int qcom_hwspinlock_probe(struct
|
||||||
|
for (i = 0; i < QCOM_MUTEX_NUM_LOCKS; i++) {
|
||||||
|
field.reg = base + i * stride;
|
||||||
|
field.lsb = 0;
|
||||||
|
- field.msb = 32;
|
||||||
|
+ field.msb = 31;
|
||||||
|
|
||||||
|
bank->lock[i].priv = devm_regmap_field_alloc(&pdev->dev,
|
||||||
|
regmap, field);
|
|
@ -0,0 +1,33 @@
|
||||||
|
From c7c482da19a5e4ba7101198c21c2434056b0b2da Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
Date: Thu, 13 Aug 2015 09:45:26 -0700
|
||||||
|
Subject: [PATCH 1/3] ARM: qcom: add SFPB nodes to IPQ806x dts
|
||||||
|
|
||||||
|
Add one new node to the ipq806x.dtsi file to declare & register the
|
||||||
|
hardware spinlock devices. This mechanism is required to be used by
|
||||||
|
other drivers such as SMEM.
|
||||||
|
|
||||||
|
Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq8064.dtsi | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
@@ -329,5 +329,16 @@
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
+ sfpb_mutex_block: syscon@1200600 {
|
||||||
|
+ compatible = "syscon";
|
||||||
|
+ reg = <0x01200600 0x100>;
|
||||||
|
+ };
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ sfpb_mutex: sfpb-mutex {
|
||||||
|
+ compatible = "qcom,sfpb-mutex";
|
||||||
|
+ syscon = <&sfpb_mutex_block 4 4>;
|
||||||
|
+
|
||||||
|
+ #hwlock-cells = <1>;
|
||||||
|
+ };
|
||||||
|
};
|
|
@ -134,10 +134,11 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Qualcomm IPQ8064";
|
model = "Qualcomm IPQ8064";
|
||||||
@@ -329,5 +331,127 @@
|
@@ -333,6 +335,129 @@
|
||||||
#reset-cells = <1>;
|
compatible = "syscon";
|
||||||
|
reg = <0x01200600 0x100>;
|
||||||
};
|
};
|
||||||
|
+
|
||||||
+ pcie0: pci@1b500000 {
|
+ pcie0: pci@1b500000 {
|
||||||
+ compatible = "qcom,pcie-v0";
|
+ compatible = "qcom,pcie-v0";
|
||||||
+ reg = <0x1b500000 0x1000
|
+ reg = <0x1b500000 0x1000
|
||||||
|
@ -261,4 +262,5 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
+ status = "disabled";
|
+ status = "disabled";
|
||||||
+ };
|
+ };
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -359,15 +359,21 @@
|
@@ -364,15 +364,21 @@
|
||||||
|
|
||||||
clocks = <&gcc PCIE_A_CLK>,
|
clocks = <&gcc PCIE_A_CLK>,
|
||||||
<&gcc PCIE_H_CLK>,
|
<&gcc PCIE_H_CLK>,
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@@ -400,15 +406,21 @@
|
@@ -405,15 +411,21 @@
|
||||||
|
|
||||||
clocks = <&gcc PCIE_1_A_CLK>,
|
clocks = <&gcc PCIE_1_A_CLK>,
|
||||||
<&gcc PCIE_1_H_CLK>,
|
<&gcc PCIE_1_H_CLK>,
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@@ -441,15 +453,21 @@
|
@@ -446,15 +458,21 @@
|
||||||
|
|
||||||
clocks = <&gcc PCIE_2_A_CLK>,
|
clocks = <&gcc PCIE_2_A_CLK>,
|
||||||
<&gcc PCIE_2_H_CLK>,
|
<&gcc PCIE_2_H_CLK>,
|
||||||
|
|
|
@ -13,7 +13,7 @@ Signed-off-by: Andy Gross <agross@codeaurora.org>
|
||||||
|
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -595,5 +595,25 @@
|
@@ -600,6 +600,26 @@
|
||||||
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -38,4 +38,5 @@ Signed-off-by: Andy Gross <agross@codeaurora.org>
|
||||||
+ status = "disabled";
|
+ status = "disabled";
|
||||||
+ };
|
+ };
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
|
@ -26,7 +26,7 @@ arch/arm/boot/dts/qcom-ipq8064.dtsi | 15 +++++++++++++++
|
||||||
|
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -615,5 +615,21 @@
|
@@ -620,6 +620,22 @@
|
||||||
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -47,4 +47,5 @@ arch/arm/boot/dts/qcom-ipq8064.dtsi | 15 +++++++++++++++
|
||||||
+ status = "disabled";
|
+ status = "disabled";
|
||||||
+ };
|
+ };
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
|
@ -117,7 +117,7 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
};
|
};
|
||||||
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
@@ -631,5 +631,91 @@
|
@@ -636,6 +636,92 @@
|
||||||
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -208,4 +208,5 @@ Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
+ status = "disabled";
|
+ status = "disabled";
|
||||||
+ };
|
+ };
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
sfpb_mutex: sfpb-mutex {
|
||||||
|
|
Loading…
Reference in a new issue