Semi-decennial update. 50% code inflation.
[cbaos.git] / drivers / 1w / bitbang_1w.c
blobecb1e19678a4e4c391632c52cee0cd64a079f663
1 /* Author: Domen Puncer <domen@cba.si>. License: WTFPL, see file LICENSE */
2 #include <drivers/bitbang_1w.h>
3 #include <drivers/1w.h>
4 #include <gpio.h>
5 #include <board.h>
6 #include <lock.h>
7 #include <errno.h>
11 * One wire over GPIO. Supports parasitic nodes.
12 * The only thing you need to do is put a 1k+ pull-up on 1-wire line.
16 static int bitbang_1w_reset(struct w1_master *master)
18 struct bitbang_1w_data *chip = master->priv;
19 int pin = chip->pin;
20 int present;
22 gpio_init(pin, GPIO_OUTPUT, 0);
23 udelay(500);
24 gpio_init(pin, GPIO_INPUT, 0);
26 /* 15-60 of delay, then 60-240us long presence slot */
27 udelay(65);
28 present = gpio_get(pin);
29 udelay(500-65);
30 present |= gpio_get(pin)<<1;
32 if (present == 0x2)
33 return 0;
35 return -ENODEV;
39 * here's how I did it:
40 * write 1/read: out 0, 2us, in (1), 10us, read, 50us (total of 62us)
41 * write 0: out 0, 60us, in (1), 2us (total of 62us)
43 static int bitbang_1w_single_bit(int pin, int bit)
45 /* write 0 */
46 if (bit == 0) {
47 gpio_init(pin, GPIO_OUTPUT, 0);
48 udelay(60);
49 gpio_init(pin, GPIO_INPUT, 0);
50 udelay(2);
51 return 0;
54 /* write 1 / read */
55 gpio_init(pin, GPIO_OUTPUT, 0);
56 udelay(2);
57 gpio_init(pin, GPIO_INPUT, 0);
58 udelay(10);
59 bit = gpio_get(pin);
60 udelay(50);
61 return bit;
64 static int bitbang_1w_write(struct w1_master *master, u8 data)
66 struct bitbang_1w_data *chip = master->priv;
67 int pin = chip->pin;
68 int i;
69 struct lock l;
71 lock(&l);
72 for (i=0; i<8; i++) {
73 bitbang_1w_single_bit(pin, data&1);
74 data >>= 1;
76 unlock(&l);
78 return 0;
81 static int bitbang_1w_read(struct w1_master *master)
83 struct bitbang_1w_data *chip = master->priv;
84 int pin = chip->pin;
85 u8 data = 0;
86 int i;
87 struct lock l;
89 lock(&l);
90 for (i=0; i<8; i++) {
91 data |= bitbang_1w_single_bit(pin, 1) << i;
93 unlock(&l);
95 return data;
98 /* dir - 0/1 direction to take in case of device conflict */
99 static int bitbang_1w_triplet(struct w1_master *master, int dir)
101 struct bitbang_1w_data *chip = master->priv;
102 int pin = chip->pin;
103 struct lock l;
105 lock(&l);
106 int bit1 = bitbang_1w_single_bit(pin, 1);
107 int bit2 = bitbang_1w_single_bit(pin, 1);
109 if (bit1 ^ bit2)
110 bitbang_1w_single_bit(pin, bit1);
111 else
112 bitbang_1w_single_bit(pin, dir);
113 unlock(&l);
115 /* return value:
116 * bit 0: path taken
117 * bit 1: conflict?
120 /* error, no device pulled the bit low */
121 if (bit1 == 1 && bit2 == 1)
122 return -ENODEV;
124 /* conflict */
125 if (bit1 == 0 && bit2 == 0)
126 return 2 | dir;
127 return bit1;
130 int bitbang_1w_register(struct w1_master *master)
132 struct bitbang_1w_data *chip = master->priv;
133 int pin = chip->pin;
135 gpio_init(pin, GPIO_INPUT, 0);
137 master->w1_reset = bitbang_1w_reset;
138 master->w1_triplet = bitbang_1w_triplet;
139 master->w1_write = bitbang_1w_write;
140 master->w1_read = bitbang_1w_read;
142 return 0;