History

Merge tag 'i3c/for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux

Pull i3c updates from Boris Brezillon: "Core changes: - Export i3c_device_match_id() so driver can get per-device data - Add addr and lvr fields to i2c_dev_desc so we can attach I2C devices that are not described in the DT - Add a missing of_node_put() - Fix a memory leak - Use dev_to_i3cmaster() instead of open-coding it Driver changes: - Use for_each_set_bit() in the Cadence driver" * tag 'i3c/for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: i3c: master: Use dev_to_i3cmaster() i3c: master: fix a memory leak bug i3c: add addr and lvr to i2c_dev_desc structure i3c: master: cdns: Use for_each_set_bit() i3c: master: Add of_node_put() before return i3c: move i3c_device_match_id to device.c and export it

Linus Torvalds committed 7 years ago

Commit 31dda852 parents aa62325 6030f426 files · +90 −73Browse files

Unified · Split

6 files
  1. drivers/i3c/device.c +53 −0
  2. drivers/i3c/master.c +14 −53
  3. drivers/i3c/master/dw-i3c-master.c +2 −2
  4. drivers/i3c/master/i3c-master-cdns.c +12 −18
  5. include/linux/i3c/device.h +4 −0
  6. include/linux/i3c/master.h +5 −0
drivers/i3c/device.c+53−0
@@ -200,6 +200,59 @@ struct i3c_device *dev_to_i3cdev(struct device *dev) · 199 unmodified lines
200}200}
201EXPORT_SYMBOL_GPL(dev_to_i3cdev);201EXPORT_SYMBOL_GPL(dev_to_i3cdev);
202 202
203/**
204 * i3c_device_match_id() - Returns the i3c_device_id entry matching @i3cdev
205 * @i3cdev: I3C device
206 * @id_table: I3C device match table
207 *
208 * Return: a pointer to an i3c_device_id object or NULL if there's no match.
209 */
210const struct i3c_device_id *
211i3c_device_match_id(struct i3c_device *i3cdev,
212 const struct i3c_device_id *id_table)
213{
214 struct i3c_device_info devinfo;
215 const struct i3c_device_id *id;
216
217 i3c_device_get_info(i3cdev, &devinfo);
218
219 /*
220 * The lower 32bits of the provisional ID is just filled with a random
221 * value, try to match using DCR info.
222 */
223 if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) {
224 u16 manuf = I3C_PID_MANUF_ID(devinfo.pid);
225 u16 part = I3C_PID_PART_ID(devinfo.pid);
226 u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid);
227
228 /* First try to match by manufacturer/part ID. */
229 for (id = id_table; id->match_flags != 0; id++) {
230 if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) !=
231 I3C_MATCH_MANUF_AND_PART)
232 continue;
233
234 if (manuf != id->manuf_id || part != id->part_id)
235 continue;
236
237 if ((id->match_flags & I3C_MATCH_EXTRA_INFO) &&
238 ext_info != id->extra_info)
239 continue;
240
241 return id;
242 }
243 }
244
245 /* Fallback to DCR match. */
246 for (id = id_table; id->match_flags != 0; id++) {
247 if ((id->match_flags & I3C_MATCH_DCR) &&
248 id->dcr == devinfo.dcr)
249 return id;
250 }
251
252 return NULL;
253}
254EXPORT_SYMBOL_GPL(i3c_device_match_id);
255
203/**256/**
204 * i3c_driver_register_with_owner() - register an I3C device driver257 * i3c_driver_register_with_owner() - register an I3C device driver
205 *258 *
drivers/i3c/master.c+14−53
@@ -123,7 +123,7 @@ static struct i3c_dev_desc *dev_to_i3cdesc(struct device *dev) · 122 unmodified lines
123 if (dev->type == &i3c_device_type)123 if (dev->type == &i3c_device_type)
124 return dev_to_i3cdev(dev)->desc;124 return dev_to_i3cdev(dev)->desc;
125 125
126 master = container_of(dev, struct i3c_master_controller, dev);126 master = dev_to_i3cmaster(dev);
127 127
128 return master->this;128 return master->this;
129}129}
@@ -276,51 +276,6 @@ static const struct device_type i3c_device_type = { · 146 unmodified lines
276 .uevent = i3c_device_uevent,276 .uevent = i3c_device_uevent,
277};277};
278 278
279static const struct i3c_device_id *
280i3c_device_match_id(struct i3c_device *i3cdev,
281 const struct i3c_device_id *id_table)
282{
283 struct i3c_device_info devinfo;
284 const struct i3c_device_id *id;
285
286 i3c_device_get_info(i3cdev, &devinfo);
287
288 /*
289 * The lower 32bits of the provisional ID is just filled with a random
290 * value, try to match using DCR info.
291 */
292 if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) {
293 u16 manuf = I3C_PID_MANUF_ID(devinfo.pid);
294 u16 part = I3C_PID_PART_ID(devinfo.pid);
295 u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid);
296
297 /* First try to match by manufacturer/part ID. */
298 for (id = id_table; id->match_flags != 0; id++) {
299 if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) !=
300 I3C_MATCH_MANUF_AND_PART)
301 continue;
302
303 if (manuf != id->manuf_id || part != id->part_id)
304 continue;
305
306 if ((id->match_flags & I3C_MATCH_EXTRA_INFO) &&
307 ext_info != id->extra_info)
308 continue;
309
310 return id;
311 }
312 }
313
314 /* Fallback to DCR match. */
315 for (id = id_table; id->match_flags != 0; id++) {
316 if ((id->match_flags & I3C_MATCH_DCR) &&
317 id->dcr == devinfo.dcr)
318 return id;
319 }
320
321 return NULL;
322}
323
324static int i3c_device_match(struct device *dev, struct device_driver *drv)279static int i3c_device_match(struct device *dev, struct device_driver *drv)
325{280{
326 struct i3c_device *i3cdev;281 struct i3c_device *i3cdev;
@@ -645,6 +600,8 @@ i3c_master_alloc_i2c_dev(struct i3c_master_controller *master, · 318 unmodified lines
645 600
646 dev->common.master = master;601 dev->common.master = master;
647 dev->boardinfo = boardinfo;602 dev->boardinfo = boardinfo;
603 dev->addr = boardinfo->base.addr;
604 dev->lvr = boardinfo->lvr;
648 605
649 return dev;606 return dev;
650}607}
@@ -963,8 +920,8 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master) · 312 unmodified lines
963 920
964 desc = defslvs->slaves;921 desc = defslvs->slaves;
965 i3c_bus_for_each_i2cdev(bus, i2cdev) {922 i3c_bus_for_each_i2cdev(bus, i2cdev) {
966 desc->lvr = i2cdev->boardinfo->lvr;923 desc->lvr = i2cdev->lvr;
967 desc->static_addr = i2cdev->boardinfo->base.addr << 1;924 desc->static_addr = i2cdev->addr << 1;
968 desc++;925 desc++;
969 }926 }
970 927
@@ -1084,8 +1041,10 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master, · 113 unmodified lines
1084 if (ret)1041 if (ret)
1085 goto out;1042 goto out;
1086 1043
1087 if (dest.payload.len != sizeof(*mwl))1044 if (dest.payload.len != sizeof(*mwl)) {
1088 return -EIO;1045 ret = -EIO;
1046 goto out;
1047 }
1089 1048
1090 info->max_write_len = be16_to_cpu(mwl->len);1049 info->max_write_len = be16_to_cpu(mwl->len);
1091 1050
@@ -1631,8 +1590,8 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master) · 539 unmodified lines
1631 common.node) {1590 common.node) {
1632 i3c_master_detach_i2c_dev(i2cdev);1591 i3c_master_detach_i2c_dev(i2cdev);
1633 i3c_bus_set_addr_slot_status(&master->bus,1592 i3c_bus_set_addr_slot_status(&master->bus,
1634 i2cdev->boardinfo->base.addr,1593 i2cdev->addr,
1635 I3C_ADDR_SLOT_FREE);1594 I3C_ADDR_SLOT_FREE);
1636 i3c_master_free_i2c_dev(i2cdev);1595 i3c_master_free_i2c_dev(i2cdev);
1637 }1596 }
1638}1597}
@@ -2093,8 +2052,10 @@ static int of_populate_i3c_bus(struct i3c_master_controller *master) · 454 unmodified lines
2093 2052
2094 for_each_available_child_of_node(i3cbus_np, node) {2053 for_each_available_child_of_node(i3cbus_np, node) {
2095 ret = of_i3c_master_add_dev(master, node);2054 ret = of_i3c_master_add_dev(master, node);
2096 if (ret)2055 if (ret) {
2056 of_node_put(node);
2097 return ret;2057 return ret;
2058 }
2098 }2059 }
2099 2060
2100 /*2061 /*
drivers/i3c/master/dw-i3c-master.c+2−2
@@ -1033,12 +1033,12 @@ static int dw_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) · 1032 unmodified lines
1033 return -ENOMEM;1033 return -ENOMEM;
1034 1034
1035 data->index = pos;1035 data->index = pos;
1036 master->addrs[pos] = dev->boardinfo->base.addr;1036 master->addrs[pos] = dev->addr;
1037 master->free_pos &= ~BIT(pos);1037 master->free_pos &= ~BIT(pos);
1038 i2c_dev_set_master_data(dev, data);1038 i2c_dev_set_master_data(dev, data);
1039 1039
1040 writel(DEV_ADDR_TABLE_LEGACY_I2C_DEV |1040 writel(DEV_ADDR_TABLE_LEGACY_I2C_DEV |
1041 DEV_ADDR_TABLE_STATIC_ADDR(dev->boardinfo->base.addr),1041 DEV_ADDR_TABLE_STATIC_ADDR(dev->addr),
1042 master->regs +1042 master->regs +
1043 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));1043 DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
1044 1044
drivers/i3c/master/i3c-master-cdns.c+12−18
@@ -903,7 +903,8 @@ static void cdns_i3c_master_upd_i3c_addr(struct i3c_dev_desc *dev) · 902 unmodified lines
903static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master,903static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master,
904 u8 dyn_addr)904 u8 dyn_addr)
905{905{
906 u32 activedevs, rr;906 unsigned long activedevs;
907 u32 rr;
907 int i;908 int i;
908 909
909 if (!dyn_addr) {910 if (!dyn_addr) {
@@ -913,13 +914,10 @@ static int cdns_i3c_master_get_rr_slot(struct cdns_i3c_master *master, · 3 unmodified lines
913 return ffs(master->free_rr_slots) - 1;914 return ffs(master->free_rr_slots) - 1;
914 }915 }
915 916
916 activedevs = readl(master->regs + DEVS_CTRL) &917 activedevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;
917 DEVS_CTRL_DEVS_ACTIVE_MASK;918 activedevs &= ~BIT(0);
918
919 for (i = 1; i <= master->maxdevs; i++) {
920 if (!(BIT(i) & activedevs))
921 continue;
922 919
920 for_each_set_bit(i, &activedevs, master->maxdevs + 1) {
923 rr = readl(master->regs + DEV_ID_RR0(i));921 rr = readl(master->regs + DEV_ID_RR0(i));
924 if (!(rr & DEV_ID_RR0_IS_I3C) ||922 if (!(rr & DEV_ID_RR0_IS_I3C) ||
925 DEV_ID_RR0_GET_DEV_ADDR(rr) != dyn_addr)923 DEV_ID_RR0_GET_DEV_ADDR(rr) != dyn_addr)
@@ -1005,9 +1003,9 @@ static int cdns_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) · 79 unmodified lines
1005 master->free_rr_slots &= ~BIT(slot);1003 master->free_rr_slots &= ~BIT(slot);
1006 i2c_dev_set_master_data(dev, data);1004 i2c_dev_set_master_data(dev, data);
1007 1005
1008 writel(prepare_rr0_dev_address(dev->boardinfo->base.addr),1006 writel(prepare_rr0_dev_address(dev->addr),
1009 master->regs + DEV_ID_RR0(data->id));1007 master->regs + DEV_ID_RR0(data->id));
1010 writel(dev->boardinfo->lvr, master->regs + DEV_ID_RR2(data->id));1008 writel(dev->lvr, master->regs + DEV_ID_RR2(data->id));
1011 writel(readl(master->regs + DEVS_CTRL) |1009 writel(readl(master->regs + DEVS_CTRL) |
1012 DEVS_CTRL_DEV_ACTIVE(data->id),1010 DEVS_CTRL_DEV_ACTIVE(data->id),
1013 master->regs + DEVS_CTRL);1011 master->regs + DEVS_CTRL);
@@ -1126,18 +1124,16 @@ static void cdns_i3c_master_upd_i3c_scl_lim(struct cdns_i3c_master *master) · 112 unmodified lines
1126static int cdns_i3c_master_do_daa(struct i3c_master_controller *m)1124static int cdns_i3c_master_do_daa(struct i3c_master_controller *m)
1127{1125{
1128 struct cdns_i3c_master *master = to_cdns_i3c_master(m);1126 struct cdns_i3c_master *master = to_cdns_i3c_master(m);
1129 u32 olddevs, newdevs;1127 unsigned long olddevs, newdevs;
1130 int ret, slot;1128 int ret, slot;
1131 u8 addrs[MAX_DEVS] = { };1129 u8 addrs[MAX_DEVS] = { };
1132 u8 last_addr = 0;1130 u8 last_addr = 0;
1133 1131
1134 olddevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;1132 olddevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;
1133 olddevs |= BIT(0);
1135 1134
1136 /* Prepare RR slots before launching DAA. */1135 /* Prepare RR slots before launching DAA. */
1137 for (slot = 1; slot <= master->maxdevs; slot++) {1136 for_each_clear_bit(slot, &olddevs, master->maxdevs + 1) {
1138 if (olddevs & BIT(slot))
1139 continue;
1140
1141 ret = i3c_master_get_free_addr(m, last_addr + 1);1137 ret = i3c_master_get_free_addr(m, last_addr + 1);
1142 if (ret < 0)1138 if (ret < 0)
1143 return -ENOSPC;1139 return -ENOSPC;
@@ -1161,10 +1157,8 @@ static int cdns_i3c_master_do_daa(struct i3c_master_controller *m) · 17 unmodified lines
1161 * Clear all retaining registers filled during DAA. We already1157 * Clear all retaining registers filled during DAA. We already
1162 * have the addressed assigned to them in the addrs array.1158 * have the addressed assigned to them in the addrs array.
1163 */1159 */
1164 for (slot = 1; slot <= master->maxdevs; slot++) {1160 for_each_set_bit(slot, &newdevs, master->maxdevs + 1)
1165 if (newdevs & BIT(slot))1161 i3c_master_add_i3c_dev_locked(m, addrs[slot]);
1166 i3c_master_add_i3c_dev_locked(m, addrs[slot]);
1167 }
1168 1162
1169 /*1163 /*
1170 * Clear slots that ended up not being used. Can be caused by I3C1164 * Clear slots that ended up not being used. Can be caused by I3C
include/linux/i3c/device.h+4−0
@@ -188,6 +188,10 @@ static inline struct i3c_driver *drv_to_i3cdrv(struct device_driver *drv) · 187 unmodified lines
188struct device *i3cdev_to_dev(struct i3c_device *i3cdev);188struct device *i3cdev_to_dev(struct i3c_device *i3cdev);
189struct i3c_device *dev_to_i3cdev(struct device *dev);189struct i3c_device *dev_to_i3cdev(struct device *dev);
190 190
191const struct i3c_device_id *
192i3c_device_match_id(struct i3c_device *i3cdev,
193 const struct i3c_device_id *id_table);
194
191static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev,195static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev,
192 void *data)196 void *data)
193{197{
include/linux/i3c/master.h+5−0
@@ -71,6 +71,9 @@ struct i2c_dev_boardinfo { · 70 unmodified lines
71 * @common: common part of the I2C device descriptor71 * @common: common part of the I2C device descriptor
72 * @boardinfo: pointer to the boardinfo attached to this I2C device72 * @boardinfo: pointer to the boardinfo attached to this I2C device
73 * @dev: I2C device object registered to the I2C framework73 * @dev: I2C device object registered to the I2C framework
74 * @addr: I2C device address
75 * @lvr: LVR (Legacy Virtual Register) needed by the I3C core to know about
76 * the I2C device limitations
74 *77 *
75 * Each I2C device connected on the bus will have an i2c_dev_desc.78 * Each I2C device connected on the bus will have an i2c_dev_desc.
76 * This object is created by the core and later attached to the controller79 * This object is created by the core and later attached to the controller
@@ -84,6 +87,8 @@ struct i2c_dev_desc { · 7 unmodified lines
84 struct i3c_i2c_dev_desc common;87 struct i3c_i2c_dev_desc common;
85 const struct i2c_dev_boardinfo *boardinfo;88 const struct i2c_dev_boardinfo *boardinfo;
86 struct i2c_client *dev;89 struct i2c_client *dev;
90 u16 addr;
91 u8 lvr;
87};92};
88 93
89/**94/**

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t