Skip to content
Snippets Groups Projects
Select Git revision
  • 726592a9be0bdf919399d3dfa633f8e2d69cbf13
  • master default protected
  • android-msm-bullhead-3.10-nougat_kgdb_less_changes
  • android-msm-bullhead-3.10-nougat_kgdb
  • android-msm-bullhead-3.10-nougat_klist
  • android-4.4
  • android-msm-vega-4.4-oreo-daydream
  • android-msm-wahoo-4.4-p-preview-5
  • android-msm-wahoo-4.4-pie
  • android-msm-marlin-3.18-p-preview-5
  • android-msm-marlin-3.18-pie
  • android-msm-wahoo-2018.07-oreo-m2
  • android-msm-wahoo-2018.07-oreo-m4
  • android-msm-wahoo-4.4-p-preview-4
  • android-msm-bullhead-3.10-oreo-m6
  • android-msm-angler-3.10-oreo-m6
  • android-msm-marlin-3.18-p-preview-4
  • android-msm-stargazer-3.18-oreo-wear-dr
  • android-msm-catshark-3.18-oreo-wear-dr
  • android-msm-wahoo-4.4-oreo-m2
  • android-msm-wahoo-4.4-oreo-m4
  • android-daydreamos-8.0.0_r0.5
  • android-8.1.0_r0.92
  • android-8.1.0_r0.91
  • android-daydreamos-8.0.0_r0.4
  • android-p-preview-5_r0.2
  • android-p-preview-5_r0.1
  • android-9.0.0_r0.5
  • android-9.0.0_r0.4
  • android-9.0.0_r0.2
  • android-9.0.0_r0.1
  • android-8.1.0_r0.81
  • android-8.1.0_r0.80
  • android-8.1.0_r0.78
  • android-8.1.0_r0.76
  • android-8.1.0_r0.75
  • android-8.1.0_r0.72
  • android-8.1.0_r0.70
  • android-p-preview-4_r0.2
  • android-p-preview-4_r0.1
  • android-wear-8.0.0_r0.30
41 results

soc.c

Blame
  • soc.c 4.15 KiB
    /*
     * Copyright (C) ST-Ericsson SA 2011
     *
     * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson.
     * License terms:  GNU General Public License (GPL), version 2
     */
    
    #include <linux/sysfs.h>
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/stat.h>
    #include <linux/slab.h>
    #include <linux/idr.h>
    #include <linux/spinlock.h>
    #include <linux/sys_soc.h>
    #include <linux/err.h>
    
    static DEFINE_IDA(soc_ida);
    static DEFINE_SPINLOCK(soc_lock);
    
    static ssize_t soc_info_get(struct device *dev,
    			    struct device_attribute *attr,
    			    char *buf);
    
    struct soc_device {
    	struct device dev;
    	struct soc_device_attribute *attr;
    	int soc_dev_num;
    };
    
    static struct bus_type soc_bus_type = {
    	.name  = "soc",
    };
    
    static DEVICE_ATTR(machine,  S_IRUGO, soc_info_get,  NULL);
    static DEVICE_ATTR(family,   S_IRUGO, soc_info_get,  NULL);
    static DEVICE_ATTR(soc_id,   S_IRUGO, soc_info_get,  NULL);
    static DEVICE_ATTR(revision, S_IRUGO, soc_info_get,  NULL);
    
    struct device *soc_device_to_device(struct soc_device *soc_dev)
    {
    	return &soc_dev->dev;
    }
    
    static umode_t soc_attribute_mode(struct kobject *kobj,
                                     struct attribute *attr,
                                     int index)
    {
    	struct device *dev = container_of(kobj, struct device, kobj);
    	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
    
    	if ((attr == &dev_attr_machine.attr)
    	    && (soc_dev->attr->machine != NULL))
    		return attr->mode;
    	if ((attr == &dev_attr_family.attr)
    	    && (soc_dev->attr->family != NULL))
    		return attr->mode;
    	if ((attr == &dev_attr_revision.attr)
    	    && (soc_dev->attr->revision != NULL))
    		return attr->mode;
    	if ((attr == &dev_attr_soc_id.attr)
    	    && (soc_dev->attr->soc_id != NULL))
    	        return attr->mode;
    
    	/* Unknown or unfilled attribute. */
    	return 0;
    }
    
    static ssize_t soc_info_get(struct device *dev,
    			    struct device_attribute *attr,
    			    char *buf)
    {
    	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
    
    	if (attr == &dev_attr_machine)
    		return sprintf(buf, "%s\n", soc_dev->attr->machine);
    	if (attr == &dev_attr_family)
    		return sprintf(buf, "%s\n", soc_dev->attr->family);
    	if (attr == &dev_attr_revision)
    		return sprintf(buf, "%s\n", soc_dev->attr->revision);
    	if (attr == &dev_attr_soc_id)
    		return sprintf(buf, "%s\n", soc_dev->attr->soc_id);
    
    	return -EINVAL;
    
    }
    
    static struct attribute *soc_attr[] = {
    	&dev_attr_machine.attr,
    	&dev_attr_family.attr,
    	&dev_attr_soc_id.attr,
    	&dev_attr_revision.attr,
    	NULL,
    };
    
    static const struct attribute_group soc_attr_group = {
    	.attrs = soc_attr,
    	.is_visible = soc_attribute_mode,
    };
    
    static const struct attribute_group *soc_attr_groups[] = {
    	&soc_attr_group,
    	NULL,
    };
    
    static void soc_release(struct device *dev)
    {
    	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
    
    	kfree(soc_dev);
    }
    
    struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
    {
    	struct soc_device *soc_dev;
    	int ret;
    
    	soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
    	if (!soc_dev) {
    	        ret = -ENOMEM;
    		goto out1;
    	}
    
    	/* Fetch a unique (reclaimable) SOC ID. */
    	do {
    		if (!ida_pre_get(&soc_ida, GFP_KERNEL)) {
    			ret = -ENOMEM;
    			goto out2;
    		}
    
    		spin_lock(&soc_lock);
    		ret = ida_get_new(&soc_ida, &soc_dev->soc_dev_num);
    		spin_unlock(&soc_lock);
    
    	} while (ret == -EAGAIN);
    
    	if (ret)
    	         goto out2;
    
    	soc_dev->attr = soc_dev_attr;
    	soc_dev->dev.bus = &soc_bus_type;
    	soc_dev->dev.groups = soc_attr_groups;
    	soc_dev->dev.release = soc_release;
    
    	dev_set_name(&soc_dev->dev, "soc%d", soc_dev->soc_dev_num);
    
    	ret = device_register(&soc_dev->dev);
    	if (ret)
    		goto out3;
    
    	return soc_dev;
    
    out3:
    	ida_remove(&soc_ida, soc_dev->soc_dev_num);
    out2:
    	kfree(soc_dev);
    out1:
    	return ERR_PTR(ret);
    }
    
    /* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */
    void soc_device_unregister(struct soc_device *soc_dev)
    {
    	ida_remove(&soc_ida, soc_dev->soc_dev_num);
    
    	device_unregister(&soc_dev->dev);
    }
    
    static int __init soc_bus_register(void)
    {
    	return bus_register(&soc_bus_type);
    }
    core_initcall(soc_bus_register);
    
    static void __exit soc_bus_unregister(void)
    {
    	ida_destroy(&soc_ida);
    
    	bus_unregister(&soc_bus_type);
    }
    module_exit(soc_bus_unregister);