lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <558336E1.5070404@linaro.org>
Date:	Thu, 18 Jun 2015 22:23:45 +0100
From:	Srinivas Kandagatla <srinivas.kandagatla@...aro.org>
To:	Sagar Dharia <sdharia@...eaurora.org>, gregkh@...uxfoundation.org,
	broonie@...nel.org, linux-kernel@...r.kernel.org, bp@...e.de,
	poeschel@...onage.de, santosh.shilimkar@...com, treding@...dia.com,
	gong.chen@...ux.intel.com, andreas.noever@...il.com,
	alan@...ux.intel.com, mathieu.poirier@...aro.org, daniel@...ll.ch,
	oded.gabbay@....com, jkosina@...e.cz, sharon.dvir1@...l.huji.ac.il,
	joe@...ches.com, davem@...emloft.net, james.hogan@...tec.com,
	michael.opdenacker@...e-electrons.com, daniel.thompson@...aro.org,
	nkaje@...eaurora.org, mbutler@...ience.com
CC:	kheitke@...ience.com, mlocke@...eaurora.org, agross@...eaurora.org,
	linux-arm-msm@...r.kernel.org
Subject: Re: [PATCH 1/3] SLIMbus: Device management on SLIMbus

Hi Sagar,

On 14/06/15 06:49, Sagar Dharia wrote:
> 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 does device enumeration, logical address assignment,
> informing device when the device reports present/absent etc.
> Reporting present may need the driver to do the needful (e.g. turning
> on voltage regulators powering the device). So probe is called
> if the device is added to board-info list for a controller.
> Additionally device is probed when it reports present if that device
> doesn't need any such steps mentioned above.
>
> Signed-off-by: Sagar Dharia <sdharia@...eaurora.org>
> ---
>   drivers/Kconfig                 |   2 +
>   drivers/Makefile                |   1 +
>   drivers/slimbus/Kconfig         |   9 +
>   drivers/slimbus/Makefile        |   4 +
>   drivers/slimbus/slimbus.c       | 767 ++++++++++++++++++++++++++++++++++++++++
>   include/linux/mod_devicetable.h |  13 +
>   include/linux/slimbus.h         | 393 ++++++++++++++++++++
>   7 files changed, 1189 insertions(+)
>   create mode 100644 drivers/slimbus/Kconfig
>   create mode 100644 drivers/slimbus/Makefile
>   create mode 100644 drivers/slimbus/slimbus.c
>   create mode 100644 include/linux/slimbus.h
>

Good to see the slimbus patches :-)

Can you also add patch to add MAINTAINERS to this?

I like to try these patches on APQ8064 or any upstream Qcom platform, Do 
you have other patches to test this on APQ8064 or any A family SOCs/ B 
family SOCs which have upstream support?

Also I keep getting lost as I start looking at code, Am missing 
understanding of how these exported functions are going to be used by 
consumers/clients/controllers?
It would help if
1> document which explains how these apis are supposed to be used.
2> split up this patch into small patches, so that you can get good 
review comments.

Pl ignore if i have repeated the same comments someone else commented on.

> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index c0cc96b..e39c969 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -182,4 +182,6 @@ source "drivers/thunderbolt/Kconfig"
>
>   source "drivers/android/Kconfig"
>
> +source "drivers/slimbus/Kconfig"
> +
>   endmenu
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 46d2554..37c1c88 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -74,6 +74,7 @@ obj-$(CONFIG_TARGET_CORE)	+= target/
>   obj-$(CONFIG_MTD)		+= mtd/
>   obj-$(CONFIG_SPI)		+= spi/
>   obj-$(CONFIG_SPMI)		+= spmi/
> +obj-$(CONFIG_SLIMBUS)		+= slimbus/
>   obj-y				+= hsi/
>   obj-y				+= net/
>   obj-$(CONFIG_ATM)		+= atm/
> diff --git a/drivers/slimbus/Kconfig b/drivers/slimbus/Kconfig
> new file mode 100644
> index 0000000..fb30497
> --- /dev/null
> +++ b/drivers/slimbus/Kconfig
> @@ -0,0 +1,9 @@
> +#
> +# SLIMBUS driver configuration
> +#
> +menuconfig SLIMBUS
> +	tristate "Slimbus support"
> +	help
> +	  Slimbus is standard interface between baseband and audio codec,
> +	  and other peripheral components in mobile terminals.
> +
For consistency reasons could you fix on single style of SLIMbus vs 
Slimbus string in comments or description.

