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