Skip to content

Commit 3648e78

Browse files
Sagar Dhariagregkh
authored andcommitted
slimbus: Add SLIMbus bus type
SLIMbus (Serial Low Power Interchip Media Bus) is a specification developed by MIPI (Mobile Industry Processor Interface) alliance. SLIMbus is a 2-wire implementation, which is used to communicate with peripheral components like audio-codec. SLIMbus uses Time-Division-Multiplexing to accommodate multiple data channels, and control channel. Control channel has messages to do device-enumeration, messages to send/receive control-data to/from SLIMbus devices, messages for port/channel management, and messages to do bandwidth allocation. The framework supports multiple instances of the bus (1 controller per bus), and multiple slave devices per controller. This patch adds support to basic silmbus core which includes support to SLIMbus type, slimbus device registeration and some basic data structures. Signed-off-by: Sagar Dharia <[email protected]> Signed-off-by: Srinivas Kandagatla <[email protected]> Reviwed-by: Mark Brown <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2df7296 commit 3648e78

File tree

7 files changed

+263
-0
lines changed

7 files changed

+263
-0
lines changed

drivers/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,6 @@ source "drivers/opp/Kconfig"
213213

214214
source "drivers/siox/Kconfig"
215215

216+
source "drivers/slimbus/Kconfig"
217+
216218
endmenu

drivers/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ obj-$(CONFIG_MTD) += mtd/
8787
obj-$(CONFIG_SPI) += spi/
8888
obj-$(CONFIG_SPMI) += spmi/
8989
obj-$(CONFIG_HSI) += hsi/
90+
obj-$(CONFIG_SLIMBUS) += slimbus/
9091
obj-y += net/
9192
obj-$(CONFIG_ATM) += atm/
9293
obj-$(CONFIG_FUSION) += message/

drivers/slimbus/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
#
3+
# SLIMbus driver configuration
4+
#
5+
menuconfig SLIMBUS
6+
tristate "SLIMbus support"
7+
help
8+
SLIMbus is standard interface between System-on-Chip and audio codec,
9+
and other peripheral components in typical embedded systems.
10+
11+
If unsure, choose N.
12+
13+
if SLIMBUS
14+
15+
# SLIMbus controllers
16+
17+
endif

drivers/slimbus/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
#
3+
# Makefile for kernel SLIMbus framework.
4+
#
5+
obj-$(CONFIG_SLIMBUS) += slimbus.o
6+
slimbus-y := core.o

drivers/slimbus/core.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2011-2017, The Linux Foundation
4+
*/
5+
6+
#include <linux/kernel.h>
7+
#include <linux/errno.h>
8+
#include <linux/slab.h>
9+
#include <linux/init.h>
10+
#include <linux/slimbus.h>
11+
12+
static const struct slim_device_id *slim_match(const struct slim_device_id *id,
13+
const struct slim_device *sbdev)
14+
{
15+
while (id->manf_id != 0 || id->prod_code != 0) {
16+
if (id->manf_id == sbdev->e_addr.manf_id &&
17+
id->prod_code == sbdev->e_addr.prod_code)
18+
return id;
19+
id++;
20+
}
21+
return NULL;
22+
}
23+
24+
static int slim_device_match(struct device *dev, struct device_driver *drv)
25+
{
26+
struct slim_device *sbdev = to_slim_device(dev);
27+
struct slim_driver *sbdrv = to_slim_driver(drv);
28+
29+
return !!slim_match(sbdrv->id_table, sbdev);
30+
}
31+
32+
static int slim_device_probe(struct device *dev)
33+
{
34+
struct slim_device *sbdev = to_slim_device(dev);
35+
struct slim_driver *sbdrv = to_slim_driver(dev->driver);
36+
37+
return sbdrv->probe(sbdev);
38+
}
39+
40+
static int slim_device_remove(struct device *dev)
41+
{
42+
struct slim_device *sbdev = to_slim_device(dev);
43+
struct slim_driver *sbdrv;
44+
45+
if (dev->driver) {
46+
sbdrv = to_slim_driver(dev->driver);
47+
if (sbdrv->remove)
48+
sbdrv->remove(sbdev);
49+
}
50+
51+
return 0;
52+
}
53+
54+
struct bus_type slimbus_bus = {
55+
.name = "slimbus",
56+
.match = slim_device_match,
57+
.probe = slim_device_probe,
58+
.remove = slim_device_remove,
59+
};
60+
EXPORT_SYMBOL_GPL(slimbus_bus);
61+
62+
/*
63+
* __slim_driver_register() - Client driver registration with SLIMbus
64+
*
65+
* @drv:Client driver to be associated with client-device.
66+
* @owner: owning module/driver
67+
*
68+
* This API will register the client driver with the SLIMbus
69+
* It is called from the driver's module-init function.
70+
*/
71+
int __slim_driver_register(struct slim_driver *drv, struct module *owner)
72+
{
73+
/* ID table and probe are mandatory */
74+
if (!drv->id_table || !drv->probe)
75+
return -EINVAL;
76+
77+
drv->driver.bus = &slimbus_bus;
78+
drv->driver.owner = owner;
79+
80+
return driver_register(&drv->driver);
81+
}
82+
EXPORT_SYMBOL_GPL(__slim_driver_register);
83+
84+
/*
85+
* slim_driver_unregister() - Undo effect of slim_driver_register
86+
*
87+
* @drv: Client driver to be unregistered
88+
*/
89+
void slim_driver_unregister(struct slim_driver *drv)
90+
{
91+
driver_unregister(&drv->driver);
92+
}
93+
EXPORT_SYMBOL_GPL(slim_driver_unregister);
94+
95+
static void __exit slimbus_exit(void)
96+
{
97+
bus_unregister(&slimbus_bus);
98+
}
99+
module_exit(slimbus_exit);
100+
101+
static int __init slimbus_init(void)
102+
{
103+
return bus_register(&slimbus_bus);
104+
}
105+
postcore_initcall(slimbus_init);
106+
107+
MODULE_LICENSE("GPL v2");
108+
MODULE_DESCRIPTION("SLIMbus core");

include/linux/mod_devicetable.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,19 @@ struct spi_device_id {
452452
kernel_ulong_t driver_data; /* Data private to the driver */
453453
};
454454

455+
/* SLIMbus */
456+
457+
#define SLIMBUS_NAME_SIZE 32
458+
#define SLIMBUS_MODULE_PREFIX "slim:"
459+
460+
struct slim_device_id {
461+
__u16 manf_id, prod_code;
462+
__u16 dev_index, instance;
463+
464+
/* Data private to the driver */
465+
kernel_ulong_t driver_data;
466+
};
467+
455468
#define SPMI_NAME_SIZE 32
456469
#define SPMI_MODULE_PREFIX "spmi:"
457470

include/linux/slimbus.h

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2011-2017, The Linux Foundation
4+
*/
5+
6+
#ifndef _LINUX_SLIMBUS_H
7+
#define _LINUX_SLIMBUS_H
8+
#include <linux/device.h>
9+
#include <linux/module.h>
10+
#include <linux/mod_devicetable.h>
11+
12+
extern struct bus_type slimbus_bus;
13+
14+
/**
15+
* struct slim_eaddr - Enumeration address for a SLIMbus device
16+
* @manf_id: Manufacturer Id for the device
17+
* @prod_code: Product code
18+
* @dev_index: Device index
19+
* @instance: Instance value
20+
*/
21+
struct slim_eaddr {
22+
u16 manf_id;
23+
u16 prod_code;
24+
u8 dev_index;
25+
u8 instance;
26+
} __packed;
27+
28+
/**
29+
* enum slim_device_status - slim device status
30+
* @SLIM_DEVICE_STATUS_DOWN: Slim device is absent or not reported yet.
31+
* @SLIM_DEVICE_STATUS_UP: Slim device is announced on the bus.
32+
* @SLIM_DEVICE_STATUS_RESERVED: Reserved for future use.
33+
*/
34+
enum slim_device_status {
35+
SLIM_DEVICE_STATUS_DOWN = 0,
36+
SLIM_DEVICE_STATUS_UP,
37+
SLIM_DEVICE_STATUS_RESERVED,
38+
};
39+
40+
/**
41+
* struct slim_device - Slim device handle.
42+
* @dev: Driver model representation of the device.
43+
* @e_addr: Enumeration address of this device.
44+
* @status: slim device status
45+
* @laddr: 1-byte Logical address of this device.
46+
* @is_laddr_valid: indicates if the laddr is valid or not
47+
*
48+
* This is the client/device handle returned when a SLIMbus
49+
* device is registered with a controller.
50+
* Pointer to this structure is used by client-driver as a handle.
51+
*/
52+
struct slim_device {
53+
struct device dev;
54+
struct slim_eaddr e_addr;
55+
enum slim_device_status status;
56+
u8 laddr;
57+
bool is_laddr_valid;
58+
};
59+
60+
#define to_slim_device(d) container_of(d, struct slim_device, dev)
61+
62+
/**
63+
* struct slim_driver - SLIMbus 'generic device' (slave) device driver
64+
* (similar to 'spi_device' on SPI)
65+
* @probe: Binds this driver to a SLIMbus device.
66+
* @remove: Unbinds this driver from the SLIMbus device.
67+
* @shutdown: Standard shutdown callback used during powerdown/halt.
68+
* @device_status: This callback is called when
69+
* - The device reports present and gets a laddr assigned
70+
* - The device reports absent, or the bus goes down.
71+
* @driver: SLIMbus device drivers should initialize name and owner field of
72+
* this structure
73+
* @id_table: List of SLIMbus devices supported by this driver
74+
*/
75+
76+
struct slim_driver {
77+
int (*probe)(struct slim_device *sl);
78+
void (*remove)(struct slim_device *sl);
79+
void (*shutdown)(struct slim_device *sl);
80+
int (*device_status)(struct slim_device *sl,
81+
enum slim_device_status s);
82+
struct device_driver driver;
83+
const struct slim_device_id *id_table;
84+
};
85+
#define to_slim_driver(d) container_of(d, struct slim_driver, driver)
86+
87+
/*
88+
* use a macro to avoid include chaining to get THIS_MODULE
89+
*/
90+
#define slim_driver_register(drv) \
91+
__slim_driver_register(drv, THIS_MODULE)
92+
int __slim_driver_register(struct slim_driver *drv, struct module *owner);
93+
void slim_driver_unregister(struct slim_driver *drv);
94+
95+
/**
96+
* module_slim_driver() - Helper macro for registering a SLIMbus driver
97+
* @__slim_driver: slimbus_driver struct
98+
*
99+
* Helper macro for SLIMbus drivers which do not do anything special in module
100+
* init/exit. This eliminates a lot of boilerplate. Each module may only
101+
* use this macro once, and calling it replaces module_init() and module_exit()
102+
*/
103+
#define module_slim_driver(__slim_driver) \
104+
module_driver(__slim_driver, slim_driver_register, \
105+
slim_driver_unregister)
106+
107+
static inline void *slim_get_devicedata(const struct slim_device *dev)
108+
{
109+
return dev_get_drvdata(&dev->dev);
110+
}
111+
112+
static inline void slim_set_devicedata(struct slim_device *dev, void *data)
113+
{
114+
dev_set_drvdata(&dev->dev, data);
115+
}
116+
#endif /* _LINUX_SLIMBUS_H */

0 commit comments

Comments
 (0)