From patchwork Thu Dec 7 10:27:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 120953 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp8179527qgn; Thu, 7 Dec 2017 02:31:43 -0800 (PST) X-Google-Smtp-Source: AGs4zMZuCDL/HbYe7SvfkUr4yQZJfseI1wK9cLDFoH0Uv/cbjIfoP0oMhpowGwG+XN6SiMq0hp7L X-Received: by 10.28.9.195 with SMTP id 186mr640879wmj.122.1512642702897; Thu, 07 Dec 2017 02:31:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512642702; cv=none; d=google.com; s=arc-20160816; b=wzzFePcMZAdJIz2yGTOHukBxncQVXtseZuPNAv6O4gSHJtmeE194xNEVlSZkqjv10l LTZCmxxBWfEa2P8NVL4iCMIBWBF/6oM8LmhoU7m8cl0Pin80WdBHT005qq8i4yqvSBMY FAtoDZao0O2/flsoKv1H7KW0QYN61Oidlb2VYPMJiWKSE8FJsY0sufTFzHvDT+ndWs/N y5EEwV35Wy+HLTvk46iAaHQFSKrjVk75micbF7gL2acJG84YF+jYQEbhn6GbPLsFwYVy 8dbL5jo5m7LnofKN0zcWGR+z55SFQTQgM+hz6kghmXrYxqgMQWwZBYG6kPMXN73xpKnJ ATXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=/Q/B0w4HLz3SsMujQH6nwiWG2x6cUJr3/O5D9hvEMbc=; b=Y7+48gttGmUG1ZD3thaJH8OGuQJxsJ5VRMk9yL/dA/mQ/TXlzvMI7+hHvPmAefIwMN MBOa9T/yDkGXw4aCbuMMUGz0ogtrZdyB5cnIlQxGSzLiLYIDE77ppimdGGDXMNXrb5lr OgMAaOtsiVs7t2gw4lO9jxXnQXcmsWxv9X2q/AJCTwZRGhGE+EtziYtrT/QFho/md5BJ 1nNUfEnCyqMxRiF0qRSMfsHBXueGBHjSbXhCmtC2q4aRNFVFejpTI5mMcIZeKyryJ1hD qX3QXBgLdSOG4HssN/6lQHyZ5UxhPUrrgoYzePU5aECFuwCr/OUYNrO2x7cExY9oxMwX Tr9Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=YwTgnAEH; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id z63si3406737wmz.126.2017.12.07.02.31.41; Thu, 07 Dec 2017 02:31:42 -0800 (PST) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=YwTgnAEH; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 0F947267AA4; Thu, 7 Dec 2017 11:30:45 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 1BB5A267A8F; Thu, 7 Dec 2017 11:30:41 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) by alsa0.perex.cz (Postfix) with ESMTP id 10461267A89 for ; Thu, 7 Dec 2017 11:30:38 +0100 (CET) Received: by mail-wm0-f68.google.com with SMTP id 9so12119746wme.4 for ; Thu, 07 Dec 2017 02:30:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=sXQsTpfmCCYslqW17Sj8TQIFwT19X/9ihNDnUPDv8Vo=; b=YwTgnAEHsS64Y2XSRpCLQ3YZ2Cjy5ZF89NaII7bLhQkgpWYR+AJUbAWc6f/YYdwHy3 HX8tXEp+kr6grunYEvmutK9AHbR3kJ2Wg7d9uWUt2VuvURMefQa4T6Uw9XVcrVdsZkXh 7/m74kCNsdKquIYPAljyTCdUO4cf4Yeahzx48= 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=sXQsTpfmCCYslqW17Sj8TQIFwT19X/9ihNDnUPDv8Vo=; b=QpJ3HpW2/ncWgdc+10ITKRhA670tK+IxdR+lOpX2eJwsg2eijKh38cgroA/2dfpXpB /uwjO/0MkINTM98/hX0IAIzV1+teLbUW7daITnnn0HXwjhHhlcfxXQs8AJW9BHgVe8Fe snr7AOsoXI2wGIximSxgWMtxhsNYc8qVcQTK1LGBvofxlJ+1wD+iPmHfqsCUrJS1WTPn ZOpZq68ehvj4mnd+t8NdhdFMAS6rHUeTUNYa3ZKNZv9w8jMAixGllxHs7hu4gZjIqzwF y28IjnKY+VBDO5epEBFWi9XBvhT/an7g3zQkXqZ4iWcCKKlxWH4ljW+aXeK5gl0cFEKi 9cKA== X-Gm-Message-State: AKGB3mL0cchz0GWaL0JCAwG7x+YZy9nCt4UW0tI8/3+0zk1qU2DDoV1u TE0AaWQAzumGIo9Yn18ILHKQ7w== X-Received: by 10.28.144.148 with SMTP id s142mr692203wmd.82.1512642638355; Thu, 07 Dec 2017 02:30:38 -0800 (PST) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id k2sm4837734wrg.4.2017.12.07.02.30.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Dec 2017 02:30:37 -0800 (PST) From: srinivas.kandagatla@linaro.org To: Mark Brown , Greg Kroah-Hartman , alsa-devel@alsa-project.org Date: Thu, 7 Dec 2017 10:27:10 +0000 Message-Id: <20171207102720.21071-4-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> References: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> Cc: Mark Rutland , devicetree@vger.kernel.org, Jonathan Corbet , linux-arm-msm@vger.kernel.org, linux-doc@vger.kernel.org, j.neuschaefer@gmx.net, linux-kernel@vger.kernel.org, Rob Herring , Srinivas Kandagatla , pombredanne@nexb.com, sdharia@codeaurora.org Subject: [alsa-devel] [PATCH v9 03/13] slimbus: Add SLIMbus bus type X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Sagar Dharia SLIMbus (Serial Low Power Interchip Media Bus) is a specification developed by MIPI (Mobile Industry Processor Interface) alliance. SLIMbus is a 2-wire implementation, which is used to communicate with peripheral components like audio-codec. SLIMbus uses Time-Division-Multiplexing to accommodate multiple data channels, and control channel. Control channel has messages to do device-enumeration, messages to send/receive control-data to/from SLIMbus devices, messages for port/channel management, and messages to do bandwidth allocation. The framework supports multiple instances of the bus (1 controller per bus), and multiple slave devices per controller. This patch adds support to basic silmbus core which includes support to SLIMbus type, slimbus device registeration and some basic data structures. Signed-off-by: Sagar Dharia Signed-off-by: Srinivas Kandagatla --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/slimbus/Kconfig | 17 ++++++ drivers/slimbus/Makefile | 6 +++ drivers/slimbus/core.c | 106 +++++++++++++++++++++++++++++++++++++ include/linux/mod_devicetable.h | 13 +++++ include/linux/slimbus.h | 114 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 259 insertions(+) create mode 100644 drivers/slimbus/Kconfig create mode 100644 drivers/slimbus/Makefile create mode 100644 drivers/slimbus/core.c create mode 100644 include/linux/slimbus.h -- 2.15.0 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/drivers/Kconfig b/drivers/Kconfig index 152744c5ef0f..c8e1d1c3f426 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -211,4 +211,6 @@ source "drivers/mux/Kconfig" source "drivers/opp/Kconfig" +source "drivers/slimbus/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 1d034b680431..d233a95b3b24 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_MTD) += mtd/ obj-$(CONFIG_SPI) += spi/ obj-$(CONFIG_SPMI) += spmi/ obj-$(CONFIG_HSI) += hsi/ +obj-$(CONFIG_SLIMBUS) += slimbus/ obj-y += net/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_FUSION) += message/ diff --git a/drivers/slimbus/Kconfig b/drivers/slimbus/Kconfig new file mode 100644 index 000000000000..9b6bb84d66ed --- /dev/null +++ b/drivers/slimbus/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# SLIMbus driver configuration +# +menuconfig SLIMBUS + tristate "SLIMbus support" + help + SLIMbus is standard interface between System-on-Chip and audio codec, + and other peripheral components in typical embedded systems. + + If unsure, choose N. + +if SLIMBUS + +# SLIMbus controllers + +endif diff --git a/drivers/slimbus/Makefile b/drivers/slimbus/Makefile new file mode 100644 index 000000000000..506ff17d6346 --- /dev/null +++ b/drivers/slimbus/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for kernel SLIMbus framework. +# +obj-$(CONFIG_SLIMBUS) += slimbus.o +slimbus-y := core.o diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c new file mode 100644 index 000000000000..f4e6bfdeef92 --- /dev/null +++ b/drivers/slimbus/core.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation + +#include +#include +#include +#include +#include + +static const struct slim_device_id *slim_match(const struct slim_device_id *id, + const struct slim_device *sbdev) +{ + while (id->manf_id != 0 || id->prod_code != 0) { + if (id->manf_id == sbdev->e_addr.manf_id && + id->prod_code == sbdev->e_addr.prod_code) + return id; + id++; + } + return NULL; +} + +static int slim_device_match(struct device *dev, struct device_driver *drv) +{ + struct slim_device *sbdev = to_slim_device(dev); + struct slim_driver *sbdrv = to_slim_driver(drv); + + return !!slim_match(sbdrv->id_table, sbdev); +} + +static int slim_device_probe(struct device *dev) +{ + struct slim_device *sbdev = to_slim_device(dev); + struct slim_driver *sbdrv = to_slim_driver(dev->driver); + + return sbdrv->probe(sbdev); +} + +static int slim_device_remove(struct device *dev) +{ + struct slim_device *sbdev = to_slim_device(dev); + struct slim_driver *sbdrv; + + if (dev->driver) { + sbdrv = to_slim_driver(dev->driver); + if (sbdrv->remove) + sbdrv->remove(sbdev); + } + + return 0; +} + +struct bus_type slimbus_bus = { + .name = "slimbus", + .match = slim_device_match, + .probe = slim_device_probe, + .remove = slim_device_remove, +}; +EXPORT_SYMBOL_GPL(slimbus_bus); + +/* + * __slim_driver_register() - Client driver registration with SLIMbus + * + * @drv:Client driver to be associated with client-device. + * @owner: owning module/driver + * + * This API will register the client driver with the SLIMbus + * It is called from the driver's module-init function. + */ +int __slim_driver_register(struct slim_driver *drv, struct module *owner) +{ + /* ID table and probe are mandatory */ + if (!drv->id_table || !drv->probe) + return -EINVAL; + + drv->driver.bus = &slimbus_bus; + drv->driver.owner = owner; + + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(__slim_driver_register); + +/* + * slim_driver_unregister() - Undo effect of slim_driver_register + * + * @drv: Client driver to be unregistered + */ +void slim_driver_unregister(struct slim_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(slim_driver_unregister); + +static void __exit slimbus_exit(void) +{ + bus_unregister(&slimbus_bus); +} +module_exit(slimbus_exit); + +static int __init slimbus_init(void) +{ + return bus_register(&slimbus_bus); +} +postcore_initcall(slimbus_init); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("SLIMbus core"); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index abb6dc2ebbf8..48e188327c02 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -452,6 +452,19 @@ struct spi_device_id { kernel_ulong_t driver_data; /* Data private to the driver */ }; +/* SLIMbus */ + +#define SLIMBUS_NAME_SIZE 32 +#define SLIMBUS_MODULE_PREFIX "slim:" + +struct slim_device_id { + __u16 manf_id, prod_code; + __u16 dev_index, instance; + + /* Data private to the driver */ + kernel_ulong_t driver_data; +}; + #define SPMI_NAME_SIZE 32 #define SPMI_MODULE_PREFIX "spmi:" diff --git a/include/linux/slimbus.h b/include/linux/slimbus.h new file mode 100644 index 000000000000..a52f8e530f27 --- /dev/null +++ b/include/linux/slimbus.h @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation + +#ifndef _LINUX_SLIMBUS_H +#define _LINUX_SLIMBUS_H +#include +#include +#include + +extern struct bus_type slimbus_bus; + +/** + * struct slim_eaddr - Enumeration address for a SLIMbus device + * @manf_id: Manufacturer Id for the device + * @prod_code: Product code + * @dev_index: Device index + * @instance: Instance value + */ +struct slim_eaddr { + u16 manf_id; + u16 prod_code; + u8 dev_index; + u8 instance; +} __packed; + +/** + * enum slim_device_status - slim device status + * @SLIM_DEVICE_STATUS_DOWN: Slim device is absent or not reported yet. + * @SLIM_DEVICE_STATUS_UP: Slim device is announced on the bus. + * @SLIM_DEVICE_STATUS_RESERVED: Reserved for future use. + */ +enum slim_device_status { + SLIM_DEVICE_STATUS_DOWN = 0, + SLIM_DEVICE_STATUS_UP, + SLIM_DEVICE_STATUS_RESERVED, +}; + +/** + * struct slim_device - Slim device handle. + * @dev: Driver model representation of the device. + * @e_addr: Enumeration address of this device. + * @status: slim device status + * @laddr: 1-byte Logical address of this device. + * @is_laddr_valid: indicates if the laddr is valid or not + * + * This is the client/device handle returned when a SLIMbus + * device is registered with a controller. + * Pointer to this structure is used by client-driver as a handle. + */ +struct slim_device { + struct device dev; + struct slim_eaddr e_addr; + enum slim_device_status status; + u8 laddr; + bool is_laddr_valid; +}; + +#define to_slim_device(d) container_of(d, struct slim_device, dev) + +/** + * struct slim_driver - SLIMbus 'generic device' (slave) device driver + * (similar to 'spi_device' on SPI) + * @probe: Binds this driver to a SLIMbus device. + * @remove: Unbinds this driver from the SLIMbus device. + * @shutdown: Standard shutdown callback used during powerdown/halt. + * @device_status: This callback is called when + * - The device reports present and gets a laddr assigned + * - The device reports absent, or the bus goes down. + * @driver: SLIMbus device drivers should initialize name and owner field of + * this structure + * @id_table: List of SLIMbus devices supported by this driver + */ + +struct slim_driver { + int (*probe)(struct slim_device *sl); + void (*remove)(struct slim_device *sl); + void (*shutdown)(struct slim_device *sl); + int (*device_status)(struct slim_device *sl, + enum slim_device_status s); + struct device_driver driver; + const struct slim_device_id *id_table; +}; +#define to_slim_driver(d) container_of(d, struct slim_driver, driver) + +/* + * use a macro to avoid include chaining to get THIS_MODULE + */ +#define slim_driver_register(drv) \ + __slim_driver_register(drv, THIS_MODULE) +int __slim_driver_register(struct slim_driver *drv, struct module *owner); +void slim_driver_unregister(struct slim_driver *drv); + +/** + * module_slim_driver() - Helper macro for registering a SLIMbus driver + * @__slim_driver: slimbus_driver struct + * + * Helper macro for SLIMbus drivers which do not do anything special in module + * init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_slim_driver(__slim_driver) \ + module_driver(__slim_driver, slim_driver_register, \ + slim_driver_unregister) + +static inline void *slim_get_devicedata(const struct slim_device *dev) +{ + return dev_get_drvdata(&dev->dev); +} + +static inline void slim_set_devicedata(struct slim_device *dev, void *data) +{ + dev_set_drvdata(&dev->dev, data); +} +#endif /* _LINUX_SLIMBUS_H */ From patchwork Thu Dec 7 10:27:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 120957 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp8180317qgn; Thu, 7 Dec 2017 02:32:32 -0800 (PST) X-Google-Smtp-Source: AGs4zMaVK7qZYr0pAO9KCpsuRzz6Uv8mEBQr3OxsauWhVHEFb7HyRR3tLMYfMrw7zGVnxZ/6xFf2 X-Received: by 10.28.216.196 with SMTP id p187mr654373wmg.158.1512642752439; Thu, 07 Dec 2017 02:32:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512642752; cv=none; d=google.com; s=arc-20160816; b=fPdhfQAhZHgnQlsai6qkMTg1TkMLN4Uu2MYIKXbo5tJ4t2Ovb2+Fq6oeOj3uhDzLAz jOjxDprrSgeYzmWiXGREB/vPIVIGMoHwCuQHOmfU09yWsU89Gz954pk8hk8uRjPT6xCG 4731hNjN3MNswO0hDpnUaj08ro+x+loaNyMeaIldewNqZX0akeXgONeI/6TVXndZbkbc WdThQ36+qOjF88Cd1+qSgIpziWwR7mz2u16LZEzDQXH05rgOAk40pvlb8WPeNxYYRG3q wZa8O4rkOoZZxQ86C76U9STd8fxrgA3w5Q3YjcKUbmNAOKnZKWoz3tV3NzZrI6+R+C5F Ye/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=M067N/qHNh1jP7VcsmkRb/5Y/mgFqkc0ZSFhVwVr6Iw=; b=sMBRqtNAWSbKbiJX2+cXK+0v+JxquCXP4QXvlN9BXoB7eN1B7+rcSuNNvh10rOcMJs SegCkMr6CWW9Iy9PBFFHtwrUwG0nGlz2OnHIOQ/x982Qg4ppy6jStiTakj2u/kUUAvjK zpTZCQdO7DKD+gSz/mqn6gnNpMOIQkeKDWhDUyuwHKh7TirlrvExo2lPXQdm0wZRnpfc f8GARbfW1MCbNRKD2eOp/y81xcxOTN1YtQ2GIu5YLpmRe6c8IXyXhFSsdGWY6JCSMVoP QNDyPgj/xTf4uilrOsZwFGXRBDR28cbGX2Tp7k0EHaPM3RZ47aBMEe1eckYjUep8PmCW tlew== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=FWVfm0Id; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id f199si2697744wmf.95.2017.12.07.02.32.27; Thu, 07 Dec 2017 02:32:32 -0800 (PST) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=FWVfm0Id; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 916CA267AB9; Thu, 7 Dec 2017 11:30:48 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id CC493267A92; Thu, 7 Dec 2017 11:30:42 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wm0-f66.google.com (mail-wm0-f66.google.com [74.125.82.66]) by alsa0.perex.cz (Postfix) with ESMTP id 51D93267A89 for ; Thu, 7 Dec 2017 11:30:40 +0100 (CET) Received: by mail-wm0-f66.google.com with SMTP id i11so11909546wmf.4 for ; Thu, 07 Dec 2017 02:30:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=63OaDrq+BjoDH/GA/vuaAfx1fh2PZ9+BhWvCeKE1bK0=; b=FWVfm0IdriytSvTI57EbGX9twD1X6r38urWHH1uSkAEGjQvLRnaWrk8IG2gBRRKtoy XiaRh2Yl8eCanxN+PMvnqUZV1GtAQWBll4Ra9wuMQK7RYF1IIQyh7ymCf3M230J4sLk1 OcFZbriBO0YOvQnEMdKZbA5HRLb20gXb4Gj5w= 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=63OaDrq+BjoDH/GA/vuaAfx1fh2PZ9+BhWvCeKE1bK0=; b=NRME3p/DeVn5wirRWOsETOEbRd6GPhQvSzAVnhSNG3AQrr7jRrKcXwOX/DcnSOohIB QjRou1wfe3KCwmVIM9R94pWeu8e3E/ucGQO5M7zpFKlTLLI2llBGfAL7jfk1Rr+HjMTp DlYymV/LQS71y2E37kDkRdZ5sbIin6oXrMtHQCog0m4iHIPIV5cwG8LSozJuAJ+EcvaR roEXem6vWlbwULJWEiJw/MFI32t3gayISAuXef5NOELW4Kwr/6fN9Lx2hojBb3TucUpJ StYyzBj0lOniEN7IrmxLEHoAHznyIcP8n6ER7dOyGv3v2hOrVXwSltFIGXrFIFkHrOpB /TsQ== X-Gm-Message-State: AKGB3mJmjo4pFnTGirw+xugwPyHC1RKgDVkR7/7xEV4MSnI6qBkEiM2y 4yum7zCmT/NrDfMIOANI38uAxQ== X-Received: by 10.28.168.88 with SMTP id r85mr701439wme.63.1512642639480; Thu, 07 Dec 2017 02:30:39 -0800 (PST) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id k2sm4837734wrg.4.2017.12.07.02.30.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Dec 2017 02:30:38 -0800 (PST) From: srinivas.kandagatla@linaro.org To: Mark Brown , Greg Kroah-Hartman , alsa-devel@alsa-project.org Date: Thu, 7 Dec 2017 10:27:11 +0000 Message-Id: <20171207102720.21071-5-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> References: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> Cc: Mark Rutland , devicetree@vger.kernel.org, Jonathan Corbet , linux-arm-msm@vger.kernel.org, linux-doc@vger.kernel.org, j.neuschaefer@gmx.net, linux-kernel@vger.kernel.org, Rob Herring , Srinivas Kandagatla , pombredanne@nexb.com, sdharia@codeaurora.org Subject: [alsa-devel] [PATCH v9 04/13] slimbus: core: Add slim controllers support X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Sagar Dharia This patch adds support to slim controllers in the slim core, including some utility functions invoked by the controller and slim device drivers. Signed-off-by: Srinivas Kandagatla --- drivers/slimbus/core.c | 306 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/slimbus/slimbus.h | 106 ++++++++++++++++ include/linux/slimbus.h | 8 ++ 3 files changed, 420 insertions(+) create mode 100644 drivers/slimbus/slimbus.h -- 2.15.0 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c index f4e6bfdeef92..a59a88a7a52d 100644 --- a/drivers/slimbus/core.c +++ b/drivers/slimbus/core.c @@ -5,7 +5,11 @@ #include #include #include +#include #include +#include "slimbus.h" + +static DEFINE_IDA(ctrl_ida); static const struct slim_device_id *slim_match(const struct slim_device_id *id, const struct slim_device *sbdev) @@ -90,6 +94,308 @@ void slim_driver_unregister(struct slim_driver *drv) } EXPORT_SYMBOL_GPL(slim_driver_unregister); +static void slim_dev_release(struct device *dev) +{ + struct slim_device *sbdev = to_slim_device(dev); + + kfree(sbdev); +} + +static int slim_add_device(struct slim_controller *ctrl, + struct slim_device *sbdev, + struct device_node *node) +{ + sbdev->dev.bus = &slimbus_bus; + sbdev->dev.parent = ctrl->dev; + sbdev->dev.release = slim_dev_release; + sbdev->dev.driver = NULL; + sbdev->ctrl = ctrl; + + dev_set_name(&sbdev->dev, "%x:%x:%x:%x", + sbdev->e_addr.manf_id, + sbdev->e_addr.prod_code, + sbdev->e_addr.dev_index, + sbdev->e_addr.instance); + + return device_register(&sbdev->dev); +} + +static struct slim_device *slim_alloc_device(struct slim_controller *ctrl, + struct slim_eaddr *eaddr, + struct device_node *node) +{ + struct slim_device *sbdev; + int ret; + + sbdev = kzalloc(sizeof(*sbdev), GFP_KERNEL); + if (!sbdev) + return NULL; + + sbdev->e_addr = *eaddr; + ret = slim_add_device(ctrl, sbdev, node); + if (ret) { + kfree(sbdev); + return NULL; + } + + return sbdev; +} + +/* + * slim_register_controller() - Controller bring-up and registration. + * + * @ctrl: Controller to be registered. + * + * A controller is registered with the framework using this API. + * If devices on a controller were registered before controller, + * this will make sure that they get probed when controller is up + */ +int slim_register_controller(struct slim_controller *ctrl) +{ + int id; + + id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); + if (id < 0) + return id; + + ctrl->id = id; + + if (!ctrl->min_cg) + ctrl->min_cg = SLIM_MIN_CLK_GEAR; + if (!ctrl->max_cg) + ctrl->max_cg = SLIM_MAX_CLK_GEAR; + + ida_init(&ctrl->laddr_ida); + idr_init(&ctrl->tid_idr); + mutex_init(&ctrl->lock); + + dev_dbg(ctrl->dev, "Bus [%s] registered:dev:%p\n", + ctrl->name, ctrl->dev); + + return 0; +} +EXPORT_SYMBOL_GPL(slim_register_controller); + +/* slim_remove_device: Remove the effect of slim_add_device() */ +static void slim_remove_device(struct slim_device *sbdev) +{ + device_unregister(&sbdev->dev); +} + +static int slim_ctrl_remove_device(struct device *dev, void *null) +{ + slim_remove_device(to_slim_device(dev)); + return 0; +} + +/** + * slim_unregister_controller() - Controller tear-down. + * + * @ctrl: Controller to tear-down. + */ +int slim_unregister_controller(struct slim_controller *ctrl) +{ + /* Remove all clients */ + device_for_each_child(ctrl->dev, NULL, slim_ctrl_remove_device); + ida_simple_remove(&ctrl_ida, ctrl->id); + + return 0; +} +EXPORT_SYMBOL_GPL(slim_unregister_controller); + +static void slim_device_update_status(struct slim_device *sbdev, + enum slim_device_status status) +{ + struct slim_driver *sbdrv; + + if (sbdev->status == status) + return; + + sbdev->status = status; + if (!sbdev->dev.driver) + return; + + sbdrv = to_slim_driver(sbdev->dev.driver); + if (sbdrv->device_status) + sbdrv->device_status(sbdev, sbdev->status); +} + +/** + * slim_report_absent() - Controller calls this function when a device + * reports absent, OR when the device cannot be communicated with + * + * @sbdev: Device that cannot be reached, or sent report absent + */ +void slim_report_absent(struct slim_device *sbdev) +{ + struct slim_controller *ctrl = sbdev->ctrl; + + if (!ctrl) + return; + + /* invalidate logical addresses */ + mutex_lock(&ctrl->lock); + sbdev->is_laddr_valid = false; + mutex_unlock(&ctrl->lock); + + ida_simple_remove(&ctrl->laddr_ida, sbdev->laddr); + slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_DOWN); +} +EXPORT_SYMBOL_GPL(slim_report_absent); + +static bool slim_eaddr_equal(struct slim_eaddr *a, struct slim_eaddr *b) +{ + return (a->manf_id == b->manf_id && + a->prod_code == b->prod_code && + a->dev_index == b->dev_index && + a->instance == b->instance); +} + +static int slim_match_dev(struct device *dev, void *data) +{ + struct slim_eaddr *e_addr = data; + struct slim_device *sbdev = to_slim_device(dev); + + return slim_eaddr_equal(&sbdev->e_addr, e_addr); +} + +static struct slim_device *find_slim_device(struct slim_controller *ctrl, + struct slim_eaddr *eaddr) +{ + struct slim_device *sbdev; + struct device *dev; + + dev = device_find_child(ctrl->dev, eaddr, slim_match_dev); + if (dev) { + sbdev = to_slim_device(dev); + return sbdev; + } + + return NULL; +} + +/** + * slim_get_device() - get handle to a device. + * + * @ctrl: Controller on which this device will be added/queried + * @e_addr: Enumeration address of the device to be queried + * + * Return: pointer to a device if it has already reported. Creates a new + * device and returns pointer to it if the device has not yet enumerated. + */ +struct slim_device *slim_get_device(struct slim_controller *ctrl, + struct slim_eaddr *e_addr) +{ + struct slim_device *sbdev; + + sbdev = find_slim_device(ctrl, e_addr); + if (!sbdev) { + sbdev = slim_alloc_device(ctrl, e_addr, NULL); + if (!sbdev) + return ERR_PTR(-ENOMEM); + } + + return sbdev; +} +EXPORT_SYMBOL_GPL(slim_get_device); + +static int slim_device_alloc_laddr(struct slim_device *sbdev, + bool report_present) +{ + struct slim_controller *ctrl = sbdev->ctrl; + u8 laddr; + int ret; + + mutex_lock(&ctrl->lock); + if (ctrl->get_laddr) { + ret = ctrl->get_laddr(ctrl, &sbdev->e_addr, &laddr); + if (ret < 0) + goto err; + } else if (report_present) { + ret = ida_simple_get(&ctrl->laddr_ida, + 0, SLIM_LA_MANAGER - 1, GFP_KERNEL); + if (ret < 0) + goto err; + + laddr = ret; + } else { + ret = -EINVAL; + goto err; + } + + if (ctrl->set_laddr) { + ret = ctrl->set_laddr(ctrl, &sbdev->e_addr, laddr); + if (ret) { + ret = -EINVAL; + goto err; + } + } + + sbdev->laddr = laddr; + sbdev->is_laddr_valid = true; + + slim_device_update_status(sbdev, SLIM_DEVICE_STATUS_UP); + + dev_dbg(ctrl->dev, "setting slimbus l-addr:%x, ea:%x,%x,%x,%x\n", + laddr, sbdev->e_addr.manf_id, sbdev->e_addr.prod_code, + sbdev->e_addr.dev_index, sbdev->e_addr.instance); + +err: + mutex_unlock(&ctrl->lock); + return ret; + +} + +/** + * slim_device_report_present() - Report enumerated device. + * + * @ctrl: Controller with which device is enumerated. + * @e_addr: Enumeration address of the device. + * @laddr: Return logical address (if valid flag is false) + * + * Called by controller in response to REPORT_PRESENT. Framework will assign + * a logical address to this enumeration address. + * Function returns -EXFULL to indicate that all logical addresses are already + * taken. + */ +int slim_device_report_present(struct slim_controller *ctrl, + struct slim_eaddr *e_addr, u8 *laddr) +{ + struct slim_device *sbdev; + int ret; + + sbdev = slim_get_device(ctrl, e_addr); + if (IS_ERR(sbdev)) + return -ENODEV; + + if (sbdev->is_laddr_valid) { + *laddr = sbdev->laddr; + return 0; + } + + ret = slim_device_alloc_laddr(sbdev, true); + + return ret; +} +EXPORT_SYMBOL_GPL(slim_device_report_present); + +/** + * slim_get_logical_addr() - get/allocate logical address of a SLIMbus device. + * + * @sbdev: client handle requesting the address. + * + * Return: zero if a logical address is valid or a new logical address + * has been assigned. error code in case of error. + */ +int slim_get_logical_addr(struct slim_device *sbdev) +{ + if (!sbdev->is_laddr_valid) + return slim_device_alloc_laddr(sbdev, false); + + return 0; +} +EXPORT_SYMBOL_GPL(slim_get_logical_addr); + static void __exit slimbus_exit(void) { bus_unregister(&slimbus_bus); diff --git a/drivers/slimbus/slimbus.h b/drivers/slimbus/slimbus.h new file mode 100644 index 000000000000..155d7231627d --- /dev/null +++ b/drivers/slimbus/slimbus.h @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation + +#ifndef _DRIVERS_SLIMBUS_H +#define _DRIVERS_SLIMBUS_H +#include +#include +#include +#include + +/* Standard values per SLIMbus spec needed by controllers and devices */ +#define SLIM_MAX_CLK_GEAR 10 +#define SLIM_MIN_CLK_GEAR 1 + +/* Manager's logical address is set to 0xFF per spec */ +#define SLIM_LA_MANAGER 0xFF + +/** + * struct slim_framer - Represents SLIMbus framer. + * Every controller may have multiple framers. There is 1 active framer device + * responsible for clocking the bus. + * Manager is responsible for framer hand-over. + * @dev: Driver model representation of the device. + * @e_addr: Enumeration address of the framer. + * @rootfreq: Root Frequency at which the framer can run. This is maximum + * frequency ('clock gear 10') at which the bus can operate. + * @superfreq: Superframes per root frequency. Every frame is 6144 bits. + */ +struct slim_framer { + struct device dev; + struct slim_eaddr e_addr; + int rootfreq; + int superfreq; +}; + +#define to_slim_framer(d) container_of(d, struct slim_framer, dev) + +/** + * struct slim_controller - Controls every instance of SLIMbus + * (similar to 'master' on SPI) + * @dev: Device interface to this driver + * @id: Board-specific number identifier for this controller/bus + * @name: Name for this controller + * @min_cg: Minimum clock gear supported by this controller (default value: 1) + * @max_cg: Maximum clock gear supported by this controller (default value: 10) + * @clkgear: Current clock gear in which this bus is running + * @laddr_ida: logical address id allocator + * @a_framer: Active framer which is clocking the bus managed by this controller + * @lock: Mutex protecting controller data structures + * @devices: Slim device list + * @tid_idr: tid id allocator + * @txn_lock: Lock to protect table of transactions + * @set_laddr: Setup logical address at laddr for the slave with elemental + * address e_addr. Drivers implementing controller will be expected to + * send unicast message to this device with its logical address. + * @get_laddr: It is possible that controller needs to set fixed logical + * address table and get_laddr can be used in that case so that controller + * can do this assignment. Use case is when the master is on the remote + * processor side, who is resposible for allocating laddr. + * + * 'Manager device' is responsible for device management, bandwidth + * allocation, channel setup, and port associations per channel. + * Device management means Logical address assignment/removal based on + * enumeration (report-present, report-absent) of a device. + * Bandwidth allocation is done dynamically by the manager based on active + * channels on the bus, message-bandwidth requests made by SLIMbus devices. + * Based on current bandwidth usage, manager chooses a frequency to run + * the bus at (in steps of 'clock-gear', 1 through 10, each clock gear + * representing twice the frequency than the previous gear). + * Manager is also responsible for entering (and exiting) low-power-mode + * (known as 'clock pause'). + * Manager can do handover of framer if there are multiple framers on the + * bus and a certain usecase warrants using certain framer to avoid keeping + * previous framer being powered-on. + * + * Controller here performs duties of the manager device, and 'interface + * device'. Interface device is responsible for monitoring the bus and + * reporting information such as loss-of-synchronization, data + * slot-collision. + */ +struct slim_controller { + struct device *dev; + unsigned int id; + char name[SLIMBUS_NAME_SIZE]; + int min_cg; + int max_cg; + int clkgear; + struct ida laddr_ida; + struct slim_framer *a_framer; + struct mutex lock; + struct list_head devices; + struct idr tid_idr; + spinlock_t txn_lock; + int (*set_laddr)(struct slim_controller *ctrl, + struct slim_eaddr *ea, u8 laddr); + int (*get_laddr)(struct slim_controller *ctrl, + struct slim_eaddr *ea, u8 *laddr); +}; + +int slim_device_report_present(struct slim_controller *ctrl, + struct slim_eaddr *e_addr, u8 *laddr); +void slim_report_absent(struct slim_device *sbdev); +int slim_register_controller(struct slim_controller *ctrl); +int slim_unregister_controller(struct slim_controller *ctrl); + +#endif /* _LINUX_SLIMBUS_H */ diff --git a/include/linux/slimbus.h b/include/linux/slimbus.h index a52f8e530f27..b59b272666b6 100644 --- a/include/linux/slimbus.h +++ b/include/linux/slimbus.h @@ -35,11 +35,14 @@ enum slim_device_status { SLIM_DEVICE_STATUS_RESERVED, }; +struct slim_controller; + /** * struct slim_device - Slim device handle. * @dev: Driver model representation of the device. * @e_addr: Enumeration address of this device. * @status: slim device status + * @ctrl: slim controller instance. * @laddr: 1-byte Logical address of this device. * @is_laddr_valid: indicates if the laddr is valid or not * @@ -50,6 +53,7 @@ enum slim_device_status { struct slim_device { struct device dev; struct slim_eaddr e_addr; + struct slim_controller *ctrl; enum slim_device_status status; u8 laddr; bool is_laddr_valid; @@ -111,4 +115,8 @@ static inline void slim_set_devicedata(struct slim_device *dev, void *data) { dev_set_drvdata(&dev->dev, data); } + +struct slim_device *slim_get_device(struct slim_controller *ctrl, + struct slim_eaddr *e_addr); +int slim_get_logical_addr(struct slim_device *sbdev); #endif /* _LINUX_SLIMBUS_H */ From patchwork Thu Dec 7 10:27:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 120960 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp8181825qgn; Thu, 7 Dec 2017 02:34:04 -0800 (PST) X-Google-Smtp-Source: AGs4zMZ18bPbfb7YcMswDXrJNzzztXTnX7tUZeSU5DwuXML3E5MZlRYNXqTfYAES2hN1ASmO07X2 X-Received: by 10.223.142.17 with SMTP id n17mr21569484wrb.244.1512642844531; Thu, 07 Dec 2017 02:34:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512642844; cv=none; d=google.com; s=arc-20160816; b=ZAGssDELdbLjwHG6i88DGUmjujlVVDOr7nfi4eswwFAh9Z21P0JZPTwmRIxI2OT2v7 tu3pb2YjOWcJ4IGBI5CeaLiMEjaWDiL5tE1Czz/mrq0ReAoJxtbOaiuYDmaH4KURxl2W rJRDDI4zLdKk4U/cs0Z0A7ek7GpA/610T/ymsa7fzeNyjjriOs0J0i9V+XQUWpQNPEcQ dW7YXfDgjdq4jMyohjJVD8jagza/ZDf2xfTi41ushzpR3zgA6Of3td+pzk+c6+pi0kmj mnJhyfU0kOu6pkAFgtWwzVonRu/0TJaSQtZzUQSdXNCIKou42ujmXbB35QD5DBsKq1CG 1kVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=OqLh8D2sUWr6/wN4P39F6L1VH6m0qALU/DdO58t/uMo=; b=lG3BGvceGWC5jDGo0o+bXc4JA1QDs72780738uhplhJyW/hMINkc+FxJqis+RTjJ/a j6u1iaE2jOMBf8nXQ8Deh8/UZhbN3GyR049fxzQjbhj7T3sSV73meL6ifzD+aDPpoReZ VV8UPXAOmmDOwZIxLWWH4+YUi1VC3D/bAqNnYledCjAuDKoBBKDA5o5jS1BFiiLUpWKE wTqw6wP6q84W2bg8/nrx+k7nUvMCB+aN2e9JTKTFqnNfUcrPZV96Sp1fJpOFyQ11JkYM o2Cex6XpyEpDYhW7n+PX0B/iMYxTA2UZL5YHFAY2PVFpSB8ZwtCScHMYx/+sqWSd9Qwm OuhA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=itSow7k+; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id p40si3702762wrb.224.2017.12.07.02.34.04; Thu, 07 Dec 2017 02:34:04 -0800 (PST) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=itSow7k+; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id E3092267AD9; Thu, 7 Dec 2017 11:30:55 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 63D5B267AC3; Thu, 7 Dec 2017 11:30:50 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wm0-f41.google.com (mail-wm0-f41.google.com [74.125.82.41]) by alsa0.perex.cz (Postfix) with ESMTP id DF7F9267AAA for ; Thu, 7 Dec 2017 11:30:42 +0100 (CET) Received: by mail-wm0-f41.google.com with SMTP id f140so11908931wmd.2 for ; Thu, 07 Dec 2017 02:30:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MbMylSZExfoWbB1CS/MUCSdIkb+dhgoLaZ7WL9zDoic=; b=itSow7k+8G5W7uleVnD3/L1q6wdBsQGBqh+G2d1dhK1/Hbcx4OpGZWcwfgH1YkzdOJ vev7s0D4KnlOBzddDxXwfpUEnmGFVrZ5DJTpt5pmPg5dbgQjfI0kTKpyWrEULG76jjXu evflQXpGKWCm2LwMDZCb8hFUZWzkXuzL3OWiA= 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=MbMylSZExfoWbB1CS/MUCSdIkb+dhgoLaZ7WL9zDoic=; b=XLJTgJxZgc8NumECApyRFMW6Mz28b86KS7fscMjDCqORjGGaRaGK8kLqnpxmo2mKMJ 985lwhE45eQwBwDuNCENoBRknt2NW0GwxxbS/IyMwcapO+qTOCTADw6KTMIK+RxH4SOw /yf9f57rqp2rrljd3razbsPOWmormLi0d5UHlvzU0fr5xR9zW5Q7YdB99K/nQN4INurP gIE0SjzpCsEgJPrxVugkwj6dEUSC0mTl2iZXURF/Jhn3YBEtZULYJdTBMJRWQPU/bK0D WhE1am/0LEztDXvrGCJdHQGg7NEJ7NBcYMO2IpWclbSwZmSkINPKJJ8c49SfcRvFnHAM sdng== X-Gm-Message-State: AKGB3mL7VZRp3Qja1uMVF78BMA5YB6dWrfHUmKJ6rBCLtiJi966peVqR Oep6QXSI1JkYUuqhggy5Jz+6aw== X-Received: by 10.28.71.5 with SMTP id u5mr689318wma.84.1512642641761; Thu, 07 Dec 2017 02:30:41 -0800 (PST) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id k2sm4837734wrg.4.2017.12.07.02.30.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Dec 2017 02:30:41 -0800 (PST) From: srinivas.kandagatla@linaro.org To: Mark Brown , Greg Kroah-Hartman , alsa-devel@alsa-project.org Date: Thu, 7 Dec 2017 10:27:13 +0000 Message-Id: <20171207102720.21071-7-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> References: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> Cc: Mark Rutland , devicetree@vger.kernel.org, Jonathan Corbet , linux-arm-msm@vger.kernel.org, linux-doc@vger.kernel.org, j.neuschaefer@gmx.net, linux-kernel@vger.kernel.org, Rob Herring , Srinivas Kandagatla , pombredanne@nexb.com, sdharia@codeaurora.org Subject: [alsa-devel] [PATCH v9 06/13] slimbus: Add messaging APIs to slimbus framework X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Sagar Dharia SLIMbus devices use value-element, and information elements to control device parameters (e.g. value element is used to represent gain for codec, information element is used to represent interrupt status for codec when codec interrupt fires). Messaging APIs are used to set/get these value and information elements. SLIMbus specification uses 8-bit "transaction IDs" for messages where a read-value is anticipated. Framework uses a table of pointers to store those TIDs and responds back to the caller in O(1). Caller can do synchronous and asynchronous reads/writes. Signed-off-by: Srinivas Kandagatla --- drivers/slimbus/Makefile | 2 +- drivers/slimbus/messaging.c | 295 ++++++++++++++++++++++++++++++++++++++++++++ drivers/slimbus/slimbus.h | 67 ++++++++++ include/linux/slimbus.h | 40 ++++++ 4 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 drivers/slimbus/messaging.c -- 2.15.0 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/drivers/slimbus/Makefile b/drivers/slimbus/Makefile index 506ff17d6346..568a14c7be78 100644 --- a/drivers/slimbus/Makefile +++ b/drivers/slimbus/Makefile @@ -3,4 +3,4 @@ # Makefile for kernel SLIMbus framework. # obj-$(CONFIG_SLIMBUS) += slimbus.o -slimbus-y := core.o +slimbus-y := core.o messaging.o diff --git a/drivers/slimbus/messaging.c b/drivers/slimbus/messaging.c new file mode 100644 index 000000000000..42798ff06e85 --- /dev/null +++ b/drivers/slimbus/messaging.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation + +#include +#include "slimbus.h" + +/** + * slim_msg_response() - Deliver Message response received from a device to the + * framework. + * + * @ctrl: Controller handle + * @reply: Reply received from the device + * @len: Length of the reply + * @tid: Transaction ID received with which framework can associate reply. + * + * Called by controller to inform framework about the response received. + * This helps in making the API asynchronous, and controller-driver doesn't need + * to manage 1 more table other than the one managed by framework mapping TID + * with buffers + */ +void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len) +{ + struct slim_msg_txn *txn; + struct slim_val_inf *msg; + unsigned long flags; + + spin_lock_irqsave(&ctrl->txn_lock, flags); + txn = idr_find(&ctrl->tid_idr, tid); + if (txn == NULL) { + spin_unlock_irqrestore(&ctrl->txn_lock, flags); + return; + } + + msg = txn->msg; + if (msg == NULL || msg->rbuf == NULL) { + dev_err(ctrl->dev, "Got response to invalid TID:%d, len:%d\n", + tid, len); + return; + } + + idr_remove(&ctrl->tid_idr, tid); + spin_unlock_irqrestore(&ctrl->txn_lock, flags); + + memcpy(msg->rbuf, reply, len); + if (txn->comp) + complete(txn->comp); +} +EXPORT_SYMBOL_GPL(slim_msg_response); + +/** + * slim_do_transfer() - Process a SLIMbus-messaging transaction + * + * @ctrl: Controller handle + * @txn: Transaction to be sent over SLIMbus + * + * Called by controller to transmit messaging transactions not dealing with + * Interface/Value elements. (e.g. transmittting a message to assign logical + * address to a slave device + * + * Return: -ETIMEDOUT: If transmission of this message timed out + * (e.g. due to bus lines not being clocked or driven by controller) + */ +int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn) +{ + DECLARE_COMPLETION_ONSTACK(done); + bool need_tid; + unsigned long flags; + int ret, tid, timeout; + + need_tid = slim_tid_txn(txn->mt, txn->mc); + + if (need_tid) { + spin_lock_irqsave(&ctrl->txn_lock, flags); + tid = idr_alloc(&ctrl->tid_idr, txn, 0, + SLIM_MAX_TIDS, GFP_KERNEL); + txn->tid = tid; + + if (!txn->msg->comp) + txn->comp = &done; + else + txn->comp = txn->comp; + + spin_unlock_irqrestore(&ctrl->txn_lock, flags); + + if (tid < 0) + return tid; + } + + ret = ctrl->xfer_msg(ctrl, txn); + + if (ret && need_tid && !txn->msg->comp) { + unsigned long ms = txn->rl + HZ; + + timeout = wait_for_completion_timeout(txn->comp, + msecs_to_jiffies(ms)); + if (!timeout) { + ret = -ETIMEDOUT; + spin_lock_irqsave(&ctrl->txn_lock, flags); + idr_remove(&ctrl->tid_idr, tid); + spin_unlock_irqrestore(&ctrl->txn_lock, flags); + } + } + + if (ret) + dev_err(ctrl->dev, "Tx:MT:0x%x, MC:0x%x, LA:0x%x failed:%d\n", + txn->mt, txn->mc, txn->la, ret); + + return ret; +} + +static int slim_val_inf_sanity(struct slim_controller *ctrl, + struct slim_val_inf *msg, u8 mc) +{ + if (!msg || msg->num_bytes > 16 || + (msg->start_offset + msg->num_bytes) > 0xC00) + goto reterr; + switch (mc) { + case SLIM_MSG_MC_REQUEST_VALUE: + case SLIM_MSG_MC_REQUEST_INFORMATION: + if (msg->rbuf != NULL) + return 0; + break; + + case SLIM_MSG_MC_CHANGE_VALUE: + case SLIM_MSG_MC_CLEAR_INFORMATION: + if (msg->wbuf != NULL) + return 0; + break; + + case SLIM_MSG_MC_REQUEST_CHANGE_VALUE: + case SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION: + if (msg->rbuf != NULL && msg->wbuf != NULL) + return 0; + break; + } +reterr: + dev_err(ctrl->dev, "Sanity check failed:msg:offset:0x%x, mc:%d\n", + msg->start_offset, mc); + return -EINVAL; +} + +static u16 slim_slicesize(int code) +{ + static const u8 sizetocode[16] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7 + }; + + clamp(code, 1, (int)ARRAY_SIZE(sizetocode)); + + return sizetocode[code - 1]; +} + +/** + * slim_xfer_msg() - Transfer a value info message on slim device + * + * @sbdev: slim device to which this msg has to be transfered + * @msg: value info message pointer + * @mc: message code of the message + * + * Called by drivers which want to transfer a vlaue or info elements. + * + * Return: -ETIMEDOUT: If transmission of this message timed out + */ +int slim_xfer_msg(struct slim_device *sbdev, struct slim_val_inf *msg, + u8 mc) +{ + DEFINE_SLIM_LDEST_TXN(txn_stack, mc, 6, sbdev->laddr, msg); + struct slim_msg_txn *txn = &txn_stack; + struct slim_controller *ctrl = sbdev->ctrl; + int ret; + u16 sl; + + if (!ctrl) + return -EINVAL; + + ret = slim_val_inf_sanity(ctrl, msg, mc); + if (ret) + return ret; + + sl = slim_slicesize(msg->num_bytes); + + dev_dbg(ctrl->dev, "SB xfer msg:os:%x, len:%d, MC:%x, sl:%x\n", + msg->start_offset, msg->num_bytes, mc, sl); + + txn->ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4)); + + switch (mc) { + case SLIM_MSG_MC_REQUEST_CHANGE_VALUE: + case SLIM_MSG_MC_CHANGE_VALUE: + case SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION: + case SLIM_MSG_MC_CLEAR_INFORMATION: + txn->rl += msg->num_bytes; + default: + break; + } + + if (slim_tid_txn(txn->mt, txn->mc)) + txn->rl++; + + return slim_do_transfer(ctrl, txn); +} + +static void slim_fill_msg(struct slim_val_inf *msg, u32 addr, + size_t count, u8 *rbuf, u8 *wbuf) +{ + msg->start_offset = addr; + msg->num_bytes = count; + msg->rbuf = rbuf; + msg->wbuf = wbuf; +} + +/** + * slim_read() - Read SLIMbus value element + * + * @sdev: client handle. + * @addr: address of value element to read. + * @count: number of bytes to read. Maximum bytes allowed are 16. + * @val: will return what the value element value was + * + * Return: + * - EINVAL: Invalid parameters + * - ETIMEDOUT: If transmission of this message timed out (e.g. due to + * bus lines not being clocked or driven by controller) + */ +int slim_read(struct slim_device *sdev, u32 addr, size_t count, u8 *val) +{ + struct slim_val_inf msg; + + slim_fill_msg(&msg, addr, count, val, NULL); + + return slim_xfer_msg(sdev, &msg, SLIM_MSG_MC_REQUEST_VALUE); +} +EXPORT_SYMBOL_GPL(slim_read); + +/** + * slim_readb() - Read byte from SLIMbus value element + * + * @sdev: client handle. + * @addr: address in the value element to read. + * + * Return: byte value of value element. + */ +int slim_readb(struct slim_device *sdev, u32 addr) +{ + int ret; + u8 buf; + + ret = slim_read(sdev, addr, 1, &buf); + if (ret < 0) + return ret; + else + return buf; +} +EXPORT_SYMBOL_GPL(slim_readb); + +/** + * slim_write() - Write SLIMbus value element + * + * @sdev: client handle. + * @addr: address in the value element to write. + * @count: number of bytes to write. Maximum bytes allowed are 16. + * @val: value to write to value element + * + * Return: + * - EINVAL: Invalid parameters + * - ETIMEDOUT: If transmission of this message timed out (e.g. due to + * bus lines not being clocked or driven by controller) + */ +int slim_write(struct slim_device *sdev, u32 addr, size_t count, u8 *val) +{ + struct slim_val_inf msg; + + slim_fill_msg(&msg, addr, count, val, NULL); + + return slim_xfer_msg(sdev, &msg, SLIM_MSG_MC_CHANGE_VALUE); +} +EXPORT_SYMBOL_GPL(slim_write); + +/** + * slim_writeb() - Write byte to SLIMbus value element + * + * @sdev: client handle. + * @addr: address of value element to write. + * @value: value to write to value element + * + * Return: + * - EINVAL: Invalid parameters + * - ETIMEDOUT: If transmission of this message timed out (e.g. due to + * bus lines not being clocked or driven by controller) + */ +int slim_writeb(struct slim_device *sdev, u32 addr, u8 value) +{ + return slim_write(sdev, addr, 1, &value); +} +EXPORT_SYMBOL_GPL(slim_writeb); diff --git a/drivers/slimbus/slimbus.h b/drivers/slimbus/slimbus.h index 155d7231627d..80c3ec44afbd 100644 --- a/drivers/slimbus/slimbus.h +++ b/drivers/slimbus/slimbus.h @@ -6,8 +6,17 @@ #include #include #include +#include #include +/* SLIMbus message types. Related to interpretation of message code. */ +#define SLIM_MSG_MT_CORE 0x0 + +/* Destination type Values */ +#define SLIM_MSG_DEST_LOGICALADDR 0 +#define SLIM_MSG_DEST_ENUMADDR 1 +#define SLIM_MSG_DEST_BROADCAST 3 + /* Standard values per SLIMbus spec needed by controllers and devices */ #define SLIM_MAX_CLK_GEAR 10 #define SLIM_MIN_CLK_GEAR 1 @@ -15,6 +24,7 @@ /* Manager's logical address is set to 0xFF per spec */ #define SLIM_LA_MANAGER 0xFF +#define SLIM_MAX_TIDS 256 /** * struct slim_framer - Represents SLIMbus framer. * Every controller may have multiple framers. There is 1 active framer device @@ -35,6 +45,39 @@ struct slim_framer { #define to_slim_framer(d) container_of(d, struct slim_framer, dev) +/** + * struct slim_msg_txn - Message to be sent by the controller. + * This structure has packet header, + * payload and buffer to be filled (if any) + * @rl: Header field. remaining length. + * @mt: Header field. Message type. + * @mc: Header field. LSB is message code for type mt. + * @dt: Header field. Destination type. + * @ec: Element code. Used for elemental access APIs. + * @tid: Transaction ID. Used for messages expecting response. + * (relevant for message-codes involving read operation) + * @la: Logical address of the device this message is going to. + * (Not used when destination type is broadcast.) + * @msg: Elemental access message to be read/written + * @comp: completion if read/write is synchronous, used internally + * for tid based transactions. + */ +struct slim_msg_txn { + u8 rl; + u8 mt; + u8 mc; + u8 dt; + u16 ec; + u8 tid; + u8 la; + struct slim_val_inf *msg; + struct completion *comp; +}; + +/* Frequently used message transaction structures */ +#define DEFINE_SLIM_LDEST_TXN(name, mc, rl, la, msg) \ + struct slim_msg_txn name = { rl, 0, mc, SLIM_MSG_DEST_LOGICALADDR, 0,\ + 0, la, msg, } /** * struct slim_controller - Controls every instance of SLIMbus * (similar to 'master' on SPI) @@ -50,6 +93,9 @@ struct slim_framer { * @devices: Slim device list * @tid_idr: tid id allocator * @txn_lock: Lock to protect table of transactions + * @xfer_msg: Transfer a message on this controller (this can be a broadcast + * control/status message like data channel setup, or a unicast message + * like value element read/write. * @set_laddr: Setup logical address at laddr for the slave with elemental * address e_addr. Drivers implementing controller will be expected to * send unicast message to this device with its logical address. @@ -91,6 +137,8 @@ struct slim_controller { struct list_head devices; struct idr tid_idr; spinlock_t txn_lock; + int (*xfer_msg)(struct slim_controller *ctrl, + struct slim_msg_txn *tx); int (*set_laddr)(struct slim_controller *ctrl, struct slim_eaddr *ea, u8 laddr); int (*get_laddr)(struct slim_controller *ctrl, @@ -102,5 +150,24 @@ int slim_device_report_present(struct slim_controller *ctrl, void slim_report_absent(struct slim_device *sbdev); int slim_register_controller(struct slim_controller *ctrl); int slim_unregister_controller(struct slim_controller *ctrl); +void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 l); +int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn); + +static inline bool slim_tid_txn(u8 mt, u8 mc) +{ + return (mt == SLIM_MSG_MT_CORE && + (mc == SLIM_MSG_MC_REQUEST_INFORMATION || + mc == SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION || + mc == SLIM_MSG_MC_REQUEST_VALUE || + mc == SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION)); +} +static inline bool slim_ec_txn(u8 mt, u8 mc) +{ + return (mt == SLIM_MSG_MT_CORE && + ((mc >= SLIM_MSG_MC_REQUEST_INFORMATION && + mc <= SLIM_MSG_MC_REPORT_INFORMATION) || + (mc >= SLIM_MSG_MC_REQUEST_VALUE && + mc <= SLIM_MSG_MC_CHANGE_VALUE))); +} #endif /* _LINUX_SLIMBUS_H */ diff --git a/include/linux/slimbus.h b/include/linux/slimbus.h index b59b272666b6..950145b7c9a8 100644 --- a/include/linux/slimbus.h +++ b/include/linux/slimbus.h @@ -5,6 +5,7 @@ #define _LINUX_SLIMBUS_H #include #include +#include #include extern struct bus_type slimbus_bus; @@ -86,6 +87,25 @@ struct slim_driver { }; #define to_slim_driver(d) container_of(d, struct slim_driver, driver) +/** + * struct slim_val_inf - Slimbus value or information element + * @start_offset: Specifies starting offset in information/value element map + * @rbuf: buffer to read the values + * @wbuf: buffer to write + * @num_bytes: upto 16. This ensures that the message will fit the slicesize + * per SLIMbus spec + * @comp: completion for asynchronous operations, valid only if TID is + * required for transaction, like REQUEST operations. + * Rest of the transactions are synchronous anyway. + */ +struct slim_val_inf { + u16 start_offset; + u8 num_bytes; + u8 *rbuf; + const u8 *wbuf; + struct completion *comp; +}; + /* * use a macro to avoid include chaining to get THIS_MODULE */ @@ -119,4 +139,24 @@ static inline void slim_set_devicedata(struct slim_device *dev, void *data) struct slim_device *slim_get_device(struct slim_controller *ctrl, struct slim_eaddr *e_addr); int slim_get_logical_addr(struct slim_device *sbdev); + +/* Information Element management messages */ +#define SLIM_MSG_MC_REQUEST_INFORMATION 0x20 +#define SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION 0x21 +#define SLIM_MSG_MC_REPLY_INFORMATION 0x24 +#define SLIM_MSG_MC_CLEAR_INFORMATION 0x28 +#define SLIM_MSG_MC_REPORT_INFORMATION 0x29 + +/* Value Element management messages */ +#define SLIM_MSG_MC_REQUEST_VALUE 0x60 +#define SLIM_MSG_MC_REQUEST_CHANGE_VALUE 0x61 +#define SLIM_MSG_MC_REPLY_VALUE 0x64 +#define SLIM_MSG_MC_CHANGE_VALUE 0x68 + +int slim_xfer_msg(struct slim_device *sbdev, struct slim_val_inf *msg, + u8 mc); +int slim_readb(struct slim_device *sdev, u32 addr); +int slim_writeb(struct slim_device *sdev, u32 addr, u8 value); +int slim_read(struct slim_device *sdev, u32 addr, size_t count, u8 *val); +int slim_write(struct slim_device *sdev, u32 addr, size_t count, u8 *val); #endif /* _LINUX_SLIMBUS_H */ From patchwork Thu Dec 7 10:27:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 120958 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp8180794qgn; Thu, 7 Dec 2017 02:33:00 -0800 (PST) X-Google-Smtp-Source: AGs4zMblUADiqjq8xxO5KaUNocZm4SOWeLbdIb+qBJ8Mz6KNEup2VjIl+BLZeZFM3evXsLbZo5na X-Received: by 10.28.65.136 with SMTP id o130mr757228wma.33.1512642780619; Thu, 07 Dec 2017 02:33:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512642780; cv=none; d=google.com; s=arc-20160816; b=ME0WyfVz9jQ2MyT736/Jh4K6XwCYALDlxpyk8dZSvRRlqHQm45bumWKQTwaQd40ATu 4dXQ32Y3whXIxGdIXjz3bpyRMUbK04UrJVqaPbS3ylgWHGHOH1NeZnJ3VYZxIVWaFvXX lP8NBuCh0OnVhAyggBvksSGeN4ewVW/9yS0QPcksMsqxA3b2i8B0WuH/iR4tbysnWiFI Z1UDYxratD3YZpnaPYWF9NQzvaIPohPRfjtUZNuDwYLZecwpsK3fRO3Ln2FUxhTXqb2n XaHx2p5H5LSrX5MUecZ9wF7tYPCYtKDcRdafttpPIdOuIxgkEFWYpEmZW7S5MG4PDC6q kYbA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=++Af2ZQjpLA/HU8W+vA9FigNzEcNcnYVsGmV1nBG+Sc=; b=doH3ZgQbpPLNsaz7EIVhsy6MW8WY5LMwC2J44nFnHjeIinSyLvLO5rfvMEozyLMHmv MfoGFL/1LCvvpjdnkmYlSDgF9GJ7N+pWl9SX0YRKGlf+mw5QQO6IkEdeTG9wrUxL+TBd 8uVeuuWLtvrp1LlVSJvB+SuZdMllEEcgEzTLV8q0lZyxkz+QXmTP76OWfymLi7REH7rT yns4iIkzhhkMAswzRFpEPmSlS33v1sjASbcrkQlS4xr6hLYfogYJcl5ICbygxgrrr2mA 10dQfdo91X4/AqoovvAjnq5n3NIEzpyeHnOefcrIoW8JEB7l27MVWo/Uh/1Y2SU76xeW 9aDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=cMmdHZ+D; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from alsa0.perex.cz (alsa0.perex.cz. [77.48.224.243]) by mx.google.com with ESMTP id h196si3411027wme.60.2017.12.07.02.33.00; Thu, 07 Dec 2017 02:33:00 -0800 (PST) Received-SPF: pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) client-ip=77.48.224.243; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=cMmdHZ+D; spf=pass (google.com: domain of alsa-devel-bounces@alsa-project.org designates 77.48.224.243 as permitted sender) smtp.mailfrom=alsa-devel-bounces@alsa-project.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 82153267AC3; Thu, 7 Dec 2017 11:30:51 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id C67C9267AB1; Thu, 7 Dec 2017 11:30:47 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.perex.cz X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_PASS autolearn=disabled version=3.4.0 Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by alsa0.perex.cz (Postfix) with ESMTP id 929A8267A97 for ; Thu, 7 Dec 2017 11:30:43 +0100 (CET) Received: by mail-wm0-f65.google.com with SMTP id r78so12218073wme.5 for ; Thu, 07 Dec 2017 02:30:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=dhVqexM5bKn2BaKBS03nW9S43Gjgac1QZ6Mt3x25MV0=; b=cMmdHZ+Dv3cPUbAyVFIfsXah0xk875iyBykQRkrdQr1lDTAeZW41BSFKWSMo6k8XvY yNH7GpaT+fiokKwwBFyE7c8Mn+wKX2p8jiS/I58WU1mXrjkBwLP/b/KipY4/GzO7FyMZ 6IRoby+XxN5t7uPXXItuzaVuar2miKGeD5CNI= 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=dhVqexM5bKn2BaKBS03nW9S43Gjgac1QZ6Mt3x25MV0=; b=JSYvGtvBjANmtcpH4hUv9faEa+10PRzrxntka2j5qCpTaI6WmzHcH/vLv3X9HU0Vtl QooM3zHrzqHp7ujiJlPolfE5i54DQdv3W5MIAJRIpSq7PtKiIU36j3dPiX1twwMpCchz nczarqtaHjpHA5RXR1mA50kzkSYs75rGnn3yuPOOjrNNbmmRoXwx5Rv4ZQcNeZGuExbL 70yBT1QnNwVk4IVmEQm8bYQ85f8IPFAJJrUSsrO21SNwD6+Gzc1RJqLUaRc46FrmbF5l OKS2on8AcMwtPCxh3isJjntcuUjgqep4KUD381axz4NlOzSBcB/hoLrtVr+3P6vcRXj0 DgNA== X-Gm-Message-State: AKGB3mK+82RUudRDX6yNOqQiQYrQ/AaY53P0fndicQkQ5DrB7EOurTwj vAvjjLck7sWmNTr9PQIyeALmrgKfCys= X-Received: by 10.28.67.68 with SMTP id q65mr706260wma.26.1512642642900; Thu, 07 Dec 2017 02:30:42 -0800 (PST) Received: from localhost.localdomain (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.gmail.com with ESMTPSA id k2sm4837734wrg.4.2017.12.07.02.30.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Dec 2017 02:30:42 -0800 (PST) From: srinivas.kandagatla@linaro.org To: Mark Brown , Greg Kroah-Hartman , alsa-devel@alsa-project.org Date: Thu, 7 Dec 2017 10:27:14 +0000 Message-Id: <20171207102720.21071-8-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> References: <20171207102720.21071-1-srinivas.kandagatla@linaro.org> Cc: Mark Rutland , devicetree@vger.kernel.org, Jonathan Corbet , linux-arm-msm@vger.kernel.org, linux-doc@vger.kernel.org, j.neuschaefer@gmx.net, linux-kernel@vger.kernel.org, Rob Herring , Srinivas Kandagatla , pombredanne@nexb.com, sdharia@codeaurora.org Subject: [alsa-devel] [PATCH v9 07/13] slimbus: Add support for 'clock-pause' feature X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org From: Sagar Dharia Per SLIMbus specification, a reconfiguration sequence known as 'clock pause' needs to be broadcast over the bus while entering low- power mode. Clock-pause is initiated by the controller driver. To exit clock-pause, controller typically wakes up the framer device. Since wakeup precedure is controller-specific, framework calls it via controller's function pointer to invoke it. Signed-off-by: Sagar Dharia Signed-off-by: Srinivas Kandagatla --- drivers/slimbus/Makefile | 2 +- drivers/slimbus/core.c | 16 ++++++ drivers/slimbus/messaging.c | 35 ++++++++++++- drivers/slimbus/sched.c | 119 ++++++++++++++++++++++++++++++++++++++++++++ drivers/slimbus/slimbus.h | 53 ++++++++++++++++++++ 5 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 drivers/slimbus/sched.c -- 2.15.0 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel diff --git a/drivers/slimbus/Makefile b/drivers/slimbus/Makefile index 568a14c7be78..cd6833ed521a 100644 --- a/drivers/slimbus/Makefile +++ b/drivers/slimbus/Makefile @@ -3,4 +3,4 @@ # Makefile for kernel SLIMbus framework. # obj-$(CONFIG_SLIMBUS) += slimbus.o -slimbus-y := core.o messaging.o +slimbus-y := core.o messaging.o sched.o diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c index cd2a47dec635..8b4b6b9f0dbf 100644 --- a/drivers/slimbus/core.c +++ b/drivers/slimbus/core.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "slimbus.h" @@ -216,6 +217,8 @@ int slim_register_controller(struct slim_controller *ctrl) ida_init(&ctrl->laddr_ida); idr_init(&ctrl->tid_idr); mutex_init(&ctrl->lock); + mutex_init(&ctrl->sched.m_reconf); + init_completion(&ctrl->sched.pause_comp); dev_dbg(ctrl->dev, "Bus [%s] registered:dev:%p\n", ctrl->name, ctrl->dev); @@ -247,6 +250,8 @@ int slim_unregister_controller(struct slim_controller *ctrl) { /* Remove all clients */ device_for_each_child(ctrl->dev, NULL, slim_ctrl_remove_device); + /* Enter Clock Pause */ + slim_ctrl_clk_pause(ctrl, false, 0); ida_simple_remove(&ctrl_ida, ctrl->id); return 0; @@ -414,6 +419,14 @@ int slim_device_report_present(struct slim_controller *ctrl, struct slim_device *sbdev; int ret; + ret = pm_runtime_get_sync(ctrl->dev); + + if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) { + dev_err(ctrl->dev, "slim ctrl not active,state:%d, ret:%d\n", + ctrl->sched.clk_state, ret); + goto slimbus_not_active; + } + sbdev = slim_get_device(ctrl, e_addr); if (IS_ERR(sbdev)) return -ENODEV; @@ -425,6 +438,9 @@ int slim_device_report_present(struct slim_controller *ctrl, ret = slim_device_alloc_laddr(sbdev, true); +slimbus_not_active: + pm_runtime_mark_last_busy(ctrl->dev); + pm_runtime_put_autosuspend(ctrl->dev); return ret; } EXPORT_SYMBOL_GPL(slim_device_report_present); diff --git a/drivers/slimbus/messaging.c b/drivers/slimbus/messaging.c index 42798ff06e85..9f19ee6ed10b 100644 --- a/drivers/slimbus/messaging.c +++ b/drivers/slimbus/messaging.c @@ -2,6 +2,7 @@ // Copyright (c) 2011-2017, The Linux Foundation #include +#include #include "slimbus.h" /** @@ -44,6 +45,10 @@ void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len) memcpy(msg->rbuf, reply, len); if (txn->comp) complete(txn->comp); + + /* Remove runtime-pm vote now that response was received for TID txn */ + pm_runtime_mark_last_busy(ctrl->dev); + pm_runtime_put_autosuspend(ctrl->dev); } EXPORT_SYMBOL_GPL(slim_msg_response); @@ -63,10 +68,29 @@ EXPORT_SYMBOL_GPL(slim_msg_response); int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn) { DECLARE_COMPLETION_ONSTACK(done); - bool need_tid; + bool need_tid = false, clk_pause_msg = false; unsigned long flags; int ret, tid, timeout; + /* + * do not vote for runtime-PM if the transactions are part of clock + * pause sequence + */ + if (ctrl->sched.clk_state == SLIM_CLK_ENTERING_PAUSE && + (txn->mt == SLIM_MSG_MT_CORE && + txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION && + txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) + clk_pause_msg = true; + + if (!clk_pause_msg) { + ret = pm_runtime_get_sync(ctrl->dev); + if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) { + dev_err(ctrl->dev, "ctrl wrong state:%d, ret:%d\n", + ctrl->sched.clk_state, ret); + goto slim_xfer_err; + } + } + need_tid = slim_tid_txn(txn->mt, txn->mc); if (need_tid) { @@ -105,6 +129,15 @@ int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn) dev_err(ctrl->dev, "Tx:MT:0x%x, MC:0x%x, LA:0x%x failed:%d\n", txn->mt, txn->mc, txn->la, ret); +slim_xfer_err: + if (!clk_pause_msg && (!need_tid || ret == -ETIMEDOUT)) { + /* + * remove runtime-pm vote if this was TX only, or + * if there was error during this transaction + */ + pm_runtime_mark_last_busy(ctrl->dev); + pm_runtime_mark_last_busy(ctrl->dev); + } return ret; } diff --git a/drivers/slimbus/sched.c b/drivers/slimbus/sched.c new file mode 100644 index 000000000000..c7dc646af31e --- /dev/null +++ b/drivers/slimbus/sched.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2011-2017, The Linux Foundation + +#include +#include "slimbus.h" + +/** + * slim_ctrl_clk_pause() - Called by slimbus controller to enter/exit + * 'clock pause' + * @ctrl: controller requesting bus to be paused or woken up + * @wakeup: Wakeup this controller from clock pause. + * @restart: Restart time value per spec used for clock pause. This value + * isn't used when controller is to be woken up. + * + * Slimbus specification needs this sequence to turn-off clocks for the bus. + * The sequence involves sending 3 broadcast messages (reconfiguration + * sequence) to inform all devices on the bus. + * To exit clock-pause, controller typically wakes up active framer device. + * This API executes clock pause reconfiguration sequence if wakeup is false. + * If wakeup is true, controller's wakeup is called. + * For entering clock-pause, -EBUSY is returned if a message txn in pending. + */ +int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart) +{ + int i, ret = 0; + unsigned long flags; + struct slim_sched *sched = &ctrl->sched; + struct slim_val_inf msg = {0, 0, NULL, NULL}; + + DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_MC_BEGIN_RECONFIGURATION, + 3, SLIM_LA_MANAGER, &msg); + + if (wakeup == false && restart > SLIM_CLK_UNSPECIFIED) + return -EINVAL; + + mutex_lock(&sched->m_reconf); + if (wakeup) { + if (sched->clk_state == SLIM_CLK_ACTIVE) { + mutex_unlock(&sched->m_reconf); + return 0; + } + + /* + * Fine-tune calculation based on clock gear, + * message-bandwidth after bandwidth management + */ + ret = wait_for_completion_timeout(&sched->pause_comp, + msecs_to_jiffies(100)); + if (!ret) { + mutex_unlock(&sched->m_reconf); + pr_err("Previous clock pause did not finish"); + return -ETIMEDOUT; + } + ret = 0; + + /* + * Slimbus framework will call controller wakeup + * Controller should make sure that it sets active framer + * out of clock pause + */ + if (sched->clk_state == SLIM_CLK_PAUSED && ctrl->wakeup) + ret = ctrl->wakeup(ctrl); + if (!ret) + sched->clk_state = SLIM_CLK_ACTIVE; + mutex_unlock(&sched->m_reconf); + + return ret; + } + + /* already paused */ + if (ctrl->sched.clk_state == SLIM_CLK_PAUSED) { + mutex_unlock(&sched->m_reconf); + return 0; + } + + spin_lock_irqsave(&ctrl->txn_lock, flags); + for (i = 0; i < SLIM_MAX_TIDS; i++) { + /* Pending response for a message */ + if (idr_find(&ctrl->tid_idr, i)) { + spin_unlock_irqrestore(&ctrl->txn_lock, flags); + mutex_unlock(&sched->m_reconf); + return -EBUSY; + } + } + spin_unlock_irqrestore(&ctrl->txn_lock, flags); + + sched->clk_state = SLIM_CLK_ENTERING_PAUSE; + + /* clock pause sequence */ + ret = slim_do_transfer(ctrl, &txn); + if (ret) + goto clk_pause_ret; + + txn.mc = SLIM_MSG_MC_NEXT_PAUSE_CLOCK; + txn.rl = 4; + msg.num_bytes = 1; + msg.wbuf = &restart; + ret = slim_do_transfer(ctrl, &txn); + if (ret) + goto clk_pause_ret; + + txn.mc = SLIM_MSG_MC_RECONFIGURE_NOW; + txn.rl = 3; + msg.num_bytes = 1; + msg.wbuf = NULL; + ret = slim_do_transfer(ctrl, &txn); + +clk_pause_ret: + if (ret) { + sched->clk_state = SLIM_CLK_ACTIVE; + } else { + sched->clk_state = SLIM_CLK_PAUSED; + complete(&sched->pause_comp); + } + mutex_unlock(&sched->m_reconf); + + return ret; +} +EXPORT_SYMBOL_GPL(slim_ctrl_clk_pause); diff --git a/drivers/slimbus/slimbus.h b/drivers/slimbus/slimbus.h index 80c3ec44afbd..e002763e7f6e 100644 --- a/drivers/slimbus/slimbus.h +++ b/drivers/slimbus/slimbus.h @@ -12,6 +12,16 @@ /* SLIMbus message types. Related to interpretation of message code. */ #define SLIM_MSG_MT_CORE 0x0 +/* Clock pause Reconfiguration messages */ +#define SLIM_MSG_MC_BEGIN_RECONFIGURATION 0x40 +#define SLIM_MSG_MC_NEXT_PAUSE_CLOCK 0x4A +#define SLIM_MSG_MC_RECONFIGURE_NOW 0x5F + +/* Clock pause values per SLIMbus spec */ +#define SLIM_CLK_FAST 0 +#define SLIM_CLK_CONST_PHASE 1 +#define SLIM_CLK_UNSPECIFIED 2 + /* Destination type Values */ #define SLIM_MSG_DEST_LOGICALADDR 0 #define SLIM_MSG_DEST_ENUMADDR 1 @@ -78,6 +88,42 @@ struct slim_msg_txn { #define DEFINE_SLIM_LDEST_TXN(name, mc, rl, la, msg) \ struct slim_msg_txn name = { rl, 0, mc, SLIM_MSG_DEST_LOGICALADDR, 0,\ 0, la, msg, } + +#define DEFINE_SLIM_BCAST_TXN(name, mc, rl, la, msg) \ + struct slim_msg_txn name = { rl, 0, mc, SLIM_MSG_DEST_BROADCAST, 0,\ + 0, la, msg, } +/** + * enum slim_clk_state: SLIMbus controller's clock state used internally for + * maintaining current clock state. + * @SLIM_CLK_ACTIVE: SLIMbus clock is active + * @SLIM_CLK_ENTERING_PAUSE: SLIMbus clock pause sequence is being sent on the + * bus. If this succeeds, state changes to SLIM_CLK_PAUSED. If the + * transition fails, state changes back to SLIM_CLK_ACTIVE + * @SLIM_CLK_PAUSED: SLIMbus controller clock has paused. + */ +enum slim_clk_state { + SLIM_CLK_ACTIVE, + SLIM_CLK_ENTERING_PAUSE, + SLIM_CLK_PAUSED, +}; + +/** + * struct slim_sched: Framework uses this structure internally for scheduling. + * @clk_state: Controller's clock state from enum slim_clk_state + * @pause_comp: Signals completion of clock pause sequence. This is useful when + * client tries to call SLIMbus transaction when controller is entering + * clock pause. + * @m_reconf: This mutex is held until current reconfiguration (data channel + * scheduling, message bandwidth reservation) is done. Message APIs can + * use the bus concurrently when this mutex is held since elemental access + * messages can be sent on the bus when reconfiguration is in progress. + */ +struct slim_sched { + enum slim_clk_state clk_state; + struct completion pause_comp; + struct mutex m_reconf; +}; + /** * struct slim_controller - Controls every instance of SLIMbus * (similar to 'master' on SPI) @@ -93,6 +139,7 @@ struct slim_msg_txn { * @devices: Slim device list * @tid_idr: tid id allocator * @txn_lock: Lock to protect table of transactions + * @sched: scheduler structure used by the controller * @xfer_msg: Transfer a message on this controller (this can be a broadcast * control/status message like data channel setup, or a unicast message * like value element read/write. @@ -103,6 +150,9 @@ struct slim_msg_txn { * address table and get_laddr can be used in that case so that controller * can do this assignment. Use case is when the master is on the remote * processor side, who is resposible for allocating laddr. + * @wakeup: This function pointer implements controller-specific procedure + * to wake it up from clock-pause. Framework will call this to bring + * the controller out of clock pause. * * 'Manager device' is responsible for device management, bandwidth * allocation, channel setup, and port associations per channel. @@ -137,12 +187,14 @@ struct slim_controller { struct list_head devices; struct idr tid_idr; spinlock_t txn_lock; + struct slim_sched sched; int (*xfer_msg)(struct slim_controller *ctrl, struct slim_msg_txn *tx); int (*set_laddr)(struct slim_controller *ctrl, struct slim_eaddr *ea, u8 laddr); int (*get_laddr)(struct slim_controller *ctrl, struct slim_eaddr *ea, u8 *laddr); + int (*wakeup)(struct slim_controller *ctrl); }; int slim_device_report_present(struct slim_controller *ctrl, @@ -152,6 +204,7 @@ int slim_register_controller(struct slim_controller *ctrl); int slim_unregister_controller(struct slim_controller *ctrl); void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 l); int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn); +int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart); static inline bool slim_tid_txn(u8 mt, u8 mc) {