1 /* 2 * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved. 3 * Copyright 2008 Luotao Fu, kernel@pengutronix.de 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include <linux/clk.h> 16 #include <linux/delay.h> 17 #include <linux/io.h> 18 #include <linux/jiffies.h> 19 #include <linux/module.h> 20 #include <linux/mod_devicetable.h> 21 #include <linux/platform_device.h> 22 23 #include <linux/w1.h> 24 25 /* 26 * MXC W1 Register offsets 27 */ 28 #define MXC_W1_CONTROL 0x00 29 # define MXC_W1_CONTROL_RDST BIT(3) 30 # define MXC_W1_CONTROL_WR(x) BIT(5 - (x)) 31 # define MXC_W1_CONTROL_PST BIT(6) 32 # define MXC_W1_CONTROL_RPP BIT(7) 33 #define MXC_W1_TIME_DIVIDER 0x02 34 #define MXC_W1_RESET 0x04 35 # define MXC_W1_RESET_RST BIT(0) 36 37 struct mxc_w1_device { 38 void __iomem *regs; 39 struct clk *clk; 40 struct w1_bus_master bus_master; 41 }; 42 43 /* 44 * this is the low level routine to 45 * reset the device on the One Wire interface 46 * on the hardware 47 */ 48 static u8 mxc_w1_ds2_reset_bus(void *data) 49 { 50 struct mxc_w1_device *dev = data; 51 unsigned long timeout; 52 53 writeb(MXC_W1_CONTROL_RPP, dev->regs + MXC_W1_CONTROL); 54 55 /* Wait for reset sequence 511+512us, use 1500us for sure */ 56 timeout = jiffies + usecs_to_jiffies(1500); 57 58 udelay(511 + 512); 59 60 do { 61 u8 ctrl = readb(dev->regs + MXC_W1_CONTROL); 62 63 /* PST bit is valid after the RPP bit is self-cleared */ 64 if (!(ctrl & MXC_W1_CONTROL_RPP)) 65 return !(ctrl & MXC_W1_CONTROL_PST); 66 } while (time_is_after_jiffies(timeout)); 67 68 return 1; 69 } 70 71 /* 72 * this is the low level routine to read/write a bit on the One Wire 73 * interface on the hardware. It does write 0 if parameter bit is set 74 * to 0, otherwise a write 1/read. 75 */ 76 static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) 77 { 78 struct mxc_w1_device *dev = data; 79 unsigned long timeout; 80 81 writeb(MXC_W1_CONTROL_WR(bit), dev->regs + MXC_W1_CONTROL); 82 83 /* Wait for read/write bit (60us, Max 120us), use 200us for sure */ 84 timeout = jiffies + usecs_to_jiffies(200); 85 86 udelay(60); 87 88 do { 89 u8 ctrl = readb(dev->regs + MXC_W1_CONTROL); 90 91 /* RDST bit is valid after the WR1/RD bit is self-cleared */ 92 if (!(ctrl & MXC_W1_CONTROL_WR(bit))) 93 return !!(ctrl & MXC_W1_CONTROL_RDST); 94 } while (time_is_after_jiffies(timeout)); 95 96 return 0; 97 } 98 99 static int mxc_w1_probe(struct platform_device *pdev) 100 { 101 struct mxc_w1_device *mdev; 102 unsigned long clkrate; 103 struct resource *res; 104 unsigned int clkdiv; 105 int err; 106 107 mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device), 108 GFP_KERNEL); 109 if (!mdev) 110 return -ENOMEM; 111 112 mdev->clk = devm_clk_get(&pdev->dev, NULL); 113 if (IS_ERR(mdev->clk)) 114 return PTR_ERR(mdev->clk); 115 116 err = clk_prepare_enable(mdev->clk); 117 if (err) 118 return err; 119 120 clkrate = clk_get_rate(mdev->clk); 121 if (clkrate < 10000000) 122 dev_warn(&pdev->dev, 123 "Low clock frequency causes improper function\n"); 124 125 clkdiv = DIV_ROUND_CLOSEST(clkrate, 1000000); 126 clkrate /= clkdiv; 127 if ((clkrate < 980000) || (clkrate > 1020000)) 128 dev_warn(&pdev->dev, 129 "Incorrect time base frequency %lu Hz\n", clkrate); 130 131 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 132 mdev->regs = devm_ioremap_resource(&pdev->dev, res); 133 if (IS_ERR(mdev->regs)) { 134 err = PTR_ERR(mdev->regs); 135 goto out_disable_clk; 136 } 137 138 /* Software reset 1-Wire module */ 139 writeb(MXC_W1_RESET_RST, mdev->regs + MXC_W1_RESET); 140 writeb(0, mdev->regs + MXC_W1_RESET); 141 142 writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER); 143 144 mdev->bus_master.data = mdev; 145 mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus; 146 mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit; 147 148 platform_set_drvdata(pdev, mdev); 149 150 err = w1_add_master_device(&mdev->bus_master); 151 if (err) 152 goto out_disable_clk; 153 154 return 0; 155 156 out_disable_clk: 157 clk_disable_unprepare(mdev->clk); 158 return err; 159 } 160 161 /* 162 * disassociate the w1 device from the driver 163 */ 164 static int mxc_w1_remove(struct platform_device *pdev) 165 { 166 struct mxc_w1_device *mdev = platform_get_drvdata(pdev); 167 168 w1_remove_master_device(&mdev->bus_master); 169 170 clk_disable_unprepare(mdev->clk); 171 172 return 0; 173 } 174 175 static const struct of_device_id mxc_w1_dt_ids[] = { 176 { .compatible = "fsl,imx21-owire" }, 177 { /* sentinel */ } 178 }; 179 MODULE_DEVICE_TABLE(of, mxc_w1_dt_ids); 180 181 static struct platform_driver mxc_w1_driver = { 182 .driver = { 183 .name = "mxc_w1", 184 .of_match_table = mxc_w1_dt_ids, 185 }, 186 .probe = mxc_w1_probe, 187 .remove = mxc_w1_remove, 188 }; 189 module_platform_driver(mxc_w1_driver); 190 191 MODULE_LICENSE("GPL"); 192 MODULE_AUTHOR("Freescale Semiconductors Inc"); 193 MODULE_DESCRIPTION("Driver for One-Wire on MXC"); 194