> diff --git a/drivers/slimbus/Makefile b/drivers/slimbus/Makefile
> new file mode 100644
> index 0000000..05f53bc
> --- /dev/null
> +++ b/drivers/slimbus/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# Makefile for kernel slimbus framework.
> +#
> +obj-$(CONFIG_SLIMBUS)			+= slimbus.o
> diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
> new file mode 100644
> index 0000000..be4f2c7
> --- /dev/null
> +++ b/drivers/slimbus/slimbus.c
> @@ -0,0 +1,767 @@
> +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/slab.h>
> +#include <linux/init.h>
> +#include <linux/gcd.h>
Do you need this?
> +#include <linux/completion.h>
> +#include <linux/idr.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slimbus.h>
> +
> +static DEFINE_MUTEX(slim_lock);
> +static DEFINE_IDR(ctrl_idr);
> +static struct device_type slim_dev_type;
> +static struct device_type slim_ctrl_type;
> +
> +static int slim_compare_eaddr(struct slim_eaddr *a, struct slim_eaddr *b)
> +{
> +	if (a->manf_id == b->manf_id && a->prod_code == b->prod_code &&
> +			a->dev_index == b->dev_index &&
> +			a->instance == b->instance)
> +		return 0;
> +	return -EIO;
A new line before return would make the code more readable, pl fix it in 
other instances too.

> +}
> +
> +static const struct slim_device_id *slim_match(const struct slim_device_id *id,
> +					const struct slim_device *slim_dev)
> +{
> +	while (id->manf_id != 0 || id->prod_code != 0) {
> +		if (id->manf_id == slim_dev->e_addr.manf_id &&
> +				id->prod_code == slim_dev->e_addr.prod_code &&
> +				id->dev_index == slim_dev->e_addr.dev_index)
> +			return id;
> +		id++;
> +	}
> +	return NULL;
> +}
> +
> +static int slim_device_match(struct device *dev, struct device_driver *driver)
> +{
> +	struct slim_device *slim_dev;
> +	struct slim_driver *drv = to_slim_driver(driver);
> +
> +	if (dev->type == &slim_dev_type)
> +		slim_dev = to_slim_device(dev);
> +	else
> +		return 0;
> +	if (drv->id_table)
Please use new lines where it makes things clear, not having new lines 
in instances like this makes the code look odd.

> +		return slim_match(drv->id_table, slim_dev) != NULL;
> +	return 0;
> +}
> +
...
> +
> +static void slim_device_shutdown(struct device *dev)
> +{
> +	struct slim_device *slim_dev;
> +	struct slim_driver *driver;
> +
> +	if (dev->type == &slim_dev_type)
> +		slim_dev = to_slim_device(dev);
> +	else
> +		return;
> +
> +	if (!dev->driver)
> +		return;
> +	driver = to_slim_driver(dev->driver);
> +	if (driver->shutdown)
> +		driver->shutdown(slim_dev);
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +
> +static int slim_pm_suspend(struct device *dev)
> +{
> +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
> +
Not sure why you need to do this, this is already in 
pm_generic_suspend/resume
> +	if (pm)
> +		return pm_generic_suspend(dev);
> +	else
> +		return 0;
You could just use return pm_generic_suspend(dev);
Or use directly.

	SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)

> +}
> +
> +static int slim_pm_resume(struct device *dev)
> +{
> +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
> +
> +	if (pm)
> +		return pm_generic_resume(dev);
> +	else
> +		return 0;
> +}
> +
> +#else
> +#define slim_pm_suspend		NULL
> +#define slim_pm_resume		NULL
> +#endif
> +
> +static const struct dev_pm_ops slimbus_pm = {
> +	.suspend = slim_pm_suspend,
> +	.resume = slim_pm_resume,
> +	SET_RUNTIME_PM_OPS(
> +		pm_generic_suspend,
> +		pm_generic_resume,
> +		NULL
> +		)
> +};
> +struct bus_type slimbus_type = {
> +	.name		= "slimbus",
> +	.match		= slim_device_match,
> +	.probe		= slim_device_probe,
> +	.remove		= slim_device_remove,
> +	.shutdown	= slim_device_shutdown,
> +	.pm		= &slimbus_pm,
> +};
> +EXPORT_SYMBOL(slimbus_type);
> +
This module is GPL v2. why the symbols are not marked as GPL?
> +static void __exit slimbus_exit(void)
> +{
> +	bus_unregister(&slimbus_type);
> +}
> +
> +static int __init slimbus_init(void)
> +{
> +	return bus_register(&slimbus_type);
> +}
> +postcore_initcall(slimbus_init);
> +module_exit(slimbus_exit);
> +

