Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
i2c-scmi.c
Go to the documentation of this file.
1 /*
2  * SMBus driver for ACPI SMBus CMI
3  *
4  * Copyright (C) 2009 Crane Cai <[email protected]>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation version 2.
9  */
10 
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/kernel.h>
14 #include <linux/stddef.h>
15 #include <linux/init.h>
16 #include <linux/i2c.h>
17 #include <linux/acpi.h>
18 
19 #define ACPI_SMBUS_HC_CLASS "smbus"
20 #define ACPI_SMBUS_HC_DEVICE_NAME "cmi"
21 
22 ACPI_MODULE_NAME("smbus_cmi");
23 
25  char *mt_info;
26  char *mt_sbr;
27  char *mt_sbw;
28 };
29 
37 };
38 
39 static const struct smbus_methods_t smbus_methods = {
40  .mt_info = "_SBI",
41  .mt_sbr = "_SBR",
42  .mt_sbw = "_SBW",
43 };
44 
45 /* Some IBM BIOSes omit the leading underscore */
46 static const struct smbus_methods_t ibm_smbus_methods = {
47  .mt_info = "SBI_",
48  .mt_sbr = "SBR_",
49  .mt_sbw = "SBW_",
50 };
51 
52 static const struct acpi_device_id acpi_smbus_cmi_ids[] = {
53  {"SMBUS01", (kernel_ulong_t)&smbus_methods},
54  {ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods},
55  {"", 0}
56 };
57 MODULE_DEVICE_TABLE(acpi, acpi_smbus_cmi_ids);
58 
59 #define ACPI_SMBUS_STATUS_OK 0x00
60 #define ACPI_SMBUS_STATUS_FAIL 0x07
61 #define ACPI_SMBUS_STATUS_DNAK 0x10
62 #define ACPI_SMBUS_STATUS_DERR 0x11
63 #define ACPI_SMBUS_STATUS_CMD_DENY 0x12
64 #define ACPI_SMBUS_STATUS_UNKNOWN 0x13
65 #define ACPI_SMBUS_STATUS_ACC_DENY 0x17
66 #define ACPI_SMBUS_STATUS_TIMEOUT 0x18
67 #define ACPI_SMBUS_STATUS_NOTSUP 0x19
68 #define ACPI_SMBUS_STATUS_BUSY 0x1a
69 #define ACPI_SMBUS_STATUS_PEC 0x1f
70 
71 #define ACPI_SMBUS_PRTCL_WRITE 0x00
72 #define ACPI_SMBUS_PRTCL_READ 0x01
73 #define ACPI_SMBUS_PRTCL_QUICK 0x02
74 #define ACPI_SMBUS_PRTCL_BYTE 0x04
75 #define ACPI_SMBUS_PRTCL_BYTE_DATA 0x06
76 #define ACPI_SMBUS_PRTCL_WORD_DATA 0x08
77 #define ACPI_SMBUS_PRTCL_BLOCK_DATA 0x0a
78 
79 
80 static int
81 acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
82  char read_write, u8 command, int size,
83  union i2c_smbus_data *data)
84 {
85  int result = 0;
86  struct acpi_smbus_cmi *smbus_cmi = adap->algo_data;
87  unsigned char protocol;
88  acpi_status status = 0;
89  struct acpi_object_list input;
90  union acpi_object mt_params[5];
91  struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
92  union acpi_object *obj;
93  union acpi_object *pkg;
94  char *method;
95  int len = 0;
96 
97  dev_dbg(&adap->dev, "access size: %d %s\n", size,
98  (read_write) ? "READ" : "WRITE");
99  switch (size) {
100  case I2C_SMBUS_QUICK:
101  protocol = ACPI_SMBUS_PRTCL_QUICK;
102  command = 0;
103  if (read_write == I2C_SMBUS_WRITE) {
104  mt_params[3].type = ACPI_TYPE_INTEGER;
105  mt_params[3].integer.value = 0;
106  mt_params[4].type = ACPI_TYPE_INTEGER;
107  mt_params[4].integer.value = 0;
108  }
109  break;
110 
111  case I2C_SMBUS_BYTE:
112  protocol = ACPI_SMBUS_PRTCL_BYTE;
113  if (read_write == I2C_SMBUS_WRITE) {
114  mt_params[3].type = ACPI_TYPE_INTEGER;
115  mt_params[3].integer.value = 0;
116  mt_params[4].type = ACPI_TYPE_INTEGER;
117  mt_params[4].integer.value = 0;
118  } else {
119  command = 0;
120  }
121  break;
122 
123  case I2C_SMBUS_BYTE_DATA:
124  protocol = ACPI_SMBUS_PRTCL_BYTE_DATA;
125  if (read_write == I2C_SMBUS_WRITE) {
126  mt_params[3].type = ACPI_TYPE_INTEGER;
127  mt_params[3].integer.value = 1;
128  mt_params[4].type = ACPI_TYPE_INTEGER;
129  mt_params[4].integer.value = data->byte;
130  }
131  break;
132 
133  case I2C_SMBUS_WORD_DATA:
134  protocol = ACPI_SMBUS_PRTCL_WORD_DATA;
135  if (read_write == I2C_SMBUS_WRITE) {
136  mt_params[3].type = ACPI_TYPE_INTEGER;
137  mt_params[3].integer.value = 2;
138  mt_params[4].type = ACPI_TYPE_INTEGER;
139  mt_params[4].integer.value = data->word;
140  }
141  break;
142 
144  protocol = ACPI_SMBUS_PRTCL_BLOCK_DATA;
145  if (read_write == I2C_SMBUS_WRITE) {
146  len = data->block[0];
147  if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
148  return -EINVAL;
149  mt_params[3].type = ACPI_TYPE_INTEGER;
150  mt_params[3].integer.value = len;
151  mt_params[4].type = ACPI_TYPE_BUFFER;
152  mt_params[4].buffer.pointer = data->block + 1;
153  }
154  break;
155 
156  default:
157  dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
158  return -EOPNOTSUPP;
159  }
160 
161  if (read_write == I2C_SMBUS_READ) {
162  protocol |= ACPI_SMBUS_PRTCL_READ;
163  method = smbus_cmi->methods->mt_sbr;
164  input.count = 3;
165  } else {
166  protocol |= ACPI_SMBUS_PRTCL_WRITE;
167  method = smbus_cmi->methods->mt_sbw;
168  input.count = 5;
169  }
170 
171  input.pointer = mt_params;
172  mt_params[0].type = ACPI_TYPE_INTEGER;
173  mt_params[0].integer.value = protocol;
174  mt_params[1].type = ACPI_TYPE_INTEGER;
175  mt_params[1].integer.value = addr;
176  mt_params[2].type = ACPI_TYPE_INTEGER;
177  mt_params[2].integer.value = command;
178 
179  status = acpi_evaluate_object(smbus_cmi->handle, method, &input,
180  &buffer);
181  if (ACPI_FAILURE(status)) {
182  ACPI_ERROR((AE_INFO, "Evaluating %s: %i", method, status));
183  return -EIO;
184  }
185 
186  pkg = buffer.pointer;
187  if (pkg && pkg->type == ACPI_TYPE_PACKAGE)
188  obj = pkg->package.elements;
189  else {
190  ACPI_ERROR((AE_INFO, "Invalid argument type"));
191  result = -EIO;
192  goto out;
193  }
194  if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) {
195  ACPI_ERROR((AE_INFO, "Invalid argument type"));
196  result = -EIO;
197  goto out;
198  }
199 
200  result = obj->integer.value;
201  ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s return status: %i\n",
202  method, result));
203 
204  switch (result) {
206  result = 0;
207  break;
209  result = -EBUSY;
210  goto out;
212  result = -ETIMEDOUT;
213  goto out;
215  result = -ENXIO;
216  goto out;
217  default:
218  result = -EIO;
219  goto out;
220  }
221 
222  if (read_write == I2C_SMBUS_WRITE || size == I2C_SMBUS_QUICK)
223  goto out;
224 
225  obj = pkg->package.elements + 1;
226  if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) {
227  ACPI_ERROR((AE_INFO, "Invalid argument type"));
228  result = -EIO;
229  goto out;
230  }
231 
232  len = obj->integer.value;
233  obj = pkg->package.elements + 2;
234  switch (size) {
235  case I2C_SMBUS_BYTE:
236  case I2C_SMBUS_BYTE_DATA:
237  case I2C_SMBUS_WORD_DATA:
238  if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) {
239  ACPI_ERROR((AE_INFO, "Invalid argument type"));
240  result = -EIO;
241  goto out;
242  }
243  if (len == 2)
244  data->word = obj->integer.value;
245  else
246  data->byte = obj->integer.value;
247  break;
249  if (obj == NULL || obj->type != ACPI_TYPE_BUFFER) {
250  ACPI_ERROR((AE_INFO, "Invalid argument type"));
251  result = -EIO;
252  goto out;
253  }
254  if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
255  return -EPROTO;
256  data->block[0] = len;
257  memcpy(data->block + 1, obj->buffer.pointer, len);
258  break;
259  }
260 
261 out:
262  kfree(buffer.pointer);
263  dev_dbg(&adap->dev, "Transaction status: %i\n", result);
264  return result;
265 }
266 
267 static u32 acpi_smbus_cmi_func(struct i2c_adapter *adapter)
268 {
269  struct acpi_smbus_cmi *smbus_cmi = adapter->algo_data;
270  u32 ret;
271 
272  ret = smbus_cmi->cap_read | smbus_cmi->cap_write ?
274 
275  ret |= smbus_cmi->cap_read ?
280 
281  ret |= smbus_cmi->cap_write ?
286 
287  return ret;
288 }
289 
290 static const struct i2c_algorithm acpi_smbus_cmi_algorithm = {
291  .smbus_xfer = acpi_smbus_cmi_access,
292  .functionality = acpi_smbus_cmi_func,
293 };
294 
295 
296 static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
297  const char *name)
298 {
300  union acpi_object *obj;
302 
303  if (!strcmp(name, smbus_cmi->methods->mt_info)) {
304  status = acpi_evaluate_object(smbus_cmi->handle,
305  smbus_cmi->methods->mt_info,
306  NULL, &buffer);
307  if (ACPI_FAILURE(status)) {
308  ACPI_ERROR((AE_INFO, "Evaluating %s: %i",
309  smbus_cmi->methods->mt_info, status));
310  return -EIO;
311  }
312 
313  obj = buffer.pointer;
314  if (obj && obj->type == ACPI_TYPE_PACKAGE)
315  obj = obj->package.elements;
316  else {
317  ACPI_ERROR((AE_INFO, "Invalid argument type"));
318  kfree(buffer.pointer);
319  return -EIO;
320  }
321 
322  if (obj->type != ACPI_TYPE_INTEGER) {
323  ACPI_ERROR((AE_INFO, "Invalid argument type"));
324  kfree(buffer.pointer);
325  return -EIO;
326  } else
327  ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SMBus CMI Version %x"
328  "\n", (int)obj->integer.value));
329 
330  kfree(buffer.pointer);
331  smbus_cmi->cap_info = 1;
332  } else if (!strcmp(name, smbus_cmi->methods->mt_sbr))
333  smbus_cmi->cap_read = 1;
334  else if (!strcmp(name, smbus_cmi->methods->mt_sbw))
335  smbus_cmi->cap_write = 1;
336  else
337  ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n",
338  name));
339 
340  return 0;
341 }
342 
343 static acpi_status acpi_smbus_cmi_query_methods(acpi_handle handle, u32 level,
344  void *context, void **return_value)
345 {
346  char node_name[5];
347  struct acpi_buffer buffer = { sizeof(node_name), node_name };
348  struct acpi_smbus_cmi *smbus_cmi = context;
350 
351  status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
352 
353  if (ACPI_SUCCESS(status))
354  acpi_smbus_cmi_add_cap(smbus_cmi, node_name);
355 
356  return AE_OK;
357 }
358 
359 static int acpi_smbus_cmi_add(struct acpi_device *device)
360 {
361  struct acpi_smbus_cmi *smbus_cmi;
362  const struct acpi_device_id *id;
363 
364  smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
365  if (!smbus_cmi)
366  return -ENOMEM;
367 
368  smbus_cmi->handle = device->handle;
369  strcpy(acpi_device_name(device), ACPI_SMBUS_HC_DEVICE_NAME);
370  strcpy(acpi_device_class(device), ACPI_SMBUS_HC_CLASS);
371  device->driver_data = smbus_cmi;
372  smbus_cmi->cap_info = 0;
373  smbus_cmi->cap_read = 0;
374  smbus_cmi->cap_write = 0;
375 
376  for (id = acpi_smbus_cmi_ids; id->id[0]; id++)
377  if (!strcmp(id->id, acpi_device_hid(device)))
378  smbus_cmi->methods =
379  (struct smbus_methods_t *) id->driver_data;
380 
382  acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
383 
384  if (smbus_cmi->cap_info == 0)
385  goto err;
386 
387  snprintf(smbus_cmi->adapter.name, sizeof(smbus_cmi->adapter.name),
388  "SMBus CMI adapter %s",
389  acpi_device_name(device));
390  smbus_cmi->adapter.owner = THIS_MODULE;
391  smbus_cmi->adapter.algo = &acpi_smbus_cmi_algorithm;
392  smbus_cmi->adapter.algo_data = smbus_cmi;
393  smbus_cmi->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
394  smbus_cmi->adapter.dev.parent = &device->dev;
395 
396  if (i2c_add_adapter(&smbus_cmi->adapter)) {
397  dev_err(&device->dev, "Couldn't register adapter!\n");
398  goto err;
399  }
400 
401  return 0;
402 
403 err:
404  kfree(smbus_cmi);
405  device->driver_data = NULL;
406  return -EIO;
407 }
408 
409 static int acpi_smbus_cmi_remove(struct acpi_device *device, int type)
410 {
411  struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device);
412 
413  i2c_del_adapter(&smbus_cmi->adapter);
414  kfree(smbus_cmi);
415  device->driver_data = NULL;
416 
417  return 0;
418 }
419 
420 static struct acpi_driver acpi_smbus_cmi_driver = {
422  .class = ACPI_SMBUS_HC_CLASS,
423  .ids = acpi_smbus_cmi_ids,
424  .ops = {
425  .add = acpi_smbus_cmi_add,
426  .remove = acpi_smbus_cmi_remove,
427  },
428 };
429 module_acpi_driver(acpi_smbus_cmi_driver);
430 
431 MODULE_LICENSE("GPL");
432 MODULE_AUTHOR("Crane Cai <[email protected]>");
433 MODULE_DESCRIPTION("ACPI SMBus CMI driver");