Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4657d12b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: bgcom_dev: handle ssr events for Blackghost and Modem"

parents 35eaac3d c3c89001
Loading
Loading
Loading
Loading
+149 −0
Original line number Diff line number Diff line
@@ -21,11 +21,37 @@
#include <linux/errno.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/subsystem_notif.h>
#include "bgcom.h"
#include "linux/bgcom_interface.h"

#define BGCOM "bg_com_dev"

enum {
	SSR_DOMAIN_BG,
	SSR_DOMAIN_MODEM,
	SSR_DOMAIN_MAX,
};

struct bg_event {
	enum bg_event_type e_type;
};

struct service_info {
	const char                      name[32];
	int                             domain_id;
	void                            *handle;
	struct notifier_block           *nb;
};

static char *ssr_domains[] = {
	"bg-wear",
	"modem",
};

static  DEFINE_MUTEX(bg_char_mutex);
static  struct cdev              bg_cdev;
static  struct class             *bg_class;
@@ -35,6 +61,23 @@ static int device_open;
static  void                     *handle;
static  struct   bgcom_open_config_type   config_type;

/**
 * send_uevent(): send events to user space
 * pce : ssr event handle value
 * Return: 0 on success, standard Linux error code on error
 *
 * It adds pce value to event and broadcasts to user space.
 */
static int send_uevent(struct bg_event *pce)
{
	char event_string[32];
	char *envp[2] = { event_string, NULL };

	snprintf(event_string, ARRAY_SIZE(event_string),
			"BG_EVENT=%d", pce->e_type);
	return kobject_uevent_env(&dev_ret->kobj, KOBJ_CHANGE, envp);
}

static int bgcom_char_open(struct inode *inode, struct file *file)
{
	int ret;
@@ -146,6 +189,12 @@ static long bg_com_ioctl(struct file *filp,
		if (ret < 0)
			pr_err("bgchar_write_cmd failed\n");
		break;
	case SET_SPI_FREE:
		ret = bgcom_set_spi_state(BGCOM_SPI_FREE);
		break;
	case SET_SPI_BUSY:
		ret = bgcom_set_spi_state(BGCOM_SPI_BUSY);
		break;
	default:
		ret = -ENOIOCTLCMD;
	}
@@ -213,6 +262,106 @@ static void __exit exit_bg_com_dev(void)
	unregister_chrdev_region(bg_dev, 1);
}

/**
 *ssr_bg_cb(): callback function is called
 *by ssr framework when BG goes down, up and during ramdump
 *collection. It handles BG shutdown and power up events.
 */
static int ssr_bg_cb(struct notifier_block *this,
		unsigned long opcode, void *data)
{
	struct bg_event bge;

	switch (opcode) {
	case SUBSYS_BEFORE_SHUTDOWN:
		bge.e_type = BG_BEFORE_POWER_DOWN;
		send_uevent(&bge);
		break;
	case SUBSYS_AFTER_POWERUP:
		bge.e_type = BG_AFTER_POWER_UP;
		send_uevent(&bge);
		break;
	}
	return NOTIFY_DONE;
}

/**
 *ssr_modem_cb(): callback function is called
 *by ssr framework when modem goes down, up and during ramdump
 *collection. It handles modem shutdown and power up events.
 */
static int ssr_modem_cb(struct notifier_block *this,
		unsigned long opcode, void *data)
{
	struct bg_event modeme;

	switch (opcode) {
	case SUBSYS_BEFORE_SHUTDOWN:
		modeme.e_type = MODEM_BEFORE_POWER_DOWN;
		send_uevent(&modeme);
		break;
	case SUBSYS_AFTER_POWERUP:
		modeme.e_type = MODEM_AFTER_POWER_UP;
		send_uevent(&modeme);
		break;
	}
	return NOTIFY_DONE;
}

static struct notifier_block ssr_modem_nb = {
	.notifier_call = ssr_modem_cb,
	.priority = 0,
};

static struct notifier_block ssr_bg_nb = {
	.notifier_call = ssr_bg_cb,
	.priority = 0,
};

static struct service_info service_data[2] = {
	{
		.name = "SSR_BG",
		.domain_id = SSR_DOMAIN_BG,
		.nb = &ssr_bg_nb,
		.handle = NULL,
	},
	{
		.name = "SSR_MODEM",
		.domain_id = SSR_DOMAIN_MODEM,
		.nb = &ssr_modem_nb,
		.handle = NULL,
	},
};

/**
 * ssr_register checks that domain id should be in range and register
 * SSR framework for value at domain id.
 */
static int __init ssr_register(void)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(service_data); i++) {
		if ((service_data[i].domain_id < 0) ||
				(service_data[i].domain_id >= SSR_DOMAIN_MAX)) {
			pr_err("Invalid service ID = %d\n",
					service_data[i].domain_id);
		} else {
			service_data[i].handle =
					subsys_notif_register_notifier(
					ssr_domains[service_data[i].domain_id],
					service_data[i].nb);
			if (IS_ERR_OR_NULL(service_data[i].handle)) {
				pr_err("subsys register failed for id = %d",
						service_data[i].domain_id);
				service_data[i].handle = NULL;
			}
		}
	}
	return 0;
}

module_init(init_bg_com_dev);
late_initcall(ssr_register);
module_exit(exit_bg_com_dev);
MODULE_LICENSE("GPL v2");
+16 −1
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
#define BGCOM_REG_READ  0
#define BGCOM_AHB_READ  1
#define BGCOM_AHB_WRITE 2
#define BGCOM_SET_SPI_FREE  3
#define BGCOM_SET_SPI_BUSY  4
#define EXCHANGE_CODE  'V'

struct bg_ui_data {
@@ -13,6 +15,13 @@ struct bg_ui_data {
	uint32_t  num_of_words;
};

enum bg_event_type {
	BG_BEFORE_POWER_DOWN = 1,
	BG_AFTER_POWER_UP,
	MODEM_BEFORE_POWER_DOWN,
	MODEM_AFTER_POWER_UP,
};

#define REG_READ \
	_IOWR(EXCHANGE_CODE, BGCOM_REG_READ, \
	struct bg_ui_data)
@@ -22,4 +31,10 @@ struct bg_ui_data {
#define AHB_WRITE \
	_IOW(EXCHANGE_CODE, BGCOM_AHB_WRITE, \
	struct bg_ui_data)
#define SET_SPI_FREE \
	_IOR(EXCHANGE_CODE, BGCOM_SET_SPI_FREE, \
	struct bg_ui_data)
#define SET_SPI_BUSY \
	_IOR(EXCHANGE_CODE, BGCOM_SET_SPI_BUSY, \
	struct bg_ui_data)
#endif