in rcar_thermal.c [443:584]
static int rcar_thermal_probe(struct platform_device *pdev)
{
struct rcar_thermal_common *common;
struct rcar_thermal_priv *priv;
struct device *dev = &pdev->dev;
struct resource *res, *irq;
const struct rcar_thermal_chip *chip = of_device_get_match_data(dev);
int mres = 0;
int i;
int ret = -ENODEV;
int idle = IDLE_INTERVAL;
u32 enr_bits = 0;
common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
if (!common)
return -ENOMEM;
platform_set_drvdata(pdev, common);
INIT_LIST_HEAD(&common->head);
spin_lock_init(&common->lock);
common->dev = dev;
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
for (i = 0; i < chip->nirqs; i++) {
irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
if (!irq)
continue;
if (!common->base) {
/*
* platform has IRQ support.
* Then, driver uses common registers
* rcar_has_irq_support() will be enabled
*/
res = platform_get_resource(pdev, IORESOURCE_MEM,
mres++);
common->base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->base)) {
ret = PTR_ERR(common->base);
goto error_unregister;
}
idle = 0; /* polling delay is not needed */
}
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq,
IRQF_SHARED, dev_name(dev), common);
if (ret) {
dev_err(dev, "irq request failed\n ");
goto error_unregister;
}
/* update ENR bits */
if (chip->irq_per_ch)
enr_bits |= 1 << i;
}
for (i = 0;; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
if (!res)
break;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto error_unregister;
}
priv->base = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->base)) {
ret = PTR_ERR(priv->base);
goto error_unregister;
}
priv->common = common;
priv->id = i;
priv->chip = chip;
mutex_init(&priv->lock);
INIT_LIST_HEAD(&priv->list);
INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
ret = rcar_thermal_update_temp(priv);
if (ret < 0)
goto error_unregister;
if (chip->use_of_thermal) {
priv->zone = devm_thermal_zone_of_sensor_register(
dev, i, priv,
&rcar_thermal_zone_of_ops);
} else {
priv->zone = thermal_zone_device_register(
"rcar_thermal",
1, 0, priv,
&rcar_thermal_zone_ops, NULL, 0,
idle);
ret = thermal_zone_device_enable(priv->zone);
if (ret) {
thermal_zone_device_unregister(priv->zone);
priv->zone = ERR_PTR(ret);
}
}
if (IS_ERR(priv->zone)) {
dev_err(dev, "can't register thermal zone\n");
ret = PTR_ERR(priv->zone);
priv->zone = NULL;
goto error_unregister;
}
if (chip->use_of_thermal) {
/*
* thermal_zone doesn't enable hwmon as default,
* but, enable it here to keep compatible
*/
priv->zone->tzp->no_hwmon = false;
ret = thermal_add_hwmon_sysfs(priv->zone);
if (ret)
goto error_unregister;
}
rcar_thermal_irq_enable(priv);
list_move_tail(&priv->list, &common->head);
/* update ENR bits */
if (!chip->irq_per_ch)
enr_bits |= 3 << (i * 8);
}
if (common->base && enr_bits)
rcar_thermal_common_write(common, ENR, enr_bits);
dev_info(dev, "%d sensor probed\n", i);
return 0;
error_unregister:
rcar_thermal_remove(pdev);
return ret;
}