^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * IBM OPAL I2C driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2014 IBM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/opal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static int i2c_opal_translate_error(int rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) switch (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) case OPAL_NO_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) case OPAL_PARAMETER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) case OPAL_I2C_ARBT_LOST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) case OPAL_I2C_TIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) case OPAL_I2C_NACK_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) case OPAL_I2C_STOP_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int i2c_opal_send_request(u32 bus_id, struct opal_i2c_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct opal_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int token, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) token = opal_async_get_token_interruptible();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (token < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (token != -ERESTARTSYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) pr_err("Failed to get the async token\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) rc = opal_i2c_request(token, bus_id, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (rc != OPAL_ASYNC_COMPLETION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rc = i2c_opal_translate_error(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rc = opal_async_wait_response(token, &msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) rc = opal_get_async_rc(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (rc != OPAL_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) rc = i2c_opal_translate_error(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) opal_async_release_token(token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned long opal_id = (unsigned long)adap->algo_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct opal_i2c_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* We only support fairly simple combinations here of one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * or two messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) memset(&req, 0, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) switch(num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) req.type = (msgs[0].flags & I2C_M_RD) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) req.addr = cpu_to_be16(msgs[0].addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) req.size = cpu_to_be32(msgs[0].len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) req.buffer_ra = cpu_to_be64(__pa(msgs[0].buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) req.type = (msgs[1].flags & I2C_M_RD) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) req.addr = cpu_to_be16(msgs[0].addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) req.subaddr_sz = msgs[0].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) for (i = 0; i < msgs[0].len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) req.subaddr = (req.subaddr << 8) | msgs[0].buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) req.subaddr = cpu_to_be32(req.subaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) req.size = cpu_to_be32(msgs[1].len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) req.buffer_ra = cpu_to_be64(__pa(msgs[1].buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) rc = i2c_opal_send_request(opal_id, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int i2c_opal_smbus_xfer(struct i2c_adapter *adap, u16 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned short flags, char read_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u8 command, int size, union i2c_smbus_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned long opal_id = (unsigned long)adap->algo_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct opal_i2c_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u8 local[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) memset(&req, 0, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) req.addr = cpu_to_be16(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case I2C_SMBUS_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) req.buffer_ra = cpu_to_be64(__pa(&data->byte));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) req.size = cpu_to_be32(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case I2C_SMBUS_QUICK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) req.type = (read_write == I2C_SMBUS_READ) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case I2C_SMBUS_BYTE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) req.buffer_ra = cpu_to_be64(__pa(&data->byte));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) req.size = cpu_to_be32(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) req.subaddr = cpu_to_be32(command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) req.subaddr_sz = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) req.type = (read_write == I2C_SMBUS_READ) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case I2C_SMBUS_WORD_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!read_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) local[0] = data->word & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) local[1] = (data->word >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) req.buffer_ra = cpu_to_be64(__pa(local));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) req.size = cpu_to_be32(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) req.subaddr = cpu_to_be32(command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) req.subaddr_sz = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) req.type = (read_write == I2C_SMBUS_READ) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case I2C_SMBUS_I2C_BLOCK_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) req.buffer_ra = cpu_to_be64(__pa(&data->block[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) req.size = cpu_to_be32(data->block[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) req.subaddr = cpu_to_be32(command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) req.subaddr_sz = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) req.type = (read_write == I2C_SMBUS_READ) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) rc = i2c_opal_send_request(opal_id, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (!rc && read_write && size == I2C_SMBUS_WORD_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) data->word = ((u16)local[1]) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) data->word |= local[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static u32 i2c_opal_func(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return I2C_FUNC_I2C | I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) I2C_FUNC_SMBUS_I2C_BLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static const struct i2c_algorithm i2c_opal_algo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .master_xfer = i2c_opal_master_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .smbus_xfer = i2c_opal_smbus_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .functionality = i2c_opal_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * For two messages, we basically support simple smbus transactions of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * write-then-anything.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static const struct i2c_adapter_quirks i2c_opal_quirks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .max_comb_1st_msg_len = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static int i2c_opal_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct i2c_adapter *adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) const char *pname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u32 opal_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!pdev->dev.of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) rc = of_property_read_u32(pdev->dev.of_node, "ibm,opal-id", &opal_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) dev_err(&pdev->dev, "Missing ibm,opal-id property !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) adapter = devm_kzalloc(&pdev->dev, sizeof(*adapter), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (!adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) adapter->algo = &i2c_opal_algo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) adapter->algo_data = (void *)(unsigned long)opal_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) adapter->quirks = &i2c_opal_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) adapter->dev.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) adapter->dev.of_node = of_node_get(pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) pname = of_get_property(pdev->dev.of_node, "ibm,port-name", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (pname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) strlcpy(adapter->name, pname, sizeof(adapter->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) strlcpy(adapter->name, "opal", sizeof(adapter->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) platform_set_drvdata(pdev, adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) rc = i2c_add_adapter(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_err(&pdev->dev, "Failed to register the i2c adapter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int i2c_opal_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct i2c_adapter *adapter = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) i2c_del_adapter(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static const struct of_device_id i2c_opal_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .compatible = "ibm,opal-i2c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) MODULE_DEVICE_TABLE(of, i2c_opal_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static struct platform_driver i2c_opal_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .probe = i2c_opal_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .remove = i2c_opal_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .name = "i2c-opal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .of_match_table = i2c_opal_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int __init i2c_opal_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!firmware_has_feature(FW_FEATURE_OPAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return platform_driver_register(&i2c_opal_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) module_init(i2c_opal_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static void __exit i2c_opal_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return platform_driver_unregister(&i2c_opal_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) module_exit(i2c_opal_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) MODULE_DESCRIPTION("IBM OPAL I2C driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) MODULE_LICENSE("GPL");