Commit a3b02a9c authored by Peter Rosin's avatar Peter Rosin Committed by Greg Kroah-Hartman

mux: minimal mux subsystem

Add a new minimalistic subsystem that handles multiplexer controllers.
When multiplexers are used in various places in the kernel, and the
same multiplexer controller can be used for several independent things,
there should be one place to implement support for said multiplexer
controller.

A single multiplexer controller can also be used to control several
parallel multiplexers, that are in turn used by different subsystems
in the kernel, leading to a need to coordinate multiplexer accesses.
The multiplexer subsystem handles this coordination.

Thanks go out to Lars-Peter Clausen, Jonathan Cameron, Rob Herring,
Wolfram Sang, Paul Gortmaker, Dan Carpenter, Colin Ian King, Greg
Kroah-Hartman and last but certainly not least to Philipp Zabel for
helpful comments, reviews, patches and general encouragement!
Reviewed-by: default avatarJonathan Cameron <jic23@kernel.org>
Signed-off-by: default avatarPeter Rosin <peda@axentia.se>
Reviewed-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Tested-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 256ac037
What: /sys/class/mux/
Date: April 2017
KernelVersion: 4.13
Contact: Peter Rosin <peda@axentia.se>
Description:
The mux/ class sub-directory belongs to the Generic MUX
Framework and provides a sysfs interface for using MUX
controllers.
What: /sys/class/mux/muxchipN/
Date: April 2017
KernelVersion: 4.13
Contact: Peter Rosin <peda@axentia.se>
Description:
A /sys/class/mux/muxchipN directory is created for each
probed MUX chip where N is a simple enumeration.
......@@ -337,6 +337,11 @@ MEM
MFD
devm_mfd_add_devices()
MUX
devm_mux_chip_alloc()
devm_mux_chip_register()
devm_mux_control_get()
PER-CPU MEM
devm_alloc_percpu()
devm_free_percpu()
......
......@@ -8719,8 +8719,11 @@ F: include/linux/spi/mmc_spi.h
MULTIPLEXER SUBSYSTEM
M: Peter Rosin <peda@axentia.se>
S: Maintained
F: Documentation/ABI/testing/mux/sysfs-class-mux*
F: Documentation/devicetree/bindings/mux/
F: include/linux/dt-bindings/mux/
F: include/linux/mux/
F: drivers/mux/
MULTISOUND SOUND DRIVER
M: Andrew Veliath <andrewtv@usa.net>
......
......@@ -206,4 +206,6 @@ source "drivers/fsi/Kconfig"
source "drivers/tee/Kconfig"
source "drivers/mux/Kconfig"
endmenu
......@@ -181,3 +181,4 @@ obj-$(CONFIG_NVMEM) += nvmem/
obj-$(CONFIG_FPGA) += fpga/
obj-$(CONFIG_FSI) += fsi/
obj-$(CONFIG_TEE) += tee/
obj-$(CONFIG_MULTIPLEXER) += mux/
#
# Multiplexer devices
#
menuconfig MULTIPLEXER
tristate "Multiplexer subsystem"
help
Multiplexer controller subsystem. Multiplexers are used in a
variety of settings, and this subsystem abstracts their use
so that the rest of the kernel sees a common interface. When
multiple parallel multiplexers are controlled by one single
multiplexer controller, this subsystem also coordinates the
multiplexer accesses.
To compile the subsystem as a module, choose M here: the module will
be called mux-core.
#
# Makefile for multiplexer devices.
#
obj-$(CONFIG_MULTIPLEXER) += mux-core.o
This diff is collapsed.
/*
* mux/consumer.h - definitions for the multiplexer consumer interface
*
* Copyright (C) 2017 Axentia Technologies AB
*
* Author: Peter Rosin <peda@axentia.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _LINUX_MUX_CONSUMER_H
#define _LINUX_MUX_CONSUMER_H
struct device;
struct mux_control;
unsigned int mux_control_states(struct mux_control *mux);
int __must_check mux_control_select(struct mux_control *mux,
unsigned int state);
int __must_check mux_control_try_select(struct mux_control *mux,
unsigned int state);
int mux_control_deselect(struct mux_control *mux);
struct mux_control *mux_control_get(struct device *dev, const char *mux_name);
void mux_control_put(struct mux_control *mux);
struct mux_control *devm_mux_control_get(struct device *dev,
const char *mux_name);
#endif /* _LINUX_MUX_CONSUMER_H */
/*
* mux/driver.h - definitions for the multiplexer driver interface
*
* Copyright (C) 2017 Axentia Technologies AB
*
* Author: Peter Rosin <peda@axentia.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _LINUX_MUX_DRIVER_H
#define _LINUX_MUX_DRIVER_H
#include <dt-bindings/mux/mux.h>
#include <linux/device.h>
#include <linux/semaphore.h>
struct mux_chip;
struct mux_control;
/**
* struct mux_control_ops - Mux controller operations for a mux chip.
* @set: Set the state of the given mux controller.
*/
struct mux_control_ops {
int (*set)(struct mux_control *mux, int state);
};
/**
* struct mux_control - Represents a mux controller.
* @lock: Protects the mux controller state.
* @chip: The mux chip that is handling this mux controller.
* @cached_state: The current mux controller state, or -1 if none.
* @states: The number of mux controller states.
* @idle_state: The mux controller state to use when inactive, or one
* of MUX_IDLE_AS_IS and MUX_IDLE_DISCONNECT.
*
* Mux drivers may only change @states and @idle_state, and may only do so
* between allocation and registration of the mux controller. Specifically,
* @cached_state is internal to the mux core and should never be written by
* mux drivers.
*/
struct mux_control {
struct semaphore lock; /* protects the state of the mux */
struct mux_chip *chip;
int cached_state;
unsigned int states;
int idle_state;
};
/**
* struct mux_chip - Represents a chip holding mux controllers.
* @controllers: Number of mux controllers handled by the chip.
* @mux: Array of mux controllers that are handled.
* @dev: Device structure.
* @id: Used to identify the device internally.
* @ops: Mux controller operations.
*/
struct mux_chip {
unsigned int controllers;
struct mux_control *mux;
struct device dev;
int id;
const struct mux_control_ops *ops;
};
#define to_mux_chip(x) container_of((x), struct mux_chip, dev)
/**
* mux_chip_priv() - Get the extra memory reserved by mux_chip_alloc().
* @mux_chip: The mux-chip to get the private memory from.
*
* Return: Pointer to the private memory reserved by the allocator.
*/
static inline void *mux_chip_priv(struct mux_chip *mux_chip)
{
return &mux_chip->mux[mux_chip->controllers];
}
struct mux_chip *mux_chip_alloc(struct device *dev,
unsigned int controllers, size_t sizeof_priv);
int mux_chip_register(struct mux_chip *mux_chip);
void mux_chip_unregister(struct mux_chip *mux_chip);
void mux_chip_free(struct mux_chip *mux_chip);
struct mux_chip *devm_mux_chip_alloc(struct device *dev,
unsigned int controllers,
size_t sizeof_priv);
int devm_mux_chip_register(struct device *dev, struct mux_chip *mux_chip);
/**
* mux_control_get_index() - Get the index of the given mux controller
* @mux: The mux-control to get the index for.
*
* Return: The index of the mux controller within the mux chip the mux
* controller is a part of.
*/
static inline unsigned int mux_control_get_index(struct mux_control *mux)
{
return mux - mux->chip->mux;
}
#endif /* _LINUX_MUX_DRIVER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment