323 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * I2C bridge driver for the Greybus "generic" I2C module.4 *5 * Copyright 2014 Google Inc.6 * Copyright 2014 Linaro Ltd.7 */8 9#include <linux/kernel.h>10#include <linux/module.h>11#include <linux/slab.h>12#include <linux/i2c.h>13#include <linux/greybus.h>14 15#include "gbphy.h"16 17struct gb_i2c_device {18 struct gb_connection *connection;19 struct gbphy_device *gbphy_dev;20 21 u32 functionality;22 23 struct i2c_adapter adapter;24};25 26/*27 * Map Greybus i2c functionality bits into Linux ones28 */29static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality)30{31 return gb_i2c_functionality; /* All bits the same for now */32}33 34/*35 * Do initial setup of the i2c device. This includes verifying we36 * can support it (based on the protocol version it advertises).37 * If that's OK, we get and cached its functionality bits.38 *39 * Note: gb_i2c_dev->connection is assumed to have been valid.40 */41static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev)42{43 struct gb_i2c_functionality_response response;44 u32 functionality;45 int ret;46 47 ret = gb_operation_sync(gb_i2c_dev->connection,48 GB_I2C_TYPE_FUNCTIONALITY,49 NULL, 0, &response, sizeof(response));50 if (ret)51 return ret;52 53 functionality = le32_to_cpu(response.functionality);54 gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality);55 56 return 0;57}58 59/*60 * Map Linux i2c_msg flags into Greybus i2c transfer op flags.61 */62static u16 gb_i2c_transfer_op_flags_map(u16 flags)63{64 return flags; /* All flags the same for now */65}66 67static void68gb_i2c_fill_transfer_op(struct gb_i2c_transfer_op *op, struct i2c_msg *msg)69{70 u16 flags = gb_i2c_transfer_op_flags_map(msg->flags);71 72 op->addr = cpu_to_le16(msg->addr);73 op->flags = cpu_to_le16(flags);74 op->size = cpu_to_le16(msg->len);75}76 77static struct gb_operation *78gb_i2c_operation_create(struct gb_connection *connection,79 struct i2c_msg *msgs, u32 msg_count)80{81 struct gb_i2c_device *gb_i2c_dev = gb_connection_get_data(connection);82 struct gb_i2c_transfer_request *request;83 struct gb_operation *operation;84 struct gb_i2c_transfer_op *op;85 struct i2c_msg *msg;86 u32 data_out_size = 0;87 u32 data_in_size = 0;88 size_t request_size;89 void *data;90 u16 op_count;91 u32 i;92 93 if (msg_count > (u32)U16_MAX) {94 dev_err(&gb_i2c_dev->gbphy_dev->dev, "msg_count (%u) too big\n",95 msg_count);96 return NULL;97 }98 op_count = (u16)msg_count;99 100 /*101 * In addition to space for all message descriptors we need102 * to have enough to hold all outbound message data.103 */104 msg = msgs;105 for (i = 0; i < msg_count; i++, msg++)106 if (msg->flags & I2C_M_RD)107 data_in_size += (u32)msg->len;108 else109 data_out_size += (u32)msg->len;110 111 request_size = sizeof(*request);112 request_size += msg_count * sizeof(*op);113 request_size += data_out_size;114 115 /* Response consists only of incoming data */116 operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER,117 request_size, data_in_size, GFP_KERNEL);118 if (!operation)119 return NULL;120 121 request = operation->request->payload;122 request->op_count = cpu_to_le16(op_count);123 /* Fill in the ops array */124 op = &request->ops[0];125 msg = msgs;126 for (i = 0; i < msg_count; i++)127 gb_i2c_fill_transfer_op(op++, msg++);128 129 if (!data_out_size)130 return operation;131 132 /* Copy over the outgoing data; it starts after the last op */133 data = op;134 msg = msgs;135 for (i = 0; i < msg_count; i++) {136 if (!(msg->flags & I2C_M_RD)) {137 memcpy(data, msg->buf, msg->len);138 data += msg->len;139 }140 msg++;141 }142 143 return operation;144}145 146static void gb_i2c_decode_response(struct i2c_msg *msgs, u32 msg_count,147 struct gb_i2c_transfer_response *response)148{149 struct i2c_msg *msg = msgs;150 u8 *data;151 u32 i;152 153 if (!response)154 return;155 data = response->data;156 for (i = 0; i < msg_count; i++) {157 if (msg->flags & I2C_M_RD) {158 memcpy(msg->buf, data, msg->len);159 data += msg->len;160 }161 msg++;162 }163}164 165/*166 * Some i2c transfer operations return results that are expected.167 */168static bool gb_i2c_expected_transfer_error(int errno)169{170 return errno == -EAGAIN || errno == -ENODEV;171}172 173static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev,174 struct i2c_msg *msgs, u32 msg_count)175{176 struct gb_connection *connection = gb_i2c_dev->connection;177 struct device *dev = &gb_i2c_dev->gbphy_dev->dev;178 struct gb_operation *operation;179 int ret;180 181 operation = gb_i2c_operation_create(connection, msgs, msg_count);182 if (!operation)183 return -ENOMEM;184 185 ret = gbphy_runtime_get_sync(gb_i2c_dev->gbphy_dev);186 if (ret)187 goto exit_operation_put;188 189 ret = gb_operation_request_send_sync(operation);190 if (!ret) {191 struct gb_i2c_transfer_response *response;192 193 response = operation->response->payload;194 gb_i2c_decode_response(msgs, msg_count, response);195 ret = msg_count;196 } else if (!gb_i2c_expected_transfer_error(ret)) {197 dev_err(dev, "transfer operation failed (%d)\n", ret);198 }199 200 gbphy_runtime_put_autosuspend(gb_i2c_dev->gbphy_dev);201 202exit_operation_put:203 gb_operation_put(operation);204 205 return ret;206}207 208static int gb_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,209 int msg_count)210{211 struct gb_i2c_device *gb_i2c_dev;212 213 gb_i2c_dev = i2c_get_adapdata(adap);214 215 return gb_i2c_transfer_operation(gb_i2c_dev, msgs, msg_count);216}217 218static u32 gb_i2c_functionality(struct i2c_adapter *adap)219{220 struct gb_i2c_device *gb_i2c_dev = i2c_get_adapdata(adap);221 222 return gb_i2c_dev->functionality;223}224 225static const struct i2c_algorithm gb_i2c_algorithm = {226 .master_xfer = gb_i2c_master_xfer,227 .functionality = gb_i2c_functionality,228};229 230static int gb_i2c_probe(struct gbphy_device *gbphy_dev,231 const struct gbphy_device_id *id)232{233 struct gb_connection *connection;234 struct gb_i2c_device *gb_i2c_dev;235 struct i2c_adapter *adapter;236 int ret;237 238 gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL);239 if (!gb_i2c_dev)240 return -ENOMEM;241 242 connection =243 gb_connection_create(gbphy_dev->bundle,244 le16_to_cpu(gbphy_dev->cport_desc->id),245 NULL);246 if (IS_ERR(connection)) {247 ret = PTR_ERR(connection);248 goto exit_i2cdev_free;249 }250 251 gb_i2c_dev->connection = connection;252 gb_connection_set_data(connection, gb_i2c_dev);253 gb_i2c_dev->gbphy_dev = gbphy_dev;254 gb_gbphy_set_data(gbphy_dev, gb_i2c_dev);255 256 ret = gb_connection_enable(connection);257 if (ret)258 goto exit_connection_destroy;259 260 ret = gb_i2c_device_setup(gb_i2c_dev);261 if (ret)262 goto exit_connection_disable;263 264 /* Looks good; up our i2c adapter */265 adapter = &gb_i2c_dev->adapter;266 adapter->owner = THIS_MODULE;267 adapter->class = I2C_CLASS_HWMON;268 adapter->algo = &gb_i2c_algorithm;269 270 adapter->dev.parent = &gbphy_dev->dev;271 snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter");272 i2c_set_adapdata(adapter, gb_i2c_dev);273 274 ret = i2c_add_adapter(adapter);275 if (ret)276 goto exit_connection_disable;277 278 gbphy_runtime_put_autosuspend(gbphy_dev);279 return 0;280 281exit_connection_disable:282 gb_connection_disable(connection);283exit_connection_destroy:284 gb_connection_destroy(connection);285exit_i2cdev_free:286 kfree(gb_i2c_dev);287 288 return ret;289}290 291static void gb_i2c_remove(struct gbphy_device *gbphy_dev)292{293 struct gb_i2c_device *gb_i2c_dev = gb_gbphy_get_data(gbphy_dev);294 struct gb_connection *connection = gb_i2c_dev->connection;295 int ret;296 297 ret = gbphy_runtime_get_sync(gbphy_dev);298 if (ret)299 gbphy_runtime_get_noresume(gbphy_dev);300 301 i2c_del_adapter(&gb_i2c_dev->adapter);302 gb_connection_disable(connection);303 gb_connection_destroy(connection);304 kfree(gb_i2c_dev);305}306 307static const struct gbphy_device_id gb_i2c_id_table[] = {308 { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_I2C) },309 { },310};311MODULE_DEVICE_TABLE(gbphy, gb_i2c_id_table);312 313static struct gbphy_driver i2c_driver = {314 .name = "i2c",315 .probe = gb_i2c_probe,316 .remove = gb_i2c_remove,317 .id_table = gb_i2c_id_table,318};319 320module_gbphy_driver(i2c_driver);321MODULE_DESCRIPTION("I2C bridge driver for the Greybus 'generic' I2C module");322MODULE_LICENSE("GPL v2");323