Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
via_i2c.c
Go to the documentation of this file.
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 
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 
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  */
194 {
195  struct via_i2c_stuff *stuff = &via_i2c_par[which];
196 
197  return &stuff->adapter;
198 }
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 }