Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / video / fbdev / via / via_i2c.c
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 }