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