diff options
Diffstat (limited to 'drivers/w1/masters')
| -rw-r--r-- | drivers/w1/masters/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/w1/masters/ds1wm.c | 391 | ||||
| -rw-r--r-- | drivers/w1/masters/ds2482.c | 64 | ||||
| -rw-r--r-- | drivers/w1/masters/ds2490.c | 180 | ||||
| -rw-r--r-- | drivers/w1/masters/matrox_w1.c | 16 | ||||
| -rw-r--r-- | drivers/w1/masters/mxc_w1.c | 146 | ||||
| -rw-r--r-- | drivers/w1/masters/omap_hdq.c | 179 | ||||
| -rw-r--r-- | drivers/w1/masters/w1-gpio.c | 158 | 
8 files changed, 653 insertions, 490 deletions
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 80b3b123dd7..1708b2300c7 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -26,7 +26,7 @@ config W1_MASTER_DS2490  config W1_MASTER_DS2482  	tristate "Maxim DS2482 I2C to 1-Wire bridge" -	depends on I2C && EXPERIMENTAL +	depends on I2C  	help  	  If you say yes here you get support for the Maxim DS2482  	  I2C to 1-Wire bridge. @@ -36,13 +36,12 @@ config W1_MASTER_DS2482  config W1_MASTER_MXC  	tristate "Freescale MXC 1-wire busmaster" -	depends on W1 && ARCH_MXC +	depends on ARCH_MXC || COMPILE_TEST  	help  	  Say Y here to enable MXC 1-wire host  config W1_MASTER_DS1WM  	tristate "Maxim DS1WM 1-wire busmaster" -	depends on W1 && ARM && HAVE_CLK  	help  	  Say Y here to enable the DS1WM 1-wire driver, such as that  	  in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like @@ -50,7 +49,7 @@ config W1_MASTER_DS1WM  config W1_MASTER_GPIO  	tristate "GPIO 1-wire busmaster" -	depends on GENERIC_GPIO +	depends on GPIOLIB  	help  	  Say Y here if you want to communicate with your 1-wire devices using  	  GPIO pins. This driver uses the GPIO API to control the wire. @@ -60,7 +59,7 @@ config W1_MASTER_GPIO  config HDQ_MASTER_OMAP  	tristate "OMAP HDQ driver" -	depends on ARCH_OMAP2430 || ARCH_OMAP3 +	depends on ARCH_OMAP  	help  	  Say Y here if you want support for the 1-wire or HDQ Interface  	  on an OMAP processor. diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index 6b85e7fefa4..02df3b1381d 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c @@ -13,6 +13,7 @@  #include <linux/module.h>  #include <linux/interrupt.h> +#include <linux/io.h>  #include <linux/irq.h>  #include <linux/pm.h>  #include <linux/platform_device.h> @@ -33,6 +34,7 @@  #define DS1WM_INT	0x02	/* R/W interrupt status */  #define DS1WM_INT_EN	0x03	/* R/W interrupt enable */  #define DS1WM_CLKDIV	0x04	/* R/W 5 bits of divisor and pre-scale */ +#define DS1WM_CNTRL	0x05	/* R/W master control register (not used yet) */  #define DS1WM_CMD_1W_RESET  (1 << 0)	/* force reset on 1-wire bus */  #define DS1WM_CMD_SRA	    (1 << 1)	/* enable Search ROM accelerator mode */ @@ -56,6 +58,7 @@  #define DS1WM_INTEN_ERSRF   (1 << 5)	/* enable rx shift register full int */  #define DS1WM_INTEN_DQO	    (1 << 6)	/* enable direct bus driving ops */ +#define DS1WM_INTEN_NOT_IAS (~DS1WM_INTEN_IAS)	/* all but INTR active state */  #define DS1WM_TIMEOUT (HZ * 5) @@ -63,41 +66,51 @@ static struct {  	unsigned long freq;  	unsigned long divisor;  } freq[] = { -	{ 4000000, 0x8 }, -	{ 5000000, 0x2 }, -	{ 6000000, 0x5 }, -	{ 7000000, 0x3 }, -	{ 8000000, 0xc }, -	{ 10000000, 0x6 }, -	{ 12000000, 0x9 }, -	{ 14000000, 0x7 }, -	{ 16000000, 0x10 }, -	{ 20000000, 0xa }, -	{ 24000000, 0xd }, -	{ 28000000, 0xb }, -	{ 32000000, 0x14 }, -	{ 40000000, 0xe }, -	{ 48000000, 0x11 }, -	{ 56000000, 0xf }, -	{ 64000000, 0x18 }, -	{ 80000000, 0x12 }, -	{ 96000000, 0x15 }, -	{ 112000000, 0x13 }, -	{ 128000000, 0x1c }, +	{   1000000, 0x80 }, +	{   2000000, 0x84 }, +	{   3000000, 0x81 }, +	{   4000000, 0x88 }, +	{   5000000, 0x82 }, +	{   6000000, 0x85 }, +	{   7000000, 0x83 }, +	{   8000000, 0x8c }, +	{  10000000, 0x86 }, +	{  12000000, 0x89 }, +	{  14000000, 0x87 }, +	{  16000000, 0x90 }, +	{  20000000, 0x8a }, +	{  24000000, 0x8d }, +	{  28000000, 0x8b }, +	{  32000000, 0x94 }, +	{  40000000, 0x8e }, +	{  48000000, 0x91 }, +	{  56000000, 0x8f }, +	{  64000000, 0x98 }, +	{  80000000, 0x92 }, +	{  96000000, 0x95 }, +	{ 112000000, 0x93 }, +	{ 128000000, 0x9c }, +/* you can continue this table, consult the OPERATION - CLOCK DIVISOR +   section of the ds1wm spec sheet. */  };  struct ds1wm_data { -	void		__iomem *map; -	int		bus_shift; /* # of shifts to calc register offsets */ +	void     __iomem *map; +	int      bus_shift; /* # of shifts to calc register offsets */  	struct platform_device *pdev; -	struct mfd_cell	*cell; -	int		irq; -	int		active_high; -	int		slave_present; -	void		*reset_complete; -	void		*read_complete; -	void		*write_complete; -	u8		read_byte; /* last byte received */ +	const struct mfd_cell   *cell; +	int      irq; +	int      slave_present; +	void     *reset_complete; +	void     *read_complete; +	void     *write_complete; +	int      read_error; +	/* last byte received */ +	u8       read_byte; +	/* byte to write that makes all intr disabled, */ +	/* considering active_state (IAS) (optimization) */ +	u8       int_en_reg_none; +	unsigned int reset_recover_delay; /* see ds1wm.h */  };  static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg, @@ -115,23 +128,39 @@ static inline u8 ds1wm_read_register(struct ds1wm_data *ds1wm_data, u32 reg)  static irqreturn_t ds1wm_isr(int isr, void *data)  {  	struct ds1wm_data *ds1wm_data = data; -	u8 intr = ds1wm_read_register(ds1wm_data, DS1WM_INT); +	u8 intr; +	u8 inten = ds1wm_read_register(ds1wm_data, DS1WM_INT_EN); +	/* if no bits are set in int enable register (except the IAS) +	than go no further, reading the regs below has side effects */ +	if (!(inten & DS1WM_INTEN_NOT_IAS)) +		return IRQ_NONE; -	ds1wm_data->slave_present = (intr & DS1WM_INT_PDR) ? 0 : 1; +	ds1wm_write_register(ds1wm_data, +		DS1WM_INT_EN, ds1wm_data->int_en_reg_none); -	if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete) -		complete(ds1wm_data->reset_complete); +	/* this read action clears the INTR and certain flags in ds1wm */ +	intr = ds1wm_read_register(ds1wm_data, DS1WM_INT); -	if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete) -		complete(ds1wm_data->write_complete); +	ds1wm_data->slave_present = (intr & DS1WM_INT_PDR) ? 0 : 1; +	if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete) { +		inten &= ~DS1WM_INTEN_ETMT; +		complete(ds1wm_data->write_complete); +	}  	if (intr & DS1WM_INT_RBF) { +		/* this read clears the RBF flag */  		ds1wm_data->read_byte = ds1wm_read_register(ds1wm_data, -							    DS1WM_DATA); +		DS1WM_DATA); +		inten &= ~DS1WM_INTEN_ERBF;  		if (ds1wm_data->read_complete)  			complete(ds1wm_data->read_complete);  	} +	if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete) { +		inten &= ~DS1WM_INTEN_EPD; +		complete(ds1wm_data->reset_complete); +	} +	ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, inten);  	return IRQ_HANDLED;  } @@ -142,63 +171,73 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data)  	ds1wm_data->reset_complete = &reset_done; +	/* enable Presence detect only */  	ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, DS1WM_INTEN_EPD | -		(ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0)); +	ds1wm_data->int_en_reg_none);  	ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_1W_RESET);  	timeleft = wait_for_completion_timeout(&reset_done, DS1WM_TIMEOUT);  	ds1wm_data->reset_complete = NULL;  	if (!timeleft) { -		dev_err(&ds1wm_data->pdev->dev, "reset failed\n"); +		dev_err(&ds1wm_data->pdev->dev, "reset failed, timed out\n");  		return 1;  	} -	/* Wait for the end of the reset. According to the specs, the time -	 * from when the interrupt is asserted to the end of the reset is: -	 *     tRSTH  - tPDH  - tPDL - tPDI -	 *     625 us - 60 us - 240 us - 100 ns = 324.9 us -	 * -	 * We'll wait a bit longer just to be sure. -	 * Was udelay(500), but if it is going to busywait the cpu that long, -	 * might as well come back later. -	 */ -	msleep(1); - -	ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, -		DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD | -		(ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0)); -  	if (!ds1wm_data->slave_present) {  		dev_dbg(&ds1wm_data->pdev->dev, "reset: no devices found\n");  		return 1;  	} +	if (ds1wm_data->reset_recover_delay) +		msleep(ds1wm_data->reset_recover_delay); +  	return 0;  }  static int ds1wm_write(struct ds1wm_data *ds1wm_data, u8 data)  { +	unsigned long timeleft;  	DECLARE_COMPLETION_ONSTACK(write_done);  	ds1wm_data->write_complete = &write_done; +	ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, +	ds1wm_data->int_en_reg_none | DS1WM_INTEN_ETMT); +  	ds1wm_write_register(ds1wm_data, DS1WM_DATA, data); -	wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT); +	timeleft = wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT); +  	ds1wm_data->write_complete = NULL; +	if (!timeleft) { +		dev_err(&ds1wm_data->pdev->dev, "write failed, timed out\n"); +		return -ETIMEDOUT; +	}  	return 0;  } -static int ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data) +static u8 ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data)  { +	unsigned long timeleft; +	u8 intEnable = DS1WM_INTEN_ERBF | ds1wm_data->int_en_reg_none;  	DECLARE_COMPLETION_ONSTACK(read_done); + +	ds1wm_read_register(ds1wm_data, DS1WM_DATA); +  	ds1wm_data->read_complete = &read_done; +	ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, intEnable); -	ds1wm_write(ds1wm_data, write_data); -	wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT); -	ds1wm_data->read_complete = NULL; +	ds1wm_write_register(ds1wm_data, DS1WM_DATA, write_data); +	timeleft = wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT); +	ds1wm_data->read_complete = NULL; +	if (!timeleft) { +		dev_err(&ds1wm_data->pdev->dev, "read failed, timed out\n"); +		ds1wm_data->read_error = -ETIMEDOUT; +		return 0xFF; +	} +	ds1wm_data->read_error = 0;  	return ds1wm_data->read_byte;  } @@ -206,8 +245,8 @@ static int ds1wm_find_divisor(int gclk)  {  	int i; -	for (i = 0; i < ARRAY_SIZE(freq); i++) -		if (gclk <= freq[i].freq) +	for (i = ARRAY_SIZE(freq)-1; i >= 0; --i) +		if (gclk >= freq[i].freq)  			return freq[i].divisor;  	return 0; @@ -216,15 +255,17 @@ static int ds1wm_find_divisor(int gclk)  static void ds1wm_up(struct ds1wm_data *ds1wm_data)  {  	int divisor; -	struct ds1wm_driver_data *plat = ds1wm_data->cell->driver_data; +	struct device *dev = &ds1wm_data->pdev->dev; +	struct ds1wm_driver_data *plat = dev_get_platdata(dev);  	if (ds1wm_data->cell->enable)  		ds1wm_data->cell->enable(ds1wm_data->pdev);  	divisor = ds1wm_find_divisor(plat->clock_rate); +	dev_dbg(dev, "found divisor 0x%x for clock %d\n", +		divisor, plat->clock_rate);  	if (divisor == 0) { -		dev_err(&ds1wm_data->pdev->dev, -			"no suitable divisor for %dHz clock\n", +		dev_err(dev, "no suitable divisor for %dHz clock\n",  			plat->clock_rate);  		return;  	} @@ -242,7 +283,7 @@ static void ds1wm_down(struct ds1wm_data *ds1wm_data)  	/* Disable interrupts. */  	ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, -			     ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0); +		ds1wm_data->int_en_reg_none);  	if (ds1wm_data->cell->disable)  		ds1wm_data->cell->disable(ds1wm_data->pdev); @@ -279,41 +320,125 @@ static void ds1wm_search(void *data, struct w1_master *master_dev,  {  	struct ds1wm_data *ds1wm_data = data;  	int i; -	unsigned long long rom_id; - -	/* XXX We need to iterate for multiple devices per the DS1WM docs. -	 * See http://www.maxim-ic.com/appnotes.cfm/appnote_number/120. */ -	if (ds1wm_reset(ds1wm_data)) -		return; - -	ds1wm_write(ds1wm_data, search_type); -	ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA); - -	for (rom_id = 0, i = 0; i < 16; i++) { - -		unsigned char resp, r, d; - -		resp = ds1wm_read(ds1wm_data, 0x00); - -		r = ((resp & 0x02) >> 1) | -		    ((resp & 0x08) >> 2) | -		    ((resp & 0x20) >> 3) | -		    ((resp & 0x80) >> 4); - -		d = ((resp & 0x01) >> 0) | -		    ((resp & 0x04) >> 1) | -		    ((resp & 0x10) >> 2) | -		    ((resp & 0x40) >> 3); - -		rom_id |= (unsigned long long) r << (i * 4); - -	} -	dev_dbg(&ds1wm_data->pdev->dev, "found 0x%08llX\n", rom_id); - -	ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); -	ds1wm_reset(ds1wm_data); - -	slave_found(master_dev, rom_id); +	int ms_discrep_bit = -1; +	u64 r = 0; /* holds the progress of the search */ +	u64 r_prime, d; +	unsigned slaves_found = 0; +	unsigned int pass = 0; + +	dev_dbg(&ds1wm_data->pdev->dev, "search begin\n"); +	while (true) { +		++pass; +		if (pass > 100) { +			dev_dbg(&ds1wm_data->pdev->dev, +				"too many attempts (100), search aborted\n"); +			return; +		} + +		mutex_lock(&master_dev->bus_mutex); +		if (ds1wm_reset(ds1wm_data)) { +			mutex_unlock(&master_dev->bus_mutex); +			dev_dbg(&ds1wm_data->pdev->dev, +				"pass: %d reset error (or no slaves)\n", pass); +			break; +		} + +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d r : %0#18llx writing SEARCH_ROM\n", pass, r); +		ds1wm_write(ds1wm_data, search_type); +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d entering ASM\n", pass); +		ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA); +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d beginning nibble loop\n", pass); + +		r_prime = 0; +		d = 0; +		/* we work one nibble at a time */ +		/* each nibble is interleaved to form a byte */ +		for (i = 0; i < 16; i++) { + +			unsigned char resp, _r, _r_prime, _d; + +			_r = (r >> (4*i)) & 0xf; +			_r = ((_r & 0x1) << 1) | +			((_r & 0x2) << 2) | +			((_r & 0x4) << 3) | +			((_r & 0x8) << 4); + +			/* writes _r, then reads back: */ +			resp = ds1wm_read(ds1wm_data, _r); + +			if (ds1wm_data->read_error) { +				dev_err(&ds1wm_data->pdev->dev, +				"pass: %d nibble: %d read error\n", pass, i); +				break; +			} + +			_r_prime = ((resp & 0x02) >> 1) | +			((resp & 0x08) >> 2) | +			((resp & 0x20) >> 3) | +			((resp & 0x80) >> 4); + +			_d = ((resp & 0x01) >> 0) | +			((resp & 0x04) >> 1) | +			((resp & 0x10) >> 2) | +			((resp & 0x40) >> 3); + +			r_prime |= (unsigned long long) _r_prime << (i * 4); +			d |= (unsigned long long) _d << (i * 4); + +		} +		if (ds1wm_data->read_error) { +			mutex_unlock(&master_dev->bus_mutex); +			dev_err(&ds1wm_data->pdev->dev, +				"pass: %d read error, retrying\n", pass); +			break; +		} +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d r\': %0#18llx d:%0#18llx\n", +			pass, r_prime, d); +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d nibble loop complete, exiting ASM\n", pass); +		ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d resetting bus\n", pass); +		ds1wm_reset(ds1wm_data); +		mutex_unlock(&master_dev->bus_mutex); +		if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) { +			dev_err(&ds1wm_data->pdev->dev, +				"pass: %d bus error, retrying\n", pass); +			continue; /* start over */ +		} + + +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d found %0#18llx\n", pass, r_prime); +		slave_found(master_dev, r_prime); +		++slaves_found; +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d complete, preparing next pass\n", pass); + +		/* any discrepency found which we already choose the +		   '1' branch is now is now irrelevant we reveal the +		   next branch with this: */ +		d &= ~r; +		/* find last bit set, i.e. the most signif. bit set */ +		ms_discrep_bit = fls64(d) - 1; +		dev_dbg(&ds1wm_data->pdev->dev, +			"pass: %d new d:%0#18llx MS discrep bit:%d\n", +			pass, d, ms_discrep_bit); + +		/* prev_ms_discrep_bit = ms_discrep_bit; +		   prepare for next ROM search:		    */ +		if (ms_discrep_bit == -1) +			break; + +		r = (r &  ~(~0ull << (ms_discrep_bit))) | 1 << ms_discrep_bit; +	} /* end while true */ +	dev_dbg(&ds1wm_data->pdev->dev, +		"pass: %d total: %d search done ms d bit pos: %d\n", pass, +		slaves_found, ms_discrep_bit);  }  /* --------------------------------------------------------------------- */ @@ -330,57 +455,52 @@ static int ds1wm_probe(struct platform_device *pdev)  	struct ds1wm_data *ds1wm_data;  	struct ds1wm_driver_data *plat;  	struct resource *res; -	struct mfd_cell *cell;  	int ret;  	if (!pdev)  		return -ENODEV; -	cell = pdev->dev.platform_data; -	if (!cell) -		return -ENODEV; - -	ds1wm_data = kzalloc(sizeof(*ds1wm_data), GFP_KERNEL); +	ds1wm_data = devm_kzalloc(&pdev->dev, sizeof(*ds1wm_data), GFP_KERNEL);  	if (!ds1wm_data)  		return -ENOMEM;  	platform_set_drvdata(pdev, ds1wm_data);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		ret = -ENXIO; -		goto err0; -	} -	ds1wm_data->map = ioremap(res->start, resource_size(res)); -	if (!ds1wm_data->map) { -		ret = -ENOMEM; -		goto err0; -	} -	plat = cell->driver_data; +	if (!res) +		return -ENXIO; +	ds1wm_data->map = devm_ioremap(&pdev->dev, res->start, +				       resource_size(res)); +	if (!ds1wm_data->map) +		return -ENOMEM;  	/* calculate bus shift from mem resource */  	ds1wm_data->bus_shift = resource_size(res) >> 3;  	ds1wm_data->pdev = pdev; -	ds1wm_data->cell = cell; +	ds1wm_data->cell = mfd_get_cell(pdev); +	if (!ds1wm_data->cell) +		return -ENODEV; +	plat = dev_get_platdata(&pdev->dev); +	if (!plat) +		return -ENODEV;  	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!res) { -		ret = -ENXIO; -		goto err1; -	} +	if (!res) +		return -ENXIO;  	ds1wm_data->irq = res->start; -	ds1wm_data->active_high = plat->active_high; +	ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0); +	ds1wm_data->reset_recover_delay = plat->reset_recover_delay;  	if (res->flags & IORESOURCE_IRQ_HIGHEDGE) -		set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); +		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING);  	if (res->flags & IORESOURCE_IRQ_LOWEDGE) -		set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING); +		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING); -	ret = request_irq(ds1wm_data->irq, ds1wm_isr, IRQF_DISABLED, -			  "ds1wm", ds1wm_data); +	ret = devm_request_irq(&pdev->dev, ds1wm_data->irq, ds1wm_isr, +			IRQF_SHARED, "ds1wm", ds1wm_data);  	if (ret) -		goto err1; +		return ret;  	ds1wm_up(ds1wm_data); @@ -388,17 +508,12 @@ static int ds1wm_probe(struct platform_device *pdev)  	ret = w1_add_master_device(&ds1wm_master);  	if (ret) -		goto err2; +		goto err;  	return 0; -err2: +err:  	ds1wm_down(ds1wm_data); -	free_irq(ds1wm_data->irq, ds1wm_data); -err1: -	iounmap(ds1wm_data->map); -err0: -	kfree(ds1wm_data);  	return ret;  } @@ -432,9 +547,6 @@ static int ds1wm_remove(struct platform_device *pdev)  	w1_remove_master_device(&ds1wm_master);  	ds1wm_down(ds1wm_data); -	free_irq(ds1wm_data->irq, ds1wm_data); -	iounmap(ds1wm_data->map); -	kfree(ds1wm_data);  	return 0;  } @@ -465,5 +577,6 @@ module_exit(ds1wm_exit);  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, " -	      "Matt Reimer <mreimer@vpop.net>"); +	"Matt Reimer <mreimer@vpop.net>," +	"Jean-Francois Dagenais <dagenaisj@sonatest.com>");  MODULE_DESCRIPTION("DS1WM w1 busmaster driver"); diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index e5f74416d4b..e033491fe30 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -51,10 +51,10 @@   * The top 4 bits always read 0.   * To write, the top nibble must be the 1's compl. of the low nibble.   */ -#define DS2482_REG_CFG_1WS		0x08 -#define DS2482_REG_CFG_SPU		0x04 -#define DS2482_REG_CFG_PPM		0x02 -#define DS2482_REG_CFG_APU		0x01 +#define DS2482_REG_CFG_1WS		0x08	/* 1-wire speed */ +#define DS2482_REG_CFG_SPU		0x04	/* strong pull-up */ +#define DS2482_REG_CFG_PPM		0x02	/* presence pulse masking */ +#define DS2482_REG_CFG_APU		0x01	/* active pull-up */  /** @@ -132,6 +132,17 @@ struct ds2482_data {  /** + * Helper to calculate values for configuration register + * @param conf the raw config value + * @return the value w/ complements that can be written to register + */ +static inline u8 ds2482_calculate_config(u8 conf) +{ +	return conf | ((~conf & 0x0f) << 4); +} + + +/**   * Sets the read pointer.   * @param pdev		The ds2482 client pointer   * @param read_ptr	see DS2482_PTR_CODE_xxx above @@ -399,7 +410,7 @@ static u8 ds2482_w1_reset_bus(void *data)  		/* If the chip did reset since detect, re-config it */  		if (err & DS2482_REG_STS_RST)  			ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG, -					     0xF0); +					     ds2482_calculate_config(0x00));  	}  	mutex_unlock(&pdev->access_lock); @@ -407,6 +418,32 @@ static u8 ds2482_w1_reset_bus(void *data)  	return retval;  } +static u8 ds2482_w1_set_pullup(void *data, int delay) +{ +	struct ds2482_w1_chan *pchan = data; +	struct ds2482_data    *pdev = pchan->pdev; +	u8 retval = 1; + +	/* if delay is non-zero activate the pullup, +	 * the strong pullup will be automatically deactivated +	 * by the master, so do not explicitly deactive it +	 */ +	if (delay) { +		/* both waits are crucial, otherwise devices might not be +		 * powered long enough, causing e.g. a w1_therm sensor to +		 * provide wrong conversion results +		 */ +		ds2482_wait_1wire_idle(pdev); +		/* note: it seems like both SPU and APU have to be set! */ +		retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG, +			ds2482_calculate_config(DS2482_REG_CFG_SPU | +						DS2482_REG_CFG_APU)); +		ds2482_wait_1wire_idle(pdev); +	} + +	return retval; +} +  static int ds2482_probe(struct i2c_client *client,  			const struct i2c_device_id *id) @@ -452,7 +489,8 @@ static int ds2482_probe(struct i2c_client *client,  		data->w1_count = 8;  	/* Set all config items to 0 (off) */ -	ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0); +	ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, +		ds2482_calculate_config(0x00));  	mutex_init(&data->access_lock); @@ -468,6 +506,7 @@ static int ds2482_probe(struct i2c_client *client,  		data->w1_ch[idx].w1_bm.touch_bit  = ds2482_w1_touch_bit;  		data->w1_ch[idx].w1_bm.triplet    = ds2482_w1_triplet;  		data->w1_ch[idx].w1_bm.reset_bus  = ds2482_w1_reset_bus; +		data->w1_ch[idx].w1_bm.set_pullup = ds2482_w1_set_pullup;  		err = w1_add_master_device(&data->w1_ch[idx].w1_bm);  		if (err) { @@ -505,19 +544,8 @@ static int ds2482_remove(struct i2c_client *client)  	return 0;  } -static int __init sensors_ds2482_init(void) -{ -	return i2c_add_driver(&ds2482_driver); -} - -static void __exit sensors_ds2482_exit(void) -{ -	i2c_del_driver(&ds2482_driver); -} +module_i2c_driver(ds2482_driver);  MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");  MODULE_DESCRIPTION("DS2482 driver");  MODULE_LICENSE("GPL"); - -module_init(sensors_ds2482_init); -module_exit(sensors_ds2482_exit); diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 02bf7bf7160..7404ad3062b 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c @@ -1,7 +1,7 @@  /* - *	dscore.c + *	ds2490.c  USB to one wire bridge   * - * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> + * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>   *   *   * This program is free software; you can redistribute it and/or modify @@ -28,6 +28,10 @@  #include "../w1_int.h"  #include "../w1.h" +/* USB Standard */ +/* USB Control request vendor type */ +#define VENDOR				0x40 +  /* COMMAND TYPE CODES */  #define CONTROL_CMD			0x00  #define COMM_CMD			0x01 @@ -107,6 +111,8 @@  #define ST_HALT				0x10  /* DS2490 is currently halted */  #define ST_IDLE				0x20  /* DS2490 is currently idle */  #define ST_EPOF				0x80 +/* Status transfer size, 16 bytes status, 16 byte result flags */ +#define ST_SIZE				0x20  /* Result Register flags */  #define RR_DETECT			0xA5 /* New device detected */ @@ -198,7 +204,7 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)  	int err;  	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), -			CONTROL_CMD, 0x40, value, index, NULL, 0, 1000); +			CONTROL_CMD, VENDOR, value, index, NULL, 0, 1000);  	if (err < 0) {  		printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",  				value, index, err); @@ -213,7 +219,7 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)  	int err;  	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), -			MODE_CMD, 0x40, value, index, NULL, 0, 1000); +			MODE_CMD, VENDOR, value, index, NULL, 0, 1000);  	if (err < 0) {  		printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",  				value, index, err); @@ -228,7 +234,7 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index)  	int err;  	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), -			COMM_CMD, 0x40, value, index, NULL, 0, 1000); +			COMM_CMD, VENDOR, value, index, NULL, 0, 1000);  	if (err < 0) {  		printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",  				value, index, err); @@ -246,7 +252,8 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,  	memset(st, 0, sizeof(*st));  	count = 0; -	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); +	err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev, +		dev->ep[EP_STATUS]), buf, size, &count, 100);  	if (err < 0) {  		printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);  		return err; @@ -353,7 +360,7 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)  	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),  				buf, size, &count, 1000);  	if (err < 0) { -		u8 buf[0x20]; +		u8 buf[ST_SIZE];  		int count;  		printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); @@ -398,7 +405,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit)  {  	struct ds_status st;  	int count = 0, err = 0; -	u8 buf[0x20]; +	u8 buf[ST_SIZE];  	do {  		err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); @@ -450,10 +457,11 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)  static int ds_wait_status(struct ds_device *dev, struct ds_status *st)  { -	u8 buf[0x20]; +	u8 buf[ST_SIZE];  	int err, count = 0;  	do { +		st->status = 0;  		err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));  #if 0  		if (err >= 0) { @@ -464,7 +472,7 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)  			printk("\n");  		}  #endif -	} while (!(buf[0x08] & ST_IDLE) && !(err < 0) && ++count < 100); +	} while (!(st->status & ST_IDLE) && !(err < 0) && ++count < 100);  	if (err >= 16 && st->status & ST_EPOF) {  		printk(KERN_INFO "Resetting device after ST_EPOF.\n"); @@ -690,37 +698,106 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)  	return !(err == len);  } -#if 0 - -static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) +static void ds9490r_search(void *data, struct w1_master *master, +	u8 search_type, w1_slave_found_callback callback)  { +	/* When starting with an existing id, the first id returned will +	 * be that device (if it is still on the bus most likely). +	 * +	 * If the number of devices found is less than or equal to the +	 * search_limit, that number of IDs will be returned.  If there are +	 * more, search_limit IDs will be returned followed by a non-zero +	 * discrepency value. +	 */ +	struct ds_device *dev = data;  	int err;  	u16 value, index;  	struct ds_status st; +	u8 st_buf[ST_SIZE]; +	int search_limit; +	int found = 0; +	int i; -	memset(buf, 0, sizeof(buf)); +	/* DS18b20 spec, 13.16 ms per device, 75 per second, sleep for +	 * discovering 8 devices (1 bulk transfer and 1/2 FIFO size) at a time. +	 */ +	const unsigned long jtime = msecs_to_jiffies(1000*8/75); +	/* FIFO 128 bytes, bulk packet size 64, read a multiple of the +	 * packet size. +	 */ +	u64 buf[2*64/8]; -	err = ds_send_data(ds_dev, (unsigned char *)&init, 8); -	if (err) -		return err; +	mutex_lock(&master->bus_mutex); -	ds_wait_status(ds_dev, &st); +	/* address to start searching at */ +	if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0) +		goto search_out; +	master->search_id = 0; -	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; -	index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); -	err = ds_send_control(ds_dev, value, index); -	if (err) -		return err; +	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F | +		COMM_RTS; +	search_limit = master->max_slave_count; +	if (search_limit > 255) +		search_limit = 0; +	index = search_type | (search_limit << 8); +	if (ds_send_control(dev, value, index) < 0) +		goto search_out; -	ds_wait_status(ds_dev, &st); +	do { +		schedule_timeout(jtime); -	err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); -	if (err < 0) -		return err; +		if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) < +			sizeof(st)) { +			break; +		} -	return err/8; +		if (st.data_in_buffer_status) { +			/* Bulk in can receive partial ids, but when it does +			 * they fail crc and will be discarded anyway. +			 * That has only been seen when status in buffer +			 * is 0 and bulk is read anyway, so don't read +			 * bulk without first checking if status says there +			 * is data to read. +			 */ +			err = ds_recv_data(dev, (u8 *)buf, sizeof(buf)); +			if (err < 0) +				break; +			for (i = 0; i < err/8; ++i) { +				++found; +				if (found <= search_limit) +					callback(master, buf[i]); +				/* can't know if there will be a discrepancy +				 * value after until the next id */ +				if (found == search_limit) +					master->search_id = buf[i]; +			} +		} + +		if (test_bit(W1_ABORT_SEARCH, &master->flags)) +			break; +	} while (!(st.status & (ST_IDLE | ST_HALT))); + +	/* only continue the search if some weren't found */ +	if (found <= search_limit) { +		master->search_id = 0; +	} else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) { +		/* Only max_slave_count will be scanned in a search, +		 * but it will start where it left off next search +		 * until all ids are identified and then it will start +		 * over.  A continued search will report the previous +		 * last id as the first id (provided it is still on the +		 * bus). +		 */ +		dev_info(&dev->udev->dev, "%s: max_slave_count %d reached, " +			"will continue next search.\n", __func__, +			master->max_slave_count); +		set_bit(W1_WARN_MAX_COUNT, &master->flags); +	} +search_out: +	mutex_unlock(&master->bus_mutex);  } +#if 0  static int ds_match_access(struct ds_device *dev, u64 init)  {  	int err; @@ -894,6 +971,7 @@ static int ds_w1_init(struct ds_device *dev)  	dev->master.write_block	= &ds9490r_write_block;  	dev->master.reset_bus	= &ds9490r_reset;  	dev->master.set_pullup	= &ds9490r_set_pullup; +	dev->master.search	= &ds9490r_search;  	return w1_add_master_device(&dev->master);  } @@ -910,15 +988,13 @@ static int ds_probe(struct usb_interface *intf,  	struct usb_endpoint_descriptor *endpoint;  	struct usb_host_interface *iface_desc;  	struct ds_device *dev; -	int i, err; +	int i, err, alt; -	dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); +	dev = kzalloc(sizeof(struct ds_device), GFP_KERNEL);  	if (!dev) {  		printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");  		return -ENOMEM;  	} -	dev->spu_sleep = 0; -	dev->spu_bit = 0;  	dev->udev = usb_get_dev(udev);  	if (!dev->udev) {  		err = -ENOMEM; @@ -928,20 +1004,25 @@ static int ds_probe(struct usb_interface *intf,  	usb_set_intfdata(intf, dev); -	err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); +	err = usb_reset_configuration(dev->udev);  	if (err) { -		printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", -				intf->altsetting[0].desc.bInterfaceNumber, err); +		dev_err(&dev->udev->dev, +			"Failed to reset configuration: err=%d.\n", err);  		goto err_out_clear;  	} -	err = usb_reset_configuration(dev->udev); +	/* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */ +	alt = 3; +	err = usb_set_interface(dev->udev, +		intf->altsetting[alt].desc.bInterfaceNumber, alt);  	if (err) { -		printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); +		dev_err(&dev->udev->dev, "Failed to set alternative setting %d " +			"for %d interface: err=%d.\n", alt, +			intf->altsetting[alt].desc.bInterfaceNumber, err);  		goto err_out_clear;  	} -	iface_desc = &intf->altsetting[0]; +	iface_desc = &intf->altsetting[alt];  	if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {  		printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);  		err = -EINVAL; @@ -1002,27 +1083,8 @@ static void ds_disconnect(struct usb_interface *intf)  	kfree(dev);  } -static int ds_init(void) -{ -	int err; - -	err = usb_register(&ds_driver); -	if (err) { -		printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); -		return err; -	} - -	return 0; -} - -static void ds_fini(void) -{ -	usb_deregister(&ds_driver); -} - -module_init(ds_init); -module_exit(ds_fini); +module_usb_driver(ds_driver);  MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); +MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");  MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c index 1550431ccb6..d8667b0212d 100644 --- a/drivers/w1/masters/matrox_w1.c +++ b/drivers/w1/masters/matrox_w1.c @@ -1,7 +1,7 @@  /*   *	matrox_w1.c   * - * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> + * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>   *   *   * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,7 @@   */  #include <asm/types.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/io.h>  #include <linux/delay.h> @@ -39,7 +39,7 @@  #include "../w1_log.h"  MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); +MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");  MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio).");  static struct pci_device_id matrox_w1_tbl[] = { @@ -48,14 +48,14 @@ static struct pci_device_id matrox_w1_tbl[] = {  };  MODULE_DEVICE_TABLE(pci, matrox_w1_tbl); -static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *); -static void __devexit matrox_w1_remove(struct pci_dev *); +static int matrox_w1_probe(struct pci_dev *, const struct pci_device_id *); +static void matrox_w1_remove(struct pci_dev *);  static struct pci_driver matrox_w1_pci_driver = {  	.name = "matrox_w1",  	.id_table = matrox_w1_tbl,  	.probe = matrox_w1_probe, -	.remove = __devexit_p(matrox_w1_remove), +	.remove = matrox_w1_remove,  };  /* @@ -152,7 +152,7 @@ static void matrox_w1_hw_init(struct matrox_device *dev)  	matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00);  } -static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	struct matrox_device *dev;  	int err; @@ -220,7 +220,7 @@ err_out_free_device:  	return err;  } -static void __devexit matrox_w1_remove(struct pci_dev *pdev) +static void matrox_w1_remove(struct pci_dev *pdev)  {  	struct matrox_device *dev = pci_get_drvdata(pdev); diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index a3b6a74c67a..a5df5e89d45 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -10,24 +10,16 @@   * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. - *   */ -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h>  #include <linux/clk.h> -#include <linux/slab.h>  #include <linux/delay.h>  #include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h>  #include "../w1.h"  #include "../w1_int.h" -#include "../w1_log.h"  /* According to the mx27 Datasheet the reset procedure should take up to about   * 1350us. We set the timeout to 500*100us = 50ms for sure */ @@ -36,17 +28,16 @@  /*   * MXC W1 Register offsets   */ -#define MXC_W1_CONTROL          0x00 -#define MXC_W1_TIME_DIVIDER     0x02 -#define MXC_W1_RESET            0x04 -#define MXC_W1_COMMAND          0x06 -#define MXC_W1_TXRX             0x08 -#define MXC_W1_INTERRUPT        0x0A -#define MXC_W1_INTERRUPT_EN     0x0C +#define MXC_W1_CONTROL		0x00 +# define MXC_W1_CONTROL_RDST	BIT(3) +# define MXC_W1_CONTROL_WR(x)	BIT(5 - (x)) +# define MXC_W1_CONTROL_PST	BIT(6) +# define MXC_W1_CONTROL_RPP	BIT(7) +#define MXC_W1_TIME_DIVIDER	0x02 +#define MXC_W1_RESET		0x04  struct mxc_w1_device {  	void __iomem *regs; -	unsigned int clkdiv;  	struct clk *clk;  	struct w1_bus_master bus_master;  }; @@ -62,12 +53,12 @@ static u8 mxc_w1_ds2_reset_bus(void *data)  	unsigned int timeout_cnt = 0;  	struct mxc_w1_device *dev = data; -	__raw_writeb(0x80, (dev->regs + MXC_W1_CONTROL)); +	writeb(MXC_W1_CONTROL_RPP, (dev->regs + MXC_W1_CONTROL));  	while (1) { -		reg_val = __raw_readb(dev->regs + MXC_W1_CONTROL); +		reg_val = readb(dev->regs + MXC_W1_CONTROL); -		if (((reg_val >> 7) & 0x1) == 0 || +		if (!(reg_val & MXC_W1_CONTROL_RPP) ||  		    timeout_cnt > MXC_W1_RESET_TIMEOUT)  			break;  		else @@ -75,7 +66,7 @@ static u8 mxc_w1_ds2_reset_bus(void *data)  		udelay(100);  	} -	return (reg_val >> 7) & 0x1; +	return !(reg_val & MXC_W1_CONTROL_PST);  }  /* @@ -91,121 +82,100 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)  					 * datasheet.  					 */ -	__raw_writeb((1 << (5 - bit)), ctrl_addr); +	writeb(MXC_W1_CONTROL_WR(bit), ctrl_addr);  	while (timeout_cnt--) { -		if (!((__raw_readb(ctrl_addr) >> (5 - bit)) & 0x1)) +		if (!(readb(ctrl_addr) & MXC_W1_CONTROL_WR(bit)))  			break;  		udelay(1);  	} -	return ((__raw_readb(ctrl_addr)) >> 3) & 0x1; +	return !!(readb(ctrl_addr) & MXC_W1_CONTROL_RDST);  } -static int __devinit mxc_w1_probe(struct platform_device *pdev) +static int mxc_w1_probe(struct platform_device *pdev)  {  	struct mxc_w1_device *mdev; +	unsigned long clkrate;  	struct resource *res; -	int err = 0; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) -		return -ENODEV; +	unsigned int clkdiv; +	int err; -	mdev = kzalloc(sizeof(struct mxc_w1_device), GFP_KERNEL); +	mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device), +			    GFP_KERNEL);  	if (!mdev)  		return -ENOMEM; -	mdev->clk = clk_get(&pdev->dev, "owire"); -	if (!mdev->clk) { -		err = -ENODEV; -		goto failed_clk; -	} +	mdev->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(mdev->clk)) +		return PTR_ERR(mdev->clk); -	mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; +	clkrate = clk_get_rate(mdev->clk); +	if (clkrate < 10000000) +		dev_warn(&pdev->dev, +			 "Low clock frequency causes improper function\n"); -	res = request_mem_region(res->start, resource_size(res), -				"mxc_w1"); -	if (!res) { -		err = -EBUSY; -		goto failed_req; -	} +	clkdiv = DIV_ROUND_CLOSEST(clkrate, 1000000); +	clkrate /= clkdiv; +	if ((clkrate < 980000) || (clkrate > 1020000)) +		dev_warn(&pdev->dev, +			 "Incorrect time base frequency %lu Hz\n", clkrate); -	mdev->regs = ioremap(res->start, resource_size(res)); -	if (!mdev->regs) { -		printk(KERN_ERR "Cannot map frame buffer registers\n"); -		goto failed_ioremap; -	} +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	mdev->regs = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(mdev->regs)) +		return PTR_ERR(mdev->regs); -	clk_enable(mdev->clk); -	__raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); +	err = clk_prepare_enable(mdev->clk); +	if (err) +		return err; + +	writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER);  	mdev->bus_master.data = mdev;  	mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus;  	mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit; -	err = w1_add_master_device(&mdev->bus_master); +	platform_set_drvdata(pdev, mdev); +	err = w1_add_master_device(&mdev->bus_master);  	if (err) -		goto failed_add; +		clk_disable_unprepare(mdev->clk); -	platform_set_drvdata(pdev, mdev); -	return 0; - -failed_add: -	iounmap(mdev->regs); -failed_ioremap: -	release_mem_region(res->start, resource_size(res)); -failed_req: -	clk_put(mdev->clk); -failed_clk: -	kfree(mdev);  	return err;  }  /*   * disassociate the w1 device from the driver   */ -static int __devexit mxc_w1_remove(struct platform_device *pdev) +static int mxc_w1_remove(struct platform_device *pdev)  {  	struct mxc_w1_device *mdev = platform_get_drvdata(pdev); -	struct resource *res; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	w1_remove_master_device(&mdev->bus_master); -	iounmap(mdev->regs); -	release_mem_region(res->start, resource_size(res)); -	clk_disable(mdev->clk); -	clk_put(mdev->clk); - -	platform_set_drvdata(pdev, NULL); +	clk_disable_unprepare(mdev->clk);  	return 0;  } +static struct of_device_id mxc_w1_dt_ids[] = { +	{ .compatible = "fsl,imx21-owire" }, +	{ /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxc_w1_dt_ids); +  static struct platform_driver mxc_w1_driver = {  	.driver = { -		   .name = "mxc_w1", +		.name = "mxc_w1", +		.owner = THIS_MODULE, +		.of_match_table = mxc_w1_dt_ids,  	},  	.probe = mxc_w1_probe,  	.remove = mxc_w1_remove,  }; - -static int __init mxc_w1_init(void) -{ -	return platform_driver_register(&mxc_w1_driver); -} - -static void mxc_w1_exit(void) -{ -	platform_driver_unregister(&mxc_w1_driver); -} - -module_init(mxc_w1_init); -module_exit(mxc_w1_exit); +module_platform_driver(mxc_w1_driver);  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Freescale Semiconductors Inc"); diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 3a7e9ff8a74..9900e8ec739 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -1,7 +1,7 @@  /*   * drivers/w1/masters/omap_hdq.c   * - * Copyright (C) 2007 Texas Instruments, Inc. + * Copyright (C) 2007,2012 Texas Instruments, Inc.   *   * This file is licensed under the terms of the GNU General Public License   * version 2. This program is licensed "as is" without any warranty of any @@ -14,12 +14,9 @@  #include <linux/interrupt.h>  #include <linux/slab.h>  #include <linux/err.h> -#include <linux/clk.h>  #include <linux/io.h>  #include <linux/sched.h> - -#include <asm/irq.h> -#include <mach/hardware.h> +#include <linux/pm_runtime.h>  #include "../w1.h"  #include "../w1_int.h" @@ -61,8 +58,6 @@ struct hdq_data {  	/* lock status update */  	struct  mutex		hdq_mutex;  	int			hdq_usecount; -	struct	clk		*hdq_ick; -	struct	clk		*hdq_fck;  	u8			hdq_irqstatus;  	/* device lock */  	spinlock_t		hdq_spinlock; @@ -74,7 +69,7 @@ struct hdq_data {  	int			init_trans;  }; -static int __devinit omap_hdq_probe(struct platform_device *pdev); +static int omap_hdq_probe(struct platform_device *pdev);  static int omap_hdq_remove(struct platform_device *pdev);  static struct platform_driver omap_hdq_driver = { @@ -102,20 +97,20 @@ static struct w1_bus_master omap_w1_master = {  /* HDQ register I/O routines */  static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)  { -	return __raw_readb(hdq_data->hdq_base + offset); +	return __raw_readl(hdq_data->hdq_base + offset);  }  static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)  { -	__raw_writeb(val, hdq_data->hdq_base + offset); +	__raw_writel(val, hdq_data->hdq_base + offset);  }  static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,  			u8 val, u8 mask)  { -	u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask) +	u8 new_val = (__raw_readl(hdq_data->hdq_base + offset) & ~mask)  			| (val & mask); -	__raw_writeb(new_val, hdq_data->hdq_base + offset); +	__raw_writel(new_val, hdq_data->hdq_base + offset);  	return new_val;  } @@ -180,6 +175,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)  		hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);  	if (ret == 0) {  		dev_dbg(hdq_data->dev, "TX wait elapsed\n"); +		ret = -ETIMEDOUT;  		goto out;  	} @@ -187,7 +183,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)  	/* check irqstatus */  	if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) {  		dev_dbg(hdq_data->dev, "timeout waiting for" -			"TXCOMPLETE/RXCOMPLETE, %x", *status); +			" TXCOMPLETE/RXCOMPLETE, %x", *status);  		ret = -ETIMEDOUT;  		goto out;  	} @@ -198,7 +194,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)  			OMAP_HDQ_FLAG_CLEAR, &tmp_status);  	if (ret) {  		dev_dbg(hdq_data->dev, "timeout waiting GO bit" -			"return to zero, %x", tmp_status); +			" return to zero, %x", tmp_status);  	}  out: @@ -341,7 +337,7 @@ static int omap_hdq_break(struct hdq_data *hdq_data)  			&tmp_status);  	if (ret)  		dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" -			"return to zero, %x", tmp_status); +			" return to zero, %x", tmp_status);  out:  	mutex_unlock(&hdq_data->hdq_mutex); @@ -353,7 +349,6 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)  {  	int ret = 0;  	u8 status; -	unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;  	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);  	if (ret < 0) { @@ -371,22 +366,20 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)  			OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,  			OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);  		/* -		 * The RX comes immediately after TX. It -		 * triggers another interrupt before we -		 * sleep. So we have to wait for RXCOMPLETE bit. +		 * The RX comes immediately after TX.  		 */ -		while (!(hdq_data->hdq_irqstatus -			& OMAP_HDQ_INT_STATUS_RXCOMPLETE) -			&& time_before(jiffies, timeout)) { -			schedule_timeout_uninterruptible(1); -		} +		wait_event_timeout(hdq_wait_queue, +				   (hdq_data->hdq_irqstatus +				    & OMAP_HDQ_INT_STATUS_RXCOMPLETE), +				   OMAP_HDQ_TIMEOUT); +  		hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0,  			OMAP_HDQ_CTRL_STATUS_DIR);  		status = hdq_data->hdq_irqstatus;  		/* check irqstatus */  		if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {  			dev_dbg(hdq_data->dev, "timeout waiting for" -				"RXCOMPLETE, %x", status); +				" RXCOMPLETE, %x", status);  			ret = -ETIMEDOUT;  			goto out;  		} @@ -396,7 +389,7 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)  out:  	mutex_unlock(&hdq_data->hdq_mutex);  rtn: -	return 0; +	return ret;  } @@ -419,17 +412,8 @@ static int omap_hdq_get(struct hdq_data *hdq_data)  		hdq_data->hdq_usecount++;  		try_module_get(THIS_MODULE);  		if (1 == hdq_data->hdq_usecount) { -			if (clk_enable(hdq_data->hdq_ick)) { -				dev_dbg(hdq_data->dev, "Can not enable ick\n"); -				ret = -ENODEV; -				goto clk_err; -			} -			if (clk_enable(hdq_data->hdq_fck)) { -				dev_dbg(hdq_data->dev, "Can not enable fck\n"); -				clk_disable(hdq_data->hdq_ick); -				ret = -ENODEV; -				goto clk_err; -			} + +			pm_runtime_get_sync(hdq_data->dev);  			/* make sure HDQ is out of reset */  			if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) & @@ -450,9 +434,6 @@ static int omap_hdq_get(struct hdq_data *hdq_data)  		}  	} -clk_err: -	clk_put(hdq_data->hdq_ick); -	clk_put(hdq_data->hdq_fck);  out:  	mutex_unlock(&hdq_data->hdq_mutex);  rtn: @@ -470,15 +451,13 @@ static int omap_hdq_put(struct hdq_data *hdq_data)  	if (0 == hdq_data->hdq_usecount) {  		dev_dbg(hdq_data->dev, "attempt to decrement use count" -			"when it is zero"); +			" when it is zero");  		ret = -EINVAL;  	} else {  		hdq_data->hdq_usecount--;  		module_put(THIS_MODULE); -		if (0 == hdq_data->hdq_usecount) { -			clk_disable(hdq_data->hdq_ick); -			clk_disable(hdq_data->hdq_fck); -		} +		if (0 == hdq_data->hdq_usecount) +			pm_runtime_put_sync(hdq_data->dev);  	}  	mutex_unlock(&hdq_data->hdq_mutex); @@ -540,12 +519,12 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)  	mutex_unlock(&hdq_data->hdq_mutex);  	ret = hdq_write_byte(hdq_data, byte, &status); -	if (ret == 0) { +	if (ret < 0) {  		dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status);  		return;  	} -	/* Second write, data transfered. Release the module */ +	/* Second write, data transferred. Release the module */  	if (hdq_data->init_trans > 1) {  		omap_hdq_put(hdq_data);  		ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); @@ -556,72 +535,35 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)  		hdq_data->init_trans = 0;  		mutex_unlock(&hdq_data->hdq_mutex);  	} - -	return;  } -static int __devinit omap_hdq_probe(struct platform_device *pdev) +static int omap_hdq_probe(struct platform_device *pdev)  { +	struct device *dev = &pdev->dev;  	struct hdq_data *hdq_data;  	struct resource *res;  	int ret, irq;  	u8 rev; -	hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL); +	hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);  	if (!hdq_data) {  		dev_dbg(&pdev->dev, "unable to allocate memory\n"); -		ret = -ENOMEM; -		goto err_kmalloc; +		return -ENOMEM;  	} -	hdq_data->dev = &pdev->dev; +	hdq_data->dev = dev;  	platform_set_drvdata(pdev, hdq_data);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_dbg(&pdev->dev, "unable to get resource\n"); -		ret = -ENXIO; -		goto err_resource; -	} - -	hdq_data->hdq_base = ioremap(res->start, SZ_4K); -	if (!hdq_data->hdq_base) { -		dev_dbg(&pdev->dev, "ioremap failed\n"); -		ret = -EINVAL; -		goto err_ioremap; -	} - -	/* get interface & functional clock objects */ -	hdq_data->hdq_ick = clk_get(&pdev->dev, "ick"); -	hdq_data->hdq_fck = clk_get(&pdev->dev, "fck"); - -	if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) { -		dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n"); -		if (IS_ERR(hdq_data->hdq_ick)) { -			ret = PTR_ERR(hdq_data->hdq_ick); -			goto err_clk; -		} -		if (IS_ERR(hdq_data->hdq_fck)) { -			ret = PTR_ERR(hdq_data->hdq_fck); -			clk_put(hdq_data->hdq_ick); -			goto err_clk; -		} -	} +	hdq_data->hdq_base = devm_ioremap_resource(dev, res); +	if (IS_ERR(hdq_data->hdq_base)) +		return PTR_ERR(hdq_data->hdq_base);  	hdq_data->hdq_usecount = 0;  	mutex_init(&hdq_data->hdq_mutex); -	if (clk_enable(hdq_data->hdq_ick)) { -		dev_dbg(&pdev->dev, "Can not enable ick\n"); -		ret = -ENODEV; -		goto err_intfclk; -	} - -	if (clk_enable(hdq_data->hdq_fck)) { -		dev_dbg(&pdev->dev, "Can not enable fck\n"); -		ret = -ENODEV; -		goto err_fnclk; -	} +	pm_runtime_enable(&pdev->dev); +	pm_runtime_get_sync(&pdev->dev);  	rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);  	dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n", @@ -635,7 +577,7 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)  		goto err_irq;  	} -	ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data); +	ret = devm_request_irq(dev, irq, hdq_isr, 0, "omap_hdq", hdq_data);  	if (ret < 0) {  		dev_dbg(&pdev->dev, "could not request irq\n");  		goto err_irq; @@ -643,9 +585,7 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)  	omap_hdq_break(hdq_data); -	/* don't clock the HDQ until it is needed */ -	clk_disable(hdq_data->hdq_ick); -	clk_disable(hdq_data->hdq_fck); +	pm_runtime_put_sync(&pdev->dev);  	omap_w1_master.data = hdq_data; @@ -657,28 +597,12 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)  	return 0; -err_w1:  err_irq: -	clk_disable(hdq_data->hdq_fck); - -err_fnclk: -	clk_disable(hdq_data->hdq_ick); - -err_intfclk: -	clk_put(hdq_data->hdq_ick); -	clk_put(hdq_data->hdq_fck); - -err_clk: -	iounmap(hdq_data->hdq_base); - -err_ioremap: -err_resource: -	platform_set_drvdata(pdev, NULL); -	kfree(hdq_data); +	pm_runtime_put_sync(&pdev->dev); +err_w1: +	pm_runtime_disable(&pdev->dev); -err_kmalloc:  	return ret; -  }  static int omap_hdq_remove(struct platform_device *pdev) @@ -696,29 +620,12 @@ static int omap_hdq_remove(struct platform_device *pdev)  	mutex_unlock(&hdq_data->hdq_mutex);  	/* remove module dependency */ -	clk_put(hdq_data->hdq_ick); -	clk_put(hdq_data->hdq_fck); -	free_irq(INT_24XX_HDQ_IRQ, hdq_data); -	platform_set_drvdata(pdev, NULL); -	iounmap(hdq_data->hdq_base); -	kfree(hdq_data); +	pm_runtime_disable(&pdev->dev);  	return 0;  } -static int __init -omap_hdq_init(void) -{ -	return platform_driver_register(&omap_hdq_driver); -} -module_init(omap_hdq_init); - -static void __exit -omap_hdq_exit(void) -{ -	platform_driver_unregister(&omap_hdq_driver); -} -module_exit(omap_hdq_exit); +module_platform_driver(omap_hdq_driver);  module_param(w1_id, int, S_IRUSR);  MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection"); diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index fcbe742188a..1d111e56c8c 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -13,11 +13,35 @@  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <linux/w1-gpio.h> +#include <linux/gpio.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/delay.h>  #include "../w1.h"  #include "../w1_int.h" -#include <asm/gpio.h> +static u8 w1_gpio_set_pullup(void *data, int delay) +{ +	struct w1_gpio_platform_data *pdata = data; + +	if (delay) { +		pdata->pullup_duration = delay; +	} else { +		if (pdata->pullup_duration) { +			gpio_direction_output(pdata->pin, 1); + +			msleep(pdata->pullup_duration); + +			gpio_direction_input(pdata->pin); +		} +		pdata->pullup_duration = 0; +	} + +	return 0; +}  static void w1_gpio_write_bit_dir(void *data, u8 bit)  { @@ -43,22 +67,91 @@ static u8 w1_gpio_read_bit(void *data)  	return gpio_get_value(pdata->pin) ? 1 : 0;  } -static int __init w1_gpio_probe(struct platform_device *pdev) +#if defined(CONFIG_OF) +static struct of_device_id w1_gpio_dt_ids[] = { +	{ .compatible = "w1-gpio" }, +	{} +}; +MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); +#endif + +static int w1_gpio_probe_dt(struct platform_device *pdev) +{ +	struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); +	struct device_node *np = pdev->dev.of_node; +	int gpio; + +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return -ENOMEM; + +	if (of_get_property(np, "linux,open-drain", NULL)) +		pdata->is_open_drain = 1; + +	gpio = of_get_gpio(np, 0); +	if (gpio < 0) { +		if (gpio != -EPROBE_DEFER) +			dev_err(&pdev->dev, +					"Failed to parse gpio property for data pin (%d)\n", +					gpio); + +		return gpio; +	} +	pdata->pin = gpio; + +	gpio = of_get_gpio(np, 1); +	if (gpio == -EPROBE_DEFER) +		return gpio; +	/* ignore other errors as the pullup gpio is optional */ +	pdata->ext_pullup_enable_pin = gpio; + +	pdev->dev.platform_data = pdata; + +	return 0; +} + +static int w1_gpio_probe(struct platform_device *pdev)  {  	struct w1_bus_master *master; -	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; +	struct w1_gpio_platform_data *pdata;  	int err; -	if (!pdata) +	if (of_have_populated_dt()) { +		err = w1_gpio_probe_dt(pdev); +		if (err < 0) +			return err; +	} + +	pdata = dev_get_platdata(&pdev->dev); + +	if (!pdata) { +		dev_err(&pdev->dev, "No configuration data\n");  		return -ENXIO; +	} -	master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL); -	if (!master) +	master = devm_kzalloc(&pdev->dev, sizeof(struct w1_bus_master), +			GFP_KERNEL); +	if (!master) { +		dev_err(&pdev->dev, "Out of memory\n");  		return -ENOMEM; +	} -	err = gpio_request(pdata->pin, "w1"); -	if (err) -		goto free_master; +	err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); +	if (err) { +		dev_err(&pdev->dev, "gpio_request (pin) failed\n"); +		return err; +	} + +	if (gpio_is_valid(pdata->ext_pullup_enable_pin)) { +		err = devm_gpio_request_one(&pdev->dev, +				pdata->ext_pullup_enable_pin, GPIOF_INIT_LOW, +				"w1 pullup"); +		if (err < 0) { +			dev_err(&pdev->dev, "gpio_request_one " +					"(ext_pullup_enable_pin) failed\n"); +			return err; +		} +	}  	master->data = pdata;  	master->read_bit = w1_gpio_read_bit; @@ -69,38 +162,38 @@ static int __init w1_gpio_probe(struct platform_device *pdev)  	} else {  		gpio_direction_input(pdata->pin);  		master->write_bit = w1_gpio_write_bit_dir; +		master->set_pullup = w1_gpio_set_pullup;  	}  	err = w1_add_master_device(master); -	if (err) -		goto free_gpio; +	if (err) { +		dev_err(&pdev->dev, "w1_add_master device failed\n"); +		return err; +	}  	if (pdata->enable_external_pullup)  		pdata->enable_external_pullup(1); +	if (gpio_is_valid(pdata->ext_pullup_enable_pin)) +		gpio_set_value(pdata->ext_pullup_enable_pin, 1); +  	platform_set_drvdata(pdev, master);  	return 0; - - free_gpio: -	gpio_free(pdata->pin); - free_master: -	kfree(master); - -	return err;  } -static int __exit w1_gpio_remove(struct platform_device *pdev) +static int w1_gpio_remove(struct platform_device *pdev)  {  	struct w1_bus_master *master = platform_get_drvdata(pdev); -	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; +	struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);  	if (pdata->enable_external_pullup)  		pdata->enable_external_pullup(0); +	if (gpio_is_valid(pdata->ext_pullup_enable_pin)) +		gpio_set_value(pdata->ext_pullup_enable_pin, 0); +  	w1_remove_master_device(master); -	gpio_free(pdata->pin); -	kfree(master);  	return 0;  } @@ -109,7 +202,7 @@ static int __exit w1_gpio_remove(struct platform_device *pdev)  static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)  { -	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; +	struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);  	if (pdata->enable_external_pullup)  		pdata->enable_external_pullup(0); @@ -119,7 +212,7 @@ static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)  static int w1_gpio_resume(struct platform_device *pdev)  { -	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; +	struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);  	if (pdata->enable_external_pullup)  		pdata->enable_external_pullup(1); @@ -136,24 +229,15 @@ static struct platform_driver w1_gpio_driver = {  	.driver = {  		.name	= "w1-gpio",  		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(w1_gpio_dt_ids),  	}, -	.remove	= __exit_p(w1_gpio_remove), +	.probe = w1_gpio_probe, +	.remove	= w1_gpio_remove,  	.suspend = w1_gpio_suspend,  	.resume = w1_gpio_resume,  }; -static int __init w1_gpio_init(void) -{ -	return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe); -} - -static void __exit w1_gpio_exit(void) -{ -	platform_driver_unregister(&w1_gpio_driver); -} - -module_init(w1_gpio_init); -module_exit(w1_gpio_exit); +module_platform_driver(w1_gpio_driver);  MODULE_DESCRIPTION("GPIO w1 bus master driver");  MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");  | 
