in fsi-occ.c [577:643]
static int occ_probe(struct platform_device *pdev)
{
int rc;
u32 reg;
struct occ *occ;
struct platform_device *hwmon_dev;
struct device *dev = &pdev->dev;
struct platform_device_info hwmon_dev_info = {
.parent = dev,
.name = "occ-hwmon",
};
occ = devm_kzalloc(dev, sizeof(*occ), GFP_KERNEL);
if (!occ)
return -ENOMEM;
/* SBE words are always four bytes */
occ->buffer = kvmalloc(OCC_MAX_RESP_WORDS * 4, GFP_KERNEL);
if (!occ->buffer)
return -ENOMEM;
occ->version = (uintptr_t)of_device_get_match_data(dev);
occ->dev = dev;
occ->sbefifo = dev->parent;
occ->sequence_number = 1;
mutex_init(&occ->occ_lock);
if (dev->of_node) {
rc = of_property_read_u32(dev->of_node, "reg", ®);
if (!rc) {
/* make sure we don't have a duplicate from dts */
occ->idx = ida_simple_get(&occ_ida, reg, reg + 1,
GFP_KERNEL);
if (occ->idx < 0)
occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX,
GFP_KERNEL);
} else {
occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX,
GFP_KERNEL);
}
} else {
occ->idx = ida_simple_get(&occ_ida, 1, INT_MAX, GFP_KERNEL);
}
platform_set_drvdata(pdev, occ);
snprintf(occ->name, sizeof(occ->name), "occ%d", occ->idx);
occ->mdev.fops = &occ_fops;
occ->mdev.minor = MISC_DYNAMIC_MINOR;
occ->mdev.name = occ->name;
occ->mdev.parent = dev;
rc = misc_register(&occ->mdev);
if (rc) {
dev_err(dev, "failed to register miscdevice: %d\n", rc);
ida_simple_remove(&occ_ida, occ->idx);
kvfree(occ->buffer);
return rc;
}
hwmon_dev_info.id = occ->idx;
hwmon_dev = platform_device_register_full(&hwmon_dev_info);
if (IS_ERR(hwmon_dev))
dev_warn(dev, "failed to create hwmon device\n");
return 0;
}