Looks like this file is appended with multiple files..
Ideally init calls stay at the end of the file..

> +/*
> + * slim_driver_register: Client driver registration with slimbus
> + * @drv:Client driver to be associated with client-device.
> + * 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)
> +{
> +	drv->driver.bus = &slimbus_type;
> +
> +	return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL(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)
> +{
> +	if (drv)
> +		driver_unregister(&drv->driver);
> +}
> +
> +#define slim_ctrl_attr_gr NULL
Would prefer to see all the defines on top of the file.
> +
> +static void slim_ctrl_release(struct device *dev)
> +{
> +	struct slim_controller *ctrl = to_slim_controller(dev);
> +
> +	complete(&ctrl->dev_released);
> +}
> +
> +static struct device_type slim_ctrl_type = {
> +	.groups		= slim_ctrl_attr_gr,
> +	.release	= slim_ctrl_release,
> +};
> +
> +static struct slim_controller *slim_ctrl_get(struct slim_controller *ctrl)
> +{
> +	if (!ctrl || !get_device(&ctrl->dev))
> +		return NULL;
> +
> +	return ctrl;
> +}
> +
> +static void slim_ctrl_put(struct slim_controller *ctrl)
> +{
> +	if (ctrl)
> +		put_device(&ctrl->dev);
> +}
> +
> +#define slim_device_attr_gr NULL
> +#define slim_device_uevent NULL
Defines go on top.

I get a feeling that this file should be split into more files, so its 
easy to navigate.

> +static void slim_dev_release(struct device *dev)
> +{
> +	struct slim_device *sbdev = to_slim_device(dev);
> +
> +	slim_ctrl_put(sbdev->ctrl);
> +}
> +
> +static struct device_type slim_dev_type = {
> +	.groups		= slim_device_attr_gr,
> +	.uevent		= slim_device_uevent,
> +	.release	= slim_dev_release,
> +};
> +
> +static void slim_report(struct work_struct *work)
> +{
> +	struct slim_driver *sbdrv;
> +	struct slim_device *sbdev =
> +			container_of(work, struct slim_device, wd);
> +	if (!sbdev->dev.driver)
> +		return;
> +	/* check if device-up or down needs to be called */
> +	if ((!sbdev->reported && !sbdev->notified) ||
> +			(sbdev->reported && sbdev->notified))
> +		return;
> +
> +	sbdrv = to_slim_driver(sbdev->dev.driver);
> +	/*
> +	 * address no longer valid, means device reported absent, whereas
> +	 * address valid, means device reported present
> +	 */
> +	if (sbdev->notified && !sbdev->reported) {
> +		sbdev->notified = false;
> +		if (sbdrv->device_down)
> +			sbdrv->device_down(sbdev);
> +	} else if (!sbdev->notified && sbdev->reported) {
> +		sbdev->notified = true;
> +		if (sbdrv->device_up)
> +			sbdrv->device_up(sbdev);
> +	}
> +}
> +
> +/*
> + * slim_add_device: Add a new device without register board info.
> + * @ctrl: Controller to which this device is to be added to.
> + * Called when device doesn't have an explicit client-driver to be probed, or
> + * the client-driver is a module installed dynamically.
> + */
> +int slim_add_device(struct slim_controller *ctrl, struct slim_device *sbdev)
> +{
> +	sbdev->dev.bus = &slimbus_type;
> +	sbdev->dev.parent = ctrl->dev.parent;
> +	sbdev->dev.type = &slim_dev_type;
> +	sbdev->dev.driver = NULL;
> +	sbdev->ctrl = ctrl;
> +	slim_ctrl_get(ctrl);
> +	if (!sbdev->name) {
> +		sbdev->name = kcalloc(SLIMBUS_NAME_SIZE, sizeof(char),
> +					GFP_KERNEL);
> +		if (!sbdev->name)
> +			return -ENOMEM;
> +		snprintf(sbdev->name, SLIMBUS_NAME_SIZE, "0x%x:0x%x:0x%x:0x%x",
> +				sbdev->e_addr.manf_id, sbdev->e_addr.prod_code,
> +				sbdev->e_addr.dev_index,
> +				sbdev->e_addr.instance);
> +	}

kasprintf ?

> +	dev_dbg(&ctrl->dev, "adding device:%s", sbdev->name);
> +	dev_set_name(&sbdev->dev, "%s", sbdev->name);
> +	INIT_WORK(&sbdev->wd, slim_report);
> +	mutex_lock(&ctrl->m_ctrl);
> +	list_add_tail(&sbdev->dev_list, &ctrl->devs);
> +	mutex_unlock(&ctrl->m_ctrl);
> +	/* probe slave on this controller */
> +	return device_register(&sbdev->dev);
> +}
> +EXPORT_SYMBOL(slim_add_device);
> +
> +struct sbi_boardinfo {
> +	struct list_head	list;
> +	struct slim_boardinfo	board_info;
> +};
> +
> +static LIST_HEAD(board_list);
> +static LIST_HEAD(slim_ctrl_list);
> +static DEFINE_MUTEX(board_lock);
> +
> +/* If controller is not present, only add to boards list */
> +static void slim_match_ctrl_to_boardinfo(struct slim_controller *ctrl,
> +				struct slim_boardinfo *bi)
> +{
> +	int ret;
> +
> +	if (ctrl->nr != bi->bus_num)
> +		return;
> +
> +	ret = slim_add_device(ctrl, bi->slim_slave);
> +	if (ret != 0)
> +		dev_err(ctrl->dev.parent, "can't create new device %s, ret:%d",
> +			bi->slim_slave->name, ret);
> +}
> +
> +
> +/* slim_remove_device: Remove the effect of slim_add_device() */
> +void slim_remove_device(struct slim_device *sbdev)
> +{
> +	struct slim_controller *ctrl = sbdev->ctrl;
> +
> +	mutex_lock(&ctrl->m_ctrl);
> +	list_del_init(&sbdev->dev_list);
> +	mutex_unlock(&ctrl->m_ctrl);
> +	device_unregister(&sbdev->dev);
> +}
> +EXPORT_SYMBOL(slim_remove_device);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION("0.1");
> +MODULE_DESCRIPTION("Slimbus module");
> +MODULE_ALIAS("platform:slimbus");

> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 3bfd567..94abc09 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -427,6 +427,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;
> +	__u8 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 0000000..05b7594
> --- /dev/null
> +++ b/include/linux/slimbus.h
> @@ -0,0 +1,393 @@
> +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _LINUX_SLIMBUS_H
> +#define _LINUX_SLIMBUS_H
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/mutex.h>
> +#include <linux/mod_devicetable.h>
> +
> +/*
> + * Interfaces between SLIMbus manager drivers, SLIMbus client drivers, and
> + * SLIMbus infrastructure.
> + */
> +
> +extern struct bus_type slimbus_type;
> +
> +/* Standard values per SLIMbus spec needed by controllers and devices */
> +#define SLIM_CL_PER_SUPERFRAME		6144
> +#define SLIM_CL_PER_SUPERFRAME_DIV8	(SLIM_CL_PER_SUPERFRAME >> 3)
> +#define SLIM_MAX_CLK_GEAR		10
> +#define SLIM_MIN_CLK_GEAR		1
> +#define SLIM_CL_PER_SL			4
> +#define SLIM_SL_PER_SUPERFRAME		(SLIM_CL_PER_SUPERFRAME >> 2)
> +#define SLIM_FRM_SLOTS_PER_SUPERFRAME	16
> +#define SLIM_GDE_SLOTS_PER_SUPERFRAME	2
> +
> +struct slim_controller;
> +struct slim_device;
> +
> +/*
> + * 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;
> +};
> +
> +/*
> + * 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.
> + * @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 slim_eaddr	e_addr;
> +	int			rootfreq;
> +	int			superfreq;
> +};
> +#define to_slim_framer(d) container_of(d, struct slim_framer, dev)
?? there is no dev in slim_framer ?
> +
> +/*
> + * struct slim_addrt: slimbus address used internally by the slimbus framework.
> + * @valid: If the device is present. Valid is set to false when device reports
> + *	absent.
> + * @eaddr: Enumeration address
> + * @laddr: It is possible that controller will set a predefined logical address
> + *	rather than the one assigned by framework. (i.e. logical address may
> + *	not be same as index into this table). This entry will store the
> + *	logical address value for this enumeration address.
> + */
> +struct slim_addrt {
> +	bool			valid;
> +	struct slim_eaddr	eaddr;
> +	u8			laddr;
> +};
> +
> +/* SLIMbus message types. Related to interpretation of message code. */
> +#define SLIM_MSG_MT_CORE			0x0
> +#define SLIM_MSG_MT_DEST_REFERRED_CLASS		0x1
> +#define SLIM_MSG_MT_DEST_REFERRED_USER		0x2
> +#define SLIM_MSG_MT_SRC_REFERRED_CLASS		0x5
> +#define SLIM_MSG_MT_SRC_REFERRED_USER		0x6
> +
> +/* SLIMbus core type Message Codes. */
> +/* Device management messages used by this framework */
> +#define SLIM_MSG_MC_REPORT_PRESENT               0x1
> +#define SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS       0x2
> +#define SLIM_MSG_MC_REPORT_ABSENT                0xF
> +
> +/* Destination type Values */
> +#define SLIM_MSG_DEST_LOGICALADDR	0
> +#define SLIM_MSG_DEST_ENUMADDR		1
> +#define	SLIM_MSG_DEST_BROADCAST		3
> +
> +/*
> + * struct slim_controller: Controls every instance of SLIMbus
> + *				(similar to 'master' on SPI)
> + *	'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) if 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.
> + * @dev: Device interface to this driver
> + * @nr: Board-specific number identifier for this controller/bus
> + * @list: Link with other slimbus controllers
> + * @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
> + * @a_framer: Active framer which is clocking the bus managed by this controller
> + * @m_ctrl: Mutex protecting controller data structures
> + * @addrt: Logical address table
> + * @num_dev: Number of active slimbus slaves on this bus
> + * @devs: List of devices on this controller
> + * @wq: Workqueue per controller used to notify devices when they report present
> + * @dev_released: completion used to signal when sysfs has released this
> + *	controller so that it can be deleted during shutdown
> + * @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.
> + * @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.
> + */
> +struct slim_controller {
> +	struct device		dev;
> +	unsigned int		nr;
> +	struct list_head	list;
> +	char			name[SLIMBUS_NAME_SIZE];
> +	int			min_cg;
> +	int			max_cg;
> +	int			clkgear;
> +	struct slim_framer	*a_framer;
> +	struct mutex		m_ctrl;
> +	struct slim_addrt	*addrt;
> +	u8			num_dev;
> +	struct list_head	devs;
> +	struct workqueue_struct *wq;
> +	struct completion	dev_released;
> +	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);
> +};
> +#define to_slim_controller(d) container_of(d, struct slim_controller, 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.
> + * @suspend: Standard suspend callback used during system suspend
> + * @resume: Standard resume callback used during system resume
> + * @device_up: This callback is called when the device reports present and
> + *		gets a logical address assigned to it
> + * @device_down: This callback is called when device reports absent, or the
> + *		bus goes down. Device will report present when bus is up and
> + *		device_up callback will be called again when that happens
> + * @reset_device: This callback is called after framer is booted.
> + *		Driver should do the needful to reset the device,
> + *		so that device acquires sync and be operational.
> + * @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);
> +	int				(*remove)(struct slim_device *sl);
> +	void				(*shutdown)(struct slim_device *sl);
> +	int				(*suspend)(struct slim_device *sl,
> +					pm_message_t pmesg);
> +	int				(*resume)(struct slim_device *sl);
> +	int				(*device_up)(struct slim_device *sl);
> +	int				(*device_down)(struct slim_device *sl);
> +	int				(*reset_device)(struct slim_device *sl);
> +
> +	struct device_driver		driver;
> +	const struct slim_device_id	*id_table;
> +};
> +#define to_slim_driver(d) container_of(d, struct slim_driver, driver)
> +
> +/*
> + * Client/device handle (struct slim_device):
> + * ------------------------------------------
> + *  This is the client/device handle returned when a slimbus
> + *  device is registered with a controller. This structure can be provided
> + *  during register_board_info, or can be allocated using slim_add_device API.
> + *  Pointer to this structure is used by client-driver as a handle.
> + *  @dev: Driver model representation of the device.
> + *  @name: Name of driver to use with this device.
> + *  @e_addr: Enumeration address of this device.
> + *  @driver: Device's driver. Pointer to access routines.
> + *  @ctrl: Slimbus controller managing the bus hosting this device.
> + *  @laddr: 1-byte Logical address of this device.
> + *  @reported: Flag to indicate whether this device reported present. The flag
> + *	is set when device reports present, and is reset when it reports
> + *	absent. This flag alongwith notified flag below is used to call
> + *	device_up, or device_down callbacks for driver of this device.
> + *  @notified: Flag to indicate whether this device has been notified. The
> + *	device may report present multiple times, but should be notified only
> + *	first time it has reported present.
> + *  @dev_list: List of devices on a controller
> + *  @wd: Work structure associated with workqueue for presence notification
> + */
> +struct slim_device {
> +	struct device		dev;
> +	char		*name;
> +	struct slim_eaddr	e_addr;
> +	struct slim_driver	*driver;
> +	struct slim_controller	*ctrl;
> +	u8			laddr;
> +	bool			reported;
> +	bool			notified;
> +	struct list_head	dev_list;
> +	struct work_struct	wd;
> +};
> +#define to_slim_device(d) container_of(d, struct slim_device, dev)
> +
> +/*
> + * struct slim_boardinfo: Declare board info for Slimbus device bringup.
> + * @bus_num: Controller number (bus) on which this device will sit.
> + * @slim_slave: Device to be registered with slimbus.
> + */
> +struct slim_boardinfo {
> +	int			bus_num;
> +	struct slim_device	*slim_slave;
> +};
> +
> +/* Manager's logical address is set to 0xFF per spec */
> +#define SLIM_LA_MANAGER 0xFF
> +/*
> + * slim_get_logical_addr: Return the logical address of a slimbus device.
> + * @sb: client handle requesting the adddress.
> + * @e_addr: Enumeration address of the device.
> + * @laddr: output buffer to store the address
> + * context: can sleep
> + * -EINVAL is returned in case of invalid parameters, and -ENXIO is returned if
> + *  the device with this elemental address is not found.
> + */

