blob: bd03f19a3568bbef7a1ec470dc653177a328a1d2 [file] [log] [blame]
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +08001/*
2 * I2C bridge driver for the Greybus "generic" I2C module.
3 *
4 * Copyright 2014 Google Inc.
5 *
6 * Released under the GPLv2 only.
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/slab.h>
12#include <linux/i2c.h>
13#include "greybus.h"
14
Greg Kroah-Hartman199d68d2014-08-30 16:20:22 -070015struct gb_i2c_device {
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080016 struct i2c_adapter *adapter;
Alex Elder778c69c2014-09-22 19:19:03 -050017 struct greybus_module *gmod;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080018};
19
Greg Kroah-Hartman6584c8a2014-09-01 13:31:31 -070020static const struct greybus_module_id id_table[] = {
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080021 { GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */
22 { }, /* terminating NULL entry */
23};
24
25/* We BETTER be able to do SMBUS protocl calls, otherwise we are bit-banging the
26 * slowest thing possible over the fastest bus possible, crazy...
27 * FIXME - research this, for now just assume we can
28 */
29
30
31static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr,
32 unsigned short flags, char read_write, u8 command,
33 int size, union i2c_smbus_data *data)
34{
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -070035 struct gb_i2c_device *gb_i2c_dev;
Alex Elder778c69c2014-09-22 19:19:03 -050036 struct greybus_module *gmod;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080037
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -070038 gb_i2c_dev = i2c_get_adapdata(adap);
Alex Elder778c69c2014-09-22 19:19:03 -050039 gmod = gb_i2c_dev->gmod;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080040
41 // FIXME - do the actual work of sending a i2c message here...
42 switch (size) {
43 case I2C_SMBUS_QUICK:
44 case I2C_SMBUS_BYTE:
45 case I2C_SMBUS_BYTE_DATA:
46 case I2C_SMBUS_WORD_DATA:
47 case I2C_SMBUS_PROC_CALL:
48 case I2C_SMBUS_BLOCK_DATA:
49 case I2C_SMBUS_I2C_BLOCK_BROKEN:
50 case I2C_SMBUS_BLOCK_PROC_CALL:
51 case I2C_SMBUS_I2C_BLOCK_DATA:
52 default:
Alex Elder778c69c2014-09-22 19:19:03 -050053 dev_err(&gmod->dev, "Unsupported transaction %d\n", size);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080054 return -EOPNOTSUPP;
55 }
56
57 return 0;
58}
59
60static u32 i2c_gb_func(struct i2c_adapter *adapter)
61{
62 // FIXME - someone figure out what we really can support, for now just guess...
63 return I2C_FUNC_SMBUS_QUICK |
64 I2C_FUNC_SMBUS_BYTE |
65 I2C_FUNC_SMBUS_BYTE_DATA |
66 I2C_FUNC_SMBUS_WORD_DATA |
67 I2C_FUNC_SMBUS_BLOCK_DATA |
68 I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
69 I2C_FUNC_SMBUS_PEC |
70 I2C_FUNC_SMBUS_READ_I2C_BLOCK;
71}
72
73static const struct i2c_algorithm smbus_algorithm = {
74 .smbus_xfer = i2c_gb_access,
75 .functionality = i2c_gb_func,
76};
77
Alex Elder778c69c2014-09-22 19:19:03 -050078int gb_i2c_probe(struct greybus_module *gmod,
Greg Kroah-Hartman6584c8a2014-09-01 13:31:31 -070079 const struct greybus_module_id *id)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080080{
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -070081 struct gb_i2c_device *gb_i2c_dev;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080082 struct i2c_adapter *adapter;
Greg Kroah-Hartman53419e02014-08-11 17:01:15 +080083 int retval;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080084
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -070085 gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL);
86 if (!gb_i2c_dev)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080087 return -ENOMEM;
88 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
89 if (!adapter) {
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -070090 kfree(gb_i2c_dev);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080091 return -ENOMEM;
92 }
93
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -070094 i2c_set_adapdata(adapter, gb_i2c_dev);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080095 adapter->owner = THIS_MODULE;
96 adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
97 adapter->algo = &smbus_algorithm;
Alex Elder778c69c2014-09-22 19:19:03 -050098 adapter->dev.parent = &gmod->dev;
Greg Kroah-Hartman53419e02014-08-11 17:01:15 +080099 adapter->retries = 3; /* we have to pick something... */
100 snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter");
101 retval = i2c_add_adapter(adapter);
102 if (retval) {
Alex Elder778c69c2014-09-22 19:19:03 -0500103 dev_err(&gmod->dev, "Can not add SMBus adapter\n");
Greg Kroah-Hartman53419e02014-08-11 17:01:15 +0800104 goto error;
105 }
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800106
Alex Elder778c69c2014-09-22 19:19:03 -0500107 gb_i2c_dev->gmod = gmod;
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700108 gb_i2c_dev->adapter = adapter;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800109
Alex Elder778c69c2014-09-22 19:19:03 -0500110 gmod->gb_i2c_dev = gb_i2c_dev;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800111 return 0;
Greg Kroah-Hartman53419e02014-08-11 17:01:15 +0800112error:
113 kfree(adapter);
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700114 kfree(gb_i2c_dev);
Greg Kroah-Hartman53419e02014-08-11 17:01:15 +0800115 return retval;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800116}
117
Alex Elder778c69c2014-09-22 19:19:03 -0500118void gb_i2c_disconnect(struct greybus_module *gmod)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800119{
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700120 struct gb_i2c_device *gb_i2c_dev;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800121
Alex Elder778c69c2014-09-22 19:19:03 -0500122 gb_i2c_dev = gmod->gb_i2c_dev;
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700123 i2c_del_adapter(gb_i2c_dev->adapter);
124 kfree(gb_i2c_dev->adapter);
125 kfree(gb_i2c_dev);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800126}
127
Greg Kroah-Hartman199d68d2014-08-30 16:20:22 -0700128#if 0
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800129static struct greybus_driver i2c_gb_driver = {
Greg Kroah-Hartman199d68d2014-08-30 16:20:22 -0700130 .probe = gb_i2c_probe,
131 .disconnect = gb_i2c_disconnect,
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800132 .id_table = id_table,
133};
134
135module_greybus_driver(i2c_gb_driver);
136MODULE_LICENSE("GPL");
137MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");
Greg Kroah-Hartman199d68d2014-08-30 16:20:22 -0700138#endif