^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * sgi_w1.c - w1 master driver for one wire support in SGI ASICs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_data/sgi-w1.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/w1.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define MCR_RD_DATA BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define MCR_DONE BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define MCR_PACK(pulse, sample) (((pulse) << 10) | ((sample) << 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct sgi_w1_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) u32 __iomem *mcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct w1_bus_master bus_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) char dev_id[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static u8 sgi_w1_wait(u32 __iomem *mcr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u32 mcr_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) mcr_val = readl(mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) } while (!(mcr_val & MCR_DONE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return (mcr_val & MCR_RD_DATA) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * this is the low level routine to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * reset the device on the One Wire interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * on the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static u8 sgi_w1_reset_bus(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct sgi_w1_device *dev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u8 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) writel(MCR_PACK(520, 65), dev->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ret = sgi_w1_wait(dev->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) udelay(500); /* recovery time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * this is the low level routine to read/write a bit on the One Wire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * interface on the hardware. It does write 0 if parameter bit is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * to 0, otherwise a write 1/read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static u8 sgi_w1_touch_bit(void *data, u8 bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct sgi_w1_device *dev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u8 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) writel(MCR_PACK(6, 13), dev->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) writel(MCR_PACK(80, 30), dev->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = sgi_w1_wait(dev->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) udelay(100); /* recovery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static int sgi_w1_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct sgi_w1_device *sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct sgi_w1_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) sdev = devm_kzalloc(&pdev->dev, sizeof(struct sgi_w1_device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) sdev->mcr = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (IS_ERR(sdev->mcr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return PTR_ERR(sdev->mcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) sdev->bus_master.data = sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sdev->bus_master.reset_bus = sgi_w1_reset_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) sdev->bus_master.touch_bit = sgi_w1_touch_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) pdata = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) strlcpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) sdev->bus_master.dev_id = sdev->dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) platform_set_drvdata(pdev, sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return w1_add_master_device(&sdev->bus_master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * disassociate the w1 device from the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int sgi_w1_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct sgi_w1_device *sdev = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) w1_remove_master_device(&sdev->bus_master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct platform_driver sgi_w1_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .name = "sgi_w1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .probe = sgi_w1_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .remove = sgi_w1_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) module_platform_driver(sgi_w1_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) MODULE_AUTHOR("Thomas Bogendoerfer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) MODULE_DESCRIPTION("Driver for One-Wire IP in SGI ASICs");