1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Driver for one wire controller in some i.MX Socs 4 * 5 * There are currently two silicon variants: 6 * V1: i.MX21, i.MX27, i.MX31, i.MX51 7 * V2: i.MX25, i.MX35, i.MX50, i.MX53 8 * Newer i.MX SoCs such as the i.MX6 do not have one wire controllers. 9 * 10 * The V1 controller only supports single bit operations. 11 * The V2 controller is backwards compatible on the register level but adds 12 * byte size operations and a "search ROM accelerator mode" 13 * 14 * This driver does not currently support the search ROM accelerator 15 * 16 * Copyright (c) 2018 Flowbird 17 * Martin Fuzzey <martin.fuzzey@flowbird.group> 18 */ 19 20 #include <asm/arch/clock.h> 21 #include <common.h> 22 #include <dm.h> 23 #include <linux/io.h> 24 #include <w1.h> 25 26 struct mxc_w1_regs { 27 u16 control; 28 #define MXC_W1_CONTROL_RPP BIT(7) 29 #define MXC_W1_CONTROL_PST BIT(6) 30 #define MXC_W1_CONTROL_WR(x) BIT(5 - (x)) 31 #define MXC_W1_CONTROL_RDST BIT(3) 32 33 u16 time_divider; 34 u16 reset; 35 36 /* Registers below on V2 silicon only */ 37 u16 command; 38 u16 tx_rx; 39 u16 interrupt; 40 #define MXC_W1_INTERRUPT_TBE BIT(2) 41 #define MXC_W1_INTERRUPT_TSRE BIT(3) 42 #define MXC_W1_INTERRUPT_RBF BIT(4) 43 #define MXC_W1_INTERRUPT_RSRF BIT(5) 44 45 u16 interrupt_en; 46 }; 47 48 struct mxc_w1_pdata { 49 struct mxc_w1_regs *regs; 50 }; 51 52 /* 53 * this is the low level routine to read/write a bit on the One Wire 54 * interface on the hardware. It does write 0 if parameter bit is set 55 * to 0, otherwise a write 1/read. 56 */ 57 static u8 mxc_w1_touch_bit(struct mxc_w1_pdata *pdata, u8 bit) 58 { 59 u16 *ctrl_addr = &pdata->regs->control; 60 u16 mask = MXC_W1_CONTROL_WR(bit); 61 unsigned int timeout_cnt = 400; /* Takes max. 120us according to 62 * datasheet. 63 */ 64 65 writew(mask, ctrl_addr); 66 67 while (timeout_cnt--) { 68 if (!(readw(ctrl_addr) & mask)) 69 break; 70 71 udelay(1); 72 } 73 74 return (readw(ctrl_addr) & MXC_W1_CONTROL_RDST) ? 1 : 0; 75 } 76 77 static u8 mxc_w1_read_byte(struct udevice *dev) 78 { 79 struct mxc_w1_pdata *pdata = dev_get_platdata(dev); 80 struct mxc_w1_regs *regs = pdata->regs; 81 u16 status; 82 83 if (dev_get_driver_data(dev) < 2) { 84 int i; 85 u8 ret = 0; 86 87 for (i = 0; i < 8; i++) 88 ret |= (mxc_w1_touch_bit(pdata, 1) << i); 89 90 return ret; 91 } 92 93 readw(®s->tx_rx); 94 writew(0xFF, ®s->tx_rx); 95 96 do { 97 udelay(1); /* Without this bytes are sometimes duplicated... */ 98 status = readw(®s->interrupt); 99 } while (!(status & MXC_W1_INTERRUPT_RBF)); 100 101 return (u8)readw(®s->tx_rx); 102 } 103 104 static void mxc_w1_write_byte(struct udevice *dev, u8 byte) 105 { 106 struct mxc_w1_pdata *pdata = dev_get_platdata(dev); 107 struct mxc_w1_regs *regs = pdata->regs; 108 u16 status; 109 110 if (dev_get_driver_data(dev) < 2) { 111 int i; 112 113 for (i = 0; i < 8; i++) 114 mxc_w1_touch_bit(pdata, (byte >> i) & 0x1); 115 116 return; 117 } 118 119 readw(®s->tx_rx); 120 writew(byte, ®s->tx_rx); 121 122 do { 123 udelay(1); 124 status = readw(®s->interrupt); 125 } while (!(status & MXC_W1_INTERRUPT_TSRE)); 126 } 127 128 static bool mxc_w1_reset(struct udevice *dev) 129 { 130 struct mxc_w1_pdata *pdata = dev_get_platdata(dev); 131 u16 reg_val; 132 133 writew(MXC_W1_CONTROL_RPP, &pdata->regs->control); 134 135 do { 136 reg_val = readw(&pdata->regs->control); 137 } while (reg_val & MXC_W1_CONTROL_RPP); 138 139 return !(reg_val & MXC_W1_CONTROL_PST); 140 } 141 142 static u8 mxc_w1_triplet(struct udevice *dev, bool bdir) 143 { 144 struct mxc_w1_pdata *pdata = dev_get_platdata(dev); 145 u8 id_bit = mxc_w1_touch_bit(pdata, 1); 146 u8 comp_bit = mxc_w1_touch_bit(pdata, 1); 147 u8 retval; 148 149 if (id_bit && comp_bit) 150 return 0x03; /* error */ 151 152 if (!id_bit && !comp_bit) { 153 /* Both bits are valid, take the direction given */ 154 retval = bdir ? 0x04 : 0; 155 } else { 156 /* Only one bit is valid, take that direction */ 157 bdir = id_bit; 158 retval = id_bit ? 0x05 : 0x02; 159 } 160 161 mxc_w1_touch_bit(pdata, bdir); 162 163 return retval; 164 } 165 166 static int mxc_w1_ofdata_to_platdata(struct udevice *dev) 167 { 168 struct mxc_w1_pdata *pdata = dev_get_platdata(dev); 169 fdt_addr_t addr; 170 171 addr = devfdt_get_addr(dev); 172 if (addr == FDT_ADDR_T_NONE) 173 return -EINVAL; 174 175 pdata->regs = (struct mxc_w1_regs *)addr; 176 177 return 0; 178 }; 179 180 static int mxc_w1_probe(struct udevice *dev) 181 { 182 struct mxc_w1_pdata *pdata = dev_get_platdata(dev); 183 unsigned int clkrate = mxc_get_clock(MXC_IPG_PERCLK); 184 unsigned int clkdiv; 185 186 if (clkrate < 10000000) { 187 dev_err(dev, "input clock frequency (%u Hz) too low\n", 188 clkrate); 189 return -EINVAL; 190 } 191 192 clkdiv = clkrate / 1000000; 193 clkrate /= clkdiv; 194 if (clkrate < 980000 || clkrate > 1020000) { 195 dev_err(dev, "Incorrect time base frequency %u Hz\n", clkrate); 196 return -EINVAL; 197 } 198 199 writew(clkdiv - 1, &pdata->regs->time_divider); 200 201 return 0; 202 } 203 204 static const struct w1_ops mxc_w1_ops = { 205 .read_byte = mxc_w1_read_byte, 206 .reset = mxc_w1_reset, 207 .triplet = mxc_w1_triplet, 208 .write_byte = mxc_w1_write_byte, 209 }; 210 211 static const struct udevice_id mxc_w1_id[] = { 212 { .compatible = "fsl,imx21-owire", .data = 1 }, 213 { .compatible = "fsl,imx27-owire", .data = 1 }, 214 { .compatible = "fsl,imx31-owire", .data = 1 }, 215 { .compatible = "fsl,imx51-owire", .data = 1 }, 216 217 { .compatible = "fsl,imx25-owire", .data = 2 }, 218 { .compatible = "fsl,imx35-owire", .data = 2 }, 219 { .compatible = "fsl,imx50-owire", .data = 2 }, 220 { .compatible = "fsl,imx53-owire", .data = 2 }, 221 { }, 222 }; 223 224 U_BOOT_DRIVER(mxc_w1_drv) = { 225 .id = UCLASS_W1, 226 .name = "mxc_w1_drv", 227 .of_match = mxc_w1_id, 228 .ofdata_to_platdata = mxc_w1_ofdata_to_platdata, 229 .ops = &mxc_w1_ops, 230 .platdata_auto_alloc_size = sizeof(struct mxc_w1_pdata), 231 .probe = mxc_w1_probe, 232 }; 233