14 #include <linux/module.h>
23 #include <linux/slab.h>
28 #include "../w1_int.h"
31 #define DS1WM_CMD 0x00
32 #define DS1WM_DATA 0x01
33 #define DS1WM_INT 0x02
34 #define DS1WM_INT_EN 0x03
35 #define DS1WM_CLKDIV 0x04
36 #define DS1WM_CNTRL 0x05
38 #define DS1WM_CMD_1W_RESET (1 << 0)
39 #define DS1WM_CMD_SRA (1 << 1)
40 #define DS1WM_CMD_DQ_OUTPUT (1 << 2)
41 #define DS1WM_CMD_DQ_INPUT (1 << 3)
42 #define DS1WM_CMD_RST (1 << 5)
43 #define DS1WM_CMD_OD (1 << 7)
45 #define DS1WM_INT_PD (1 << 0)
46 #define DS1WM_INT_PDR (1 << 1)
47 #define DS1WM_INT_TBE (1 << 2)
48 #define DS1WM_INT_TSRE (1 << 3)
49 #define DS1WM_INT_RBF (1 << 4)
50 #define DS1WM_INT_RSRF (1 << 5)
52 #define DS1WM_INTEN_EPD (1 << 0)
53 #define DS1WM_INTEN_IAS (1 << 1)
54 #define DS1WM_INTEN_ETBE (1 << 2)
55 #define DS1WM_INTEN_ETMT (1 << 3)
56 #define DS1WM_INTEN_ERBF (1 << 4)
57 #define DS1WM_INTEN_ERSRF (1 << 5)
58 #define DS1WM_INTEN_DQO (1 << 6)
60 #define DS1WM_INTEN_NOT_IAS (~DS1WM_INTEN_IAS)
62 #define DS1WM_TIMEOUT (HZ * 5)
137 ds1wm_write_register(ds1wm_data,
141 intr = ds1wm_read_register(ds1wm_data,
DS1WM_INT);
151 ds1wm_data->
read_byte = ds1wm_read_register(ds1wm_data,
166 static int ds1wm_reset(
struct ds1wm_data *ds1wm_data)
168 unsigned long timeleft;
182 dev_err(&ds1wm_data->
pdev->dev,
"reset failed, timed out\n");
187 dev_dbg(&ds1wm_data->
pdev->dev,
"reset: no devices found\n");
197 static int ds1wm_write(
struct ds1wm_data *ds1wm_data,
u8 data)
199 unsigned long timeleft;
206 ds1wm_write_register(ds1wm_data,
DS1WM_DATA, data);
212 dev_err(&ds1wm_data->
pdev->dev,
"write failed, timed out\n");
219 static u8 ds1wm_read(
struct ds1wm_data *ds1wm_data,
unsigned char write_data)
221 unsigned long timeleft;
228 ds1wm_write_register(ds1wm_data,
DS1WM_INT_EN, intEnable);
230 ds1wm_write_register(ds1wm_data,
DS1WM_DATA, write_data);
235 dev_err(&ds1wm_data->
pdev->dev,
"read failed, timed out\n");
243 static int ds1wm_find_divisor(
int gclk)
249 return freq[
i].divisor;
254 static void ds1wm_up(
struct ds1wm_data *ds1wm_data)
259 if (ds1wm_data->
cell->enable)
260 ds1wm_data->
cell->enable(ds1wm_data->
pdev);
262 divisor = ds1wm_find_divisor(plat->
clock_rate);
264 "found divisor 0x%x for clock %d\n", divisor, plat->
clock_rate);
267 "no suitable divisor for %dHz clock\n",
271 ds1wm_write_register(ds1wm_data,
DS1WM_CLKDIV, divisor);
276 ds1wm_reset(ds1wm_data);
279 static void ds1wm_down(
struct ds1wm_data *ds1wm_data)
281 ds1wm_reset(ds1wm_data);
287 if (ds1wm_data->
cell->disable)
288 ds1wm_data->
cell->disable(ds1wm_data->
pdev);
294 static u8 ds1wm_read_byte(
void *data)
296 struct ds1wm_data *ds1wm_data =
data;
298 return ds1wm_read(ds1wm_data, 0xff);
301 static void ds1wm_write_byte(
void *data,
u8 byte)
303 struct ds1wm_data *ds1wm_data =
data;
305 ds1wm_write(ds1wm_data, byte);
308 static u8 ds1wm_reset_bus(
void *data)
310 struct ds1wm_data *ds1wm_data =
data;
312 ds1wm_reset(ds1wm_data);
317 static void ds1wm_search(
void *data,
struct w1_master *master_dev,
318 u8 search_type, w1_slave_found_callback slave_found)
320 struct ds1wm_data *ds1wm_data =
data;
322 int ms_discrep_bit = -1;
325 unsigned slaves_found = 0;
326 unsigned int pass = 0;
333 "too many attempts (100), search aborted\n");
338 if (ds1wm_reset(ds1wm_data)) {
341 "pass: %d reset error (or no slaves)\n", pass);
346 "pass: %d r : %0#18llx writing SEARCH_ROM\n", pass, r);
347 ds1wm_write(ds1wm_data, search_type);
349 "pass: %d entering ASM\n", pass);
352 "pass: %d beginning nibble loop\n", pass);
358 for (i = 0; i < 16; i++) {
360 unsigned char resp,
_r, _r_prime,
_d;
362 _r = (r >> (4*
i)) & 0xf;
363 _r = ((_r & 0x1) << 1) |
369 resp = ds1wm_read(ds1wm_data, _r);
373 "pass: %d nibble: %d read error\n", pass, i);
377 _r_prime = ((resp & 0x02) >> 1) |
378 ((resp & 0x08) >> 2) |
379 ((resp & 0x20) >> 3) |
380 ((resp & 0x80) >> 4);
382 _d = ((resp & 0x01) >> 0) |
383 ((resp & 0x04) >> 1) |
384 ((resp & 0x10) >> 2) |
385 ((resp & 0x40) >> 3);
387 r_prime |= (
unsigned long long) _r_prime << (i * 4);
388 d |= (
unsigned long long) _d << (i * 4);
394 "pass: %d read error, retrying\n", pass);
398 "pass: %d r\': %0#18llx d:%0#18llx\n",
401 "pass: %d nibble loop complete, exiting ASM\n", pass);
404 "pass: %d resetting bus\n", pass);
405 ds1wm_reset(ds1wm_data);
407 if ((r_prime & ((
u64)1 << 63)) && (d & ((
u64)1 << 63))) {
409 "pass: %d bus error, retrying\n", pass);
415 "pass: %d found %0#18llx\n", pass, r_prime);
416 slave_found(master_dev, r_prime);
419 "pass: %d complete, preparing next pass\n", pass);
426 ms_discrep_bit = fls64(d) - 1;
428 "pass: %d new d:%0#18llx MS discrep bit:%d\n",
429 pass, d, ms_discrep_bit);
433 if (ms_discrep_bit == -1)
436 r = (r & ~(~0ull << (ms_discrep_bit))) | 1 << ms_discrep_bit;
439 "pass: %d total: %d search done ms d bit pos: %d\n", pass,
440 slaves_found, ms_discrep_bit);
445 static struct w1_bus_master ds1wm_master = {
446 .read_byte = ds1wm_read_byte,
447 .write_byte = ds1wm_write_byte,
448 .reset_bus = ds1wm_reset_bus,
449 .search = ds1wm_search,
454 struct ds1wm_data *ds1wm_data;
462 ds1wm_data = kzalloc(
sizeof(*ds1wm_data),
GFP_KERNEL);
466 platform_set_drvdata(pdev, ds1wm_data);
474 if (!ds1wm_data->
map) {
480 ds1wm_data->
bus_shift = resource_size(res) >> 3;
482 ds1wm_data->
pdev = pdev;
483 ds1wm_data->
cell = mfd_get_cell(pdev);
484 if (!ds1wm_data->
cell) {
488 plat = pdev->
dev.platform_data;
513 ds1wm_up(ds1wm_data);
515 ds1wm_master.data = (
void *)ds1wm_data;
524 ds1wm_down(ds1wm_data);
537 struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
539 ds1wm_down(ds1wm_data);
546 struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
548 ds1wm_up(ds1wm_data);
553 #define ds1wm_suspend NULL
554 #define ds1wm_resume NULL
559 struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
562 ds1wm_down(ds1wm_data);
574 .probe = ds1wm_probe,
575 .remove = ds1wm_remove,
580 static int __init ds1wm_init(
void)
582 printk(
"DS1WM w1 busmaster driver - (c) 2004 Szabolcs Gyurko\n");
586 static void __exit ds1wm_exit(
void)