Loading drivers/sensors/sensors_ssc.c +190 −2 Original line number Original line Diff line number Diff line /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading @@ -22,6 +22,14 @@ #include <asm/arch_timer.h> #include <asm/arch_timer.h> #include <linux/uaccess.h> #include <linux/uaccess.h> #include <linux/kernel.h> #include <linux/err.h> #include <linux/delay.h> #include <linux/sysfs.h> #include <soc/qcom/subsystem_restart.h> #define IMAGE_LOAD_CMD 1 #define IMAGE_UNLOAD_CMD 0 #define CLASS_NAME "ssc" #define CLASS_NAME "ssc" #define DRV_NAME "sensors" #define DRV_NAME "sensors" #define DRV_VERSION "2.00" #define DRV_VERSION "2.00" Loading @@ -37,6 +45,180 @@ struct sns_ssc_control_s { }; }; static struct sns_ssc_control_s sns_ctl; static struct sns_ssc_control_s sns_ctl; static ssize_t slpi_boot_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); struct slpi_loader_private { void *pil_h; struct kobject *boot_slpi_obj; struct attribute_group *attr_group; }; static struct kobj_attribute slpi_boot_attribute = __ATTR(boot, 0220, NULL, slpi_boot_store); static struct attribute *attrs[] = { &slpi_boot_attribute.attr, NULL, }; static struct platform_device *slpi_private; static void slpi_loader_do(struct platform_device *pdev) { struct slpi_loader_private *priv = NULL; if (!pdev) { dev_err(&pdev->dev, "%s: Platform device null\n", __func__); goto fail; } if (!pdev->dev.of_node) { dev_err(&pdev->dev, "%s: Device tree information missing\n", __func__); goto fail; } priv = platform_get_drvdata(pdev); if (!priv) { dev_err(&pdev->dev, " %s: Private data get failed\n", __func__); goto fail; } priv->pil_h = subsystem_get("slpi"); if (IS_ERR(priv->pil_h)) { dev_err(&pdev->dev, "%s: pil get failed,\n", __func__); goto fail; } dev_err(&pdev->dev, "%s: SLPI image is loaded\n", __func__); return; fail: dev_err(&pdev->dev, "%s: SLPI image loading failed\n", __func__); } static void slpi_loader_unload(struct platform_device *pdev) { struct slpi_loader_private *priv = NULL; priv = platform_get_drvdata(pdev); if (!priv) return; if (priv->pil_h) { dev_dbg(&pdev->dev, "%s: calling subsystem put\n", __func__); subsystem_put(priv->pil_h); priv->pil_h = NULL; } } static ssize_t slpi_boot_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int boot = 0; if (sscanf(buf, "%du", &boot) != 1) return -EINVAL; if (boot == IMAGE_LOAD_CMD) { pr_debug("%s: going to call slpi_loader_do\n", __func__); slpi_loader_do(slpi_private); } else if (boot == IMAGE_UNLOAD_CMD) { pr_debug("%s: going to call slpi_unloader\n", __func__); slpi_loader_unload(slpi_private); } return count; } static int slpi_loader_init_sysfs(struct platform_device *pdev) { int ret = -EINVAL; struct slpi_loader_private *priv = NULL; slpi_private = NULL; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; return ret; } platform_set_drvdata(pdev, priv); priv->pil_h = NULL; priv->boot_slpi_obj = NULL; priv->attr_group = devm_kzalloc(&pdev->dev, sizeof(*(priv->attr_group)), GFP_KERNEL); if (!priv->attr_group) { dev_err(&pdev->dev, "%s: malloc attr_group failed\n", __func__); ret = -ENOMEM; goto error_return; } priv->attr_group->attrs = attrs; priv->boot_slpi_obj = kobject_create_and_add("boot_slpi", kernel_kobj); if (!priv->boot_slpi_obj) { dev_err(&pdev->dev, "%s: sysfs create and add failed\n", __func__); ret = -ENOMEM; goto error_return; } ret = sysfs_create_group(priv->boot_slpi_obj, priv->attr_group); if (ret) { dev_err(&pdev->dev, "%s: sysfs create group failed %d\n", __func__, ret); goto error_return; } slpi_private = pdev; return 0; error_return: if (priv->boot_slpi_obj) { kobject_del(priv->boot_slpi_obj); priv->boot_slpi_obj = NULL; } return ret; } static int slpi_loader_remove(struct platform_device *pdev) { struct slpi_loader_private *priv = NULL; priv = platform_get_drvdata(pdev); if (!priv) return 0; if (priv->pil_h) { subsystem_put(priv->pil_h); priv->pil_h = NULL; } if (priv->boot_slpi_obj) { sysfs_remove_group(priv->boot_slpi_obj, priv->attr_group); kobject_del(priv->boot_slpi_obj); priv->boot_slpi_obj = NULL; } return 0; } /* /* * Read QTimer clock ticks and scale down to 32KHz clock as used * Read QTimer clock ticks and scale down to 32KHz clock as used * in DSPS * in DSPS Loading Loading @@ -104,7 +286,12 @@ const struct file_operations sensors_ssc_fops = { static int sensors_ssc_probe(struct platform_device *pdev) static int sensors_ssc_probe(struct platform_device *pdev) { { int ret = 0; int ret = slpi_loader_init_sysfs(pdev); if (ret != 0) { dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__); return ret; } sns_ctl.dev_class = class_create(THIS_MODULE, CLASS_NAME); sns_ctl.dev_class = class_create(THIS_MODULE, CLASS_NAME); if (sns_ctl.dev_class == NULL) { if (sns_ctl.dev_class == NULL) { Loading Loading @@ -156,6 +343,7 @@ res_err: static int sensors_ssc_remove(struct platform_device *pdev) static int sensors_ssc_remove(struct platform_device *pdev) { { slpi_loader_remove(pdev); cdev_del(sns_ctl.cdev); cdev_del(sns_ctl.cdev); kfree(sns_ctl.cdev); kfree(sns_ctl.cdev); sns_ctl.cdev = NULL; sns_ctl.cdev = NULL; Loading Loading
drivers/sensors/sensors_ssc.c +190 −2 Original line number Original line Diff line number Diff line /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading @@ -22,6 +22,14 @@ #include <asm/arch_timer.h> #include <asm/arch_timer.h> #include <linux/uaccess.h> #include <linux/uaccess.h> #include <linux/kernel.h> #include <linux/err.h> #include <linux/delay.h> #include <linux/sysfs.h> #include <soc/qcom/subsystem_restart.h> #define IMAGE_LOAD_CMD 1 #define IMAGE_UNLOAD_CMD 0 #define CLASS_NAME "ssc" #define CLASS_NAME "ssc" #define DRV_NAME "sensors" #define DRV_NAME "sensors" #define DRV_VERSION "2.00" #define DRV_VERSION "2.00" Loading @@ -37,6 +45,180 @@ struct sns_ssc_control_s { }; }; static struct sns_ssc_control_s sns_ctl; static struct sns_ssc_control_s sns_ctl; static ssize_t slpi_boot_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); struct slpi_loader_private { void *pil_h; struct kobject *boot_slpi_obj; struct attribute_group *attr_group; }; static struct kobj_attribute slpi_boot_attribute = __ATTR(boot, 0220, NULL, slpi_boot_store); static struct attribute *attrs[] = { &slpi_boot_attribute.attr, NULL, }; static struct platform_device *slpi_private; static void slpi_loader_do(struct platform_device *pdev) { struct slpi_loader_private *priv = NULL; if (!pdev) { dev_err(&pdev->dev, "%s: Platform device null\n", __func__); goto fail; } if (!pdev->dev.of_node) { dev_err(&pdev->dev, "%s: Device tree information missing\n", __func__); goto fail; } priv = platform_get_drvdata(pdev); if (!priv) { dev_err(&pdev->dev, " %s: Private data get failed\n", __func__); goto fail; } priv->pil_h = subsystem_get("slpi"); if (IS_ERR(priv->pil_h)) { dev_err(&pdev->dev, "%s: pil get failed,\n", __func__); goto fail; } dev_err(&pdev->dev, "%s: SLPI image is loaded\n", __func__); return; fail: dev_err(&pdev->dev, "%s: SLPI image loading failed\n", __func__); } static void slpi_loader_unload(struct platform_device *pdev) { struct slpi_loader_private *priv = NULL; priv = platform_get_drvdata(pdev); if (!priv) return; if (priv->pil_h) { dev_dbg(&pdev->dev, "%s: calling subsystem put\n", __func__); subsystem_put(priv->pil_h); priv->pil_h = NULL; } } static ssize_t slpi_boot_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int boot = 0; if (sscanf(buf, "%du", &boot) != 1) return -EINVAL; if (boot == IMAGE_LOAD_CMD) { pr_debug("%s: going to call slpi_loader_do\n", __func__); slpi_loader_do(slpi_private); } else if (boot == IMAGE_UNLOAD_CMD) { pr_debug("%s: going to call slpi_unloader\n", __func__); slpi_loader_unload(slpi_private); } return count; } static int slpi_loader_init_sysfs(struct platform_device *pdev) { int ret = -EINVAL; struct slpi_loader_private *priv = NULL; slpi_private = NULL; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; return ret; } platform_set_drvdata(pdev, priv); priv->pil_h = NULL; priv->boot_slpi_obj = NULL; priv->attr_group = devm_kzalloc(&pdev->dev, sizeof(*(priv->attr_group)), GFP_KERNEL); if (!priv->attr_group) { dev_err(&pdev->dev, "%s: malloc attr_group failed\n", __func__); ret = -ENOMEM; goto error_return; } priv->attr_group->attrs = attrs; priv->boot_slpi_obj = kobject_create_and_add("boot_slpi", kernel_kobj); if (!priv->boot_slpi_obj) { dev_err(&pdev->dev, "%s: sysfs create and add failed\n", __func__); ret = -ENOMEM; goto error_return; } ret = sysfs_create_group(priv->boot_slpi_obj, priv->attr_group); if (ret) { dev_err(&pdev->dev, "%s: sysfs create group failed %d\n", __func__, ret); goto error_return; } slpi_private = pdev; return 0; error_return: if (priv->boot_slpi_obj) { kobject_del(priv->boot_slpi_obj); priv->boot_slpi_obj = NULL; } return ret; } static int slpi_loader_remove(struct platform_device *pdev) { struct slpi_loader_private *priv = NULL; priv = platform_get_drvdata(pdev); if (!priv) return 0; if (priv->pil_h) { subsystem_put(priv->pil_h); priv->pil_h = NULL; } if (priv->boot_slpi_obj) { sysfs_remove_group(priv->boot_slpi_obj, priv->attr_group); kobject_del(priv->boot_slpi_obj); priv->boot_slpi_obj = NULL; } return 0; } /* /* * Read QTimer clock ticks and scale down to 32KHz clock as used * Read QTimer clock ticks and scale down to 32KHz clock as used * in DSPS * in DSPS Loading Loading @@ -104,7 +286,12 @@ const struct file_operations sensors_ssc_fops = { static int sensors_ssc_probe(struct platform_device *pdev) static int sensors_ssc_probe(struct platform_device *pdev) { { int ret = 0; int ret = slpi_loader_init_sysfs(pdev); if (ret != 0) { dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__); return ret; } sns_ctl.dev_class = class_create(THIS_MODULE, CLASS_NAME); sns_ctl.dev_class = class_create(THIS_MODULE, CLASS_NAME); if (sns_ctl.dev_class == NULL) { if (sns_ctl.dev_class == NULL) { Loading Loading @@ -156,6 +343,7 @@ res_err: static int sensors_ssc_remove(struct platform_device *pdev) static int sensors_ssc_remove(struct platform_device *pdev) { { slpi_loader_remove(pdev); cdev_del(sns_ctl.cdev); cdev_del(sns_ctl.cdev); kfree(sns_ctl.cdev); kfree(sns_ctl.cdev); sns_ctl.cdev = NULL; sns_ctl.cdev = NULL; Loading