diff options
author | Vignesh R <vigneshr@ti.com> | 2015-09-14 13:54:33 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-04 23:47:09 -0400 |
commit | e93762bbf68143594223024532fdeef71f5e8f75 (patch) | |
tree | 3d3a334353e7131a5a3777a586a9dfc4cf35a537 /drivers/w1 | |
parent | 5052436dcb7eac532cf2ffd6650be01d3f15e0b5 (diff) |
w1: masters: omap_hdq: add support for 1-wire mode
This patches makes following changes to omap_hdq driver
- Enable 1-wire mode.
- Implement w1_triplet callback to facilitate search rom
procedure and auto detection of 1-wire slaves.
- Proper enabling and disabling of interrupt.
- Cleanups (formatting and return value checks).
HDQ mode remains unchanged.
Signed-off-by: Vignesh R <vigneshr@ti.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Cc: Jonathan Corbet <corbet@lwn.net>
CC: Tony Lindgren <tony@atomide.com>
Cc: Vignesh R <vigneshr@ti.com>
Cc: NeilBrown <neilb@suse.de>
Cc: Fabian Frederick <fabf@skynet.be>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/w1')
-rw-r--r-- | drivers/w1/masters/omap_hdq.c | 224 |
1 files changed, 191 insertions, 33 deletions
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index e7d448963a24..0e2f43bccf1f 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/pm_runtime.h> | 19 | #include <linux/pm_runtime.h> |
20 | #include <linux/of.h> | ||
20 | 21 | ||
21 | #include "../w1.h" | 22 | #include "../w1.h" |
22 | #include "../w1_int.h" | 23 | #include "../w1_int.h" |
@@ -27,21 +28,23 @@ | |||
27 | #define OMAP_HDQ_TX_DATA 0x04 | 28 | #define OMAP_HDQ_TX_DATA 0x04 |
28 | #define OMAP_HDQ_RX_DATA 0x08 | 29 | #define OMAP_HDQ_RX_DATA 0x08 |
29 | #define OMAP_HDQ_CTRL_STATUS 0x0c | 30 | #define OMAP_HDQ_CTRL_STATUS 0x0c |
30 | #define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK (1<<6) | 31 | #define OMAP_HDQ_CTRL_STATUS_SINGLE BIT(7) |
31 | #define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE (1<<5) | 32 | #define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK BIT(6) |
32 | #define OMAP_HDQ_CTRL_STATUS_GO (1<<4) | 33 | #define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE BIT(5) |
33 | #define OMAP_HDQ_CTRL_STATUS_INITIALIZATION (1<<2) | 34 | #define OMAP_HDQ_CTRL_STATUS_GO BIT(4) |
34 | #define OMAP_HDQ_CTRL_STATUS_DIR (1<<1) | 35 | #define OMAP_HDQ_CTRL_STATUS_PRESENCE BIT(3) |
35 | #define OMAP_HDQ_CTRL_STATUS_MODE (1<<0) | 36 | #define OMAP_HDQ_CTRL_STATUS_INITIALIZATION BIT(2) |
37 | #define OMAP_HDQ_CTRL_STATUS_DIR BIT(1) | ||
36 | #define OMAP_HDQ_INT_STATUS 0x10 | 38 | #define OMAP_HDQ_INT_STATUS 0x10 |
37 | #define OMAP_HDQ_INT_STATUS_TXCOMPLETE (1<<2) | 39 | #define OMAP_HDQ_INT_STATUS_TXCOMPLETE BIT(2) |
38 | #define OMAP_HDQ_INT_STATUS_RXCOMPLETE (1<<1) | 40 | #define OMAP_HDQ_INT_STATUS_RXCOMPLETE BIT(1) |
39 | #define OMAP_HDQ_INT_STATUS_TIMEOUT (1<<0) | 41 | #define OMAP_HDQ_INT_STATUS_TIMEOUT BIT(0) |
40 | #define OMAP_HDQ_SYSCONFIG 0x14 | 42 | #define OMAP_HDQ_SYSCONFIG 0x14 |
41 | #define OMAP_HDQ_SYSCONFIG_SOFTRESET (1<<1) | 43 | #define OMAP_HDQ_SYSCONFIG_SOFTRESET BIT(1) |
42 | #define OMAP_HDQ_SYSCONFIG_AUTOIDLE (1<<0) | 44 | #define OMAP_HDQ_SYSCONFIG_AUTOIDLE BIT(0) |
45 | #define OMAP_HDQ_SYSCONFIG_NOIDLE 0x0 | ||
43 | #define OMAP_HDQ_SYSSTATUS 0x18 | 46 | #define OMAP_HDQ_SYSSTATUS 0x18 |
44 | #define OMAP_HDQ_SYSSTATUS_RESETDONE (1<<0) | 47 | #define OMAP_HDQ_SYSSTATUS_RESETDONE BIT(0) |
45 | 48 | ||
46 | #define OMAP_HDQ_FLAG_CLEAR 0 | 49 | #define OMAP_HDQ_FLAG_CLEAR 0 |
47 | #define OMAP_HDQ_FLAG_SET 1 | 50 | #define OMAP_HDQ_FLAG_SET 1 |
@@ -67,6 +70,10 @@ struct hdq_data { | |||
67 | * the data wrire or read. | 70 | * the data wrire or read. |
68 | */ | 71 | */ |
69 | int init_trans; | 72 | int init_trans; |
73 | int rrw; | ||
74 | /* mode: 0-HDQ 1-W1 */ | ||
75 | int mode; | ||
76 | |||
70 | }; | 77 | }; |
71 | 78 | ||
72 | static int omap_hdq_probe(struct platform_device *pdev); | 79 | static int omap_hdq_probe(struct platform_device *pdev); |
@@ -74,6 +81,7 @@ static int omap_hdq_remove(struct platform_device *pdev); | |||
74 | 81 | ||
75 | static const struct of_device_id omap_hdq_dt_ids[] = { | 82 | static const struct of_device_id omap_hdq_dt_ids[] = { |
76 | { .compatible = "ti,omap3-1w" }, | 83 | { .compatible = "ti,omap3-1w" }, |
84 | { .compatible = "ti,am4372-hdq" }, | ||
77 | {} | 85 | {} |
78 | }; | 86 | }; |
79 | MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids); | 87 | MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids); |
@@ -90,15 +98,12 @@ static struct platform_driver omap_hdq_driver = { | |||
90 | static u8 omap_w1_read_byte(void *_hdq); | 98 | static u8 omap_w1_read_byte(void *_hdq); |
91 | static void omap_w1_write_byte(void *_hdq, u8 byte); | 99 | static void omap_w1_write_byte(void *_hdq, u8 byte); |
92 | static u8 omap_w1_reset_bus(void *_hdq); | 100 | static u8 omap_w1_reset_bus(void *_hdq); |
93 | static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev, | ||
94 | u8 search_type, w1_slave_found_callback slave_found); | ||
95 | 101 | ||
96 | 102 | ||
97 | static struct w1_bus_master omap_w1_master = { | 103 | static struct w1_bus_master omap_w1_master = { |
98 | .read_byte = omap_w1_read_byte, | 104 | .read_byte = omap_w1_read_byte, |
99 | .write_byte = omap_w1_write_byte, | 105 | .write_byte = omap_w1_write_byte, |
100 | .reset_bus = omap_w1_reset_bus, | 106 | .reset_bus = omap_w1_reset_bus, |
101 | .search = omap_w1_search_bus, | ||
102 | }; | 107 | }; |
103 | 108 | ||
104 | /* HDQ register I/O routines */ | 109 | /* HDQ register I/O routines */ |
@@ -122,6 +127,15 @@ static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset, | |||
122 | return new_val; | 127 | return new_val; |
123 | } | 128 | } |
124 | 129 | ||
130 | static void hdq_disable_interrupt(struct hdq_data *hdq_data, u32 offset, | ||
131 | u32 mask) | ||
132 | { | ||
133 | u32 ie; | ||
134 | |||
135 | ie = readl(hdq_data->hdq_base + offset); | ||
136 | writel(ie & mask, hdq_data->hdq_base + offset); | ||
137 | } | ||
138 | |||
125 | /* | 139 | /* |
126 | * Wait for one or more bits in flag change. | 140 | * Wait for one or more bits in flag change. |
127 | * HDQ_FLAG_SET: wait until any bit in the flag is set. | 141 | * HDQ_FLAG_SET: wait until any bit in the flag is set. |
@@ -229,13 +243,7 @@ static irqreturn_t hdq_isr(int irq, void *_hdq) | |||
229 | return IRQ_HANDLED; | 243 | return IRQ_HANDLED; |
230 | } | 244 | } |
231 | 245 | ||
232 | /* HDQ Mode: always return success */ | 246 | /* W1 search callback function in HDQ mode */ |
233 | static u8 omap_w1_reset_bus(void *_hdq) | ||
234 | { | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | /* W1 search callback function */ | ||
239 | static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev, | 247 | static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev, |
240 | u8 search_type, w1_slave_found_callback slave_found) | 248 | u8 search_type, w1_slave_found_callback slave_found) |
241 | { | 249 | { |
@@ -262,9 +270,10 @@ static int _omap_hdq_reset(struct hdq_data *hdq_data) | |||
262 | int ret; | 270 | int ret; |
263 | u8 tmp_status; | 271 | u8 tmp_status; |
264 | 272 | ||
265 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET); | 273 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, |
274 | OMAP_HDQ_SYSCONFIG_SOFTRESET); | ||
266 | /* | 275 | /* |
267 | * Select HDQ mode & enable clocks. | 276 | * Select HDQ/1W mode & enable clocks. |
268 | * It is observed that INT flags can't be cleared via a read and GO/INIT | 277 | * It is observed that INT flags can't be cleared via a read and GO/INIT |
269 | * won't return to zero if interrupt is disabled. So we always enable | 278 | * won't return to zero if interrupt is disabled. So we always enable |
270 | * interrupt. | 279 | * interrupt. |
@@ -282,7 +291,8 @@ static int _omap_hdq_reset(struct hdq_data *hdq_data) | |||
282 | else { | 291 | else { |
283 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | 292 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, |
284 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | 293 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | |
285 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | 294 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK | |
295 | hdq_data->mode); | ||
286 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, | 296 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, |
287 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); | 297 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); |
288 | } | 298 | } |
@@ -334,6 +344,18 @@ static int omap_hdq_break(struct hdq_data *hdq_data) | |||
334 | ret = -ETIMEDOUT; | 344 | ret = -ETIMEDOUT; |
335 | goto out; | 345 | goto out; |
336 | } | 346 | } |
347 | |||
348 | /* | ||
349 | * check for the presence detect bit to get | ||
350 | * set to show that the slave is responding | ||
351 | */ | ||
352 | if (!(hdq_reg_in(hdq_data, OMAP_HDQ_CTRL_STATUS) & | ||
353 | OMAP_HDQ_CTRL_STATUS_PRESENCE)) { | ||
354 | dev_dbg(hdq_data->dev, "Presence bit not set\n"); | ||
355 | ret = -ETIMEDOUT; | ||
356 | goto out; | ||
357 | } | ||
358 | |||
337 | /* | 359 | /* |
338 | * wait for both INIT and GO bits rerurn to zero. | 360 | * wait for both INIT and GO bits rerurn to zero. |
339 | * zero wait time expected for interrupt mode. | 361 | * zero wait time expected for interrupt mode. |
@@ -368,6 +390,8 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) | |||
368 | goto out; | 390 | goto out; |
369 | } | 391 | } |
370 | 392 | ||
393 | hdq_data->hdq_irqstatus = 0; | ||
394 | |||
371 | if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { | 395 | if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { |
372 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, | 396 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, |
373 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, | 397 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, |
@@ -400,7 +424,7 @@ rtn: | |||
400 | 424 | ||
401 | } | 425 | } |
402 | 426 | ||
403 | /* Enable clocks and set the controller to HDQ mode */ | 427 | /* Enable clocks and set the controller to HDQ/1W mode */ |
404 | static int omap_hdq_get(struct hdq_data *hdq_data) | 428 | static int omap_hdq_get(struct hdq_data *hdq_data) |
405 | { | 429 | { |
406 | int ret = 0; | 430 | int ret = 0; |
@@ -422,7 +446,7 @@ static int omap_hdq_get(struct hdq_data *hdq_data) | |||
422 | 446 | ||
423 | pm_runtime_get_sync(hdq_data->dev); | 447 | pm_runtime_get_sync(hdq_data->dev); |
424 | 448 | ||
425 | /* make sure HDQ is out of reset */ | 449 | /* make sure HDQ/1W is out of reset */ |
426 | if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) & | 450 | if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) & |
427 | OMAP_HDQ_SYSSTATUS_RESETDONE)) { | 451 | OMAP_HDQ_SYSSTATUS_RESETDONE)) { |
428 | ret = _omap_hdq_reset(hdq_data); | 452 | ret = _omap_hdq_reset(hdq_data); |
@@ -430,12 +454,13 @@ static int omap_hdq_get(struct hdq_data *hdq_data) | |||
430 | /* back up the count */ | 454 | /* back up the count */ |
431 | hdq_data->hdq_usecount--; | 455 | hdq_data->hdq_usecount--; |
432 | } else { | 456 | } else { |
433 | /* select HDQ mode & enable clocks */ | 457 | /* select HDQ/1W mode & enable clocks */ |
434 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, | 458 | hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, |
435 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | | 459 | OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | |
436 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | 460 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK | |
461 | hdq_data->mode); | ||
437 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, | 462 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, |
438 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); | 463 | OMAP_HDQ_SYSCONFIG_NOIDLE); |
439 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); | 464 | hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); |
440 | } | 465 | } |
441 | } | 466 | } |
@@ -456,6 +481,8 @@ static int omap_hdq_put(struct hdq_data *hdq_data) | |||
456 | if (ret < 0) | 481 | if (ret < 0) |
457 | return -EINTR; | 482 | return -EINTR; |
458 | 483 | ||
484 | hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, | ||
485 | OMAP_HDQ_SYSCONFIG_AUTOIDLE); | ||
459 | if (0 == hdq_data->hdq_usecount) { | 486 | if (0 == hdq_data->hdq_usecount) { |
460 | dev_dbg(hdq_data->dev, "attempt to decrement use count" | 487 | dev_dbg(hdq_data->dev, "attempt to decrement use count" |
461 | " when it is zero"); | 488 | " when it is zero"); |
@@ -471,6 +498,100 @@ static int omap_hdq_put(struct hdq_data *hdq_data) | |||
471 | return ret; | 498 | return ret; |
472 | } | 499 | } |
473 | 500 | ||
501 | /* | ||
502 | * W1 triplet callback function - used for searching ROM addresses. | ||
503 | * Registered only when controller is in 1-wire mode. | ||
504 | */ | ||
505 | static u8 omap_w1_triplet(void *_hdq, u8 bdir) | ||
506 | { | ||
507 | u8 id_bit, comp_bit; | ||
508 | int err; | ||
509 | u8 ret = 0x3; /* no slaves responded */ | ||
510 | struct hdq_data *hdq_data = _hdq; | ||
511 | u8 ctrl = OMAP_HDQ_CTRL_STATUS_SINGLE | OMAP_HDQ_CTRL_STATUS_GO | | ||
512 | OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK; | ||
513 | u8 mask = ctrl | OMAP_HDQ_CTRL_STATUS_DIR; | ||
514 | |||
515 | omap_hdq_get(_hdq); | ||
516 | |||
517 | err = mutex_lock_interruptible(&hdq_data->hdq_mutex); | ||
518 | if (err < 0) { | ||
519 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | ||
520 | goto rtn; | ||
521 | } | ||
522 | |||
523 | hdq_data->hdq_irqstatus = 0; | ||
524 | /* read id_bit */ | ||
525 | hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS, | ||
526 | ctrl | OMAP_HDQ_CTRL_STATUS_DIR, mask); | ||
527 | err = wait_event_timeout(hdq_wait_queue, | ||
528 | (hdq_data->hdq_irqstatus | ||
529 | & OMAP_HDQ_INT_STATUS_RXCOMPLETE), | ||
530 | OMAP_HDQ_TIMEOUT); | ||
531 | if (err == 0) { | ||
532 | dev_dbg(hdq_data->dev, "RX wait elapsed\n"); | ||
533 | goto out; | ||
534 | } | ||
535 | id_bit = (hdq_reg_in(_hdq, OMAP_HDQ_RX_DATA) & 0x01); | ||
536 | |||
537 | hdq_data->hdq_irqstatus = 0; | ||
538 | /* read comp_bit */ | ||
539 | hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS, | ||
540 | ctrl | OMAP_HDQ_CTRL_STATUS_DIR, mask); | ||
541 | err = wait_event_timeout(hdq_wait_queue, | ||
542 | (hdq_data->hdq_irqstatus | ||
543 | & OMAP_HDQ_INT_STATUS_RXCOMPLETE), | ||
544 | OMAP_HDQ_TIMEOUT); | ||
545 | if (err == 0) { | ||
546 | dev_dbg(hdq_data->dev, "RX wait elapsed\n"); | ||
547 | goto out; | ||
548 | } | ||
549 | comp_bit = (hdq_reg_in(_hdq, OMAP_HDQ_RX_DATA) & 0x01); | ||
550 | |||
551 | if (id_bit && comp_bit) { | ||
552 | ret = 0x03; /* no slaves responded */ | ||
553 | goto out; | ||
554 | } | ||
555 | if (!id_bit && !comp_bit) { | ||
556 | /* Both bits are valid, take the direction given */ | ||
557 | ret = bdir ? 0x04 : 0; | ||
558 | } else { | ||
559 | /* Only one bit is valid, take that direction */ | ||
560 | bdir = id_bit; | ||
561 | ret = id_bit ? 0x05 : 0x02; | ||
562 | } | ||
563 | |||
564 | /* write bdir bit */ | ||
565 | hdq_reg_out(_hdq, OMAP_HDQ_TX_DATA, bdir); | ||
566 | hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS, ctrl, mask); | ||
567 | err = wait_event_timeout(hdq_wait_queue, | ||
568 | (hdq_data->hdq_irqstatus | ||
569 | & OMAP_HDQ_INT_STATUS_TXCOMPLETE), | ||
570 | OMAP_HDQ_TIMEOUT); | ||
571 | if (err == 0) { | ||
572 | dev_dbg(hdq_data->dev, "TX wait elapsed\n"); | ||
573 | goto out; | ||
574 | } | ||
575 | |||
576 | hdq_reg_merge(_hdq, OMAP_HDQ_CTRL_STATUS, 0, | ||
577 | OMAP_HDQ_CTRL_STATUS_SINGLE); | ||
578 | |||
579 | out: | ||
580 | mutex_unlock(&hdq_data->hdq_mutex); | ||
581 | rtn: | ||
582 | omap_hdq_put(_hdq); | ||
583 | return ret; | ||
584 | } | ||
585 | |||
586 | /* reset callback */ | ||
587 | static u8 omap_w1_reset_bus(void *_hdq) | ||
588 | { | ||
589 | omap_hdq_get(_hdq); | ||
590 | omap_hdq_break(_hdq); | ||
591 | omap_hdq_put(_hdq); | ||
592 | return 0; | ||
593 | } | ||
594 | |||
474 | /* Read a byte of data from the device */ | 595 | /* Read a byte of data from the device */ |
475 | static u8 omap_w1_read_byte(void *_hdq) | 596 | static u8 omap_w1_read_byte(void *_hdq) |
476 | { | 597 | { |
@@ -478,6 +599,10 @@ static u8 omap_w1_read_byte(void *_hdq) | |||
478 | u8 val = 0; | 599 | u8 val = 0; |
479 | int ret; | 600 | int ret; |
480 | 601 | ||
602 | /* First write to initialize the transfer */ | ||
603 | if (hdq_data->init_trans == 0) | ||
604 | omap_hdq_get(hdq_data); | ||
605 | |||
481 | ret = hdq_read_byte(hdq_data, &val); | 606 | ret = hdq_read_byte(hdq_data, &val); |
482 | if (ret) { | 607 | if (ret) { |
483 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | 608 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); |
@@ -491,6 +616,10 @@ static u8 omap_w1_read_byte(void *_hdq) | |||
491 | return -1; | 616 | return -1; |
492 | } | 617 | } |
493 | 618 | ||
619 | hdq_disable_interrupt(hdq_data, OMAP_HDQ_CTRL_STATUS, | ||
620 | ~OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); | ||
621 | hdq_data->hdq_usecount = 0; | ||
622 | |||
494 | /* Write followed by a read, release the module */ | 623 | /* Write followed by a read, release the module */ |
495 | if (hdq_data->init_trans) { | 624 | if (hdq_data->init_trans) { |
496 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | 625 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); |
@@ -517,6 +646,14 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) | |||
517 | if (hdq_data->init_trans == 0) | 646 | if (hdq_data->init_trans == 0) |
518 | omap_hdq_get(hdq_data); | 647 | omap_hdq_get(hdq_data); |
519 | 648 | ||
649 | /* | ||
650 | * We need to reset the slave before | ||
651 | * issuing the SKIP ROM command, else | ||
652 | * the slave will not work. | ||
653 | */ | ||
654 | if (byte == W1_SKIP_ROM) | ||
655 | omap_hdq_break(hdq_data); | ||
656 | |||
520 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | 657 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); |
521 | if (ret < 0) { | 658 | if (ret < 0) { |
522 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); | 659 | dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); |
@@ -551,6 +688,7 @@ static int omap_hdq_probe(struct platform_device *pdev) | |||
551 | struct resource *res; | 688 | struct resource *res; |
552 | int ret, irq; | 689 | int ret, irq; |
553 | u8 rev; | 690 | u8 rev; |
691 | const char *mode; | ||
554 | 692 | ||
555 | hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL); | 693 | hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL); |
556 | if (!hdq_data) { | 694 | if (!hdq_data) { |
@@ -567,10 +705,21 @@ static int omap_hdq_probe(struct platform_device *pdev) | |||
567 | return PTR_ERR(hdq_data->hdq_base); | 705 | return PTR_ERR(hdq_data->hdq_base); |
568 | 706 | ||
569 | hdq_data->hdq_usecount = 0; | 707 | hdq_data->hdq_usecount = 0; |
708 | hdq_data->rrw = 0; | ||
570 | mutex_init(&hdq_data->hdq_mutex); | 709 | mutex_init(&hdq_data->hdq_mutex); |
571 | 710 | ||
572 | pm_runtime_enable(&pdev->dev); | 711 | pm_runtime_enable(&pdev->dev); |
573 | pm_runtime_get_sync(&pdev->dev); | 712 | ret = pm_runtime_get_sync(&pdev->dev); |
713 | if (ret < 0) { | ||
714 | dev_dbg(&pdev->dev, "pm_runtime_get_sync failed\n"); | ||
715 | goto err_w1; | ||
716 | } | ||
717 | |||
718 | ret = _omap_hdq_reset(hdq_data); | ||
719 | if (ret) { | ||
720 | dev_dbg(&pdev->dev, "reset failed\n"); | ||
721 | return -EINVAL; | ||
722 | } | ||
574 | 723 | ||
575 | rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION); | 724 | rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION); |
576 | dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n", | 725 | dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n", |
@@ -594,6 +743,15 @@ static int omap_hdq_probe(struct platform_device *pdev) | |||
594 | 743 | ||
595 | pm_runtime_put_sync(&pdev->dev); | 744 | pm_runtime_put_sync(&pdev->dev); |
596 | 745 | ||
746 | ret = of_property_read_string(pdev->dev.of_node, "ti,mode", &mode); | ||
747 | if (ret < 0 || !strcmp(mode, "hdq")) { | ||
748 | hdq_data->mode = 0; | ||
749 | omap_w1_master.search = omap_w1_search_bus; | ||
750 | } else { | ||
751 | hdq_data->mode = 1; | ||
752 | omap_w1_master.triplet = omap_w1_triplet; | ||
753 | } | ||
754 | |||
597 | omap_w1_master.data = hdq_data; | 755 | omap_w1_master.data = hdq_data; |
598 | 756 | ||
599 | ret = w1_add_master_device(&omap_w1_master); | 757 | ret = w1_add_master_device(&omap_w1_master); |
@@ -635,8 +793,8 @@ static int omap_hdq_remove(struct platform_device *pdev) | |||
635 | module_platform_driver(omap_hdq_driver); | 793 | module_platform_driver(omap_hdq_driver); |
636 | 794 | ||
637 | module_param(w1_id, int, S_IRUSR); | 795 | module_param(w1_id, int, S_IRUSR); |
638 | MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection"); | 796 | MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection in HDQ mode"); |
639 | 797 | ||
640 | MODULE_AUTHOR("Texas Instruments"); | 798 | MODULE_AUTHOR("Texas Instruments"); |
641 | MODULE_DESCRIPTION("HDQ driver Library"); | 799 | MODULE_DESCRIPTION("HDQ-1W driver Library"); |
642 | MODULE_LICENSE("GPL"); | 800 | MODULE_LICENSE("GPL"); |