documentation should go to c-file..
> +
> +extern int slim_get_logical_addr(struct slim_device *sb,
> +				struct slim_eaddr *e_addr, u8 *laddr);
> +
> +/*
> + * slim_driver_register: Client driver registration with slimbus
> + * @drv:Client driver to be associated with client-device.
> + * This API will register the client driver with the slimbus
> + * It is called from the driver's module-init function.
> + */
> +extern int slim_driver_register(struct slim_driver *drv);
> +
> +/*
> + * slim_driver_unregister: Undo effects of slim_driver_register
> + * @drv: Client driver to be unregistered
> + */
> +extern void slim_driver_unregister(struct slim_driver *drv);
> +
> +/*
> + * slim_add_numbered_controller: Controller bring-up.
> + * @ctrl: Controller to be registered.
> + * A controller is registered with the framework using this API. ctrl->nr is the
> + * desired number with which slimbus framework registers the controller.
> + * Function will return -EBUSY if the number is in use.
> + */
> +extern int slim_add_numbered_controller(struct slim_controller *ctrl);
> +
> +/*
> + * slim_del_controller: Controller tear-down.
> + * Controller added with the above API is teared down using this API.
> + */
> +extern int slim_del_controller(struct slim_controller *ctrl);
> +
> +/*
> + * slim_add_device: Add a new device without register board info.
> + * @ctrl: Controller to which this device is to be added to.
> + * Called when device doesn't have an explicit client-driver to be probed, or
> + * the client-driver is a module installed dynamically.
> + */
> +extern int slim_add_device(struct slim_controller *ctrl,
> +			struct slim_device *sbdev);
> +
> +/* slim_remove_device: Remove the effect of slim_add_device() */
> +extern void slim_remove_device(struct slim_device *sbdev);
> +
> +/*
> + * slim_assign_laddr: Assign logical address to a device enumerated.
> + * @ctrl: Controller with which device is enumerated.
> + * @e_addr: Enumeration address of the device.
> + * @laddr: Return logical address (if valid flag is false)
> + * @valid: true if laddr holds a valid address that controller wants to
> + *	set for this enumeration address. Otherwise framework sets index into
> + *	address table as logical address.
> + * 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.
> + */
> +extern int slim_assign_laddr(struct slim_controller *ctrl,
> +			struct slim_eaddr *e_addr, u8 *laddr, bool valid);
> +
> +/*
> + * 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 that sent report absent
> + */
> +void slim_report_absent(struct slim_device *sbdev);
> +
> +/*
> + * slim_framer_booted: This function is called by controller after the active
> + * framer has booted (using Bus Reset sequence, or after it has shutdown and has
> + * come back up). Components, devices on the bus may be in undefined state,
> + * and this function triggers their drivers to do the needful
> + * to bring them back in Reset state so that they can acquire sync, report
> + * present and be operational again.
> + */
> +void slim_framer_booted(struct slim_controller *ctrl);
> +
> +/*
> + * slim_ctrl_add_boarddevs: Add devices registered by board-info
> + * @ctrl: Controller to which these devices are to be added to.
> + * This API is called by controller when it is up and running.
> + * If devices on a controller were registered before controller,
> + * this will make sure that they get probed when controller is up
> + */
> +extern void slim_ctrl_add_boarddevs(struct slim_controller *ctrl);
> +
> +/*
> + * slim_register_board_info: Board-initialization routine.
> + * @info: List of all devices on all controllers present on the board.
> + * @n: number of entries.
> + * API enumerates respective devices on corresponding controller.
> + * Called from board-init function.
> + */
> +#ifdef CONFIG_SLIMBUS
> +extern int slim_register_board_info(struct slim_boardinfo const *info,
> +					unsigned n);
> +#else
> +static inline int slim_register_board_info(struct slim_boardinfo const *info,
> +					unsigned n)
> +{
> +	return 0;
Should'nt it return error code?

Also don't you want to add dummy functions for other functions?
--srini
> +}
> +#endif
> +
> +static inline void *slim_get_ctrldata(const struct slim_controller *dev)
> +{
> +	return dev_get_drvdata(&dev->dev);
> +}
> +
> +static inline void slim_set_ctrldata(struct slim_controller *dev, void *data)
> +{
> +	dev_set_drvdata(&dev->dev, data);
> +}
> +
> +static inline void *slim_get_devicedata(const struct slim_device *dev)
> +{
> +	return dev_get_drvdata(&dev->dev);
> +}
> +
> +static inline void slim_set_clientdata(struct slim_device *dev, void *data)
> +{
> +	dev_set_drvdata(&dev->dev, data);
> +}
> +
> +#endif /* _LINUX_SLIMBUS_H */
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