in qcom/tsens.c [741:925]
int __init init_common(struct tsens_priv *priv)
{
void __iomem *tm_base, *srot_base;
struct device *dev = priv->dev;
u32 ver_minor;
struct resource *res;
u32 enabled;
int ret, i, j;
struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
if (!op)
return -EINVAL;
if (op->num_resources > 1) {
/* DT with separate SROT and TM address space */
priv->tm_offset = 0;
res = platform_get_resource(op, IORESOURCE_MEM, 1);
srot_base = devm_ioremap_resource(dev, res);
if (IS_ERR(srot_base)) {
ret = PTR_ERR(srot_base);
goto err_put_device;
}
priv->srot_map = devm_regmap_init_mmio(dev, srot_base,
&tsens_srot_config);
if (IS_ERR(priv->srot_map)) {
ret = PTR_ERR(priv->srot_map);
goto err_put_device;
}
} else {
/* old DTs where SROT and TM were in a contiguous 2K block */
priv->tm_offset = 0x1000;
}
if (tsens_version(priv) >= VER_0_1) {
res = platform_get_resource(op, IORESOURCE_MEM, 0);
tm_base = devm_ioremap_resource(dev, res);
if (IS_ERR(tm_base)) {
ret = PTR_ERR(tm_base);
goto err_put_device;
}
priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config);
} else { /* VER_0 share the same gcc regs using a syscon */
struct device *parent = priv->dev->parent;
if (parent)
priv->tm_map = syscon_node_to_regmap(parent->of_node);
}
if (IS_ERR_OR_NULL(priv->tm_map)) {
if (!priv->tm_map)
ret = -ENODEV;
else
ret = PTR_ERR(priv->tm_map);
goto err_put_device;
}
/* VER_0 have only tm_map */
if (!priv->srot_map)
priv->srot_map = priv->tm_map;
if (tsens_version(priv) > VER_0_1) {
for (i = VER_MAJOR; i <= VER_STEP; i++) {
priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map,
priv->fields[i]);
if (IS_ERR(priv->rf[i])) {
ret = PTR_ERR(priv->rf[i]);
goto err_put_device;
}
}
ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor);
if (ret)
goto err_put_device;
}
priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
priv->fields[TSENS_EN]);
if (IS_ERR(priv->rf[TSENS_EN])) {
ret = PTR_ERR(priv->rf[TSENS_EN]);
goto err_put_device;
}
/* in VER_0 TSENS need to be explicitly enabled */
if (tsens_version(priv) == VER_0)
regmap_field_write(priv->rf[TSENS_EN], 1);
ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
if (ret)
goto err_put_device;
if (!enabled) {
dev_err(dev, "%s: device not enabled\n", __func__);
ret = -ENODEV;
goto err_put_device;
}
priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
priv->fields[SENSOR_EN]);
if (IS_ERR(priv->rf[SENSOR_EN])) {
ret = PTR_ERR(priv->rf[SENSOR_EN]);
goto err_put_device;
}
priv->rf[INT_EN] = devm_regmap_field_alloc(dev, priv->tm_map,
priv->fields[INT_EN]);
if (IS_ERR(priv->rf[INT_EN])) {
ret = PTR_ERR(priv->rf[INT_EN]);
goto err_put_device;
}
priv->rf[TSENS_SW_RST] =
devm_regmap_field_alloc(dev, priv->srot_map, priv->fields[TSENS_SW_RST]);
if (IS_ERR(priv->rf[TSENS_SW_RST])) {
ret = PTR_ERR(priv->rf[TSENS_SW_RST]);
goto err_put_device;
}
priv->rf[TRDY] = devm_regmap_field_alloc(dev, priv->tm_map, priv->fields[TRDY]);
if (IS_ERR(priv->rf[TRDY])) {
ret = PTR_ERR(priv->rf[TRDY]);
goto err_put_device;
}
/* This loop might need changes if enum regfield_ids is reordered */
for (j = LAST_TEMP_0; j <= UP_THRESH_15; j += 16) {
for (i = 0; i < priv->feat->max_sensors; i++) {
int idx = j + i;
priv->rf[idx] = devm_regmap_field_alloc(dev,
priv->tm_map,
priv->fields[idx]);
if (IS_ERR(priv->rf[idx])) {
ret = PTR_ERR(priv->rf[idx]);
goto err_put_device;
}
}
}
if (priv->feat->crit_int || tsens_version(priv) < VER_0_1) {
/* Loop might need changes if enum regfield_ids is reordered */
for (j = CRITICAL_STATUS_0; j <= CRIT_THRESH_15; j += 16) {
for (i = 0; i < priv->feat->max_sensors; i++) {
int idx = j + i;
priv->rf[idx] =
devm_regmap_field_alloc(dev,
priv->tm_map,
priv->fields[idx]);
if (IS_ERR(priv->rf[idx])) {
ret = PTR_ERR(priv->rf[idx]);
goto err_put_device;
}
}
}
}
if (tsens_version(priv) > VER_1_X && ver_minor > 2) {
/* Watchdog is present only on v2.3+ */
priv->feat->has_watchdog = 1;
for (i = WDOG_BARK_STATUS; i <= CC_MON_MASK; i++) {
priv->rf[i] = devm_regmap_field_alloc(dev, priv->tm_map,
priv->fields[i]);
if (IS_ERR(priv->rf[i])) {
ret = PTR_ERR(priv->rf[i]);
goto err_put_device;
}
}
/*
* Watchdog is already enabled, unmask the bark.
* Disable cycle completion monitoring
*/
regmap_field_write(priv->rf[WDOG_BARK_MASK], 0);
regmap_field_write(priv->rf[CC_MON_MASK], 1);
}
spin_lock_init(&priv->ul_lock);
/* VER_0 interrupt doesn't need to be enabled */
if (tsens_version(priv) >= VER_0_1)
tsens_enable_irq(priv);
tsens_debug_init(op);
err_put_device:
put_device(&op->dev);
return ret;
}