Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp3604489imm; Wed, 5 Sep 2018 02:59:52 -0700 (PDT) X-Google-Smtp-Source: ANB0VdaTZFjbOcWbXbGfPe7RzbHjHCFPTK0LXnlVl6oghEiqSYjNS9KuSRjaYZR1zCoaYfPA6m4L X-Received: by 2002:a62:9ed1:: with SMTP id f78-v6mr39786613pfk.206.1536141592100; Wed, 05 Sep 2018 02:59:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536141592; cv=none; d=google.com; s=arc-20160816; b=FWSE/fp7u/oItIg/NpfeKorrPcF7zczUxCOQ21QPRXU1ygGOIDh8uZow9Tfdr5agwj iHH1muI2E71xi7v+EsURejGpsKmzWAZEgNWukBjZn/r9j/K4u7BrbgqFcayC0RUBql0P QQxZILhsA1WKQi43KCB/UJL3QU6fsi2+20NnTH5841oeZNjBefEr+V0ybXux1oyZM4Ls iry/UcB1qHN2mmSYLjGU+YLjs5O/Tbs/+ItmOr3OSrh42ngIL20Zt5jvp4EzHcfotrfG FtwC5X5GnmbU3IvZxsjOunoSlkVjMUAPkJaPAvP2DNAZ5dgze1rula71SMNujwkAw8np riMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=xbD+J6a0tMgk2zQN6erD8m4XuFwf23lXrCsSj/OMCpo=; b=pqLY6qdZnnmI2HyaousCDC8b3ie08N5oOiDmE7FYvmZcD6gcGFkpu+pR4mlbfa7yNk vsaabXWDNLD/sv/l+9U5sdCs09R67C4GLoewJjIbil8UC/4gez1MZaAvfqhppL2lPMMD KehdFya/AzmWh5NCqstvB8VUzAxBy+atiGCBNmdyY7niHsdbnBpC289GAl3gsOBGIe3b yjV63wFkS3DcnxN0u4icBYhdpjo+lsQvnd3JHJ6XnJHhl6QUoelsayYhIUwlbQumlzfc ZXrcRgMaK05qEhcH9RR30gNFWrneX0du3uEKUb8yBzCyzNrTMcL4t1ABfknsCpKBeqtL f30g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bgdev-pl.20150623.gappssmtp.com header.s=20150623 header.b=Quijgqu6; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f3-v6si1484083plb.207.2018.09.05.02.59.37; Wed, 05 Sep 2018 02:59:52 -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=@bgdev-pl.20150623.gappssmtp.com header.s=20150623 header.b=Quijgqu6; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728436AbeIEO1t (ORCPT + 99 others); Wed, 5 Sep 2018 10:27:49 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:34341 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728094AbeIEO1r (ORCPT ); Wed, 5 Sep 2018 10:27:47 -0400 Received: by mail-wm0-f65.google.com with SMTP id j25-v6so13530115wmc.1 for ; Wed, 05 Sep 2018 02:58:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xbD+J6a0tMgk2zQN6erD8m4XuFwf23lXrCsSj/OMCpo=; b=Quijgqu6LsCyqrF+TYT+95ciTxKfYuaH2X0+4Vkli6R8Ctv9FVr7xe82qw89NWjMUY irLCseX7NMUdhxD9D+M5EebuK3+GbywbEXDqZuyj6dQsiAQzx7dISOeFin/oSjxqIa4F FOaelEJ6jMe/M8EMwyKa0R/MznLoL+VpTMus63m9M/wKVkmZOj6oHg+tx4WnXN1EOmJy HACmst39FtmMeYoCj+p5riLg1o2cHXnKelT/w0W9a/N0LaYx1Roq30f+Zm9aNp1soMfE b9p9x41nSP2qPpnJqxpFh2QhOVsh1U0iXvsPS1H/neQPvBGhNN2ZjCQaArR5zpr1RWZo 3NlA== 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:in-reply-to :references; bh=xbD+J6a0tMgk2zQN6erD8m4XuFwf23lXrCsSj/OMCpo=; b=nXmAKy2jwHxoxFn0pkG7rb/nHMQYcnK6NWelyN2husf9gt5e85D/LfUN5R31ancrX8 HUsGjCQzEVPJ5+oKtJ9f0mlCGhdIfvg5jekjFRfxMsX4wmuaH6pSBVEXMHlNoyTtI/r6 dhcJUluOi8GlV/tUyB0vN0o16zE+ayk+SjNh4sz92HJmLpEQ4PgJ9e76ngPfiq3R2Rf+ M2SG/lKc9QSTX2jDiXovf13eiheXny2xRSvJp2e9nyb4L6RyEPgDjnQLN/BD7vXvKyou thnt07p0MZhWZ19R5QophFLr3oyj7HpK8mJXUNaOfRevk8QznO2GC2soabUoPosXrwQV dfnA== X-Gm-Message-State: APzg51DHisZVb4ueRjte2Sl4yreyF++7OI5c0FbA9tJL+wVjAtBhFbWQ nloVKsllQEntSSH6aWwoKCimbg== X-Received: by 2002:a1c:7c18:: with SMTP id x24-v6mr10398920wmc.33.1536141497929; Wed, 05 Sep 2018 02:58:17 -0700 (PDT) Received: from brgl-bgdev.baylibre.local (AStLambert-681-1-33-235.w90-86.abo.wanadoo.fr. [90.86.152.235]) by smtp.gmail.com with ESMTPSA id l12-v6sm2127815wrv.29.2018.09.05.02.58.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Sep 2018 02:58:17 -0700 (PDT) From: Bartosz Golaszewski To: Srinivas Kandagatla , Joachim Eastwood , "David S . Miller" , Mauro Carvalho Chehab , Greg Kroah-Hartman , Andrew Morton , Arnd Bergmann , Jonathan Corbet , Sekhar Nori , Kevin Hilman , David Lechner , Boris Brezillon , Andrew Lunn , Alban Bedel , Maxime Ripard Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Bartosz Golaszewski Subject: [PATCH 11/13] nvmem: add support for cell lookups from machine code Date: Wed, 5 Sep 2018 11:57:36 +0200 Message-Id: <20180905095738.26406-12-brgl@bgdev.pl> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180905095738.26406-1-brgl@bgdev.pl> References: <20180905095738.26406-1-brgl@bgdev.pl> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bartosz Golaszewski Add a way for machine code users to associate devices with nvmem cells. Signed-off-by: Bartosz Golaszewski --- drivers/nvmem/core.c | 142 +++++++++++++++++++++++++++------- include/linux/nvmem-machine.h | 15 ++++ 2 files changed, 130 insertions(+), 27 deletions(-) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index da7a9d5beb33..d7c609109cfd 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -62,6 +62,9 @@ static DEFINE_IDA(nvmem_ida); static DEFINE_MUTEX(nvmem_cell_mutex); static LIST_HEAD(nvmem_cell_tables); +static DEFINE_MUTEX(nvmem_lookup_mutex); +static LIST_HEAD(nvmem_lookup_list); + static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -285,6 +288,18 @@ static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np) return to_nvmem_device(d); } +static struct nvmem_device *nvmem_find(const char *name) +{ + struct device *d; + + d = bus_find_device_by_name(&nvmem_bus_type, NULL, name); + + if (!d) + return NULL; + + return to_nvmem_device(d); +} + static void nvmem_cell_drop(struct nvmem_cell *cell) { mutex_lock(&nvmem_mutex); @@ -421,6 +436,21 @@ nvmem_find_cell_by_index(struct nvmem_device *nvmem, int index) return cell; } +static struct nvmem_cell * +nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id) +{ + struct nvmem_cell *cell = NULL; + + mutex_lock(&nvmem_mutex); + list_for_each_entry(cell, &nvmem->cells, node) { + if (strcmp(cell_id, cell->name) == 0) + break; + } + mutex_unlock(&nvmem_mutex); + + return cell; +} + static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) { struct device_node *parent, *child; @@ -691,22 +721,16 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem) } EXPORT_SYMBOL(devm_nvmem_unregister); -static struct nvmem_device *__nvmem_device_get(struct device_node *np) +static struct nvmem_device * +__nvmem_device_get(struct device_node *np, const char *name) { struct nvmem_device *nvmem = NULL; - if (!np) - return ERR_PTR(-EINVAL); - mutex_lock(&nvmem_mutex); - - nvmem = of_nvmem_find(np); - if (!nvmem) { - mutex_unlock(&nvmem_mutex); - return ERR_PTR(-EPROBE_DEFER); - } - + nvmem = np ? of_nvmem_find(np) : nvmem_find(name); mutex_unlock(&nvmem_mutex); + if (!nvmem) + return ERR_PTR(-EPROBE_DEFER); if (!try_module_get(nvmem->owner)) { dev_err(&nvmem->dev, @@ -726,18 +750,6 @@ static void __nvmem_device_put(struct nvmem_device *nvmem) kref_put(&nvmem->refcnt, nvmem_device_release); } -static struct nvmem_device *nvmem_find(const char *name) -{ - struct device *d; - - d = bus_find_device_by_name(&nvmem_bus_type, NULL, name); - - if (!d) - return NULL; - - return to_nvmem_device(d); -} - #if IS_ENABLED(CONFIG_OF) /** * of_nvmem_device_get() - Get nvmem device from a given id @@ -760,7 +772,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id) if (!nvmem_np) return ERR_PTR(-EINVAL); - return __nvmem_device_get(nvmem_np); + return __nvmem_device_get(nvmem_np, NULL); } EXPORT_SYMBOL_GPL(of_nvmem_device_get); #endif @@ -897,7 +909,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, if (!nvmem_np) return ERR_PTR(-EINVAL); - nvmem = __nvmem_device_get(nvmem_np); + nvmem = __nvmem_device_get(nvmem_np, NULL); of_node_put(nvmem_np); if (IS_ERR(nvmem)) return ERR_CAST(nvmem); @@ -913,6 +925,43 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, EXPORT_SYMBOL_GPL(of_nvmem_cell_get); #endif +static struct nvmem_cell * +nvmem_cell_get_from_lookup(struct device *dev, const char *cell_id) +{ + struct nvmem_cell *cell = ERR_PTR(-ENOENT); + struct nvmem_cell_lookup *lookup; + struct nvmem_device *nvmem; + const char *dev_id; + + if (!dev) + return ERR_PTR(-EINVAL); + + dev_id = dev_name(dev); + + mutex_lock(&nvmem_lookup_mutex); + + list_for_each_entry(lookup, &nvmem_lookup_list, node) { + if ((strcmp(lookup->dev_id, dev_id) == 0) && + (strcmp(lookup->cell_id, cell_id) == 0)) { + /* This is the right entry. */ + nvmem = __nvmem_device_get(NULL, lookup->nvmem_name); + if (!nvmem) { + /* Provider may not be registered yet. */ + cell = ERR_PTR(-EPROBE_DEFER); + goto out; + } + + cell = nvmem_find_cell_by_name(nvmem, cell_id); + if (!cell) + goto out; + } + } + +out: + mutex_unlock(&nvmem_lookup_mutex); + return cell; +} + /** * nvmem_cell_get() - Get nvmem cell of device form a given cell name * @@ -925,10 +974,14 @@ EXPORT_SYMBOL_GPL(of_nvmem_cell_get); */ struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id) { - if (!dev->of_node) + if (dev->of_node) + return of_nvmem_cell_get(dev->of_node, cell_id); + + /* Only allow empty cell_id for DT systems. */ + if (!cell_id) return ERR_PTR(-EINVAL); - return of_nvmem_cell_get(dev->of_node, cell_id); + return nvmem_cell_get_from_lookup(dev, cell_id); } EXPORT_SYMBOL_GPL(nvmem_cell_get); @@ -1300,6 +1353,41 @@ void nvmem_del_cell_table(struct nvmem_cell_table *table) } EXPORT_SYMBOL_GPL(nvmem_del_cell_table); +/** + * nvmem_add_cell_lookups() - register a list of cell lookup entries + * + * @entries: array of cell lookup entries + * @nentries: number of cell lookup entries in the array + */ +void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries) +{ + int i; + + mutex_lock(&nvmem_lookup_mutex); + for (i = 0; i < nentries; i++) + list_add_tail(&entries[i].node, &nvmem_lookup_list); + mutex_unlock(&nvmem_lookup_mutex); +} +EXPORT_SYMBOL_GPL(nvmem_add_cell_lookups); + +/** + * nvmem_del_cell_lookups() - remove a list of previously added cell lookup + * entries + * + * @entries: array of cell lookup entries + * @nentries: number of cell lookup entries in the array + */ +void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries) +{ + int i; + + mutex_lock(&nvmem_lookup_mutex); + for (i = 0; i < nentries; i++) + list_del(&entries[i].node); + mutex_unlock(&nvmem_lookup_mutex); +} +EXPORT_SYMBOL_GPL(nvmem_del_cell_lookups); + /** * nvmem_dev_name() - Get the name of a given nvmem device. * diff --git a/include/linux/nvmem-machine.h b/include/linux/nvmem-machine.h index 1e199dfaacab..79421bbf9d13 100644 --- a/include/linux/nvmem-machine.h +++ b/include/linux/nvmem-machine.h @@ -26,16 +26,31 @@ struct nvmem_cell_table { struct list_head node; }; +struct nvmem_cell_lookup { + const char *nvmem_name; + const char *dev_id; + const char *cell_id; + struct list_head node; +}; + #if IS_ENABLED(CONFIG_NVMEM) void nvmem_add_cell_table(struct nvmem_cell_table *table); void nvmem_del_cell_table(struct nvmem_cell_table *table); +void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries); +void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries); + #else /* CONFIG_NVMEM */ static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {} static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {} +static inline void +nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries) {} +static inline void +nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries) {} + #endif /* CONFIG_NVMEM */ #endif /* ifndef _LINUX_NVMEM_MACHINE_H */ -- 2.18.0