summaryrefslogtreecommitdiffstats
path: root/thread-pool.c
Commit message (Expand)AuthorAgeFilesLines
* all: Clean up includesPeter Maydell2016-02-041-1/+1
* coroutine: move into libqemuutil.a libraryDaniel P. Berrange2015-10-201-1/+1
* thread-pool: clean up thread_pool_completion_bh()Stefan Hajnoczi2015-04-281-8/+6Star
* block: Rename BlockDriverCompletionFunc to BlockCompletionFuncMarkus Armbruster2014-10-201-1/+1
* block: Rename BlockDriverAIOCB* to BlockAIOCB*Markus Armbruster2014-10-201-4/+4
* block: Rename qemu_aio_release -> qemu_aio_unrefFam Zheng2014-09-221-2/+2
* thread-pool: Convert thread_pool_aiocb_info.cancel to cancel_asyncFam Zheng2014-09-221-18/+14Star
* thread-pool: Drop unnecessary includesMarkus Armbruster2014-09-101-1/+0Star
* thread-pool: avoid deadlock in nested aio_poll() callsStefan Hajnoczi2014-08-151-0/+6
* thread-pool: avoid per-thread-pool EventNotifierStefan Hajnoczi2014-08-151-13/+8Star
* aio: Fix use-after-free in cancellation pathFam Zheng2014-05-281-0/+1
* Add a 'name' parameter to qemu_thread_createDr. David Alan Gilbert2014-03-091-1/+1
* aio / timers: Untangle include filesAlex Bligh2013-08-221-0/+1
* aio: drop io_flush argumentStefan Hajnoczi2013-08-191-3/+2Star
* thread-pool: drop thread_pool_active()Stefan Hajnoczi2013-08-191-7/+1Star
* threadpool: drop global thread poolStefan Hajnoczi2013-03-151-16/+7Star
* threadpool: add thread_pool_new() and thread_pool_free()Stefan Hajnoczi2013-03-151-4/+48
* threadpool: move globals into struct ThreadPoolStefan Hajnoczi2013-03-151-80/+110
* misc: move include files to include/qemu/Paolo Bonzini2012-12-191-4/+4
* block: move include files to include/block/Paolo Bonzini2012-12-191-3/+3
* aio: rename AIOPool to AIOCBInfoStefan Hajnoczi2012-11-141-2/+2
* threadpool: do not take lock in event_notifier_readyPaolo Bonzini2012-10-311-6/+13
* aio: add generic thread-pool facilityPaolo Bonzini2012-10-311-0/+282
26'>126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157



























                                                                            


                                      






































                                                                             
                                          



















                                                                    
                             
                               































































                                                                       
/*
 * tps6507x.c  --  TPS6507x chip family multi-function driver
 *
 *  Copyright (c) 2010 RidgeRun (todd.fischer@ridgerun.com)
 *
 * Author: Todd Fischer
 *         todd.fischer@ridgerun.com
 *
 * Credits:
 *
 *    Using code from wm831x-*.c, wm8400-core, Wolfson Microelectronics PLC.
 *
 * For licencing details see kernel-base/COPYING
 *
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6507x.h>

static struct mfd_cell tps6507x_devs[] = {
	{
		.name = "tps6507x-pmic",
	},
	{
		.name = "tps6507x-ts",
	},
};


static int tps6507x_i2c_read_device(struct tps6507x_dev *tps6507x, char reg,
				  int bytes, void *dest)
{
	struct i2c_client *i2c = tps6507x->i2c_client;
	struct i2c_msg xfer[2];
	int ret;

	/* Write register */
	xfer[0].addr = i2c->addr;
	xfer[0].flags = 0;
	xfer[0].len = 1;
	xfer[0].buf = &reg;

	/* Read data */
	xfer[1].addr = i2c->addr;
	xfer[1].flags = I2C_M_RD;
	xfer[1].len = bytes;
	xfer[1].buf = dest;

	ret = i2c_transfer(i2c->adapter, xfer, 2);
	if (ret == 2)
		ret = 0;
	else if (ret >= 0)
		ret = -EIO;

	return ret;
}

static int tps6507x_i2c_write_device(struct tps6507x_dev *tps6507x, char reg,
				   int bytes, void *src)
{
	struct i2c_client *i2c = tps6507x->i2c_client;
	/* we add 1 byte for device register */
	u8 msg[TPS6507X_MAX_REGISTER + 1];
	int ret;

	if (bytes > TPS6507X_MAX_REGISTER)
		return -EINVAL;

	msg[0] = reg;
	memcpy(&msg[1], src, bytes);

	ret = i2c_master_send(i2c, msg, bytes + 1);
	if (ret < 0)
		return ret;
	if (ret != bytes + 1)
		return -EIO;
	return 0;
}

static int tps6507x_i2c_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	struct tps6507x_dev *tps6507x;
	int ret = 0;

	tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL);
	if (tps6507x == NULL)
		return -ENOMEM;

	i2c_set_clientdata(i2c, tps6507x);
	tps6507x->dev = &i2c->dev;
	tps6507x->i2c_client = i2c;
	tps6507x->read_dev = tps6507x_i2c_read_device;
	tps6507x->write_dev = tps6507x_i2c_write_device;

	ret = mfd_add_devices(tps6507x->dev, -1,
			      tps6507x_devs, ARRAY_SIZE(tps6507x_devs),
			      NULL, 0);

	if (ret < 0)
		goto err;

	return ret;

err:
	mfd_remove_devices(tps6507x->dev);
	kfree(tps6507x);
	return ret;
}

static int tps6507x_i2c_remove(struct i2c_client *i2c)
{
	struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c);

	mfd_remove_devices(tps6507x->dev);
	kfree(tps6507x);

	return 0;
}

static const struct i2c_device_id tps6507x_i2c_id[] = {
       { "tps6507x", 0 },
       { }
};
MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id);


static struct i2c_driver tps6507x_i2c_driver = {
	.driver = {
		   .name = "tps6507x",
		   .owner = THIS_MODULE,
	},
	.probe = tps6507x_i2c_probe,
	.remove = tps6507x_i2c_remove,
	.id_table = tps6507x_i2c_id,
};

static int __init tps6507x_i2c_init(void)
{
	return i2c_add_driver(&tps6507x_i2c_driver);
}
/* init early so consumer devices can complete system boot */
subsys_initcall(tps6507x_i2c_init);

static void __exit tps6507x_i2c_exit(void)
{
	i2c_del_driver(&tps6507x_i2c_driver);
}
module_exit(tps6507x_i2c_exit);

MODULE_DESCRIPTION("TPS6507x chip family multi-function driver");
MODULE_LICENSE("GPL");