mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	Merge branch 'char-misc-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
* 'char-misc-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: isl29020: Remove a redundant semi-colon from return statement BMP085: Remove redundant semi-colon from return statement drivers:misc: ti-st: DEBUG uart, baud rate mods drivers:misc: ti-st: flush UART upon fw failure drivers:misc: ti-st: protect registrations char_dev.c: fix up some whitespace errors s390: tape_class.h: remove kobj_map.h inclusion misc: ad525x_dpot: Add support for SPI module device table matching
This commit is contained in:
		
						commit
						21a2cb565a
					
				
					 10 changed files with 126 additions and 126 deletions
				
			
		|  | @ -1,7 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Driver for the Analog Devices digital potentiometers (I2C bus) |  * Driver for the Analog Devices digital potentiometers (I2C bus) | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc. |  * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc. | ||||||
|  * |  * | ||||||
|  * Licensed under the GPL-2 or later. |  * Licensed under the GPL-2 or later. | ||||||
|  */ |  */ | ||||||
|  | @ -11,7 +11,6 @@ | ||||||
| 
 | 
 | ||||||
| #include "ad525x_dpot.h" | #include "ad525x_dpot.h" | ||||||
| 
 | 
 | ||||||
| /* ------------------------------------------------------------------------- */ |  | ||||||
| /* I2C bus functions */ | /* I2C bus functions */ | ||||||
| static int write_d8(void *client, u8 val) | static int write_d8(void *client, u8 val) | ||||||
| { | { | ||||||
|  | @ -60,18 +59,13 @@ static int __devinit ad_dpot_i2c_probe(struct i2c_client *client, | ||||||
| 		.bops = &bops, | 		.bops = &bops, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	struct ad_dpot_id dpot_id = { |  | ||||||
| 		.name = (char *) &id->name, |  | ||||||
| 		.devid = id->driver_data, |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	if (!i2c_check_functionality(client->adapter, | 	if (!i2c_check_functionality(client->adapter, | ||||||
| 				     I2C_FUNC_SMBUS_WORD_DATA)) { | 				     I2C_FUNC_SMBUS_WORD_DATA)) { | ||||||
| 		dev_err(&client->dev, "SMBUS Word Data not Supported\n"); | 		dev_err(&client->dev, "SMBUS Word Data not Supported\n"); | ||||||
| 		return -EIO; | 		return -EIO; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return ad_dpot_probe(&client->dev, &bdata, &dpot_id); | 	return ad_dpot_probe(&client->dev, &bdata, id->driver_data, id->name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int __devexit ad_dpot_i2c_remove(struct i2c_client *client) | static int __devexit ad_dpot_i2c_remove(struct i2c_client *client) | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Driver for the Analog Devices digital potentiometers (SPI bus) |  * Driver for the Analog Devices digital potentiometers (SPI bus) | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc. |  * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc. | ||||||
|  * |  * | ||||||
|  * Licensed under the GPL-2 or later. |  * Licensed under the GPL-2 or later. | ||||||
|  */ |  */ | ||||||
|  | @ -11,40 +11,6 @@ | ||||||
| 
 | 
 | ||||||
| #include "ad525x_dpot.h" | #include "ad525x_dpot.h" | ||||||
| 
 | 
 | ||||||
| static const struct ad_dpot_id ad_dpot_spi_devlist[] = { |  | ||||||
| 	{.name = "ad5160", .devid = AD5160_ID}, |  | ||||||
| 	{.name = "ad5161", .devid = AD5161_ID}, |  | ||||||
| 	{.name = "ad5162", .devid = AD5162_ID}, |  | ||||||
| 	{.name = "ad5165", .devid = AD5165_ID}, |  | ||||||
| 	{.name = "ad5200", .devid = AD5200_ID}, |  | ||||||
| 	{.name = "ad5201", .devid = AD5201_ID}, |  | ||||||
| 	{.name = "ad5203", .devid = AD5203_ID}, |  | ||||||
| 	{.name = "ad5204", .devid = AD5204_ID}, |  | ||||||
| 	{.name = "ad5206", .devid = AD5206_ID}, |  | ||||||
| 	{.name = "ad5207", .devid = AD5207_ID}, |  | ||||||
| 	{.name = "ad5231", .devid = AD5231_ID}, |  | ||||||
| 	{.name = "ad5232", .devid = AD5232_ID}, |  | ||||||
| 	{.name = "ad5233", .devid = AD5233_ID}, |  | ||||||
| 	{.name = "ad5235", .devid = AD5235_ID}, |  | ||||||
| 	{.name = "ad5260", .devid = AD5260_ID}, |  | ||||||
| 	{.name = "ad5262", .devid = AD5262_ID}, |  | ||||||
| 	{.name = "ad5263", .devid = AD5263_ID}, |  | ||||||
| 	{.name = "ad5290", .devid = AD5290_ID}, |  | ||||||
| 	{.name = "ad5291", .devid = AD5291_ID}, |  | ||||||
| 	{.name = "ad5292", .devid = AD5292_ID}, |  | ||||||
| 	{.name = "ad5293", .devid = AD5293_ID}, |  | ||||||
| 	{.name = "ad7376", .devid = AD7376_ID}, |  | ||||||
| 	{.name = "ad8400", .devid = AD8400_ID}, |  | ||||||
| 	{.name = "ad8402", .devid = AD8402_ID}, |  | ||||||
| 	{.name = "ad8403", .devid = AD8403_ID}, |  | ||||||
| 	{.name = "adn2850", .devid = ADN2850_ID}, |  | ||||||
| 	{.name = "ad5270", .devid = AD5270_ID}, |  | ||||||
| 	{.name = "ad5271", .devid = AD5271_ID}, |  | ||||||
| 	{} |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* ------------------------------------------------------------------------- */ |  | ||||||
| 
 |  | ||||||
| /* SPI bus functions */ | /* SPI bus functions */ | ||||||
| static int write8(void *client, u8 val) | static int write8(void *client, u8 val) | ||||||
| { | { | ||||||
|  | @ -109,36 +75,16 @@ static const struct ad_dpot_bus_ops bops = { | ||||||
| 	.write_r8d8	= write16, | 	.write_r8d8	= write16, | ||||||
| 	.write_r8d16	= write24, | 	.write_r8d16	= write24, | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
| static const struct ad_dpot_id *dpot_match_id(const struct ad_dpot_id *id, |  | ||||||
| 						char *name) |  | ||||||
| { |  | ||||||
| 	while (id->name && id->name[0]) { |  | ||||||
| 		if (strcmp(name, id->name) == 0) |  | ||||||
| 			return id; |  | ||||||
| 		id++; |  | ||||||
| 	} |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int __devinit ad_dpot_spi_probe(struct spi_device *spi) | static int __devinit ad_dpot_spi_probe(struct spi_device *spi) | ||||||
| { | { | ||||||
| 	char *name = spi->dev.platform_data; |  | ||||||
| 	const struct ad_dpot_id *dpot_id; |  | ||||||
| 
 |  | ||||||
| 	struct ad_dpot_bus_data bdata = { | 	struct ad_dpot_bus_data bdata = { | ||||||
| 		.client = spi, | 		.client = spi, | ||||||
| 		.bops = &bops, | 		.bops = &bops, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	dpot_id = dpot_match_id(ad_dpot_spi_devlist, name); | 	return ad_dpot_probe(&spi->dev, &bdata, | ||||||
| 
 | 			     spi_get_device_id(spi)->driver_data, | ||||||
| 	if (dpot_id == NULL) { | 			     spi_get_device_id(spi)->name); | ||||||
| 		dev_err(&spi->dev, "%s not in supported device list", name); |  | ||||||
| 		return -ENODEV; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return ad_dpot_probe(&spi->dev, &bdata, dpot_id); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int __devexit ad_dpot_spi_remove(struct spi_device *spi) | static int __devexit ad_dpot_spi_remove(struct spi_device *spi) | ||||||
|  | @ -146,14 +92,47 @@ static int __devexit ad_dpot_spi_remove(struct spi_device *spi) | ||||||
| 	return ad_dpot_remove(&spi->dev); | 	return ad_dpot_remove(&spi->dev); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const struct spi_device_id ad_dpot_spi_id[] = { | ||||||
|  | 	{"ad5160", AD5160_ID}, | ||||||
|  | 	{"ad5161", AD5161_ID}, | ||||||
|  | 	{"ad5162", AD5162_ID}, | ||||||
|  | 	{"ad5165", AD5165_ID}, | ||||||
|  | 	{"ad5200", AD5200_ID}, | ||||||
|  | 	{"ad5201", AD5201_ID}, | ||||||
|  | 	{"ad5203", AD5203_ID}, | ||||||
|  | 	{"ad5204", AD5204_ID}, | ||||||
|  | 	{"ad5206", AD5206_ID}, | ||||||
|  | 	{"ad5207", AD5207_ID}, | ||||||
|  | 	{"ad5231", AD5231_ID}, | ||||||
|  | 	{"ad5232", AD5232_ID}, | ||||||
|  | 	{"ad5233", AD5233_ID}, | ||||||
|  | 	{"ad5235", AD5235_ID}, | ||||||
|  | 	{"ad5260", AD5260_ID}, | ||||||
|  | 	{"ad5262", AD5262_ID}, | ||||||
|  | 	{"ad5263", AD5263_ID}, | ||||||
|  | 	{"ad5290", AD5290_ID}, | ||||||
|  | 	{"ad5291", AD5291_ID}, | ||||||
|  | 	{"ad5292", AD5292_ID}, | ||||||
|  | 	{"ad5293", AD5293_ID}, | ||||||
|  | 	{"ad7376", AD7376_ID}, | ||||||
|  | 	{"ad8400", AD8400_ID}, | ||||||
|  | 	{"ad8402", AD8402_ID}, | ||||||
|  | 	{"ad8403", AD8403_ID}, | ||||||
|  | 	{"adn2850", ADN2850_ID}, | ||||||
|  | 	{"ad5270", AD5270_ID}, | ||||||
|  | 	{"ad5271", AD5271_ID}, | ||||||
|  | 	{} | ||||||
|  | }; | ||||||
|  | MODULE_DEVICE_TABLE(spi, ad_dpot_spi_id); | ||||||
|  | 
 | ||||||
| static struct spi_driver ad_dpot_spi_driver = { | static struct spi_driver ad_dpot_spi_driver = { | ||||||
| 	.driver = { | 	.driver = { | ||||||
| 		.name	= "ad_dpot", | 		.name	= "ad_dpot", | ||||||
| 		.bus	= &spi_bus_type, |  | ||||||
| 		.owner	= THIS_MODULE, | 		.owner	= THIS_MODULE, | ||||||
| 	}, | 	}, | ||||||
| 	.probe		= ad_dpot_spi_probe, | 	.probe		= ad_dpot_spi_probe, | ||||||
| 	.remove		= __devexit_p(ad_dpot_spi_remove), | 	.remove		= __devexit_p(ad_dpot_spi_remove), | ||||||
|  | 	.id_table	= ad_dpot_spi_id, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int __init ad_dpot_spi_init(void) | static int __init ad_dpot_spi_init(void) | ||||||
|  |  | ||||||
|  | @ -64,7 +64,7 @@ | ||||||
|  * Author: Chris Verges <chrisv@cyberswitching.com> |  * Author: Chris Verges <chrisv@cyberswitching.com> | ||||||
|  * |  * | ||||||
|  * derived from ad5252.c |  * derived from ad5252.c | ||||||
|  * Copyright (c) 2006 Michael Hennerich <hennerich@blackfin.uclinux.org> |  * Copyright (c) 2006-2011 Michael Hennerich <hennerich@blackfin.uclinux.org> | ||||||
|  * |  * | ||||||
|  * Licensed under the GPL-2 or later. |  * Licensed under the GPL-2 or later. | ||||||
|  */ |  */ | ||||||
|  | @ -76,8 +76,6 @@ | ||||||
| #include <linux/delay.h> | #include <linux/delay.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| 
 | 
 | ||||||
| #define DRIVER_VERSION			"0.2" |  | ||||||
| 
 |  | ||||||
| #include "ad525x_dpot.h" | #include "ad525x_dpot.h" | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -687,8 +685,9 @@ inline void ad_dpot_remove_files(struct device *dev, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| __devinit int ad_dpot_probe(struct device *dev, | int __devinit ad_dpot_probe(struct device *dev, | ||||||
| 		struct ad_dpot_bus_data *bdata, const struct ad_dpot_id *id) | 		struct ad_dpot_bus_data *bdata, unsigned long devid, | ||||||
|  | 			    const char *name) | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| 	struct dpot_data *data; | 	struct dpot_data *data; | ||||||
|  | @ -704,13 +703,13 @@ __devinit int ad_dpot_probe(struct device *dev, | ||||||
| 	mutex_init(&data->update_lock); | 	mutex_init(&data->update_lock); | ||||||
| 
 | 
 | ||||||
| 	data->bdata = *bdata; | 	data->bdata = *bdata; | ||||||
| 	data->devid = id->devid; | 	data->devid = devid; | ||||||
| 
 | 
 | ||||||
| 	data->max_pos = 1 << DPOT_MAX_POS(data->devid); | 	data->max_pos = 1 << DPOT_MAX_POS(devid); | ||||||
| 	data->rdac_mask = data->max_pos - 1; | 	data->rdac_mask = data->max_pos - 1; | ||||||
| 	data->feat = DPOT_FEAT(data->devid); | 	data->feat = DPOT_FEAT(devid); | ||||||
| 	data->uid = DPOT_UID(data->devid); | 	data->uid = DPOT_UID(devid); | ||||||
| 	data->wipers = DPOT_WIPERS(data->devid); | 	data->wipers = DPOT_WIPERS(devid); | ||||||
| 
 | 
 | ||||||
| 	for (i = DPOT_RDAC0; i < MAX_RDACS; i++) | 	for (i = DPOT_RDAC0; i < MAX_RDACS; i++) | ||||||
| 		if (data->wipers & (1 << i)) { | 		if (data->wipers & (1 << i)) { | ||||||
|  | @ -731,7 +730,7 @@ __devinit int ad_dpot_probe(struct device *dev, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dev_info(dev, "%s %d-Position Digital Potentiometer registered\n", | 	dev_info(dev, "%s %d-Position Digital Potentiometer registered\n", | ||||||
| 		 id->name, data->max_pos); | 		 name, data->max_pos); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
|  | @ -745,7 +744,7 @@ exit_free: | ||||||
| 	dev_set_drvdata(dev, NULL); | 	dev_set_drvdata(dev, NULL); | ||||||
| exit: | exit: | ||||||
| 	dev_err(dev, "failed to create client for %s ID 0x%lX\n", | 	dev_err(dev, "failed to create client for %s ID 0x%lX\n", | ||||||
| 			id->name, id->devid); | 		name, devid); | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(ad_dpot_probe); | EXPORT_SYMBOL(ad_dpot_probe); | ||||||
|  | @ -770,4 +769,3 @@ MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, " | ||||||
| 	      "Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 	      "Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||||||
| MODULE_DESCRIPTION("Digital potentiometer driver"); | MODULE_DESCRIPTION("Digital potentiometer driver"); | ||||||
| MODULE_LICENSE("GPL"); | MODULE_LICENSE("GPL"); | ||||||
| MODULE_VERSION(DRIVER_VERSION); |  | ||||||
|  |  | ||||||
|  | @ -208,12 +208,8 @@ struct ad_dpot_bus_data { | ||||||
| 	const struct ad_dpot_bus_ops *bops; | 	const struct ad_dpot_bus_ops *bops; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ad_dpot_id { | int ad_dpot_probe(struct device *dev, struct ad_dpot_bus_data *bdata, | ||||||
| 	char *name; | 		  unsigned long devid, const char *name); | ||||||
| 	unsigned long devid; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int ad_dpot_probe(struct device *dev, struct ad_dpot_bus_data *bdata, const struct ad_dpot_id *id); |  | ||||||
| int ad_dpot_remove(struct device *dev); | int ad_dpot_remove(struct device *dev); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -216,7 +216,7 @@ static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature) | ||||||
| 		*temperature = (x1+x2+8) >> 4; | 		*temperature = (x1+x2+8) >> 4; | ||||||
| 
 | 
 | ||||||
| exit: | exit: | ||||||
| 	return status;; | 	return status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
|  | @ -158,7 +158,7 @@ static int als_set_default_config(struct i2c_client *client) | ||||||
| 		dev_err(&client->dev, "default write failed."); | 		dev_err(&client->dev, "default write failed."); | ||||||
| 		return retval; | 		return retval; | ||||||
| 	} | 	} | ||||||
| 	return 0;; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int  isl29020_probe(struct i2c_client *client, | static int  isl29020_probe(struct i2c_client *client, | ||||||
|  |  | ||||||
|  | @ -137,6 +137,8 @@ void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) | ||||||
|  * st_reg_complete - |  * st_reg_complete - | ||||||
|  * to call registration complete callbacks |  * to call registration complete callbacks | ||||||
|  * of all protocol stack drivers |  * of all protocol stack drivers | ||||||
|  |  * This function is being called with spin lock held, protocol drivers are | ||||||
|  |  * only expected to complete their waits and do nothing more than that. | ||||||
|  */ |  */ | ||||||
| void st_reg_complete(struct st_data_s *st_gdata, char err) | void st_reg_complete(struct st_data_s *st_gdata, char err) | ||||||
| { | { | ||||||
|  | @ -538,11 +540,12 @@ long st_register(struct st_proto_s *new_proto) | ||||||
| 		set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state); | 		set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state); | ||||||
| 		st_recv = st_kim_recv; | 		st_recv = st_kim_recv; | ||||||
| 
 | 
 | ||||||
|  | 		/* enable the ST LL - to set default chip state */ | ||||||
|  | 		st_ll_enable(st_gdata); | ||||||
|  | 
 | ||||||
| 		/* release lock previously held - re-locked below */ | 		/* release lock previously held - re-locked below */ | ||||||
| 		spin_unlock_irqrestore(&st_gdata->lock, flags); | 		spin_unlock_irqrestore(&st_gdata->lock, flags); | ||||||
| 
 | 
 | ||||||
| 		/* enable the ST LL - to set default chip state */ |  | ||||||
| 		st_ll_enable(st_gdata); |  | ||||||
| 		/* this may take a while to complete
 | 		/* this may take a while to complete
 | ||||||
| 		 * since it involves BT fw download | 		 * since it involves BT fw download | ||||||
| 		 */ | 		 */ | ||||||
|  | @ -553,10 +556,13 @@ long st_register(struct st_proto_s *new_proto) | ||||||
| 			    (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { | 			    (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { | ||||||
| 				pr_err(" KIM failure complete callback "); | 				pr_err(" KIM failure complete callback "); | ||||||
| 				st_reg_complete(st_gdata, err); | 				st_reg_complete(st_gdata, err); | ||||||
|  | 				clear_bit(ST_REG_PENDING, &st_gdata->st_state); | ||||||
| 			} | 			} | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		spin_lock_irqsave(&st_gdata->lock, flags); | ||||||
|  | 
 | ||||||
| 		clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state); | 		clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state); | ||||||
| 		st_recv = st_int_recv; | 		st_recv = st_int_recv; | ||||||
| 
 | 
 | ||||||
|  | @ -576,10 +582,10 @@ long st_register(struct st_proto_s *new_proto) | ||||||
| 		if (st_gdata->is_registered[new_proto->chnl_id] == true) { | 		if (st_gdata->is_registered[new_proto->chnl_id] == true) { | ||||||
| 			pr_err(" proto %d already registered ", | 			pr_err(" proto %d already registered ", | ||||||
| 				   new_proto->chnl_id); | 				   new_proto->chnl_id); | ||||||
|  | 			spin_unlock_irqrestore(&st_gdata->lock, flags); | ||||||
| 			return -EALREADY; | 			return -EALREADY; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		spin_lock_irqsave(&st_gdata->lock, flags); |  | ||||||
| 		add_channel_to_table(st_gdata, new_proto); | 		add_channel_to_table(st_gdata, new_proto); | ||||||
| 		st_gdata->protos_registered++; | 		st_gdata->protos_registered++; | ||||||
| 		new_proto->write = st_write; | 		new_proto->write = st_write; | ||||||
|  | @ -619,7 +625,7 @@ long st_unregister(struct st_proto_s *proto) | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&st_gdata->lock, flags); | 	spin_lock_irqsave(&st_gdata->lock, flags); | ||||||
| 
 | 
 | ||||||
| 	if (st_gdata->list[proto->chnl_id] == NULL) { | 	if (st_gdata->is_registered[proto->chnl_id] == false) { | ||||||
| 		pr_err(" chnl_id %d not registered", proto->chnl_id); | 		pr_err(" chnl_id %d not registered", proto->chnl_id); | ||||||
| 		spin_unlock_irqrestore(&st_gdata->lock, flags); | 		spin_unlock_irqrestore(&st_gdata->lock, flags); | ||||||
| 		return -EPROTONOSUPPORT; | 		return -EPROTONOSUPPORT; | ||||||
|  | @ -629,6 +635,10 @@ long st_unregister(struct st_proto_s *proto) | ||||||
| 	remove_channel_from_table(st_gdata, proto); | 	remove_channel_from_table(st_gdata, proto); | ||||||
| 	spin_unlock_irqrestore(&st_gdata->lock, flags); | 	spin_unlock_irqrestore(&st_gdata->lock, flags); | ||||||
| 
 | 
 | ||||||
|  | 	/* paranoid check */ | ||||||
|  | 	if (st_gdata->protos_registered < ST_EMPTY) | ||||||
|  | 		st_gdata->protos_registered = ST_EMPTY; | ||||||
|  | 
 | ||||||
| 	if ((st_gdata->protos_registered == ST_EMPTY) && | 	if ((st_gdata->protos_registered == ST_EMPTY) && | ||||||
| 	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) { | 	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) { | ||||||
| 		pr_info(" all chnl_ids unregistered "); | 		pr_info(" all chnl_ids unregistered "); | ||||||
|  |  | ||||||
|  | @ -469,37 +469,21 @@ long st_kim_start(void *kim_data) | ||||||
| 		/* wait for ldisc to be installed */ | 		/* wait for ldisc to be installed */ | ||||||
| 		err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, | 		err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, | ||||||
| 				msecs_to_jiffies(LDISC_TIME)); | 				msecs_to_jiffies(LDISC_TIME)); | ||||||
| 		if (!err) {	/* timeout */ | 		if (!err) { | ||||||
| 			pr_err("line disc installation timed out "); | 			/* ldisc installation timeout,
 | ||||||
| 			kim_gdata->ldisc_install = 0; | 			 * flush uart, power cycle BT_EN */ | ||||||
| 			pr_info("ldisc_install = 0"); | 			pr_err("ldisc installation timeout"); | ||||||
| 			sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, | 			err = st_kim_stop(kim_gdata); | ||||||
| 					NULL, "install"); |  | ||||||
| 			/* the following wait is never going to be completed,
 |  | ||||||
| 			 * since the ldisc was never installed, hence serving |  | ||||||
| 			 * as a mdelay of LDISC_TIME msecs */ |  | ||||||
| 			err = wait_for_completion_timeout |  | ||||||
| 				(&kim_gdata->ldisc_installed, |  | ||||||
| 				 msecs_to_jiffies(LDISC_TIME)); |  | ||||||
| 			err = -ETIMEDOUT; |  | ||||||
| 			continue; | 			continue; | ||||||
| 		} else { | 		} else { | ||||||
| 			/* ldisc installed now */ | 			/* ldisc installed now */ | ||||||
| 			pr_info(" line discipline installed "); | 			pr_info("line discipline installed"); | ||||||
| 			err = download_firmware(kim_gdata); | 			err = download_firmware(kim_gdata); | ||||||
| 			if (err != 0) { | 			if (err != 0) { | ||||||
|  | 				/* ldisc installed but fw download failed,
 | ||||||
|  | 				 * flush uart & power cycle BT_EN */ | ||||||
| 				pr_err("download firmware failed"); | 				pr_err("download firmware failed"); | ||||||
| 				kim_gdata->ldisc_install = 0; | 				err = st_kim_stop(kim_gdata); | ||||||
| 				pr_info("ldisc_install = 0"); |  | ||||||
| 				sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, |  | ||||||
| 						NULL, "install"); |  | ||||||
| 				/* this wait might be completed, though in the
 |  | ||||||
| 				 * tty_close() since the ldisc is already |  | ||||||
| 				 * installed */ |  | ||||||
| 				err = wait_for_completion_timeout |  | ||||||
| 					(&kim_gdata->ldisc_installed, |  | ||||||
| 					 msecs_to_jiffies(LDISC_TIME)); |  | ||||||
| 				err = -EINVAL; |  | ||||||
| 				continue; | 				continue; | ||||||
| 			} else {	/* on success don't retry */ | 			} else {	/* on success don't retry */ | ||||||
| 				break; | 				break; | ||||||
|  | @ -510,8 +494,14 @@ long st_kim_start(void *kim_data) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * st_kim_stop - called from ST Core, on the last un-registration |  * st_kim_stop - stop communication with chip. | ||||||
|  *	toggle low the chip enable gpio |  *	This can be called from ST Core/KIM, on the- | ||||||
|  |  *	(a) last un-register when chip need not be powered there-after, | ||||||
|  |  *	(b) upon failure to either install ldisc or download firmware. | ||||||
|  |  *	The function is responsible to (a) notify UIM about un-installation, | ||||||
|  |  *	(b) flush UART if the ldisc was installed. | ||||||
|  |  *	(c) reset BT_EN - pull down nshutdown at the end. | ||||||
|  |  *	(d) invoke platform's chip disabling routine. | ||||||
|  */ |  */ | ||||||
| long st_kim_stop(void *kim_data) | long st_kim_stop(void *kim_data) | ||||||
| { | { | ||||||
|  | @ -519,12 +509,16 @@ long st_kim_stop(void *kim_data) | ||||||
| 	struct kim_data_s	*kim_gdata = (struct kim_data_s *)kim_data; | 	struct kim_data_s	*kim_gdata = (struct kim_data_s *)kim_data; | ||||||
| 	struct ti_st_plat_data	*pdata = | 	struct ti_st_plat_data	*pdata = | ||||||
| 		kim_gdata->kim_pdev->dev.platform_data; | 		kim_gdata->kim_pdev->dev.platform_data; | ||||||
|  | 	struct tty_struct	*tty = kim_gdata->core_data->tty; | ||||||
| 
 | 
 | ||||||
| 	INIT_COMPLETION(kim_gdata->ldisc_installed); | 	INIT_COMPLETION(kim_gdata->ldisc_installed); | ||||||
| 
 | 
 | ||||||
| 	/* Flush any pending characters in the driver and discipline. */ | 	if (tty) {	/* can be called before ldisc is installed */ | ||||||
| 	tty_ldisc_flush(kim_gdata->core_data->tty); | 		/* Flush any pending characters in the driver and discipline. */ | ||||||
| 	tty_driver_flush_buffer(kim_gdata->core_data->tty); | 		tty_ldisc_flush(tty); | ||||||
|  | 		tty_driver_flush_buffer(tty); | ||||||
|  | 		tty->ops->flush_buffer(tty); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* send uninstall notification to UIM */ | 	/* send uninstall notification to UIM */ | ||||||
| 	pr_info("ldisc_install = 0"); | 	pr_info("ldisc_install = 0"); | ||||||
|  | @ -579,6 +573,28 @@ static ssize_t show_install(struct device *dev, | ||||||
| 	return sprintf(buf, "%d\n", kim_data->ldisc_install); | 	return sprintf(buf, "%d\n", kim_data->ldisc_install); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  | static ssize_t store_dev_name(struct device *dev, | ||||||
|  | 		struct device_attribute *attr, const char *buf, size_t count) | ||||||
|  | { | ||||||
|  | 	struct kim_data_s *kim_data = dev_get_drvdata(dev); | ||||||
|  | 	pr_debug("storing dev name >%s<", buf); | ||||||
|  | 	strncpy(kim_data->dev_name, buf, count); | ||||||
|  | 	pr_debug("stored dev name >%s<", kim_data->dev_name); | ||||||
|  | 	return count; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static ssize_t store_baud_rate(struct device *dev, | ||||||
|  | 		struct device_attribute *attr, const char *buf, size_t count) | ||||||
|  | { | ||||||
|  | 	struct kim_data_s *kim_data = dev_get_drvdata(dev); | ||||||
|  | 	pr_debug("storing baud rate >%s<", buf); | ||||||
|  | 	sscanf(buf, "%ld", &kim_data->baud_rate); | ||||||
|  | 	pr_debug("stored baud rate >%ld<", kim_data->baud_rate); | ||||||
|  | 	return count; | ||||||
|  | } | ||||||
|  | #endif	/* if DEBUG */ | ||||||
|  | 
 | ||||||
| static ssize_t show_dev_name(struct device *dev, | static ssize_t show_dev_name(struct device *dev, | ||||||
| 		struct device_attribute *attr, char *buf) | 		struct device_attribute *attr, char *buf) | ||||||
| { | { | ||||||
|  | @ -605,10 +621,18 @@ static struct kobj_attribute ldisc_install = | ||||||
| __ATTR(install, 0444, (void *)show_install, NULL); | __ATTR(install, 0444, (void *)show_install, NULL); | ||||||
| 
 | 
 | ||||||
| static struct kobj_attribute uart_dev_name = | static struct kobj_attribute uart_dev_name = | ||||||
|  | #ifdef DEBUG	/* TODO: move this to debug-fs if possible */ | ||||||
|  | __ATTR(dev_name, 0644, (void *)show_dev_name, (void *)store_dev_name); | ||||||
|  | #else | ||||||
| __ATTR(dev_name, 0444, (void *)show_dev_name, NULL); | __ATTR(dev_name, 0444, (void *)show_dev_name, NULL); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| static struct kobj_attribute uart_baud_rate = | static struct kobj_attribute uart_baud_rate = | ||||||
|  | #ifdef DEBUG	/* TODO: move to debugfs */ | ||||||
|  | __ATTR(baud_rate, 0644, (void *)show_baud_rate, (void *)store_baud_rate); | ||||||
|  | #else | ||||||
| __ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL); | __ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| static struct kobj_attribute uart_flow_cntrl = | static struct kobj_attribute uart_flow_cntrl = | ||||||
| __ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL); | __ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL); | ||||||
|  |  | ||||||
|  | @ -14,7 +14,6 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/fs.h> | #include <linux/fs.h> | ||||||
| #include <linux/major.h> | #include <linux/major.h> | ||||||
| #include <linux/kobj_map.h> |  | ||||||
| #include <linux/cdev.h> | #include <linux/cdev.h> | ||||||
| 
 | 
 | ||||||
| #include <linux/device.h> | #include <linux/device.h> | ||||||
|  |  | ||||||
|  | @ -272,7 +272,7 @@ int __register_chrdev(unsigned int major, unsigned int baseminor, | ||||||
| 	cd = __register_chrdev_region(major, baseminor, count, name); | 	cd = __register_chrdev_region(major, baseminor, count, name); | ||||||
| 	if (IS_ERR(cd)) | 	if (IS_ERR(cd)) | ||||||
| 		return PTR_ERR(cd); | 		return PTR_ERR(cd); | ||||||
| 	 | 
 | ||||||
| 	cdev = cdev_alloc(); | 	cdev = cdev_alloc(); | ||||||
| 	if (!cdev) | 	if (!cdev) | ||||||
| 		goto out2; | 		goto out2; | ||||||
|  | @ -280,7 +280,7 @@ int __register_chrdev(unsigned int major, unsigned int baseminor, | ||||||
| 	cdev->owner = fops->owner; | 	cdev->owner = fops->owner; | ||||||
| 	cdev->ops = fops; | 	cdev->ops = fops; | ||||||
| 	kobject_set_name(&cdev->kobj, "%s", name); | 	kobject_set_name(&cdev->kobj, "%s", name); | ||||||
| 		 | 
 | ||||||
| 	err = cdev_add(cdev, MKDEV(cd->major, baseminor), count); | 	err = cdev_add(cdev, MKDEV(cd->major, baseminor), count); | ||||||
| 	if (err) | 	if (err) | ||||||
| 		goto out; | 		goto out; | ||||||
|  | @ -405,7 +405,7 @@ static int chrdev_open(struct inode *inode, struct file *filp) | ||||||
| 		goto out_cdev_put; | 		goto out_cdev_put; | ||||||
| 
 | 
 | ||||||
| 	if (filp->f_op->open) { | 	if (filp->f_op->open) { | ||||||
| 		ret = filp->f_op->open(inode,filp); | 		ret = filp->f_op->open(inode, filp); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			goto out_cdev_put; | 			goto out_cdev_put; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds