in fsi-core.c [466:551]
static int fsi_slave_scan(struct fsi_slave *slave)
{
uint32_t engine_addr;
int rc, i;
/*
* scan engines
*
* We keep the peek mode and slave engines for the core; so start
* at the third slot in the configuration table. We also need to
* skip the chip ID entry at the start of the address space.
*/
engine_addr = engine_page_size * 3;
for (i = 2; i < engine_page_size / sizeof(uint32_t); i++) {
uint8_t slots, version, type, crc;
struct fsi_device *dev;
uint32_t conf;
__be32 data;
rc = fsi_slave_read(slave, (i + 1) * sizeof(data),
&data, sizeof(data));
if (rc) {
dev_warn(&slave->dev,
"error reading slave registers\n");
return -1;
}
conf = be32_to_cpu(data);
crc = crc4(0, conf, 32);
if (crc) {
dev_warn(&slave->dev,
"crc error in slave register at 0x%04x\n",
i);
return -1;
}
slots = (conf & FSI_SLAVE_CONF_SLOTS_MASK)
>> FSI_SLAVE_CONF_SLOTS_SHIFT;
version = (conf & FSI_SLAVE_CONF_VERSION_MASK)
>> FSI_SLAVE_CONF_VERSION_SHIFT;
type = (conf & FSI_SLAVE_CONF_TYPE_MASK)
>> FSI_SLAVE_CONF_TYPE_SHIFT;
/*
* Unused address areas are marked by a zero type value; this
* skips the defined address areas
*/
if (type != 0 && slots != 0) {
/* create device */
dev = fsi_create_device(slave);
if (!dev)
return -ENOMEM;
dev->slave = slave;
dev->engine_type = type;
dev->version = version;
dev->unit = i;
dev->addr = engine_addr;
dev->size = slots * engine_page_size;
dev_dbg(&slave->dev,
"engine[%i]: type %x, version %x, addr %x size %x\n",
dev->unit, dev->engine_type, version,
dev->addr, dev->size);
dev_set_name(&dev->dev, "%02x:%02x:%02x:%02x",
slave->master->idx, slave->link,
slave->id, i - 2);
dev->dev.of_node = fsi_device_find_of_node(dev);
rc = device_register(&dev->dev);
if (rc) {
dev_warn(&slave->dev, "add failed: %d\n", rc);
put_device(&dev->dev);
}
}
engine_addr += slots * engine_page_size;
if (!(conf & FSI_SLAVE_CONF_NEXT_MASK))
break;
}
return 0;
}