Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
0004  * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
0005 
0006  */
0007 
0008 #include <linux/platform_device.h>
0009 #include <linux/delay.h>
0010 #include <linux/spinlock.h>
0011 #include <linux/module.h>
0012 #include <linux/via-core.h>
0013 #include <linux/via_i2c.h>
0014 
0015 /*
0016  * There can only be one set of these, so there's no point in having
0017  * them be dynamically allocated...
0018  */
0019 #define VIAFB_NUM_I2C       5
0020 static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
0021 static struct viafb_dev *i2c_vdev;  /* Passed in from core */
0022 
0023 static void via_i2c_setscl(void *data, int state)
0024 {
0025     u8 val;
0026     struct via_port_cfg *adap_data = data;
0027     unsigned long flags;
0028 
0029     spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
0030     val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
0031     if (state)
0032         val |= 0x20;
0033     else
0034         val &= ~0x20;
0035     switch (adap_data->type) {
0036     case VIA_PORT_I2C:
0037         val |= 0x01;
0038         break;
0039     case VIA_PORT_GPIO:
0040         val |= 0x82;
0041         break;
0042     default:
0043         printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
0044     }
0045     via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
0046     spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
0047 }
0048 
0049 static int via_i2c_getscl(void *data)
0050 {
0051     struct via_port_cfg *adap_data = data;
0052     unsigned long flags;
0053     int ret = 0;
0054 
0055     spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
0056     if (adap_data->type == VIA_PORT_GPIO)
0057         via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
0058             0, 0x80);
0059     if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08)
0060         ret = 1;
0061     spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
0062     return ret;
0063 }
0064 
0065 static int via_i2c_getsda(void *data)
0066 {
0067     struct via_port_cfg *adap_data = data;
0068     unsigned long flags;
0069     int ret = 0;
0070 
0071     spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
0072     if (adap_data->type == VIA_PORT_GPIO)
0073         via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
0074             0, 0x40);
0075     if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04)
0076         ret = 1;
0077     spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
0078     return ret;
0079 }
0080 
0081 static void via_i2c_setsda(void *data, int state)
0082 {
0083     u8 val;
0084     struct via_port_cfg *adap_data = data;
0085     unsigned long flags;
0086 
0087     spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
0088     val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
0089     if (state)
0090         val |= 0x10;
0091     else
0092         val &= ~0x10;
0093     switch (adap_data->type) {
0094     case VIA_PORT_I2C:
0095         val |= 0x01;
0096         break;
0097     case VIA_PORT_GPIO:
0098         val |= 0x42;
0099         break;
0100     default:
0101         printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
0102     }
0103     via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
0104     spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
0105 }
0106 
0107 int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
0108 {
0109     int ret;
0110     u8 mm1[] = {0x00};
0111     struct i2c_msg msgs[2];
0112 
0113     if (!via_i2c_par[adap].is_active)
0114         return -ENODEV;
0115     *pdata = 0;
0116     msgs[0].flags = 0;
0117     msgs[1].flags = I2C_M_RD;
0118     msgs[0].addr = msgs[1].addr = slave_addr / 2;
0119     mm1[0] = index;
0120     msgs[0].len = 1; msgs[1].len = 1;
0121     msgs[0].buf = mm1; msgs[1].buf = pdata;
0122     ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
0123     if (ret == 2)
0124         ret = 0;
0125     else if (ret >= 0)
0126         ret = -EIO;
0127 
0128     return ret;
0129 }
0130 
0131 int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
0132 {
0133     int ret;
0134     u8 msg[2] = { index, data };
0135     struct i2c_msg msgs;
0136 
0137     if (!via_i2c_par[adap].is_active)
0138         return -ENODEV;
0139     msgs.flags = 0;
0140     msgs.addr = slave_addr / 2;
0141     msgs.len = 2;
0142     msgs.buf = msg;
0143     ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
0144     if (ret == 1)
0145         ret = 0;
0146     else if (ret >= 0)
0147         ret = -EIO;
0148 
0149     return ret;
0150 }
0151 
0152 int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
0153 {
0154     int ret;
0155     u8 mm1[] = {0x00};
0156     struct i2c_msg msgs[2];
0157 
0158     if (!via_i2c_par[adap].is_active)
0159         return -ENODEV;
0160     msgs[0].flags = 0;
0161     msgs[1].flags = I2C_M_RD;
0162     msgs[0].addr = msgs[1].addr = slave_addr / 2;
0163     mm1[0] = index;
0164     msgs[0].len = 1; msgs[1].len = buff_len;
0165     msgs[0].buf = mm1; msgs[1].buf = buff;
0166     ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
0167     if (ret == 2)
0168         ret = 0;
0169     else if (ret >= 0)
0170         ret = -EIO;
0171 
0172     return ret;
0173 }
0174 
0175 /*
0176  * Allow other viafb subdevices to look up a specific adapter
0177  * by port name.
0178  */
0179 struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which)
0180 {
0181     struct via_i2c_stuff *stuff = &via_i2c_par[which];
0182 
0183     return &stuff->adapter;
0184 }
0185 EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter);
0186 
0187 
0188 static int create_i2c_bus(struct i2c_adapter *adapter,
0189               struct i2c_algo_bit_data *algo,
0190               struct via_port_cfg *adap_cfg,
0191               struct pci_dev *pdev)
0192 {
0193     algo->setsda = via_i2c_setsda;
0194     algo->setscl = via_i2c_setscl;
0195     algo->getsda = via_i2c_getsda;
0196     algo->getscl = via_i2c_getscl;
0197     algo->udelay = 10;
0198     algo->timeout = 2;
0199     algo->data = adap_cfg;
0200 
0201     sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
0202         adap_cfg->ioport_index);
0203     adapter->owner = THIS_MODULE;
0204     adapter->class = I2C_CLASS_DDC;
0205     adapter->algo_data = algo;
0206     if (pdev)
0207         adapter->dev.parent = &pdev->dev;
0208     else
0209         adapter->dev.parent = NULL;
0210     /* i2c_set_adapdata(adapter, adap_cfg); */
0211 
0212     /* Raise SCL and SDA */
0213     via_i2c_setsda(adap_cfg, 1);
0214     via_i2c_setscl(adap_cfg, 1);
0215     udelay(20);
0216 
0217     return i2c_bit_add_bus(adapter);
0218 }
0219 
0220 static int viafb_i2c_probe(struct platform_device *platdev)
0221 {
0222     int i, ret;
0223     struct via_port_cfg *configs;
0224 
0225     i2c_vdev = platdev->dev.platform_data;
0226     configs = i2c_vdev->port_cfg;
0227 
0228     for (i = 0; i < VIAFB_NUM_PORTS; i++) {
0229         struct via_port_cfg *adap_cfg = configs++;
0230         struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
0231 
0232         i2c_stuff->is_active = 0;
0233         if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C)
0234             continue;
0235         ret = create_i2c_bus(&i2c_stuff->adapter,
0236                      &i2c_stuff->algo, adap_cfg,
0237                 NULL); /* FIXME: PCIDEV */
0238         if (ret < 0) {
0239             printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n",
0240                 i, ret);
0241             continue;  /* Still try to make the rest */
0242         }
0243         i2c_stuff->is_active = 1;
0244     }
0245 
0246     return 0;
0247 }
0248 
0249 static int viafb_i2c_remove(struct platform_device *platdev)
0250 {
0251     int i;
0252 
0253     for (i = 0; i < VIAFB_NUM_PORTS; i++) {
0254         struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
0255         /*
0256          * Only remove those entries in the array that we've
0257          * actually used (and thus initialized algo_data)
0258          */
0259         if (i2c_stuff->is_active)
0260             i2c_del_adapter(&i2c_stuff->adapter);
0261     }
0262     return 0;
0263 }
0264 
0265 static struct platform_driver via_i2c_driver = {
0266     .driver = {
0267         .name = "viafb-i2c",
0268     },
0269     .probe = viafb_i2c_probe,
0270     .remove = viafb_i2c_remove,
0271 };
0272 
0273 int viafb_i2c_init(void)
0274 {
0275     return platform_driver_register(&via_i2c_driver);
0276 }
0277 
0278 void viafb_i2c_exit(void)
0279 {
0280     platform_driver_unregister(&via_i2c_driver);
0281 }