static int fsl_otp_probe(struct platform_device *pdev) { struct resource *res; struct attribute **attrs; const char **desc; int i, num; int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); otp_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(otp_base)) { ret = PTR_ERR(otp_base); dev_err(&pdev->dev, "failed to ioremap resource: %d\n", ret); return ret; } otp_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(otp_clk)) { ret = PTR_ERR(otp_clk); dev_err(&pdev->dev, "failed to get clock: %d\n", ret); return ret; } desc = (const char **) imx6q_otp_desc; num = sizeof(imx6q_otp_desc) / sizeof(void *); /* The last one is NULL, which is used to detect the end */ attrs = devm_kzalloc(&pdev->dev, (num + 1) * sizeof(*attrs), GFP_KERNEL); otp_kattr = devm_kzalloc(&pdev->dev, num * sizeof(*otp_kattr), GFP_KERNEL); otp_attr_group = devm_kzalloc(&pdev->dev, sizeof(*otp_attr_group), GFP_KERNEL); if (!attrs || !otp_kattr || !otp_attr_group) return -ENOMEM; for (i = 0; i < num; i++) { sysfs_attr_init(&otp_kattr[i].attr); otp_kattr[i].attr.name = desc[i]; otp_kattr[i].attr.mode = 0600; otp_kattr[i].show = fsl_otp_show; otp_kattr[i].store = fsl_otp_store; attrs[i] = &otp_kattr[i].attr; } otp_attr_group->attrs = attrs; otp_kobj = kobject_create_and_add("fsl_otp", NULL); if (!otp_kobj) { dev_err(&pdev->dev, "failed to add kobject\n"); return -ENOMEM; } ret = sysfs_create_group(otp_kobj, otp_attr_group); if (ret) { dev_err(&pdev->dev, "failed to create sysfs group: %d\n", ret); kobject_put(otp_kobj); return ret; } mutex_init(&otp_mutex); return 0; }
int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) { struct thermal_hwmon_device *hwmon; struct thermal_hwmon_temp *temp; int new_hwmon_device = 1; int result; hwmon = thermal_hwmon_lookup_by_type(tz); if (hwmon) { new_hwmon_device = 0; goto register_sys_interface; } hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL); if (!hwmon) return -ENOMEM; INIT_LIST_HEAD(&hwmon->tz_list); strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); hwmon->device = hwmon_device_register(NULL); if (IS_ERR(hwmon->device)) { result = PTR_ERR(hwmon->device); goto free_mem; } dev_set_drvdata(hwmon->device, hwmon); result = device_create_file(hwmon->device, &dev_attr_name); if (result) goto free_mem; register_sys_interface: temp = kzalloc(sizeof(*temp), GFP_KERNEL); if (!temp) { result = -ENOMEM; goto unregister_name; } temp->tz = tz; hwmon->count++; snprintf(temp->temp_input.name, sizeof(temp->temp_input.name), "temp%d_input", hwmon->count); temp->temp_input.attr.attr.name = temp->temp_input.name; temp->temp_input.attr.attr.mode = 0444; temp->temp_input.attr.show = temp_input_show; sysfs_attr_init(&temp->temp_input.attr.attr); result = device_create_file(hwmon->device, &temp->temp_input.attr); if (result) goto free_temp_mem; if (thermal_zone_crit_temp_valid(tz)) { snprintf(temp->temp_crit.name, sizeof(temp->temp_crit.name), "temp%d_crit", hwmon->count); temp->temp_crit.attr.attr.name = temp->temp_crit.name; temp->temp_crit.attr.attr.mode = 0444; temp->temp_crit.attr.show = temp_crit_show; sysfs_attr_init(&temp->temp_crit.attr.attr); result = device_create_file(hwmon->device, &temp->temp_crit.attr); if (result) goto unregister_input; } mutex_lock(&thermal_hwmon_list_lock); if (new_hwmon_device) list_add_tail(&hwmon->node, &thermal_hwmon_list); list_add_tail(&temp->hwmon_node, &hwmon->tz_list); mutex_unlock(&thermal_hwmon_list_lock); return 0; unregister_input: device_remove_file(hwmon->device, &temp->temp_input.attr); free_temp_mem: kfree(temp); unregister_name: if (new_hwmon_device) { device_remove_file(hwmon->device, &dev_attr_name); hwmon_device_unregister(hwmon->device); } free_mem: if (new_hwmon_device) kfree(hwmon); return result; }
int nvhost_syncpt_init(struct platform_device *dev, struct nvhost_syncpt *sp) { int i; struct nvhost_master *host = syncpt_to_dev(sp); int err = 0; /* Allocate structs for min, max and base values */ sp->min_val = kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_pts(sp), GFP_KERNEL); sp->max_val = kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_pts(sp), GFP_KERNEL); sp->base_val = kzalloc(sizeof(u32) * nvhost_syncpt_nb_bases(sp), GFP_KERNEL); sp->lock_counts = kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_mlocks(sp), GFP_KERNEL); if (!(sp->min_val && sp->max_val && sp->base_val && sp->lock_counts)) { /* frees happen in the deinit */ err = -ENOMEM; goto fail; } sp->kobj = kobject_create_and_add("syncpt", &dev->dev.kobj); if (!sp->kobj) { err = -EIO; goto fail; } /* Allocate two attributes for each sync point: min and max */ sp->syncpt_attrs = kzalloc(sizeof(*sp->syncpt_attrs) * nvhost_syncpt_nb_pts(sp) * 2, GFP_KERNEL); if (!sp->syncpt_attrs) { err = -ENOMEM; goto fail; } /* Fill in the attributes */ for (i = 0; i < nvhost_syncpt_nb_pts(sp); i++) { char name[MAX_SYNCPT_LENGTH]; struct kobject *kobj; struct nvhost_syncpt_attr *min = &sp->syncpt_attrs[i*2]; struct nvhost_syncpt_attr *max = &sp->syncpt_attrs[i*2+1]; /* Create one directory per sync point */ snprintf(name, sizeof(name), "%d", i); kobj = kobject_create_and_add(name, sp->kobj); if (!kobj) { err = -EIO; goto fail; } min->id = i; min->host = host; min->attr.attr.name = min_name; min->attr.attr.mode = S_IRUGO; min->attr.show = syncpt_min_show; #ifdef CONFIG_DEBUG_LOCK_ALLOC sysfs_attr_init(&min->attr.attr); sysfs_attr_init(&max->attr.attr); #endif if (sysfs_create_file(kobj, &min->attr.attr)) { err = -EIO; goto fail; } max->id = i; max->host = host; max->attr.attr.name = max_name; max->attr.attr.mode = S_IRUGO; max->attr.show = syncpt_max_show; if (sysfs_create_file(kobj, &max->attr.attr)) { err = -EIO; goto fail; } } return err; fail: nvhost_syncpt_deinit(sp); return err; }
static int iio_hwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct iio_hwmon_state *st; struct sensor_device_attribute *a; int ret, i; int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1; enum iio_chan_type type; struct iio_channel *channels; struct device *hwmon_dev; char *sname; channels = devm_iio_channel_get_all(dev); if (IS_ERR(channels)) { if (PTR_ERR(channels) == -ENODEV) return -EPROBE_DEFER; return PTR_ERR(channels); } st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); if (st == NULL) return -ENOMEM; st->channels = channels; /* count how many attributes we have */ while (st->channels[st->num_channels].indio_dev) st->num_channels++; st->attrs = devm_kcalloc(dev, st->num_channels + 1, sizeof(*st->attrs), GFP_KERNEL); if (st->attrs == NULL) return -ENOMEM; for (i = 0; i < st->num_channels; i++) { const char *prefix; int n; a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL); if (a == NULL) return -ENOMEM; sysfs_attr_init(&a->dev_attr.attr); ret = iio_get_channel_type(&st->channels[i], &type); if (ret < 0) return ret; switch (type) { case IIO_VOLTAGE: n = in_i++; prefix = "in"; break; case IIO_TEMP: n = temp_i++; prefix = "temp"; break; case IIO_CURRENT: n = curr_i++; prefix = "curr"; break; case IIO_HUMIDITYRELATIVE: n = humidity_i++; prefix = "humidity"; break; default: return -EINVAL; } a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d_input", prefix, n); if (a->dev_attr.attr.name == NULL) return -ENOMEM; a->dev_attr.show = iio_hwmon_read_val; a->dev_attr.attr.mode = 0444; a->index = i; st->attrs[i] = &a->dev_attr.attr; } st->attr_group.attrs = st->attrs; st->groups[0] = &st->attr_group; if (dev->of_node) { sname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); if (!sname) return -ENOMEM; strreplace(sname, '-', '_'); } else { sname = "iio_hwmon"; } hwmon_dev = devm_hwmon_device_register_with_groups(dev, sname, st, st->groups); return PTR_ERR_OR_ZERO(hwmon_dev); }
static int __devinit fsl_ssi_probe(struct platform_device *pdev) { struct fsl_ssi_private *ssi_private; int ret = 0; struct device_attribute *dev_attr = NULL; struct device_node *np = pdev->dev.of_node; const char *p, *sprop; const uint32_t *iprop; struct resource res; char name[64]; /* SSIs that are not connected on the board should have a * status = "disabled" * property in their device tree nodes. */ if (!of_device_is_available(np)) return -ENODEV; /* Check for a codec-handle property. */ if (!of_get_property(np, "codec-handle", NULL)) { dev_err(&pdev->dev, "missing codec-handle property\n"); return -ENODEV; } /* We only support the SSI in "I2S Slave" mode */ sprop = of_get_property(np, "fsl,mode", NULL); if (!sprop || strcmp(sprop, "i2s-slave")) { dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); return -ENODEV; } /* The DAI name is the last part of the full name of the node. */ p = strrchr(np->full_name, '/') + 1; ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), GFP_KERNEL); if (!ssi_private) { dev_err(&pdev->dev, "could not allocate DAI object\n"); return -ENOMEM; } strcpy(ssi_private->name, p); /* Initialize this copy of the CPU DAI driver structure */ memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, sizeof(fsl_ssi_dai_template)); ssi_private->cpu_dai_drv.name = ssi_private->name; /* Get the addresses and IRQ */ ret = of_address_to_resource(np, 0, &res); if (ret) { dev_err(&pdev->dev, "could not determine device resources\n"); goto error_kmalloc; } ssi_private->ssi = of_iomap(np, 0); if (!ssi_private->ssi) { dev_err(&pdev->dev, "could not map device resources\n"); ret = -ENOMEM; goto error_kmalloc; } ssi_private->ssi_phys = res.start; ssi_private->irq = irq_of_parse_and_map(np, 0); if (ssi_private->irq == NO_IRQ) { dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); ret = -ENXIO; goto error_iomap; } /* The 'name' should not have any slashes in it. */ ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, ssi_private); if (ret < 0) { dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); goto error_irqmap; } /* Are the RX and the TX clocks locked? */ if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) ssi_private->cpu_dai_drv.symmetric_rates = 1; /* Determine the FIFO depth. */ iprop = of_get_property(np, "fsl,fifo-depth", NULL); if (iprop) ssi_private->fifo_depth = be32_to_cpup(iprop); else /* Older 8610 DTs didn't have the fifo-depth property */ ssi_private->fifo_depth = 8; /* Initialize the the device_attribute structure */ dev_attr = &ssi_private->dev_attr; sysfs_attr_init(&dev_attr->attr); dev_attr->attr.name = "statistics"; dev_attr->attr.mode = S_IRUGO; dev_attr->show = fsl_sysfs_ssi_show; ret = device_create_file(&pdev->dev, dev_attr); if (ret) { dev_err(&pdev->dev, "could not create sysfs %s file\n", ssi_private->dev_attr.attr.name); goto error_irq; } /* Register with ASoC */ dev_set_drvdata(&pdev->dev, ssi_private); ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); if (ret) { dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); goto error_dev; } /* Trigger the machine driver's probe function. The platform driver * name of the machine driver is taken from /compatible property of the * device tree. We also pass the address of the CPU DAI driver * structure. */ sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL); /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */ p = strrchr(sprop, ','); if (p) sprop = p + 1; snprintf(name, sizeof(name), "snd-soc-%s", sprop); make_lowercase(name); ssi_private->pdev = platform_device_register_data(&pdev->dev, name, 0, NULL, 0); if (IS_ERR(ssi_private->pdev)) { ret = PTR_ERR(ssi_private->pdev); dev_err(&pdev->dev, "failed to register platform: %d\n", ret); goto error_dai; } return 0; error_dai: snd_soc_unregister_dai(&pdev->dev); error_dev: dev_set_drvdata(&pdev->dev, NULL); device_remove_file(&pdev->dev, dev_attr); error_irq: free_irq(ssi_private->irq, ssi_private); error_irqmap: irq_dispose_mapping(ssi_private->irq); error_iomap: iounmap(ssi_private->ssi); error_kmalloc: kfree(ssi_private); return ret; }
static int iio_hwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct iio_hwmon_state *st; struct sensor_device_attribute *a; int ret, i; int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1; enum iio_chan_type type; struct iio_channel *channels; const char *name = "iio_hwmon"; if (dev->of_node && dev->of_node->name) name = dev->of_node->name; channels = iio_channel_get_all(dev); if (IS_ERR(channels)) return PTR_ERR(channels); st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); if (st == NULL) { ret = -ENOMEM; goto error_release_channels; } st->channels = channels; /* count how many attributes we have */ while (st->channels[st->num_channels].indio_dev) st->num_channels++; st->attrs = devm_kzalloc(dev, sizeof(*st->attrs) * (st->num_channels + 1), GFP_KERNEL); if (st->attrs == NULL) { ret = -ENOMEM; goto error_release_channels; } for (i = 0; i < st->num_channels; i++) { a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL); if (a == NULL) { ret = -ENOMEM; goto error_release_channels; } sysfs_attr_init(&a->dev_attr.attr); ret = iio_get_channel_type(&st->channels[i], &type); if (ret < 0) goto error_release_channels; switch (type) { case IIO_VOLTAGE: a->dev_attr.attr.name = kasprintf(GFP_KERNEL, "in%d_input", in_i++); break; case IIO_TEMP: a->dev_attr.attr.name = kasprintf(GFP_KERNEL, "temp%d_input", temp_i++); break; case IIO_CURRENT: a->dev_attr.attr.name = kasprintf(GFP_KERNEL, "curr%d_input", curr_i++); break; case IIO_HUMIDITYRELATIVE: a->dev_attr.attr.name = kasprintf(GFP_KERNEL, "humidity%d_input", humidity_i++); break; default: ret = -EINVAL; goto error_release_channels; } if (a->dev_attr.attr.name == NULL) { ret = -ENOMEM; goto error_release_channels; } a->dev_attr.show = iio_hwmon_read_val; a->dev_attr.attr.mode = S_IRUGO; a->index = i; st->attrs[i] = &a->dev_attr.attr; } st->attr_group.attrs = st->attrs; st->groups[0] = &st->attr_group; st->hwmon_dev = hwmon_device_register_with_groups(dev, name, st, st->groups); if (IS_ERR(st->hwmon_dev)) { ret = PTR_ERR(st->hwmon_dev); goto error_release_channels; } platform_set_drvdata(pdev, st); return 0; error_release_channels: iio_channel_release_all(channels); return ret; }
/* * Register a new MMC card with the driver model. */ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; const char *uhs_bus_speed_mode = ""; static const char *const uhs_speeds[] = { [UHS_SDR12_BUS_SPEED] = "SDR12 ", [UHS_SDR25_BUS_SPEED] = "SDR25 ", [UHS_SDR50_BUS_SPEED] = "SDR50 ", [UHS_SDR104_BUS_SPEED] = "SDR104 ", [UHS_DDR50_BUS_SPEED] = "DDR50 ", }; dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); switch (card->type) { case MMC_TYPE_MMC: type = "MMC"; break; case MMC_TYPE_SD: type = "SD"; if (mmc_card_blockaddr(card)) { if (mmc_card_ext_capacity(card)) type = "SDXC"; else type = "SDHC"; } break; case MMC_TYPE_SDIO: type = "SDIO"; break; case MMC_TYPE_SD_COMBO: type = "SD-combo"; if (mmc_card_blockaddr(card)) type = "SDHC-combo"; break; default: type = "?"; break; } if (mmc_sd_card_uhs(card) && (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; if (mmc_host_is_spi(card->host)) { pr_info("%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), mmc_card_highspeed(card) ? "high speed " : "", mmc_card_ddr_mode(card) ? "DDR " : "", type); } else { pr_info("%s: new %s%s%s%s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_card_uhs(card) ? "ultra high speed " : (mmc_card_highspeed(card) ? "high speed " : ""), (mmc_card_hs400(card) ? "HS400 " : ""), (mmc_card_hs200(card) ? "HS200 " : ""), mmc_card_ddr_mode(card) ? "DDR " : "", uhs_bus_speed_mode, type, card->rca); } #ifdef CONFIG_MACH_LGE /* */ printk(KERN_INFO "[LGE][MMC][%-18s( )] mmc_hostname:%s, type:%s\n", __func__, mmc_hostname(card->host), type); #endif #ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); #endif mmc_init_context_info(card->host); if (mmc_use_core_runtime_pm(card->host)) { ret = pm_runtime_set_active(&card->dev); if (ret) pr_err("%s: %s: failed setting runtime active: ret: %d\n", mmc_hostname(card->host), __func__, ret); else if (!mmc_card_sdio(card)) pm_runtime_enable(&card->dev); } ret = device_add(&card->dev); #ifdef CONFIG_MACH_LGE /* */ if (ret) { printk(KERN_INFO "[LGE][MMC][%-18s( )] device_add & uevent posting fail!, ret:%d \n", __func__, ret); return ret; } else { printk(KERN_INFO "[LGE][MMC][%-18s( )] device_add & uevent posting complete!\n", __func__); } #else if (ret) return ret; #endif if (mmc_use_core_runtime_pm(card->host) && !mmc_card_sdio(card)) { card->rpm_attrib.show = show_rpm_delay; card->rpm_attrib.store = store_rpm_delay; sysfs_attr_init(&card->rpm_attrib.attr); card->rpm_attrib.attr.name = "runtime_pm_timeout"; card->rpm_attrib.attr.mode = S_IRUGO | S_IWUSR; ret = device_create_file(&card->dev, &card->rpm_attrib); if (ret) pr_err("%s: %s: creating runtime pm sysfs entry: failed: %d\n", mmc_hostname(card->host), __func__, ret); /* Default timeout is 10 seconds */ card->idle_timeout = RUNTIME_SUSPEND_DELAY_MS; } mmc_card_set_present(card); return 0; }
static int pcf2123_probe(struct spi_device *spi) { struct rtc_device *rtc; struct pcf2123_plat_data *pdata; u8 txbuf[2], rxbuf[2]; int ret, i; pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data), GFP_KERNEL); if (!pdata) return -ENOMEM; spi->dev.platform_data = pdata; /* Send a software reset command */ txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; txbuf[1] = 0x58; dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n", txbuf[0], txbuf[1]); ret = spi_write(spi, txbuf, 2 * sizeof(u8)); if (ret < 0) goto kfree_exit; pcf2123_delay_trec(); /* Stop the counter */ txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; txbuf[1] = 0x20; dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n", txbuf[0], txbuf[1]); ret = spi_write(spi, txbuf, 2 * sizeof(u8)); if (ret < 0) goto kfree_exit; pcf2123_delay_trec(); /* See if the counter was actually stopped */ txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1; dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n", txbuf[0]); ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8), rxbuf, 2 * sizeof(u8)); dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n", rxbuf[0], rxbuf[1]); if (ret < 0) goto kfree_exit; pcf2123_delay_trec(); if (!(rxbuf[0] & 0x20)) { dev_err(&spi->dev, "chip not found\n"); ret = -ENODEV; goto kfree_exit; } dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n"); dev_info(&spi->dev, "spiclk %u KHz.\n", (spi->max_speed_hz + 500) / 1000); /* Start the counter */ txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; txbuf[1] = 0x00; ret = spi_write(spi, txbuf, sizeof(txbuf)); if (ret < 0) goto kfree_exit; pcf2123_delay_trec(); /* Finalize the initialization */ rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name, &pcf2123_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { dev_err(&spi->dev, "failed to register.\n"); ret = PTR_ERR(rtc); goto kfree_exit; } pdata->rtc = rtc; for (i = 0; i < 16; i++) { sysfs_attr_init(&pdata->regs[i].attr.attr); sprintf(pdata->regs[i].name, "%1x", i); pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; pdata->regs[i].attr.attr.name = pdata->regs[i].name; pdata->regs[i].attr.show = pcf2123_show; pdata->regs[i].attr.store = pcf2123_store; ret = device_create_file(&spi->dev, &pdata->regs[i].attr); if (ret) { dev_err(&spi->dev, "Unable to create sysfs %s\n", pdata->regs[i].name); goto sysfs_exit; } } return 0; sysfs_exit: for (i--; i >= 0; i--) device_remove_file(&spi->dev, &pdata->regs[i].attr); kfree_exit: spi->dev.platform_data = NULL; return ret; }
static struct attribute_group * nct6683_create_attr_group(struct device *dev, const struct sensor_template_group *tg, int repeat) { struct sensor_device_attribute_2 *a2; struct sensor_device_attribute *a; struct sensor_device_template **t; struct sensor_device_attr_u *su; struct attribute_group *group; struct attribute **attrs; int i, j, count; if (repeat <= 0) return ERR_PTR(-EINVAL); t = tg->templates; for (count = 0; *t; t++, count++) ; if (count == 0) return ERR_PTR(-EINVAL); group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL); if (group == NULL) return ERR_PTR(-ENOMEM); attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) return ERR_PTR(-ENOMEM); su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)), GFP_KERNEL); if (su == NULL) return ERR_PTR(-ENOMEM); group->attrs = attrs; group->is_visible = tg->is_visible; for (i = 0; i < repeat; i++) { t = tg->templates; for (j = 0; *t != NULL; j++) { snprintf(su->name, sizeof(su->name), (*t)->dev_attr.attr.name, tg->base + i); if ((*t)->s2) { a2 = &su->u.a2; sysfs_attr_init(&a2->dev_attr.attr); a2->dev_attr.attr.name = su->name; a2->nr = (*t)->u.s.nr + i; a2->index = (*t)->u.s.index; a2->dev_attr.attr.mode = (*t)->dev_attr.attr.mode; a2->dev_attr.show = (*t)->dev_attr.show; a2->dev_attr.store = (*t)->dev_attr.store; *attrs = &a2->dev_attr.attr; } else { a = &su->u.a1; sysfs_attr_init(&a->dev_attr.attr); a->dev_attr.attr.name = su->name; a->index = (*t)->u.index + i; a->dev_attr.attr.mode = (*t)->dev_attr.attr.mode; a->dev_attr.show = (*t)->dev_attr.show; a->dev_attr.store = (*t)->dev_attr.store; *attrs = &a->dev_attr.attr; } attrs++; su++; t++; } } return group; }