1 // SPDX-License-Identifier: GPL-2.0
3 * sgi_w1.c - w1 master driver for one wire support in SGI ASICs
7 #include <linux/delay.h>
9 #include <linux/jiffies.h>
10 #include <linux/module.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/platform_device.h>
13 #include <linux/platform_data/sgi-w1.h>
17 #define MCR_RD_DATA BIT(0)
18 #define MCR_DONE BIT(1)
20 #define MCR_PACK(pulse, sample) (((pulse) << 10) | ((sample) << 2))
22 struct sgi_w1_device
{
24 struct w1_bus_master bus_master
;
28 static u8
sgi_w1_wait(u32 __iomem
*mcr
)
34 } while (!(mcr_val
& MCR_DONE
));
36 return (mcr_val
& MCR_RD_DATA
) ? 1 : 0;
40 * this is the low level routine to
41 * reset the device on the One Wire interface
44 static u8
sgi_w1_reset_bus(void *data
)
46 struct sgi_w1_device
*dev
= data
;
49 writel(MCR_PACK(520, 65), dev
->mcr
);
50 ret
= sgi_w1_wait(dev
->mcr
);
51 udelay(500); /* recovery time */
56 * this is the low level routine to read/write a bit on the One Wire
57 * interface on the hardware. It does write 0 if parameter bit is set
58 * to 0, otherwise a write 1/read.
60 static u8
sgi_w1_touch_bit(void *data
, u8 bit
)
62 struct sgi_w1_device
*dev
= data
;
66 writel(MCR_PACK(6, 13), dev
->mcr
);
68 writel(MCR_PACK(80, 30), dev
->mcr
);
70 ret
= sgi_w1_wait(dev
->mcr
);
72 udelay(100); /* recovery */
76 static int sgi_w1_probe(struct platform_device
*pdev
)
78 struct sgi_w1_device
*sdev
;
79 struct sgi_w1_platform_data
*pdata
;
81 sdev
= devm_kzalloc(&pdev
->dev
, sizeof(struct sgi_w1_device
),
86 sdev
->mcr
= devm_platform_ioremap_resource(pdev
, 0);
87 if (IS_ERR(sdev
->mcr
))
88 return PTR_ERR(sdev
->mcr
);
90 sdev
->bus_master
.data
= sdev
;
91 sdev
->bus_master
.reset_bus
= sgi_w1_reset_bus
;
92 sdev
->bus_master
.touch_bit
= sgi_w1_touch_bit
;
94 pdata
= dev_get_platdata(&pdev
->dev
);
96 strscpy(sdev
->dev_id
, pdata
->dev_id
, sizeof(sdev
->dev_id
));
97 sdev
->bus_master
.dev_id
= sdev
->dev_id
;
100 platform_set_drvdata(pdev
, sdev
);
102 return w1_add_master_device(&sdev
->bus_master
);
106 * disassociate the w1 device from the driver
108 static void sgi_w1_remove(struct platform_device
*pdev
)
110 struct sgi_w1_device
*sdev
= platform_get_drvdata(pdev
);
112 w1_remove_master_device(&sdev
->bus_master
);
115 static struct platform_driver sgi_w1_driver
= {
119 .probe
= sgi_w1_probe
,
120 .remove
= sgi_w1_remove
,
122 module_platform_driver(sgi_w1_driver
);
124 MODULE_LICENSE("GPL");
125 MODULE_AUTHOR("Thomas Bogendoerfer");
126 MODULE_DESCRIPTION("Driver for One-Wire IP in SGI ASICs");