My apologies for the dup. gmail somehow added html to my original message and it got rejected by multiple maillists. > On Fri, Feb 27, 2015 at 2:30 PM, Bjorn Andersson <bjorn.andersson@xxxxxxxxxxxxxx> wrote: > > Add driver for Qualcomm Hardware Mutex block found in many Qualcomm > SoCs. > > Based on initial effort by Kumar Gala <galak@xxxxxxxxxxxxxx> > > Signed-off-by: Bjorn Andersson <bjorn.andersson@xxxxxxxxxxxxxx> > --- > > As Andy Gross introduced the tcsr syscon we can no longer just ioremap the > memory directly, so rework the driver to run ontop of syscon. > > Changes since v5: > - Dropped all but hwspinlock specific dt bindings > - Hardcoded the number of locks (there is 32) > - Rework to sit ontop of syscon > > Changes since v4: > - Aligned with devicetree support in hwlock framework and hence depends on [1] > > Changes since v3: > - Reverted back to getting stride from of_match, per Kumars request > > Changes since v2: > - MODULE_DEVICE_TABLE > - Changed prefix to qcom > - Cleaned up includes > - Rely on reg and num-locks to figure out stride, instead of of_match data > > Changes since v1: > - Added the pm_runtime calls needed to be able to boot a kernel with > pm_runtime and this driver, patch from Courtney. > - Added sfpb-mutex compatible, for re-use of the driver in family A platforms. > - Updated formatting of DT binding documentation, while adding the extra > compatible. > - Dropped Stephen Boyds Reviewed-by due to these changes. > > drivers/hwspinlock/Kconfig | 11 +++ > drivers/hwspinlock/Makefile | 1 + > drivers/hwspinlock/qcom_hwspinlock.c | 181 +++++++++++++++++++++++++++++++++++ > 3 files changed, 193 insertions(+) > create mode 100644 drivers/hwspinlock/qcom_hwspinlock.c > > diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig > index 3612cb5..762216d 100644 > --- a/drivers/hwspinlock/Kconfig > +++ b/drivers/hwspinlock/Kconfig > @@ -18,6 +18,17 @@ config HWSPINLOCK_OMAP > > If unsure, say N. > > +config HWSPINLOCK_QCOM > + tristate "Qualcomm Hardware Spinlock device" > + depends on ARCH_QCOM > + select HWSPINLOCK > + 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 > diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile > index 93eb64b..68f95d9 100644 > --- 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 > diff --git a/drivers/hwspinlock/qcom_hwspinlock.c > b/drivers/hwspinlock/qcom_hwspinlock.c > new file mode 100644 > index 0000000..93b62e0 > --- /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"); > -- > 1.8.2.2 I'm pretty anxious about this one, as my current work has a dependency on it. Virtually the entirety of the QualComm SOC work is dependent on this because it's needed by the interprocessor communication framework and the regulator driver. I assume we're waiting on the response from Ohad about getting this upstream? It's been almost 2 weeks with no reply. Ohad - do you plan to do anything with this patch? We seem to be at an impasse (once again). This is the 6th attempt over the course of the last year and a half to get this hwspinlock code mainlined. Should we just not use the hwspinlock framework? What are our options going forward? -- Tim Bird Senior Software Engineer, Sony Mobile Architecture Group Chair, CE Workgroup, Linux Foundation -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html