|
| 1 | +From 3e212b8886a21fad8df621992b00b6bd1f5a7f16 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Don Bollinger < [email protected]> |
| 3 | +Date: Sat, 3 Aug 2019 12:06:05 -0700 |
| 4 | +Subject: [PATCH] drivers/misc/eeprom: Support QSFP-DD (CMIS) type |
| 5 | + devices |
| 6 | + |
| 7 | + Add support for CMIS devices (QSFP-DD, OSFP, etc) to optoe driver |
| 8 | + Backward compatible, still supports SFP* and QSFP* devices |
| 9 | + Note: CMIS devices are 'optoe3' (SFP remain optoe2, QSFP optoe1) |
| 10 | + |
| 11 | +Signed-off-by: Don Bollinger < [email protected]> |
| 12 | +--- |
| 13 | + drivers/misc/eeprom/optoe.c | 61 +++++++++++++++++++++++++++++++++++++---- |
| 14 | + 1 file changed, 56 insertions(+), 5 deletions(-) |
| 15 | + |
| 16 | +diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c |
| 17 | +index c22b92a..16287fd 100644 |
| 18 | +--- a/drivers/misc/eeprom/optoe.c |
| 19 | ++++ b/drivers/misc/eeprom/optoe.c |
| 20 | +@@ -97,6 +97,13 @@ |
| 21 | + * In anticipation of future applications and devices, this driver |
| 22 | + * supports access to the full architected range, 256 pages. |
| 23 | + * |
| 24 | ++ * The CMIS (Common Management Interface Specification) defines use of |
| 25 | ++ * considerably more pages (at least to page 0xAF), which this driver |
| 26 | ++ * supports. |
| 27 | ++ * |
| 28 | ++ * NOTE: This version of the driver ONLY SUPPORTS BANK 0 PAGES on CMIS |
| 29 | ++ * devices. |
| 30 | ++ * |
| 31 | + **/ |
| 32 | + |
| 33 | + /* #define DEBUG 1 */ |
| 34 | +@@ -163,7 +170,8 @@ struct optoe_platform_data { |
| 35 | + /* a few constants to find our way around the EEPROM */ |
| 36 | + #define OPTOE_PAGE_SELECT_REG 0x7F |
| 37 | + #define ONE_ADDR_PAGEABLE_REG 0x02 |
| 38 | +-#define ONE_ADDR_NOT_PAGEABLE (1<<2) |
| 39 | ++#define QSFP_NOT_PAGEABLE (1<<2) |
| 40 | ++#define CMIS_NOT_PAGEABLE (1<<7) |
| 41 | + #define TWO_ADDR_PAGEABLE_REG 0x40 |
| 42 | + #define TWO_ADDR_PAGEABLE (1<<4) |
| 43 | + #define TWO_ADDR_0X51_REG 92 |
| 44 | +@@ -225,10 +233,12 @@ static unsigned int write_timeout = 25; |
| 45 | + */ |
| 46 | + #define ONE_ADDR 1 |
| 47 | + #define TWO_ADDR 2 |
| 48 | ++#define CMIS_ADDR 3 |
| 49 | + |
| 50 | + static const struct i2c_device_id optoe_ids[] = { |
| 51 | + { "optoe1", ONE_ADDR }, |
| 52 | + { "optoe2", TWO_ADDR }, |
| 53 | ++ { "optoe3", CMIS_ADDR }, |
| 54 | + { "sff8436", ONE_ADDR }, |
| 55 | + { "24c04", TWO_ADDR }, |
| 56 | + { /* END OF LIST */ } |
| 57 | +@@ -575,6 +585,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, |
| 58 | + { |
| 59 | + struct i2c_client *client = optoe->client[0]; |
| 60 | + u8 regval; |
| 61 | ++ int not_pageable; |
| 62 | + int status; |
| 63 | + size_t maxlen; |
| 64 | + |
| 65 | +@@ -622,7 +633,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, |
| 66 | + "page_legal, SFP, off %lld len %ld\n", |
| 67 | + off, (long int) len); |
| 68 | + } else { |
| 69 | +- /* QSFP case */ |
| 70 | ++ /* QSFP case, CMIS case */ |
| 71 | + /* if no pages needed, we're good */ |
| 72 | + if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) |
| 73 | + return len; |
| 74 | +@@ -634,7 +645,17 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, |
| 75 | + ONE_ADDR_PAGEABLE_REG, 1); |
| 76 | + if (status < 0) |
| 77 | + return status; /* error out (no module?) */ |
| 78 | +- if (regval & ONE_ADDR_NOT_PAGEABLE) { |
| 79 | ++ |
| 80 | ++ if (optoe->dev_class == ONE_ADDR) { |
| 81 | ++ not_pageable = QSFP_NOT_PAGEABLE; |
| 82 | ++ } else { |
| 83 | ++ not_pageable = CMIS_NOT_PAGEABLE; |
| 84 | ++ } |
| 85 | ++ dev_dbg(&client->dev, |
| 86 | ++ "Paging Register: 0x%x; not_pageable mask: 0x%x\n", |
| 87 | ++ regval, not_pageable); |
| 88 | ++ |
| 89 | ++ if (regval & not_pageable) { |
| 90 | + /* pages not supported, trim len to unpaged size */ |
| 91 | + if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) |
| 92 | + return OPTOE_EOF; |
| 93 | +@@ -826,13 +847,37 @@ static ssize_t set_dev_class(struct device *dev, |
| 94 | + /* |
| 95 | + * dev_class is actually the number of i2c addresses used, thus |
| 96 | + * legal values are "1" (QSFP class) and "2" (SFP class) |
| 97 | ++ * And... CMIS spec is 1 i2c address, but puts the pageable |
| 98 | ++ * bit in a different location, so CMIS devices are "3" |
| 99 | + */ |
| 100 | + |
| 101 | + if (kstrtoint(buf, 0, &dev_class) != 0 || |
| 102 | +- dev_class < 1 || dev_class > 2) |
| 103 | ++ dev_class < 1 || dev_class > 3) |
| 104 | + return -EINVAL; |
| 105 | + |
| 106 | + mutex_lock(&optoe->lock); |
| 107 | ++ if (dev_class == TWO_ADDR) { |
| 108 | ++ /* SFP family */ |
| 109 | ++ /* if it doesn't exist, create 0x51 i2c address */ |
| 110 | ++ if (!optoe->client[1]) { |
| 111 | ++ optoe->client[1] = i2c_new_dummy(client->adapter, 0x51); |
| 112 | ++ if (!optoe->client[1]) { |
| 113 | ++ dev_err(&client->dev, |
| 114 | ++ "address 0x51 unavailable\n"); |
| 115 | ++ mutex_unlock(&optoe->lock); |
| 116 | ++ return -EADDRINUSE; |
| 117 | ++ } |
| 118 | ++ } |
| 119 | ++ optoe->bin.size = TWO_ADDR_EEPROM_SIZE; |
| 120 | ++ optoe->num_addresses = 2; |
| 121 | ++ } else { |
| 122 | ++ /* one-address (eg QSFP) and CMIS family */ |
| 123 | ++ /* if it exists, remove 0x51 i2c address */ |
| 124 | ++ if (optoe->client[1]) |
| 125 | ++ i2c_unregister_device(optoe->client[1]); |
| 126 | ++ optoe->bin.size = ONE_ADDR_EEPROM_SIZE; |
| 127 | ++ optoe->num_addresses = 1; |
| 128 | ++ } |
| 129 | + optoe->dev_class = dev_class; |
| 130 | + mutex_unlock(&optoe->lock); |
| 131 | + |
| 132 | +@@ -983,7 +1028,13 @@ static int optoe_probe(struct i2c_client *client, |
| 133 | + /* SFP family */ |
| 134 | + optoe->dev_class = TWO_ADDR; |
| 135 | + chip.byte_len = TWO_ADDR_EEPROM_SIZE; |
| 136 | +- } else { /* those were the only two choices */ |
| 137 | ++ num_addresses = 2; |
| 138 | ++ } else if (strcmp(client->name, "optoe3") == 0) { |
| 139 | ++ /* CMIS spec */ |
| 140 | ++ optoe->dev_class = CMIS_ADDR; |
| 141 | ++ chip.byte_len = ONE_ADDR_EEPROM_SIZE; |
| 142 | ++ num_addresses = 1; |
| 143 | ++ } else { /* those were the only choices */ |
| 144 | + err = -EINVAL; |
| 145 | + goto exit; |
| 146 | + } |
| 147 | +-- |
| 148 | +2.16.2 |
| 149 | + |
0 commit comments