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/module.h> 19 #include <linux/platform_device.h> 20 21 #include "../w1.h" 22 #include "../w1_int.h" 23 24 /* According to the mx27 Datasheet the reset procedure should take up to about 25 * 1350us. We set the timeout to 500*100us = 50ms for sure */ 26 #define MXC_W1_RESET_TIMEOUT 500 27 28 /* 29 * MXC W1 Register offsets 30 */ 31 #define MXC_W1_CONTROL 0x00 32 # define MXC_W1_CONTROL_RDST BIT(3) 33 # define MXC_W1_CONTROL_WR(x) BIT(5 - (x)) 34 # define MXC_W1_CONTROL_PST BIT(6) 35 # define MXC_W1_CONTROL_RPP BIT(7) 36 #define MXC_W1_TIME_DIVIDER 0x02 37 #define MXC_W1_RESET 0x04 38 39 struct mxc_w1_device { 40 void __iomem *regs; 41 struct clk *clk; 42 struct w1_bus_master bus_master; 43 }; 44 45 /* 46 * this is the low level routine to 47 * reset the device on the One Wire interface 48 * on the hardware 49 */ 50 static u8 mxc_w1_ds2_reset_bus(void *data) 51 { 52 u8 reg_val; 53 unsigned int timeout_cnt = 0; 54 struct mxc_w1_device *dev = data; 55 56 writeb(MXC_W1_CONTROL_RPP, (dev->regs + MXC_W1_CONTROL)); 57 58 while (1) { 59 reg_val = readb(dev->regs + MXC_W1_CONTROL); 60 61 if (!(reg_val & MXC_W1_CONTROL_RPP) || 62 timeout_cnt > MXC_W1_RESET_TIMEOUT) 63 break; 64 else 65 timeout_cnt++; 66 67 udelay(100); 68 } 69 return !!(reg_val & MXC_W1_CONTROL_PST); 70 } 71 72 /* 73 * this is the low level routine to read/write a bit on the One Wire 74 * interface on the hardware. It does write 0 if parameter bit is set 75 * to 0, otherwise a write 1/read. 76 */ 77 static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) 78 { 79 struct mxc_w1_device *mdev = data; 80 void __iomem *ctrl_addr = mdev->regs + MXC_W1_CONTROL; 81 unsigned int timeout_cnt = 400; /* Takes max. 120us according to 82 * datasheet. 83 */ 84 85 writeb(MXC_W1_CONTROL_WR(bit), ctrl_addr); 86 87 while (timeout_cnt--) { 88 if (!(readb(ctrl_addr) & MXC_W1_CONTROL_WR(bit))) 89 break; 90 91 udelay(1); 92 } 93 94 return !!(readb(ctrl_addr) & MXC_W1_CONTROL_RDST); 95 } 96 97 static int mxc_w1_probe(struct platform_device *pdev) 98 { 99 struct mxc_w1_device *mdev; 100 unsigned long clkrate; 101 struct resource *res; 102 unsigned int clkdiv; 103 int err; 104 105 mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device), 106 GFP_KERNEL); 107 if (!mdev) 108 return -ENOMEM; 109 110 mdev->clk = devm_clk_get(&pdev->dev, NULL); 111 if (IS_ERR(mdev->clk)) 112 return PTR_ERR(mdev->clk); 113 114 clkrate = clk_get_rate(mdev->clk); 115 if (clkrate < 10000000) 116 dev_warn(&pdev->dev, 117 "Low clock frequency causes improper function\n"); 118 119 clkdiv = DIV_ROUND_CLOSEST(clkrate, 1000000); 120 clkrate /= clkdiv; 121 if ((clkrate < 980000) || (clkrate > 1020000)) 122 dev_warn(&pdev->dev, 123 "Incorrect time base frequency %lu Hz\n", clkrate); 124 125 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 126 mdev->regs = devm_ioremap_resource(&pdev->dev, res); 127 if (IS_ERR(mdev->regs)) 128 return PTR_ERR(mdev->regs); 129 130 err = clk_prepare_enable(mdev->clk); 131 if (err) 132 return err; 133 134 writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER); 135 136 mdev->bus_master.data = mdev; 137 mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus; 138 mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit; 139 140 platform_set_drvdata(pdev, mdev); 141 142 err = w1_add_master_device(&mdev->bus_master); 143 if (err) 144 clk_disable_unprepare(mdev->clk); 145 146 return err; 147 } 148 149 /* 150 * disassociate the w1 device from the driver 151 */ 152 static int mxc_w1_remove(struct platform_device *pdev) 153 { 154 struct mxc_w1_device *mdev = platform_get_drvdata(pdev); 155 156 w1_remove_master_device(&mdev->bus_master); 157 158 clk_disable_unprepare(mdev->clk); 159 160 return 0; 161 } 162 163 static struct of_device_id mxc_w1_dt_ids[] = { 164 { .compatible = "fsl,imx21-owire" }, 165 { /* sentinel */ } 166 }; 167 MODULE_DEVICE_TABLE(of, mxc_w1_dt_ids); 168 169 static struct platform_driver mxc_w1_driver = { 170 .driver = { 171 .name = "mxc_w1", 172 .owner = THIS_MODULE, 173 .of_match_table = mxc_w1_dt_ids, 174 }, 175 .probe = mxc_w1_probe, 176 .remove = mxc_w1_remove, 177 }; 178 module_platform_driver(mxc_w1_driver); 179 180 MODULE_LICENSE("GPL"); 181 MODULE_AUTHOR("Freescale Semiconductors Inc"); 182 MODULE_DESCRIPTION("Driver for One-Wire on MXC"); 183