1 /* 2 * I2C multiplexer using a single register 3 * 4 * Copyright 2015 Freescale Semiconductor 5 * York Sun <yorksun@freescale.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 */ 12 13 #include <linux/i2c.h> 14 #include <linux/i2c-mux.h> 15 #include <linux/init.h> 16 #include <linux/io.h> 17 #include <linux/module.h> 18 #include <linux/of_address.h> 19 #include <linux/platform_data/i2c-mux-reg.h> 20 #include <linux/platform_device.h> 21 #include <linux/slab.h> 22 23 struct regmux { 24 struct i2c_mux_reg_platform_data data; 25 }; 26 27 static int i2c_mux_reg_set(const struct regmux *mux, unsigned int chan_id) 28 { 29 if (!mux->data.reg) 30 return -EINVAL; 31 32 /* 33 * Write to the register, followed by a read to ensure the write is 34 * completed on a "posted" bus, for example PCI or write buffers. 35 * The endianness of reading doesn't matter and the return data 36 * is not used. 37 */ 38 switch (mux->data.reg_size) { 39 case 4: 40 if (mux->data.little_endian) 41 iowrite32(chan_id, mux->data.reg); 42 else 43 iowrite32be(chan_id, mux->data.reg); 44 if (!mux->data.write_only) 45 ioread32(mux->data.reg); 46 break; 47 case 2: 48 if (mux->data.little_endian) 49 iowrite16(chan_id, mux->data.reg); 50 else 51 iowrite16be(chan_id, mux->data.reg); 52 if (!mux->data.write_only) 53 ioread16(mux->data.reg); 54 break; 55 case 1: 56 iowrite8(chan_id, mux->data.reg); 57 if (!mux->data.write_only) 58 ioread8(mux->data.reg); 59 break; 60 } 61 62 return 0; 63 } 64 65 static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan) 66 { 67 struct regmux *mux = i2c_mux_priv(muxc); 68 69 return i2c_mux_reg_set(mux, chan); 70 } 71 72 static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan) 73 { 74 struct regmux *mux = i2c_mux_priv(muxc); 75 76 if (mux->data.idle_in_use) 77 return i2c_mux_reg_set(mux, mux->data.idle); 78 79 return 0; 80 } 81 82 #ifdef CONFIG_OF 83 static int i2c_mux_reg_probe_dt(struct regmux *mux, 84 struct platform_device *pdev) 85 { 86 struct device_node *np = pdev->dev.of_node; 87 struct device_node *adapter_np, *child; 88 struct i2c_adapter *adapter; 89 struct resource res; 90 unsigned *values; 91 int i = 0; 92 93 if (!np) 94 return -ENODEV; 95 96 adapter_np = of_parse_phandle(np, "i2c-parent", 0); 97 if (!adapter_np) { 98 dev_err(&pdev->dev, "Cannot parse i2c-parent\n"); 99 return -ENODEV; 100 } 101 adapter = of_find_i2c_adapter_by_node(adapter_np); 102 of_node_put(adapter_np); 103 if (!adapter) 104 return -EPROBE_DEFER; 105 106 mux->data.parent = i2c_adapter_id(adapter); 107 put_device(&adapter->dev); 108 109 mux->data.n_values = of_get_child_count(np); 110 if (of_find_property(np, "little-endian", NULL)) { 111 mux->data.little_endian = true; 112 } else if (of_find_property(np, "big-endian", NULL)) { 113 mux->data.little_endian = false; 114 } else { 115 #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \ 116 defined(__LITTLE_ENDIAN) 117 mux->data.little_endian = true; 118 #elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : \ 119 defined(__BIG_ENDIAN) 120 mux->data.little_endian = false; 121 #else 122 #error Endianness not defined? 123 #endif 124 } 125 if (of_find_property(np, "write-only", NULL)) 126 mux->data.write_only = true; 127 else 128 mux->data.write_only = false; 129 130 values = devm_kzalloc(&pdev->dev, 131 sizeof(*mux->data.values) * mux->data.n_values, 132 GFP_KERNEL); 133 if (!values) { 134 dev_err(&pdev->dev, "Cannot allocate values array"); 135 return -ENOMEM; 136 } 137 138 for_each_child_of_node(np, child) { 139 of_property_read_u32(child, "reg", values + i); 140 i++; 141 } 142 mux->data.values = values; 143 144 if (!of_property_read_u32(np, "idle-state", &mux->data.idle)) 145 mux->data.idle_in_use = true; 146 147 /* map address from "reg" if exists */ 148 if (of_address_to_resource(np, 0, &res) == 0) { 149 mux->data.reg_size = resource_size(&res); 150 mux->data.reg = devm_ioremap_resource(&pdev->dev, &res); 151 if (IS_ERR(mux->data.reg)) 152 return PTR_ERR(mux->data.reg); 153 } 154 155 return 0; 156 } 157 #else 158 static int i2c_mux_reg_probe_dt(struct regmux *mux, 159 struct platform_device *pdev) 160 { 161 return 0; 162 } 163 #endif 164 165 static int i2c_mux_reg_probe(struct platform_device *pdev) 166 { 167 struct i2c_mux_core *muxc; 168 struct regmux *mux; 169 struct i2c_adapter *parent; 170 struct resource *res; 171 unsigned int class; 172 int i, ret, nr; 173 174 mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); 175 if (!mux) 176 return -ENOMEM; 177 178 if (dev_get_platdata(&pdev->dev)) { 179 memcpy(&mux->data, dev_get_platdata(&pdev->dev), 180 sizeof(mux->data)); 181 } else { 182 ret = i2c_mux_reg_probe_dt(mux, pdev); 183 if (ret < 0) { 184 dev_err(&pdev->dev, "Error parsing device tree"); 185 return ret; 186 } 187 } 188 189 parent = i2c_get_adapter(mux->data.parent); 190 if (!parent) 191 return -EPROBE_DEFER; 192 193 if (!mux->data.reg) { 194 dev_info(&pdev->dev, 195 "Register not set, using platform resource\n"); 196 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 197 mux->data.reg_size = resource_size(res); 198 mux->data.reg = devm_ioremap_resource(&pdev->dev, res); 199 if (IS_ERR(mux->data.reg)) { 200 ret = PTR_ERR(mux->data.reg); 201 goto err_put_parent; 202 } 203 } 204 205 if (mux->data.reg_size != 4 && mux->data.reg_size != 2 && 206 mux->data.reg_size != 1) { 207 dev_err(&pdev->dev, "Invalid register size\n"); 208 ret = -EINVAL; 209 goto err_put_parent; 210 } 211 212 muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0, 213 i2c_mux_reg_select, NULL); 214 if (!muxc) { 215 ret = -ENOMEM; 216 goto err_put_parent; 217 } 218 muxc->priv = mux; 219 220 platform_set_drvdata(pdev, muxc); 221 222 if (mux->data.idle_in_use) 223 muxc->deselect = i2c_mux_reg_deselect; 224 225 for (i = 0; i < mux->data.n_values; i++) { 226 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0; 227 class = mux->data.classes ? mux->data.classes[i] : 0; 228 229 ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class); 230 if (ret) 231 goto err_del_mux_adapters; 232 } 233 234 dev_dbg(&pdev->dev, "%d port mux on %s adapter\n", 235 mux->data.n_values, muxc->parent->name); 236 237 return 0; 238 239 err_del_mux_adapters: 240 i2c_mux_del_adapters(muxc); 241 err_put_parent: 242 i2c_put_adapter(parent); 243 244 return ret; 245 } 246 247 static int i2c_mux_reg_remove(struct platform_device *pdev) 248 { 249 struct i2c_mux_core *muxc = platform_get_drvdata(pdev); 250 251 i2c_mux_del_adapters(muxc); 252 i2c_put_adapter(muxc->parent); 253 254 return 0; 255 } 256 257 static const struct of_device_id i2c_mux_reg_of_match[] = { 258 { .compatible = "i2c-mux-reg", }, 259 {}, 260 }; 261 MODULE_DEVICE_TABLE(of, i2c_mux_reg_of_match); 262 263 static struct platform_driver i2c_mux_reg_driver = { 264 .probe = i2c_mux_reg_probe, 265 .remove = i2c_mux_reg_remove, 266 .driver = { 267 .name = "i2c-mux-reg", 268 .of_match_table = of_match_ptr(i2c_mux_reg_of_match), 269 }, 270 }; 271 272 module_platform_driver(i2c_mux_reg_driver); 273 274 MODULE_DESCRIPTION("Register-based I2C multiplexer driver"); 275 MODULE_AUTHOR("York Sun <yorksun@freescale.com>"); 276 MODULE_LICENSE("GPL"); 277 MODULE_ALIAS("platform:i2c-mux-reg"); 278