1 /* 2 * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. 3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. 4 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public 7 * License as published by the Free Software Foundation; 8 * either version 2, or (at your option) any later version. 9 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even 12 * the implied warranty of MERCHANTABILITY or FITNESS FOR 13 * A PARTICULAR PURPOSE.See the GNU General Public License 14 * for more details. 15 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 */ 21 22 #include <linux/platform_device.h> 23 #include <linux/delay.h> 24 #include <linux/spinlock.h> 25 #include <linux/module.h> 26 #include <linux/via-core.h> 27 #include <linux/via_i2c.h> 28 29 /* 30 * There can only be one set of these, so there's no point in having 31 * them be dynamically allocated... 32 */ 33 #define VIAFB_NUM_I2C 5 34 static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C]; 35 static struct viafb_dev *i2c_vdev; /* Passed in from core */ 36 37 static void via_i2c_setscl(void *data, int state) 38 { 39 u8 val; 40 struct via_port_cfg *adap_data = data; 41 unsigned long flags; 42 43 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 44 val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; 45 if (state) 46 val |= 0x20; 47 else 48 val &= ~0x20; 49 switch (adap_data->type) { 50 case VIA_PORT_I2C: 51 val |= 0x01; 52 break; 53 case VIA_PORT_GPIO: 54 val |= 0x82; 55 break; 56 default: 57 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); 58 } 59 via_write_reg(adap_data->io_port, adap_data->ioport_index, val); 60 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 61 } 62 63 static int via_i2c_getscl(void *data) 64 { 65 struct via_port_cfg *adap_data = data; 66 unsigned long flags; 67 int ret = 0; 68 69 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 70 if (adap_data->type == VIA_PORT_GPIO) 71 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index, 72 0, 0x80); 73 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) 74 ret = 1; 75 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 76 return ret; 77 } 78 79 static int via_i2c_getsda(void *data) 80 { 81 struct via_port_cfg *adap_data = data; 82 unsigned long flags; 83 int ret = 0; 84 85 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 86 if (adap_data->type == VIA_PORT_GPIO) 87 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index, 88 0, 0x40); 89 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) 90 ret = 1; 91 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 92 return ret; 93 } 94 95 static void via_i2c_setsda(void *data, int state) 96 { 97 u8 val; 98 struct via_port_cfg *adap_data = data; 99 unsigned long flags; 100 101 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 102 val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; 103 if (state) 104 val |= 0x10; 105 else 106 val &= ~0x10; 107 switch (adap_data->type) { 108 case VIA_PORT_I2C: 109 val |= 0x01; 110 break; 111 case VIA_PORT_GPIO: 112 val |= 0x42; 113 break; 114 default: 115 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); 116 } 117 via_write_reg(adap_data->io_port, adap_data->ioport_index, val); 118 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 119 } 120 121 int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) 122 { 123 int ret; 124 u8 mm1[] = {0x00}; 125 struct i2c_msg msgs[2]; 126 127 if (!via_i2c_par[adap].is_active) 128 return -ENODEV; 129 *pdata = 0; 130 msgs[0].flags = 0; 131 msgs[1].flags = I2C_M_RD; 132 msgs[0].addr = msgs[1].addr = slave_addr / 2; 133 mm1[0] = index; 134 msgs[0].len = 1; msgs[1].len = 1; 135 msgs[0].buf = mm1; msgs[1].buf = pdata; 136 ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); 137 if (ret == 2) 138 ret = 0; 139 else if (ret >= 0) 140 ret = -EIO; 141 142 return ret; 143 } 144 145 int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) 146 { 147 int ret; 148 u8 msg[2] = { index, data }; 149 struct i2c_msg msgs; 150 151 if (!via_i2c_par[adap].is_active) 152 return -ENODEV; 153 msgs.flags = 0; 154 msgs.addr = slave_addr / 2; 155 msgs.len = 2; 156 msgs.buf = msg; 157 ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1); 158 if (ret == 1) 159 ret = 0; 160 else if (ret >= 0) 161 ret = -EIO; 162 163 return ret; 164 } 165 166 int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len) 167 { 168 int ret; 169 u8 mm1[] = {0x00}; 170 struct i2c_msg msgs[2]; 171 172 if (!via_i2c_par[adap].is_active) 173 return -ENODEV; 174 msgs[0].flags = 0; 175 msgs[1].flags = I2C_M_RD; 176 msgs[0].addr = msgs[1].addr = slave_addr / 2; 177 mm1[0] = index; 178 msgs[0].len = 1; msgs[1].len = buff_len; 179 msgs[0].buf = mm1; msgs[1].buf = buff; 180 ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); 181 if (ret == 2) 182 ret = 0; 183 else if (ret >= 0) 184 ret = -EIO; 185 186 return ret; 187 } 188 189 /* 190 * Allow other viafb subdevices to look up a specific adapter 191 * by port name. 192 */ 193 struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which) 194 { 195 struct via_i2c_stuff *stuff = &via_i2c_par[which]; 196 197 return &stuff->adapter; 198 } 199 EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter); 200 201 202 static int create_i2c_bus(struct i2c_adapter *adapter, 203 struct i2c_algo_bit_data *algo, 204 struct via_port_cfg *adap_cfg, 205 struct pci_dev *pdev) 206 { 207 algo->setsda = via_i2c_setsda; 208 algo->setscl = via_i2c_setscl; 209 algo->getsda = via_i2c_getsda; 210 algo->getscl = via_i2c_getscl; 211 algo->udelay = 10; 212 algo->timeout = 2; 213 algo->data = adap_cfg; 214 215 sprintf(adapter->name, "viafb i2c io_port idx 0x%02x", 216 adap_cfg->ioport_index); 217 adapter->owner = THIS_MODULE; 218 adapter->class = I2C_CLASS_DDC; 219 adapter->algo_data = algo; 220 if (pdev) 221 adapter->dev.parent = &pdev->dev; 222 else 223 adapter->dev.parent = NULL; 224 /* i2c_set_adapdata(adapter, adap_cfg); */ 225 226 /* Raise SCL and SDA */ 227 via_i2c_setsda(adap_cfg, 1); 228 via_i2c_setscl(adap_cfg, 1); 229 udelay(20); 230 231 return i2c_bit_add_bus(adapter); 232 } 233 234 static int viafb_i2c_probe(struct platform_device *platdev) 235 { 236 int i, ret; 237 struct via_port_cfg *configs; 238 239 i2c_vdev = platdev->dev.platform_data; 240 configs = i2c_vdev->port_cfg; 241 242 for (i = 0; i < VIAFB_NUM_PORTS; i++) { 243 struct via_port_cfg *adap_cfg = configs++; 244 struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; 245 246 i2c_stuff->is_active = 0; 247 if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C) 248 continue; 249 ret = create_i2c_bus(&i2c_stuff->adapter, 250 &i2c_stuff->algo, adap_cfg, 251 NULL); /* FIXME: PCIDEV */ 252 if (ret < 0) { 253 printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n", 254 i, ret); 255 continue; /* Still try to make the rest */ 256 } 257 i2c_stuff->is_active = 1; 258 } 259 260 return 0; 261 } 262 263 static int viafb_i2c_remove(struct platform_device *platdev) 264 { 265 int i; 266 267 for (i = 0; i < VIAFB_NUM_PORTS; i++) { 268 struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; 269 /* 270 * Only remove those entries in the array that we've 271 * actually used (and thus initialized algo_data) 272 */ 273 if (i2c_stuff->is_active) 274 i2c_del_adapter(&i2c_stuff->adapter); 275 } 276 return 0; 277 } 278 279 static struct platform_driver via_i2c_driver = { 280 .driver = { 281 .name = "viafb-i2c", 282 }, 283 .probe = viafb_i2c_probe, 284 .remove = viafb_i2c_remove, 285 }; 286 287 int viafb_i2c_init(void) 288 { 289 return platform_driver_register(&via_i2c_driver); 290 } 291 292 void viafb_i2c_exit(void) 293 { 294 platform_driver_unregister(&via_i2c_driver); 295 } 296