Loading drivers/esoc/esoc-mdm-drv.c +40 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <linux/workqueue.h> #include <linux/reboot.h> #include <linux/of.h> #include <linux/esoc_client.h> #include "esoc.h" #include "mdm-dbg.h" Loading Loading @@ -105,6 +106,39 @@ static void mdm_ssr_fn(struct work_struct *work) esoc_clink_request_ssr(mdm_drv->esoc_clink); } static void esoc_client_link_power_on(struct esoc_clink *esoc_clink, bool mdm_crashed) { int i; struct esoc_client_hook *client_hook; dev_dbg(&esoc_clink->dev, "Calling power_on hooks\n"); for (i = 0; i < ESOC_MAX_HOOKS; i++) { client_hook = esoc_clink->client_hook[i]; if (client_hook && client_hook->esoc_link_power_on) client_hook->esoc_link_power_on(client_hook->priv, mdm_crashed); } } static void esoc_client_link_power_off(struct esoc_clink *esoc_clink, bool mdm_crashed) { int i; struct esoc_client_hook *client_hook; dev_dbg(&esoc_clink->dev, "Calling power_off hooks\n"); for (i = 0; i < ESOC_MAX_HOOKS; i++) { client_hook = esoc_clink->client_hook[i]; if (client_hook && client_hook->esoc_link_power_off) { client_hook->esoc_link_power_off(client_hook->priv, mdm_crashed); } } } static void mdm_crash_shutdown(const struct subsys_desc *mdm_subsys) { struct esoc_clink *esoc_clink = Loading Loading @@ -134,6 +168,9 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, * to move to next stage */ return 0; esoc_client_link_power_off(esoc_clink, true); ret = clink_ops->cmd_exe(ESOC_PREPARE_DEBUG, esoc_clink); if (ret) { Loading @@ -159,6 +196,7 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, return ret; } mdm_drv->mode = PWR_OFF; esoc_client_link_power_off(esoc_clink, false); } return 0; } Loading @@ -185,6 +223,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) dev_err(&esoc_clink->dev, "pwr on fail\n"); return ret; } esoc_client_link_power_on(esoc_clink, false); } else if (mdm_drv->mode == IN_DEBUG) { ret = clink_ops->cmd_exe(ESOC_EXIT_DEBUG, esoc_clink); if (ret) { Loading @@ -197,6 +236,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) dev_err(&esoc_clink->dev, "pwr on fail\n"); return ret; } esoc_client_link_power_on(esoc_clink, true); } /* Loading drivers/esoc/esoc.h +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/cdev.h> #include <linux/completion.h> #include <linux/esoc_ctrl.h> #include <linux/esoc_client.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/platform_device.h> Loading Loading @@ -89,6 +90,7 @@ struct esoc_clink { bool primary; bool statusline_not_a_powersource; bool userspace_handle_shutdown; struct esoc_client_hook *client_hook[ESOC_MAX_HOOKS]; }; /** Loading drivers/esoc/esoc_client.c +64 −0 Original line number Diff line number Diff line Loading @@ -142,3 +142,67 @@ void notify_esoc_clients(struct esoc_clink *esoc_clink, unsigned long evt) spin_unlock_irqrestore(¬ify_lock, flags); } EXPORT_SYMBOL(notify_esoc_clients); int esoc_register_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook) { int i; struct esoc_clink *esoc_clink; if (IS_ERR_OR_NULL(desc) || IS_ERR_OR_NULL(client_hook)) { pr_debug("%s: Invalid parameters\n", __func__); return -EINVAL; } esoc_clink = desc->priv; if (IS_ERR_OR_NULL(esoc_clink)) { pr_debug("%s: Invalid esoc link\n", __func__); return -EINVAL; } for (i = 0; i < ESOC_MAX_HOOKS; i++) { if (i == client_hook->prio && esoc_clink->client_hook[i] == NULL) { esoc_clink->client_hook[i] = client_hook; dev_dbg(&esoc_clink->dev, "Client hook registration successful\n"); return 0; } } dev_dbg(&esoc_clink->dev, "Client hook registration failed!\n"); return -EINVAL; } EXPORT_SYMBOL(esoc_register_client_hook); int esoc_unregister_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook) { int i; struct esoc_clink *esoc_clink; if (IS_ERR_OR_NULL(desc) || IS_ERR_OR_NULL(client_hook)) { pr_debug("%s: Invalid parameters\n", __func__); return -EINVAL; } esoc_clink = desc->priv; if (IS_ERR_OR_NULL(esoc_clink)) { pr_debug("%s: Invalid esoc link\n", __func__); return -EINVAL; } for (i = 0; i < ESOC_MAX_HOOKS; i++) { if (i == client_hook->prio && esoc_clink->client_hook[i] != NULL) { esoc_clink->client_hook[i] = NULL; dev_dbg(&esoc_clink->dev, "Client hook unregistration successful\n"); return 0; } } dev_dbg(&esoc_clink->dev, "Client hook unregistration failed!\n"); return -EINVAL; } EXPORT_SYMBOL(esoc_unregister_client_hook); drivers/esoc/esoc_dev.c +47 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <linux/sched.h> #include <linux/uaccess.h> #include <linux/wait.h> #include <linux/esoc_client.h> #include "esoc.h" /** Loading Loading @@ -172,6 +173,50 @@ void esoc_udev_handle_clink_evt(enum esoc_evt evt, struct esoc_eng *eng) wake_up_interruptible(&esoc_udev->evt_wait); } static int esoc_get_link_id(struct esoc_clink *esoc_clink, unsigned long arg) { struct esoc_link_data link_data; struct esoc_client_hook *client_hook; struct esoc_link_data __user *user_arg; user_arg = (struct esoc_link_data __user *) arg; if (!user_arg) { dev_err(&esoc_clink->dev, "Missing argument for link id\n"); return -EINVAL; } if (copy_from_user((void *) &link_data, user_arg, sizeof(*user_arg))) { dev_err(&esoc_clink->dev, "Unable to copy the data from the user\n"); return -EFAULT; } if (link_data.prio < 0 || link_data.prio >= ESOC_MAX_HOOKS) { dev_err(&esoc_clink->dev, "Invalid client identifier passed\n"); return -EINVAL; } client_hook = esoc_clink->client_hook[link_data.prio]; if (client_hook && client_hook->esoc_link_get_id) { link_data.link_id = client_hook->esoc_link_get_id(client_hook->priv); if (copy_to_user((void *) user_arg, &link_data, sizeof(*user_arg))) { dev_err(&esoc_clink->dev, "Failed to send the data to the user\n"); return -EFAULT; } return 0; } dev_err(&esoc_clink->dev, "Client hooks not registered for the device\n"); return -EINVAL; } static long esoc_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading Loading @@ -246,6 +291,8 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd, put_user(evt, (unsigned int __user *)uarg); } return err; case ESOC_GET_LINK_ID: return esoc_get_link_id(esoc_clink, arg); default: return -EINVAL; }; Loading include/linux/esoc_client.h +23 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,15 @@ #include <linux/esoc_ctrl.h> #include <linux/notifier.h> struct esoc_client_hook { char *name; void *priv; enum esoc_client_hook_prio prio; int (*esoc_link_power_on)(void *priv, bool mdm_crashed); void (*esoc_link_power_off)(void *priv, bool mdm_crashed); u64 (*esoc_link_get_id)(void *priv); }; /* * struct esoc_desc: Describes an external soc * @name: external soc name Loading @@ -35,6 +44,10 @@ struct esoc_desc *devm_register_esoc_client(struct device *dev, void devm_unregister_esoc_client(struct device *dev, struct esoc_desc *esoc_desc); int esoc_register_client_notifier(struct notifier_block *nb); int esoc_register_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook); int esoc_unregister_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook); #else static inline struct esoc_desc *devm_register_esoc_client(struct device *dev, const char *name) Loading @@ -49,5 +62,15 @@ static inline int esoc_register_client_notifier(struct notifier_block *nb) { return -EIO; } int esoc_register_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook) { return -EIO; } int esoc_unregister_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook); { return -EIO; } #endif #endif Loading
drivers/esoc/esoc-mdm-drv.c +40 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <linux/workqueue.h> #include <linux/reboot.h> #include <linux/of.h> #include <linux/esoc_client.h> #include "esoc.h" #include "mdm-dbg.h" Loading Loading @@ -105,6 +106,39 @@ static void mdm_ssr_fn(struct work_struct *work) esoc_clink_request_ssr(mdm_drv->esoc_clink); } static void esoc_client_link_power_on(struct esoc_clink *esoc_clink, bool mdm_crashed) { int i; struct esoc_client_hook *client_hook; dev_dbg(&esoc_clink->dev, "Calling power_on hooks\n"); for (i = 0; i < ESOC_MAX_HOOKS; i++) { client_hook = esoc_clink->client_hook[i]; if (client_hook && client_hook->esoc_link_power_on) client_hook->esoc_link_power_on(client_hook->priv, mdm_crashed); } } static void esoc_client_link_power_off(struct esoc_clink *esoc_clink, bool mdm_crashed) { int i; struct esoc_client_hook *client_hook; dev_dbg(&esoc_clink->dev, "Calling power_off hooks\n"); for (i = 0; i < ESOC_MAX_HOOKS; i++) { client_hook = esoc_clink->client_hook[i]; if (client_hook && client_hook->esoc_link_power_off) { client_hook->esoc_link_power_off(client_hook->priv, mdm_crashed); } } } static void mdm_crash_shutdown(const struct subsys_desc *mdm_subsys) { struct esoc_clink *esoc_clink = Loading Loading @@ -134,6 +168,9 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, * to move to next stage */ return 0; esoc_client_link_power_off(esoc_clink, true); ret = clink_ops->cmd_exe(ESOC_PREPARE_DEBUG, esoc_clink); if (ret) { Loading @@ -159,6 +196,7 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, return ret; } mdm_drv->mode = PWR_OFF; esoc_client_link_power_off(esoc_clink, false); } return 0; } Loading @@ -185,6 +223,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) dev_err(&esoc_clink->dev, "pwr on fail\n"); return ret; } esoc_client_link_power_on(esoc_clink, false); } else if (mdm_drv->mode == IN_DEBUG) { ret = clink_ops->cmd_exe(ESOC_EXIT_DEBUG, esoc_clink); if (ret) { Loading @@ -197,6 +236,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) dev_err(&esoc_clink->dev, "pwr on fail\n"); return ret; } esoc_client_link_power_on(esoc_clink, true); } /* Loading
drivers/esoc/esoc.h +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/cdev.h> #include <linux/completion.h> #include <linux/esoc_ctrl.h> #include <linux/esoc_client.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/platform_device.h> Loading Loading @@ -89,6 +90,7 @@ struct esoc_clink { bool primary; bool statusline_not_a_powersource; bool userspace_handle_shutdown; struct esoc_client_hook *client_hook[ESOC_MAX_HOOKS]; }; /** Loading
drivers/esoc/esoc_client.c +64 −0 Original line number Diff line number Diff line Loading @@ -142,3 +142,67 @@ void notify_esoc_clients(struct esoc_clink *esoc_clink, unsigned long evt) spin_unlock_irqrestore(¬ify_lock, flags); } EXPORT_SYMBOL(notify_esoc_clients); int esoc_register_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook) { int i; struct esoc_clink *esoc_clink; if (IS_ERR_OR_NULL(desc) || IS_ERR_OR_NULL(client_hook)) { pr_debug("%s: Invalid parameters\n", __func__); return -EINVAL; } esoc_clink = desc->priv; if (IS_ERR_OR_NULL(esoc_clink)) { pr_debug("%s: Invalid esoc link\n", __func__); return -EINVAL; } for (i = 0; i < ESOC_MAX_HOOKS; i++) { if (i == client_hook->prio && esoc_clink->client_hook[i] == NULL) { esoc_clink->client_hook[i] = client_hook; dev_dbg(&esoc_clink->dev, "Client hook registration successful\n"); return 0; } } dev_dbg(&esoc_clink->dev, "Client hook registration failed!\n"); return -EINVAL; } EXPORT_SYMBOL(esoc_register_client_hook); int esoc_unregister_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook) { int i; struct esoc_clink *esoc_clink; if (IS_ERR_OR_NULL(desc) || IS_ERR_OR_NULL(client_hook)) { pr_debug("%s: Invalid parameters\n", __func__); return -EINVAL; } esoc_clink = desc->priv; if (IS_ERR_OR_NULL(esoc_clink)) { pr_debug("%s: Invalid esoc link\n", __func__); return -EINVAL; } for (i = 0; i < ESOC_MAX_HOOKS; i++) { if (i == client_hook->prio && esoc_clink->client_hook[i] != NULL) { esoc_clink->client_hook[i] = NULL; dev_dbg(&esoc_clink->dev, "Client hook unregistration successful\n"); return 0; } } dev_dbg(&esoc_clink->dev, "Client hook unregistration failed!\n"); return -EINVAL; } EXPORT_SYMBOL(esoc_unregister_client_hook);
drivers/esoc/esoc_dev.c +47 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <linux/sched.h> #include <linux/uaccess.h> #include <linux/wait.h> #include <linux/esoc_client.h> #include "esoc.h" /** Loading Loading @@ -172,6 +173,50 @@ void esoc_udev_handle_clink_evt(enum esoc_evt evt, struct esoc_eng *eng) wake_up_interruptible(&esoc_udev->evt_wait); } static int esoc_get_link_id(struct esoc_clink *esoc_clink, unsigned long arg) { struct esoc_link_data link_data; struct esoc_client_hook *client_hook; struct esoc_link_data __user *user_arg; user_arg = (struct esoc_link_data __user *) arg; if (!user_arg) { dev_err(&esoc_clink->dev, "Missing argument for link id\n"); return -EINVAL; } if (copy_from_user((void *) &link_data, user_arg, sizeof(*user_arg))) { dev_err(&esoc_clink->dev, "Unable to copy the data from the user\n"); return -EFAULT; } if (link_data.prio < 0 || link_data.prio >= ESOC_MAX_HOOKS) { dev_err(&esoc_clink->dev, "Invalid client identifier passed\n"); return -EINVAL; } client_hook = esoc_clink->client_hook[link_data.prio]; if (client_hook && client_hook->esoc_link_get_id) { link_data.link_id = client_hook->esoc_link_get_id(client_hook->priv); if (copy_to_user((void *) user_arg, &link_data, sizeof(*user_arg))) { dev_err(&esoc_clink->dev, "Failed to send the data to the user\n"); return -EFAULT; } return 0; } dev_err(&esoc_clink->dev, "Client hooks not registered for the device\n"); return -EINVAL; } static long esoc_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { Loading Loading @@ -246,6 +291,8 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd, put_user(evt, (unsigned int __user *)uarg); } return err; case ESOC_GET_LINK_ID: return esoc_get_link_id(esoc_clink, arg); default: return -EINVAL; }; Loading
include/linux/esoc_client.h +23 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,15 @@ #include <linux/esoc_ctrl.h> #include <linux/notifier.h> struct esoc_client_hook { char *name; void *priv; enum esoc_client_hook_prio prio; int (*esoc_link_power_on)(void *priv, bool mdm_crashed); void (*esoc_link_power_off)(void *priv, bool mdm_crashed); u64 (*esoc_link_get_id)(void *priv); }; /* * struct esoc_desc: Describes an external soc * @name: external soc name Loading @@ -35,6 +44,10 @@ struct esoc_desc *devm_register_esoc_client(struct device *dev, void devm_unregister_esoc_client(struct device *dev, struct esoc_desc *esoc_desc); int esoc_register_client_notifier(struct notifier_block *nb); int esoc_register_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook); int esoc_unregister_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook); #else static inline struct esoc_desc *devm_register_esoc_client(struct device *dev, const char *name) Loading @@ -49,5 +62,15 @@ static inline int esoc_register_client_notifier(struct notifier_block *nb) { return -EIO; } int esoc_register_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook) { return -EIO; } int esoc_unregister_client_hook(struct esoc_desc *desc, struct esoc_client_hook *client_hook); { return -EIO; } #endif #endif