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_property_read_bool(np, "little-endian")) { 111 mux->data.little_endian = true; 112 } else if (of_property_read_bool(np, "big-endian")) { 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 mux->data.write_only = of_property_read_bool(np, "write-only"); 126 127 values = devm_kcalloc(&pdev->dev, 128 mux->data.n_values, sizeof(*mux->data.values), 129 GFP_KERNEL); 130 if (!values) 131 return -ENOMEM; 132 133 for_each_child_of_node(np, child) { 134 of_property_read_u32(child, "reg", values + i); 135 i++; 136 } 137 mux->data.values = values; 138 139 if (!of_property_read_u32(np, "idle-state", &mux->data.idle)) 140 mux->data.idle_in_use = true; 141 142 /* map address from "reg" if exists */ 143 if (of_address_to_resource(np, 0, &res) == 0) { 144 mux->data.reg_size = resource_size(&res); 145 mux->data.reg = devm_ioremap_resource(&pdev->dev, &res); 146 if (IS_ERR(mux->data.reg)) 147 return PTR_ERR(mux->data.reg); 148 } 149 150 return 0; 151 } 152 #else 153 static int i2c_mux_reg_probe_dt(struct regmux *mux, 154 struct platform_device *pdev) 155 { 156 return 0; 157 } 158 #endif 159 160 static int i2c_mux_reg_probe(struct platform_device *pdev) 161 { 162 struct i2c_mux_core *muxc; 163 struct regmux *mux; 164 struct i2c_adapter *parent; 165 struct resource *res; 166 unsigned int class; 167 int i, ret, nr; 168 169 mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); 170 if (!mux) 171 return -ENOMEM; 172 173 if (dev_get_platdata(&pdev->dev)) { 174 memcpy(&mux->data, dev_get_platdata(&pdev->dev), 175 sizeof(mux->data)); 176 } else { 177 ret = i2c_mux_reg_probe_dt(mux, pdev); 178 if (ret == -EPROBE_DEFER) 179 return ret; 180 181 if (ret < 0) { 182 dev_err(&pdev->dev, "Error parsing device tree"); 183 return ret; 184 } 185 } 186 187 parent = i2c_get_adapter(mux->data.parent); 188 if (!parent) 189 return -EPROBE_DEFER; 190 191 if (!mux->data.reg) { 192 dev_info(&pdev->dev, 193 "Register not set, using platform resource\n"); 194 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 195 mux->data.reg_size = resource_size(res); 196 mux->data.reg = devm_ioremap_resource(&pdev->dev, res); 197 if (IS_ERR(mux->data.reg)) { 198 ret = PTR_ERR(mux->data.reg); 199 goto err_put_parent; 200 } 201 } 202 203 if (mux->data.reg_size != 4 && mux->data.reg_size != 2 && 204 mux->data.reg_size != 1) { 205 dev_err(&pdev->dev, "Invalid register size\n"); 206 ret = -EINVAL; 207 goto err_put_parent; 208 } 209 210 muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0, 211 i2c_mux_reg_select, NULL); 212 if (!muxc) { 213 ret = -ENOMEM; 214 goto err_put_parent; 215 } 216 muxc->priv = mux; 217 218 platform_set_drvdata(pdev, muxc); 219 220 if (mux->data.idle_in_use) 221 muxc->deselect = i2c_mux_reg_deselect; 222 223 for (i = 0; i < mux->data.n_values; i++) { 224 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0; 225 class = mux->data.classes ? mux->data.classes[i] : 0; 226 227 ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class); 228 if (ret) 229 goto err_del_mux_adapters; 230 } 231 232 dev_dbg(&pdev->dev, "%d port mux on %s adapter\n", 233 mux->data.n_values, muxc->parent->name); 234 235 return 0; 236 237 err_del_mux_adapters: 238 i2c_mux_del_adapters(muxc); 239 err_put_parent: 240 i2c_put_adapter(parent); 241 242 return ret; 243 } 244 245 static int i2c_mux_reg_remove(struct platform_device *pdev) 246 { 247 struct i2c_mux_core *muxc = platform_get_drvdata(pdev); 248 249 i2c_mux_del_adapters(muxc); 250 i2c_put_adapter(muxc->parent); 251 252 return 0; 253 } 254 255 static const struct of_device_id i2c_mux_reg_of_match[] = { 256 { .compatible = "i2c-mux-reg", }, 257 {}, 258 }; 259 MODULE_DEVICE_TABLE(of, i2c_mux_reg_of_match); 260 261 static struct platform_driver i2c_mux_reg_driver = { 262 .probe = i2c_mux_reg_probe, 263 .remove = i2c_mux_reg_remove, 264 .driver = { 265 .name = "i2c-mux-reg", 266 .of_match_table = of_match_ptr(i2c_mux_reg_of_match), 267 }, 268 }; 269 270 module_platform_driver(i2c_mux_reg_driver); 271 272 MODULE_DESCRIPTION("Register-based I2C multiplexer driver"); 273 MODULE_AUTHOR("York Sun <yorksun@freescale.com>"); 274 MODULE_LICENSE("GPL"); 275 MODULE_ALIAS("platform:i2c-mux-reg"); 276