Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

eeprom: idt_89hpesx: Support both ACPI and OF probing

Allow the idt_89hpesx driver to get information from child nodes from
both OF and ACPI by using more generic fwnode_property_read*() functions.

Below is an example of instantiating idt_89hpesx driver via ACPI Table:

Device(IDT0) {
Name(_HID, "PRP0001")
Name(_CID, "PRP0001")
Name(_CCA, ONE)
Name(_STR, Unicode("IDT SW I2C Slave"))
Name(_CRS, ResourceTemplate () {
I2cSerialBus (0x74, ControllerInitiated, 1000,
AddressingMode7Bit, "\\_SB.I2CS",
0x00, ResourceConsumer, ,
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "idt,89hpes32nt8ag2"},
},
})
Device (EPR0) {
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "onsemi,24c64"},
Package () {"reg", 0x50},
}
})
}
}

Signed-off-by: Huy Duong <qhuyduong@hotmail.com>
Acked-by: Serge Semin <fancer.lancer@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Huy Duong and committed by
Greg Kroah-Hartman
db15d73e 5ec6bff1

+59 -75
+59 -75
drivers/misc/eeprom/idt_89hpesx.c
··· 77 77 #include <linux/sysfs.h> 78 78 #include <linux/debugfs.h> 79 79 #include <linux/mod_devicetable.h> 80 - #include <linux/of.h> 80 + #include <linux/property.h> 81 81 #include <linux/i2c.h> 82 82 #include <linux/pci_ids.h> 83 83 #include <linux/delay.h> ··· 1089 1089 pdev->eeaddr = 0; 1090 1090 } 1091 1091 1092 - #ifdef CONFIG_OF 1093 1092 static const struct i2c_device_id ee_ids[]; 1093 + 1094 1094 /* 1095 1095 * idt_ee_match_id() - check whether the node belongs to compatible EEPROMs 1096 1096 */ 1097 - static const struct i2c_device_id *idt_ee_match_id(struct device_node *node) 1097 + static const struct i2c_device_id *idt_ee_match_id(struct fwnode_handle *fwnode) 1098 1098 { 1099 1099 const struct i2c_device_id *id = ee_ids; 1100 + const char *compatible, *p; 1100 1101 char devname[I2C_NAME_SIZE]; 1102 + int ret; 1101 1103 1102 - /* Retrieve the device name without manufacturer name */ 1103 - if (of_modalias_node(node, devname, sizeof(devname))) 1104 + ret = fwnode_property_read_string(fwnode, "compatible", &compatible); 1105 + if (ret) 1104 1106 return NULL; 1105 1107 1108 + p = strchr(compatible, ','); 1109 + strlcpy(devname, p ? p + 1 : compatible, sizeof(devname)); 1106 1110 /* Search through the device name */ 1107 - while (id->name[0]) { 1108 - if (strcmp(devname, id->name) == 0) 1109 - return id; 1110 - id++; 1111 - } 1112 - return NULL; 1111 + while (id->name[0]) { 1112 + if (strcmp(devname, id->name) == 0) 1113 + return id; 1114 + id++; 1115 + } 1116 + return NULL; 1113 1117 } 1114 1118 1115 1119 /* 1116 - * idt_get_ofdata() - get IDT i2c-device parameters from device tree 1120 + * idt_get_fw_data() - get IDT i2c-device parameters from device tree 1117 1121 * @pdev: Pointer to the driver data 1118 1122 */ 1119 - static void idt_get_ofdata(struct idt_89hpesx_dev *pdev) 1123 + static void idt_get_fw_data(struct idt_89hpesx_dev *pdev) 1120 1124 { 1121 - const struct device_node *node = pdev->client->dev.of_node; 1122 1125 struct device *dev = &pdev->client->dev; 1126 + struct fwnode_handle *fwnode; 1127 + const struct i2c_device_id *ee_id = NULL; 1128 + u32 eeprom_addr; 1129 + int ret; 1123 1130 1124 - /* Read dts node parameters */ 1125 - if (node) { 1126 - const struct i2c_device_id *ee_id = NULL; 1127 - struct device_node *child; 1128 - const __be32 *addr_be; 1129 - int len; 1130 - 1131 - /* Walk through all child nodes looking for compatible one */ 1132 - for_each_available_child_of_node(node, child) { 1133 - ee_id = idt_ee_match_id(child); 1134 - if (IS_ERR_OR_NULL(ee_id)) { 1135 - dev_warn(dev, "Skip unsupported child node %pOF", 1136 - child); 1137 - continue; 1138 - } else 1139 - break; 1140 - } 1141 - 1142 - /* If there is no child EEPROM device, then set zero size */ 1143 - if (!ee_id) { 1144 - idt_set_defval(pdev); 1145 - return; 1146 - } 1147 - 1148 - /* Retrieve EEPROM size */ 1149 - pdev->eesize = (u32)ee_id->driver_data; 1150 - 1151 - /* Get custom EEPROM address from 'reg' attribute */ 1152 - addr_be = of_get_property(child, "reg", &len); 1153 - if (!addr_be || (len < sizeof(*addr_be))) { 1154 - dev_warn(dev, "No reg on %pOF, use default address %d", 1155 - child, EEPROM_DEF_ADDR); 1156 - pdev->inieecmd = 0; 1157 - pdev->eeaddr = EEPROM_DEF_ADDR << 1; 1158 - } else { 1159 - pdev->inieecmd = EEPROM_USA; 1160 - pdev->eeaddr = be32_to_cpup(addr_be) << 1; 1161 - } 1162 - 1163 - /* Check EEPROM 'read-only' flag */ 1164 - if (of_get_property(child, "read-only", NULL)) 1165 - pdev->eero = true; 1166 - else /* if (!of_get_property(node, "read-only", NULL)) */ 1167 - pdev->eero = false; 1168 - 1169 - dev_dbg(dev, "EEPROM of %u bytes found by %hhu", 1170 - pdev->eesize, pdev->eeaddr); 1171 - } else { 1172 - dev_warn(dev, "No dts node, EEPROM access disabled"); 1173 - idt_set_defval(pdev); 1131 + device_for_each_child_node(dev, fwnode) { 1132 + ee_id = idt_ee_match_id(fwnode); 1133 + if (IS_ERR_OR_NULL(ee_id)) { 1134 + dev_warn(dev, "Skip unsupported EEPROM device"); 1135 + continue; 1136 + } else 1137 + break; 1174 1138 } 1175 - } 1176 - #else 1177 - static void idt_get_ofdata(struct idt_89hpesx_dev *pdev) 1178 - { 1179 - struct device *dev = &pdev->client->dev; 1180 1139 1181 - dev_warn(dev, "OF table is unsupported, EEPROM access disabled"); 1140 + /* If there is no fwnode EEPROM device, then set zero size */ 1141 + if (!ee_id) { 1142 + dev_warn(dev, "No fwnode, EEPROM access disabled"); 1143 + idt_set_defval(pdev); 1144 + return; 1145 + } 1182 1146 1183 - /* Nothing we can do, just set the default values */ 1184 - idt_set_defval(pdev); 1147 + /* Retrieve EEPROM size */ 1148 + pdev->eesize = (u32)ee_id->driver_data; 1149 + 1150 + /* Get custom EEPROM address from 'reg' attribute */ 1151 + ret = fwnode_property_read_u32(fwnode, "reg", &eeprom_addr); 1152 + if (ret || (eeprom_addr == 0)) { 1153 + dev_warn(dev, "No EEPROM reg found, use default address 0x%x", 1154 + EEPROM_DEF_ADDR); 1155 + pdev->inieecmd = 0; 1156 + pdev->eeaddr = EEPROM_DEF_ADDR << 1; 1157 + } else { 1158 + pdev->inieecmd = EEPROM_USA; 1159 + pdev->eeaddr = eeprom_addr << 1; 1160 + } 1161 + 1162 + /* Check EEPROM 'read-only' flag */ 1163 + if (fwnode_property_read_bool(fwnode, "read-only")) 1164 + pdev->eero = true; 1165 + else /* if (!fwnode_property_read_bool(node, "read-only")) */ 1166 + pdev->eero = false; 1167 + 1168 + dev_info(dev, "EEPROM of %d bytes found by 0x%x", 1169 + pdev->eesize, pdev->eeaddr); 1185 1170 } 1186 - #endif /* CONFIG_OF */ 1187 1171 1188 1172 /* 1189 1173 * idt_create_pdev() - create and init data structure of the driver ··· 1187 1203 pdev->client = client; 1188 1204 i2c_set_clientdata(client, pdev); 1189 1205 1190 - /* Read OF nodes information */ 1191 - idt_get_ofdata(pdev); 1206 + /* Read firmware nodes information */ 1207 + idt_get_fw_data(pdev); 1192 1208 1193 1209 /* Initialize basic CSR CMD field - use full DWORD-sized r/w ops */ 1194 1210 pdev->inicsrcmd = CSR_DWE;