From patchwork Tue Oct 31 06:35:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 117516 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp3508815qgn; Mon, 30 Oct 2017 23:37:06 -0700 (PDT) X-Google-Smtp-Source: ABhQp+R2W0vVs3/aeut0yYDOOCcgmSsAxSqY47pugShTwgJDxUEtnPQZ61bi6tpYvgFC3gcp91A+ X-Received: by 10.98.160.90 with SMTP id r87mr1033386pfe.324.1509431826162; Mon, 30 Oct 2017 23:37:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1509431826; cv=none; d=google.com; s=arc-20160816; b=vvS1G0KhQ4mJ9Rf5qVqCm4zT+TKfkLs+spxgu1Fur8uw1J61u0yHZpJtHNxGwFhpv9 DCgMV8JDsmqX2JU/GR0pViHGc1wWGJkMJFPX/aQ/n3GCfeSGOAXuYqATUOq98N9dfI7s i4/OdPD8usgty/u/imhUd0cjDVG33nObgeqNWKZKOASE2kZVn1HB9eArlGbsqklIu6po D3mD/BwP33jhZkkVTctjdEKbTxeFFeVRS74s5dNjH7rxV/L0t2NSTnnZJymnH5uEJrbM 7Gx3X2qbTzP52iFOsPO3OlbPIJeF8h2WeDGhnqNidtH3rHwGOazWubrGpnNo4buKrkUW ZnHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=0P+yo4RV3PpvOdGzm3BNfXsCYND1dPjtx9q3X5v6828=; b=LjzLOjuVGzGm+kLQ4avVlCybOe77vKbF0HJBXRrekk72gqCKOzpFaNUXUWKEwi5ZDW fnoDpTgUtuA+TZwZUIXlFNMcFqgZfPwB9Ew0rRY11WxQdgcBR5izgmuSvEsbh3QOXPqG xK8ZSqnuFEHEdnWAvyBgV5RdHU/G9Qr/oA9SpnhuklNBS+AtyVWLH2h9erDIV7WxHaCR 22l09nD4i7e5k/i1y8wqDxgREOBm0gSgVYzaB3ZNEK9GCRtCY7bjUXpJa4/R8U0KvoFi 7JUgUW5EaBockq7uU+sMPGz+DBc9Lhr0RJV6rHb1IsG2VvAhwIGPTqws3Bf7FNhtivg2 qcGg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dbUvKP3I; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l5si706223plk.103.2017.10.30.23.37.05; Mon, 30 Oct 2017 23:37:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dbUvKP3I; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752726AbdJaGhE (ORCPT + 27 others); Tue, 31 Oct 2017 02:37:04 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:52683 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750916AbdJaGhC (ORCPT ); Tue, 31 Oct 2017 02:37:02 -0400 Received: by mail-pg0-f65.google.com with SMTP id a192so13814289pge.9 for ; Mon, 30 Oct 2017 23:37:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=0P+yo4RV3PpvOdGzm3BNfXsCYND1dPjtx9q3X5v6828=; b=dbUvKP3IrzoEyhNXgzi7XWdBgmRoSgN++hx+0sWVd29DkyPFTtZQpZAn9L+upJrLoR W2tiV5SiOowaGT+lAwsnSyKYSesRxg1HhARD5WjOXUv4WyzRwoTlxLw/VDY0X7UVgkJt CCaoDD2wElpjBgni9HaITbp8PPMMJb+/9/34w= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=0P+yo4RV3PpvOdGzm3BNfXsCYND1dPjtx9q3X5v6828=; b=YkA+nsX8EfZ7RHvYNcN+n7SVFWd6MSr4KtJQrk2slqPQwk3X1N8aT2QFuNlFS2Kaeh VssNHsu0k/P+4p0P94IfUsxmBaJfKiPIMfVyd0PNZQnHf46LhXnEYjoMk3zkA7MhOJ13 WoazscI6BCJq+wsxP1p5d3enqB8tdj40cLA/r6QCOdUbUyiIP+GXq1TSjwTDVuYvVfbA mWfObbok3/mQRul9TrALqSb9V/UcJGg9dTLvJKsjZ739TnXueLaBD0Ms/vNELDtgRPFt Wm6le68JdJ99P5+TT7+MSm8dpN1T8TnlfLl5OSmSjvWn7iNpX5lhQ138m1EoTylW+3f0 QC8Q== X-Gm-Message-State: AMCzsaVH3dAkhIUwH6B1PiH1Wlcf5iKI37boZdjDz/3takEgHWGcaFkw Hrdy6yT9Fj4ve0lXzw9jQVszoA== X-Received: by 10.159.246.12 with SMTP id b12mr968177pls.380.1509431822031; Mon, 30 Oct 2017 23:37:02 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id 76sm1597477pfp.80.2017.10.30.23.36.59 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 30 Oct 2017 23:37:01 -0700 (PDT) From: Baolin Wang To: broonie@kernel.org, gregkh@linuxfoundation.org, lee.jones@linaro.org, arnd@arndb.de Cc: linux-kernel@vger.kernel.org, baolin.wang@linaro.org Subject: [PATCH 1/2] regmap: Add hardware spinlock support Date: Tue, 31 Oct 2017 14:35:55 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On some platforms, when reading or writing some special registers through regmap, we should acquire one hardware spinlock to synchronize between the multiple subsystems. Thus this patch adds the hardware spinlock support for regmap. Signed-off-by: Baolin Wang --- drivers/base/regmap/internal.h | 3 + drivers/base/regmap/regmap.c | 118 ++++++++++++++++++++++++++++++++++------ include/linux/regmap.h | 9 +++ 3 files changed, 114 insertions(+), 16 deletions(-) -- 1.7.9.5 diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 2a4435d..bb8b663 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -157,6 +157,9 @@ struct regmap { struct rb_root range_tree; void *selector_work_buf; /* Scratch buffer used for selector */ + + struct hwspinlock *hwlock; + unsigned int hwlock_timeout; }; struct regcache_ops { diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index b9a779a..615e8d0 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -413,6 +413,71 @@ static unsigned int regmap_parse_64_native(const void *buf) } #endif +static void regmap_lock_hwlock(void *__map) +{ + struct regmap *map = __map; + int ret; + + if (map->hwlock_timeout) + ret = hwspin_lock_timeout(map->hwlock, map->hwlock_timeout); + else + ret = hwspin_trylock(map->hwlock); + + if (ret) + dev_err(map->dev, "Failed to get hwlock %d\n", ret); +} + +static void regmap_lock_hwlock_irq(void *__map) +{ + struct regmap *map = __map; + int ret; + + if (map->hwlock_timeout) + ret = hwspin_lock_timeout_irq(map->hwlock, map->hwlock_timeout); + else + ret = hwspin_trylock_irq(map->hwlock); + + if (ret) + dev_err(map->dev, "Failed to get hwlock %d\n", ret); +} + +static void regmap_lock_hwlock_irqsave(void *__map) +{ + struct regmap *map = __map; + int ret; + + if (map->hwlock_timeout) + ret = hwspin_lock_timeout_irqsave(map->hwlock, + map->hwlock_timeout, + &map->spinlock_flags); + else + ret = hwspin_trylock_irqsave(map->hwlock, &map->spinlock_flags); + + if (ret) + dev_err(map->dev, "Failed to get hwlock %d\n", ret); +} + +static void regmap_unlock_hwlock(void *__map) +{ + struct regmap *map = __map; + + hwspin_unlock(map->hwlock); +} + +static void regmap_unlock_hwlock_irq(void *__map) +{ + struct regmap *map = __map; + + hwspin_unlock_irq(map->hwlock); +} + +static void regmap_unlock_hwlock_irqrestore(void *__map) +{ + struct regmap *map = __map; + + hwspin_unlock_irqrestore(map->hwlock, &map->spinlock_flags); +} + static void regmap_lock_mutex(void *__map) { struct regmap *map = __map; @@ -627,6 +692,25 @@ struct regmap *__regmap_init(struct device *dev, map->lock = config->lock; map->unlock = config->unlock; map->lock_arg = config->lock_arg; + } else if (config->hwlock_id) { + map->hwlock = hwspin_lock_request_specific(config->hwlock_id); + if (!map->hwlock) { + ret = -ENXIO; + goto err_map; + } + + map->hwlock_timeout = config->hwlock_timeout; + if (config->hwlock_mode == HWLOCK_IRQSTATE) { + map->lock = regmap_lock_hwlock_irqsave; + map->unlock = regmap_unlock_hwlock_irqrestore; + } else if (config->hwlock_mode == HWLOCK_IRQ) { + map->lock = regmap_lock_hwlock_irq; + map->unlock = regmap_unlock_hwlock_irq; + } else { + map->lock = regmap_lock_hwlock; + map->unlock = regmap_unlock_hwlock; + } + map->lock_arg = map; } else { if ((bus && bus->fast_io) || config->fast_io) { @@ -729,7 +813,7 @@ struct regmap *__regmap_init(struct device *dev, map->format.format_write = regmap_format_2_6_write; break; default: - goto err_map; + goto err_hwlock; } break; @@ -739,7 +823,7 @@ struct regmap *__regmap_init(struct device *dev, map->format.format_write = regmap_format_4_12_write; break; default: - goto err_map; + goto err_hwlock; } break; @@ -749,7 +833,7 @@ struct regmap *__regmap_init(struct device *dev, map->format.format_write = regmap_format_7_9_write; break; default: - goto err_map; + goto err_hwlock; } break; @@ -759,7 +843,7 @@ struct regmap *__regmap_init(struct device *dev, map->format.format_write = regmap_format_10_14_write; break; default: - goto err_map; + goto err_hwlock; } break; @@ -779,13 +863,13 @@ struct regmap *__regmap_init(struct device *dev, map->format.format_reg = regmap_format_16_native; break; default: - goto err_map; + goto err_hwlock; } break; case 24: if (reg_endian != REGMAP_ENDIAN_BIG) - goto err_map; + goto err_hwlock; map->format.format_reg = regmap_format_24; break; @@ -801,7 +885,7 @@ struct regmap *__regmap_init(struct device *dev, map->format.format_reg = regmap_format_32_native; break; default: - goto err_map; + goto err_hwlock; } break; @@ -818,13 +902,13 @@ struct regmap *__regmap_init(struct device *dev, map->format.format_reg = regmap_format_64_native; break; default: - goto err_map; + goto err_hwlock; } break; #endif default: - goto err_map; + goto err_hwlock; } if (val_endian == REGMAP_ENDIAN_NATIVE) @@ -853,12 +937,12 @@ struct regmap *__regmap_init(struct device *dev, map->format.parse_val = regmap_parse_16_native; break; default: - goto err_map; + goto err_hwlock; } break; case 24: if (val_endian != REGMAP_ENDIAN_BIG) - goto err_map; + goto err_hwlock; map->format.format_val = regmap_format_24; map->format.parse_val = regmap_parse_24; break; @@ -879,7 +963,7 @@ struct regmap *__regmap_init(struct device *dev, map->format.parse_val = regmap_parse_32_native; break; default: - goto err_map; + goto err_hwlock; } break; #ifdef CONFIG_64BIT @@ -900,7 +984,7 @@ struct regmap *__regmap_init(struct device *dev, map->format.parse_val = regmap_parse_64_native; break; default: - goto err_map; + goto err_hwlock; } break; #endif @@ -909,18 +993,18 @@ struct regmap *__regmap_init(struct device *dev, if (map->format.format_write) { if ((reg_endian != REGMAP_ENDIAN_BIG) || (val_endian != REGMAP_ENDIAN_BIG)) - goto err_map; + goto err_hwlock; map->use_single_write = true; } if (!map->format.format_write && !(map->format.format_reg && map->format.format_val)) - goto err_map; + goto err_hwlock; map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL); if (map->work_buf == NULL) { ret = -ENOMEM; - goto err_map; + goto err_hwlock; } if (map->format.format_write) { @@ -1041,6 +1125,8 @@ struct regmap *__regmap_init(struct device *dev, err_range: regmap_range_exit(map); kfree(map->work_buf); +err_hwlock: + hwspin_lock_free(map->hwlock); err_map: kfree(map); err: diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 978abfb..fe958e2 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -19,6 +19,7 @@ #include #include #include +#include struct module; struct device; @@ -273,6 +274,10 @@ struct regmap_access_table { * * @ranges: Array of configuration entries for virtual address ranges. * @num_ranges: Number of range configuration entries. + * @hwlock_id: Specify the hardware spinlock id. + * @hwlock_mode: The hardware spinlock mode, should be HWLOCK_IRQSTATE, + * HWLOCK_IRQ or 0. + * @hwlock_timeout: Timeout value in msecs. */ struct regmap_config { const char *name; @@ -317,6 +322,10 @@ struct regmap_config { const struct regmap_range_cfg *ranges; unsigned int num_ranges; + + unsigned int hwlock_id; + unsigned int hwlock_mode; + unsigned int hwlock_timeout; }; /**