162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2011-2016 Synaptics Incorporated
462306a36Sopenharmony_ci * Copyright (c) 2011 Unixphere
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/device.h>
962306a36Sopenharmony_ci#include <linux/irq.h>
1062306a36Sopenharmony_ci#include <linux/irqdomain.h>
1162306a36Sopenharmony_ci#include <linux/list.h>
1262306a36Sopenharmony_ci#include <linux/pm.h>
1362306a36Sopenharmony_ci#include <linux/rmi.h>
1462306a36Sopenharmony_ci#include <linux/slab.h>
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <linux/of.h>
1762306a36Sopenharmony_ci#include "rmi_bus.h"
1862306a36Sopenharmony_ci#include "rmi_driver.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic int debug_flags;
2162306a36Sopenharmony_cimodule_param(debug_flags, int, 0644);
2262306a36Sopenharmony_ciMODULE_PARM_DESC(debug_flags, "control debugging information");
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_civoid rmi_dbg(int flags, struct device *dev, const char *fmt, ...)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	struct va_format vaf;
2762306a36Sopenharmony_ci	va_list args;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	if (flags & debug_flags) {
3062306a36Sopenharmony_ci		va_start(args, fmt);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci		vaf.fmt = fmt;
3362306a36Sopenharmony_ci		vaf.va = &args;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, dev, "%pV", &vaf);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci		va_end(args);
3862306a36Sopenharmony_ci	}
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rmi_dbg);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/*
4362306a36Sopenharmony_ci * RMI Physical devices
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci * Physical RMI device consists of several functions serving particular
4662306a36Sopenharmony_ci * purpose. For example F11 is a 2D touch sensor while F01 is a generic
4762306a36Sopenharmony_ci * function present in every RMI device.
4862306a36Sopenharmony_ci */
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic void rmi_release_device(struct device *dev)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	struct rmi_device *rmi_dev = to_rmi_device(dev);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	kfree(rmi_dev);
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic const struct device_type rmi_device_type = {
5862306a36Sopenharmony_ci	.name		= "rmi4_sensor",
5962306a36Sopenharmony_ci	.release	= rmi_release_device,
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cibool rmi_is_physical_device(struct device *dev)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	return dev->type == &rmi_device_type;
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/**
6862306a36Sopenharmony_ci * rmi_register_transport_device - register a transport device connection
6962306a36Sopenharmony_ci * on the RMI bus.  Transport drivers provide communication from the devices
7062306a36Sopenharmony_ci * on a bus (such as SPI, I2C, and so on) to the RMI4 sensor.
7162306a36Sopenharmony_ci *
7262306a36Sopenharmony_ci * @xport: the transport device to register
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_ciint rmi_register_transport_device(struct rmi_transport_dev *xport)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	static atomic_t transport_device_count = ATOMIC_INIT(0);
7762306a36Sopenharmony_ci	struct rmi_device *rmi_dev;
7862306a36Sopenharmony_ci	int error;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	rmi_dev = kzalloc(sizeof(struct rmi_device), GFP_KERNEL);
8162306a36Sopenharmony_ci	if (!rmi_dev)
8262306a36Sopenharmony_ci		return -ENOMEM;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	device_initialize(&rmi_dev->dev);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	rmi_dev->xport = xport;
8762306a36Sopenharmony_ci	rmi_dev->number = atomic_inc_return(&transport_device_count) - 1;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	dev_set_name(&rmi_dev->dev, "rmi4-%02d", rmi_dev->number);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	rmi_dev->dev.bus = &rmi_bus_type;
9262306a36Sopenharmony_ci	rmi_dev->dev.type = &rmi_device_type;
9362306a36Sopenharmony_ci	rmi_dev->dev.parent = xport->dev;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	xport->rmi_dev = rmi_dev;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	error = device_add(&rmi_dev->dev);
9862306a36Sopenharmony_ci	if (error)
9962306a36Sopenharmony_ci		goto err_put_device;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	rmi_dbg(RMI_DEBUG_CORE, xport->dev,
10262306a36Sopenharmony_ci		"%s: Registered %s as %s.\n", __func__,
10362306a36Sopenharmony_ci		dev_name(rmi_dev->xport->dev), dev_name(&rmi_dev->dev));
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	return 0;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cierr_put_device:
10862306a36Sopenharmony_ci	put_device(&rmi_dev->dev);
10962306a36Sopenharmony_ci	return error;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rmi_register_transport_device);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/**
11462306a36Sopenharmony_ci * rmi_unregister_transport_device - unregister a transport device connection
11562306a36Sopenharmony_ci * @xport: the transport driver to unregister
11662306a36Sopenharmony_ci *
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_civoid rmi_unregister_transport_device(struct rmi_transport_dev *xport)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	struct rmi_device *rmi_dev = xport->rmi_dev;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	device_del(&rmi_dev->dev);
12362306a36Sopenharmony_ci	put_device(&rmi_dev->dev);
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ciEXPORT_SYMBOL(rmi_unregister_transport_device);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/* Function specific stuff */
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic void rmi_release_function(struct device *dev)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct rmi_function *fn = to_rmi_function(dev);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	kfree(fn);
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic const struct device_type rmi_function_type = {
13862306a36Sopenharmony_ci	.name		= "rmi4_function",
13962306a36Sopenharmony_ci	.release	= rmi_release_function,
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cibool rmi_is_function_device(struct device *dev)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	return dev->type == &rmi_function_type;
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic int rmi_function_match(struct device *dev, struct device_driver *drv)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	struct rmi_function_handler *handler = to_rmi_function_handler(drv);
15062306a36Sopenharmony_ci	struct rmi_function *fn = to_rmi_function(dev);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return fn->fd.function_number == handler->func;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci#ifdef CONFIG_OF
15662306a36Sopenharmony_cistatic void rmi_function_of_probe(struct rmi_function *fn)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	char of_name[9];
15962306a36Sopenharmony_ci	struct device_node *node = fn->rmi_dev->xport->dev->of_node;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	snprintf(of_name, sizeof(of_name), "rmi4-f%02x",
16262306a36Sopenharmony_ci		fn->fd.function_number);
16362306a36Sopenharmony_ci	fn->dev.of_node = of_get_child_by_name(node, of_name);
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci#else
16662306a36Sopenharmony_cistatic inline void rmi_function_of_probe(struct rmi_function *fn)
16762306a36Sopenharmony_ci{}
16862306a36Sopenharmony_ci#endif
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic struct irq_chip rmi_irq_chip = {
17162306a36Sopenharmony_ci	.name = "rmi4",
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic int rmi_create_function_irq(struct rmi_function *fn,
17562306a36Sopenharmony_ci				   struct rmi_function_handler *handler)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
17862306a36Sopenharmony_ci	int i, error;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	for (i = 0; i < fn->num_of_irqs; i++) {
18162306a36Sopenharmony_ci		set_bit(fn->irq_pos + i, fn->irq_mask);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci		fn->irq[i] = irq_create_mapping(drvdata->irqdomain,
18462306a36Sopenharmony_ci						fn->irq_pos + i);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		irq_set_chip_data(fn->irq[i], fn);
18762306a36Sopenharmony_ci		irq_set_chip_and_handler(fn->irq[i], &rmi_irq_chip,
18862306a36Sopenharmony_ci					 handle_simple_irq);
18962306a36Sopenharmony_ci		irq_set_nested_thread(fn->irq[i], 1);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci		error = devm_request_threaded_irq(&fn->dev, fn->irq[i], NULL,
19262306a36Sopenharmony_ci					handler->attention, IRQF_ONESHOT,
19362306a36Sopenharmony_ci					dev_name(&fn->dev), fn);
19462306a36Sopenharmony_ci		if (error) {
19562306a36Sopenharmony_ci			dev_err(&fn->dev, "Error %d registering IRQ\n", error);
19662306a36Sopenharmony_ci			return error;
19762306a36Sopenharmony_ci		}
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	return 0;
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cistatic int rmi_function_probe(struct device *dev)
20462306a36Sopenharmony_ci{
20562306a36Sopenharmony_ci	struct rmi_function *fn = to_rmi_function(dev);
20662306a36Sopenharmony_ci	struct rmi_function_handler *handler =
20762306a36Sopenharmony_ci					to_rmi_function_handler(dev->driver);
20862306a36Sopenharmony_ci	int error;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	rmi_function_of_probe(fn);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	if (handler->probe) {
21362306a36Sopenharmony_ci		error = handler->probe(fn);
21462306a36Sopenharmony_ci		if (error)
21562306a36Sopenharmony_ci			return error;
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	if (fn->num_of_irqs && handler->attention) {
21962306a36Sopenharmony_ci		error = rmi_create_function_irq(fn, handler);
22062306a36Sopenharmony_ci		if (error)
22162306a36Sopenharmony_ci			return error;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	return 0;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic int rmi_function_remove(struct device *dev)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	struct rmi_function *fn = to_rmi_function(dev);
23062306a36Sopenharmony_ci	struct rmi_function_handler *handler =
23162306a36Sopenharmony_ci					to_rmi_function_handler(dev->driver);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (handler->remove)
23462306a36Sopenharmony_ci		handler->remove(fn);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	return 0;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ciint rmi_register_function(struct rmi_function *fn)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	struct rmi_device *rmi_dev = fn->rmi_dev;
24262306a36Sopenharmony_ci	int error;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	device_initialize(&fn->dev);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	dev_set_name(&fn->dev, "%s.fn%02x",
24762306a36Sopenharmony_ci		     dev_name(&rmi_dev->dev), fn->fd.function_number);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	fn->dev.parent = &rmi_dev->dev;
25062306a36Sopenharmony_ci	fn->dev.type = &rmi_function_type;
25162306a36Sopenharmony_ci	fn->dev.bus = &rmi_bus_type;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	error = device_add(&fn->dev);
25462306a36Sopenharmony_ci	if (error) {
25562306a36Sopenharmony_ci		dev_err(&rmi_dev->dev,
25662306a36Sopenharmony_ci			"Failed device_register function device %s\n",
25762306a36Sopenharmony_ci			dev_name(&fn->dev));
25862306a36Sopenharmony_ci		goto err_put_device;
25962306a36Sopenharmony_ci	}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Registered F%02X.\n",
26262306a36Sopenharmony_ci			fn->fd.function_number);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return 0;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cierr_put_device:
26762306a36Sopenharmony_ci	put_device(&fn->dev);
26862306a36Sopenharmony_ci	return error;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_civoid rmi_unregister_function(struct rmi_function *fn)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	int i;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	rmi_dbg(RMI_DEBUG_CORE, &fn->dev, "Unregistering F%02X.\n",
27662306a36Sopenharmony_ci			fn->fd.function_number);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	device_del(&fn->dev);
27962306a36Sopenharmony_ci	of_node_put(fn->dev.of_node);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	for (i = 0; i < fn->num_of_irqs; i++)
28262306a36Sopenharmony_ci		irq_dispose_mapping(fn->irq[i]);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	put_device(&fn->dev);
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci/**
28862306a36Sopenharmony_ci * __rmi_register_function_handler - register a handler for an RMI function
28962306a36Sopenharmony_ci * @handler: RMI handler that should be registered.
29062306a36Sopenharmony_ci * @owner: pointer to module that implements the handler
29162306a36Sopenharmony_ci * @mod_name: name of the module implementing the handler
29262306a36Sopenharmony_ci *
29362306a36Sopenharmony_ci * This function performs additional setup of RMI function handler and
29462306a36Sopenharmony_ci * registers it with the RMI core so that it can be bound to
29562306a36Sopenharmony_ci * RMI function devices.
29662306a36Sopenharmony_ci */
29762306a36Sopenharmony_ciint __rmi_register_function_handler(struct rmi_function_handler *handler,
29862306a36Sopenharmony_ci				     struct module *owner,
29962306a36Sopenharmony_ci				     const char *mod_name)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	struct device_driver *driver = &handler->driver;
30262306a36Sopenharmony_ci	int error;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	driver->bus = &rmi_bus_type;
30562306a36Sopenharmony_ci	driver->owner = owner;
30662306a36Sopenharmony_ci	driver->mod_name = mod_name;
30762306a36Sopenharmony_ci	driver->probe = rmi_function_probe;
30862306a36Sopenharmony_ci	driver->remove = rmi_function_remove;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	error = driver_register(driver);
31162306a36Sopenharmony_ci	if (error) {
31262306a36Sopenharmony_ci		pr_err("driver_register() failed for %s, error: %d\n",
31362306a36Sopenharmony_ci			driver->name, error);
31462306a36Sopenharmony_ci		return error;
31562306a36Sopenharmony_ci	}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	return 0;
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__rmi_register_function_handler);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci/**
32262306a36Sopenharmony_ci * rmi_unregister_function_handler - unregister given RMI function handler
32362306a36Sopenharmony_ci * @handler: RMI handler that should be unregistered.
32462306a36Sopenharmony_ci *
32562306a36Sopenharmony_ci * This function unregisters given function handler from RMI core which
32662306a36Sopenharmony_ci * causes it to be unbound from the function devices.
32762306a36Sopenharmony_ci */
32862306a36Sopenharmony_civoid rmi_unregister_function_handler(struct rmi_function_handler *handler)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	driver_unregister(&handler->driver);
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rmi_unregister_function_handler);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci/* Bus specific stuff */
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic int rmi_bus_match(struct device *dev, struct device_driver *drv)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	bool physical = rmi_is_physical_device(dev);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	/* First see if types are not compatible */
34162306a36Sopenharmony_ci	if (physical != rmi_is_physical_driver(drv))
34262306a36Sopenharmony_ci		return 0;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return physical || rmi_function_match(dev, drv);
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistruct bus_type rmi_bus_type = {
34862306a36Sopenharmony_ci	.match		= rmi_bus_match,
34962306a36Sopenharmony_ci	.name		= "rmi4",
35062306a36Sopenharmony_ci};
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_cistatic struct rmi_function_handler *fn_handlers[] = {
35362306a36Sopenharmony_ci	&rmi_f01_handler,
35462306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F03
35562306a36Sopenharmony_ci	&rmi_f03_handler,
35662306a36Sopenharmony_ci#endif
35762306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F11
35862306a36Sopenharmony_ci	&rmi_f11_handler,
35962306a36Sopenharmony_ci#endif
36062306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F12
36162306a36Sopenharmony_ci	&rmi_f12_handler,
36262306a36Sopenharmony_ci#endif
36362306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F30
36462306a36Sopenharmony_ci	&rmi_f30_handler,
36562306a36Sopenharmony_ci#endif
36662306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F34
36762306a36Sopenharmony_ci	&rmi_f34_handler,
36862306a36Sopenharmony_ci#endif
36962306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F3A
37062306a36Sopenharmony_ci	&rmi_f3a_handler,
37162306a36Sopenharmony_ci#endif
37262306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F54
37362306a36Sopenharmony_ci	&rmi_f54_handler,
37462306a36Sopenharmony_ci#endif
37562306a36Sopenharmony_ci#ifdef CONFIG_RMI4_F55
37662306a36Sopenharmony_ci	&rmi_f55_handler,
37762306a36Sopenharmony_ci#endif
37862306a36Sopenharmony_ci};
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_cistatic void __rmi_unregister_function_handlers(int start_idx)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	int i;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	for (i = start_idx; i >= 0; i--)
38562306a36Sopenharmony_ci		rmi_unregister_function_handler(fn_handlers[i]);
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_cistatic void rmi_unregister_function_handlers(void)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	__rmi_unregister_function_handlers(ARRAY_SIZE(fn_handlers) - 1);
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic int rmi_register_function_handlers(void)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	int ret;
39662306a36Sopenharmony_ci	int i;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(fn_handlers); i++)	{
39962306a36Sopenharmony_ci		ret = rmi_register_function_handler(fn_handlers[i]);
40062306a36Sopenharmony_ci		if (ret) {
40162306a36Sopenharmony_ci			pr_err("%s: error registering the RMI F%02x handler: %d\n",
40262306a36Sopenharmony_ci				__func__, fn_handlers[i]->func, ret);
40362306a36Sopenharmony_ci			goto err_unregister_function_handlers;
40462306a36Sopenharmony_ci		}
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	return 0;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cierr_unregister_function_handlers:
41062306a36Sopenharmony_ci	__rmi_unregister_function_handlers(i - 1);
41162306a36Sopenharmony_ci	return ret;
41262306a36Sopenharmony_ci}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ciint rmi_of_property_read_u32(struct device *dev, u32 *result,
41562306a36Sopenharmony_ci				const char *prop, bool optional)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	int retval;
41862306a36Sopenharmony_ci	u32 val = 0;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	retval = of_property_read_u32(dev->of_node, prop, &val);
42162306a36Sopenharmony_ci	if (retval && (!optional && retval == -EINVAL)) {
42262306a36Sopenharmony_ci		dev_err(dev, "Failed to get %s value: %d\n",
42362306a36Sopenharmony_ci			prop, retval);
42462306a36Sopenharmony_ci		return retval;
42562306a36Sopenharmony_ci	}
42662306a36Sopenharmony_ci	*result = val;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	return 0;
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rmi_of_property_read_u32);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_cistatic int __init rmi_bus_init(void)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	int error;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	error = bus_register(&rmi_bus_type);
43762306a36Sopenharmony_ci	if (error) {
43862306a36Sopenharmony_ci		pr_err("%s: error registering the RMI bus: %d\n",
43962306a36Sopenharmony_ci			__func__, error);
44062306a36Sopenharmony_ci		return error;
44162306a36Sopenharmony_ci	}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	error = rmi_register_function_handlers();
44462306a36Sopenharmony_ci	if (error)
44562306a36Sopenharmony_ci		goto err_unregister_bus;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	error = rmi_register_physical_driver();
44862306a36Sopenharmony_ci	if (error) {
44962306a36Sopenharmony_ci		pr_err("%s: error registering the RMI physical driver: %d\n",
45062306a36Sopenharmony_ci			__func__, error);
45162306a36Sopenharmony_ci		goto err_unregister_bus;
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	return 0;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_cierr_unregister_bus:
45762306a36Sopenharmony_ci	bus_unregister(&rmi_bus_type);
45862306a36Sopenharmony_ci	return error;
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_cimodule_init(rmi_bus_init);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic void __exit rmi_bus_exit(void)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	/*
46562306a36Sopenharmony_ci	 * We should only ever get here if all drivers are unloaded, so
46662306a36Sopenharmony_ci	 * all we have to do at this point is unregister ourselves.
46762306a36Sopenharmony_ci	 */
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	rmi_unregister_physical_driver();
47062306a36Sopenharmony_ci	rmi_unregister_function_handlers();
47162306a36Sopenharmony_ci	bus_unregister(&rmi_bus_type);
47262306a36Sopenharmony_ci}
47362306a36Sopenharmony_cimodule_exit(rmi_bus_exit);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ciMODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com");
47662306a36Sopenharmony_ciMODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com");
47762306a36Sopenharmony_ciMODULE_DESCRIPTION("RMI bus");
47862306a36Sopenharmony_ciMODULE_LICENSE("GPL");
479