mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
net: wan: Add framer framework support
A framer is a component in charge of an E1/T1 line interface. Connected usually to a TDM bus, it converts TDM frames to/from E1/T1 frames. It also provides information related to the E1/T1 line. The framer framework provides a set of APIs for the framer drivers (framer provider) to create/destroy a framer and APIs for the framer users (framer consumer) to obtain a reference to the framer, and use the framer. This basic implementation provides a framer abstraction for: - power on/off the framer - get the framer status (line state) - be notified on framer status changes - get/set the framer configuration Signed-off-by: Herve Codina <herve.codina@bootlin.com> Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu> Acked-by: Jakub Kicinski <kuba@kernel.org> Link: https://lore.kernel.org/r/20231128132534.258459-2-herve.codina@bootlin.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
committed by
Linus Walleij
parent
b85ea95d08
commit
82c944d05b
@@ -95,6 +95,8 @@ config HDLC_X25
|
||||
comment "X.25/LAPB support is disabled"
|
||||
depends on HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y
|
||||
|
||||
source "drivers/net/wan/framer/Kconfig"
|
||||
|
||||
config PCI200SYN
|
||||
tristate "Goramo PCI200SYN support"
|
||||
depends on HDLC && PCI
|
||||
|
||||
@@ -14,6 +14,8 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o
|
||||
obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
|
||||
obj-$(CONFIG_HDLC_X25) += hdlc_x25.o
|
||||
|
||||
obj-y += framer/
|
||||
|
||||
obj-$(CONFIG_FARSYNC) += farsync.o
|
||||
|
||||
obj-$(CONFIG_LAPBETHER) += lapbether.o
|
||||
|
||||
25
drivers/net/wan/framer/Kconfig
Normal file
25
drivers/net/wan/framer/Kconfig
Normal file
@@ -0,0 +1,25 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# FRAMER
|
||||
#
|
||||
|
||||
menuconfig FRAMER
|
||||
tristate "Framer Subsystem"
|
||||
help
|
||||
A framer is a component in charge of an E1/T1 line interface.
|
||||
Connected usually to a TDM bus, it converts TDM frames to/from E1/T1
|
||||
frames. It also provides information related to the E1/T1 line.
|
||||
Used with HDLC, the network can be reached through the E1/T1 line.
|
||||
|
||||
This framework is designed to provide a generic interface for framer
|
||||
devices present in the kernel. This layer will have the generic
|
||||
API by which framer drivers can create framer using the framer
|
||||
framework and framer users can obtain reference to the framer.
|
||||
All the users of this framework should select this config.
|
||||
|
||||
if FRAMER
|
||||
|
||||
config GENERIC_FRAMER
|
||||
bool
|
||||
|
||||
endif # FRAMER
|
||||
6
drivers/net/wan/framer/Makefile
Normal file
6
drivers/net/wan/framer/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for the framer drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_GENERIC_FRAMER) += framer-core.o
|
||||
882
drivers/net/wan/framer/framer-core.c
Normal file
882
drivers/net/wan/framer/framer-core.c
Normal file
File diff suppressed because it is too large
Load Diff
194
include/linux/framer/framer-provider.h
Normal file
194
include/linux/framer/framer-provider.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Generic framer profider header file
|
||||
*
|
||||
* Copyright 2023 CS GROUP France
|
||||
*
|
||||
* Author: Herve Codina <herve.codina@bootlin.com>
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_PROVIDER_FRAMER_H
|
||||
#define __DRIVERS_PROVIDER_FRAMER_H
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/framer/framer.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define FRAMER_FLAG_POLL_STATUS BIT(0)
|
||||
|
||||
/**
|
||||
* struct framer_ops - set of function pointers for performing framer operations
|
||||
* @init: operation to be performed for initializing the framer
|
||||
* @exit: operation to be performed while exiting
|
||||
* @power_on: powering on the framer
|
||||
* @power_off: powering off the framer
|
||||
* @flags: OR-ed flags (FRAMER_FLAG_*) to ask for core functionality
|
||||
* - @FRAMER_FLAG_POLL_STATUS:
|
||||
* Ask the core to perform a polling to get the framer status and
|
||||
* notify consumers on change.
|
||||
* The framer should call @framer_notify_status_change() when it
|
||||
* detects a status change. This is usually done using interrupts.
|
||||
* If the framer cannot detect this change, it can ask the core for
|
||||
* a status polling. The core will call @get_status() periodically
|
||||
* and, on change detected, it will notify the consumer.
|
||||
* the @get_status()
|
||||
* @owner: the module owner containing the ops
|
||||
*/
|
||||
struct framer_ops {
|
||||
int (*init)(struct framer *framer);
|
||||
void (*exit)(struct framer *framer);
|
||||
int (*power_on)(struct framer *framer);
|
||||
int (*power_off)(struct framer *framer);
|
||||
|
||||
/**
|
||||
* @get_status:
|
||||
*
|
||||
* Optional.
|
||||
*
|
||||
* Used to get the framer status. framer_init() must have
|
||||
* been called on the framer.
|
||||
*
|
||||
* Returns: 0 if successful, an negative error code otherwise
|
||||
*/
|
||||
int (*get_status)(struct framer *framer, struct framer_status *status);
|
||||
|
||||
/**
|
||||
* @set_config:
|
||||
*
|
||||
* Optional.
|
||||
*
|
||||
* Used to set the framer configuration. framer_init() must have
|
||||
* been called on the framer.
|
||||
*
|
||||
* Returns: 0 if successful, an negative error code otherwise
|
||||
*/
|
||||
int (*set_config)(struct framer *framer, const struct framer_config *config);
|
||||
|
||||
/**
|
||||
* @get_config:
|
||||
*
|
||||
* Optional.
|
||||
*
|
||||
* Used to get the framer configuration. framer_init() must have
|
||||
* been called on the framer.
|
||||
*
|
||||
* Returns: 0 if successful, an negative error code otherwise
|
||||
*/
|
||||
int (*get_config)(struct framer *framer, struct framer_config *config);
|
||||
|
||||
u32 flags;
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct framer_provider - represents the framer provider
|
||||
* @dev: framer provider device
|
||||
* @children: can be used to override the default (dev->of_node) child node
|
||||
* @owner: the module owner having of_xlate
|
||||
* @list: to maintain a linked list of framer providers
|
||||
* @of_xlate: function pointer to obtain framer instance from framer pointer
|
||||
*/
|
||||
struct framer_provider {
|
||||
struct device *dev;
|
||||
struct module *owner;
|
||||
struct list_head list;
|
||||
struct framer * (*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args);
|
||||
};
|
||||
|
||||
static inline void framer_set_drvdata(struct framer *framer, void *data)
|
||||
{
|
||||
dev_set_drvdata(&framer->dev, data);
|
||||
}
|
||||
|
||||
static inline void *framer_get_drvdata(struct framer *framer)
|
||||
{
|
||||
return dev_get_drvdata(&framer->dev);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_GENERIC_FRAMER)
|
||||
|
||||
/* Create and destroy a framer */
|
||||
struct framer *framer_create(struct device *dev, struct device_node *node,
|
||||
const struct framer_ops *ops);
|
||||
void framer_destroy(struct framer *framer);
|
||||
|
||||
/* devm version */
|
||||
struct framer *devm_framer_create(struct device *dev, struct device_node *node,
|
||||
const struct framer_ops *ops);
|
||||
|
||||
struct framer *framer_provider_simple_of_xlate(struct device *dev,
|
||||
struct of_phandle_args *args);
|
||||
|
||||
struct framer_provider *
|
||||
__framer_provider_of_register(struct device *dev, struct module *owner,
|
||||
struct framer *(*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args));
|
||||
|
||||
void framer_provider_of_unregister(struct framer_provider *framer_provider);
|
||||
|
||||
struct framer_provider *
|
||||
__devm_framer_provider_of_register(struct device *dev, struct module *owner,
|
||||
struct framer *(*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args));
|
||||
|
||||
void framer_notify_status_change(struct framer *framer);
|
||||
|
||||
#else /* IS_ENABLED(CONFIG_GENERIC_FRAMER) */
|
||||
|
||||
static inline struct framer *framer_create(struct device *dev, struct device_node *node,
|
||||
const struct framer_ops *ops)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void framer_destroy(struct framer *framer)
|
||||
{
|
||||
}
|
||||
|
||||
/* devm version */
|
||||
static inline struct framer *devm_framer_create(struct device *dev, struct device_node *node,
|
||||
const struct framer_ops *ops)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct framer *framer_provider_simple_of_xlate(struct device *dev,
|
||||
struct of_phandle_args *args)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct framer_provider *
|
||||
__framer_provider_of_register(struct device *dev, struct module *owner,
|
||||
struct framer *(*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args))
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
void framer_provider_of_unregister(struct framer_provider *framer_provider)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct framer_provider *
|
||||
__devm_framer_provider_of_register(struct device *dev, struct module *owner,
|
||||
struct framer *(*of_xlate)(struct device *dev,
|
||||
struct of_phandle_args *args))
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
void framer_notify_status_change(struct framer *framer)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_GENERIC_FRAMER) */
|
||||
|
||||
#define framer_provider_of_register(dev, xlate) \
|
||||
__framer_provider_of_register((dev), THIS_MODULE, (xlate))
|
||||
|
||||
#define devm_framer_provider_of_register(dev, xlate) \
|
||||
__devm_framer_provider_of_register((dev), THIS_MODULE, (xlate))
|
||||
|
||||
#endif /* __DRIVERS_PROVIDER_FRAMER_H */
|
||||
205
include/linux/framer/framer.h
Normal file
205
include/linux/framer/framer.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Generic framer header file
|
||||
*
|
||||
* Copyright 2023 CS GROUP France
|
||||
*
|
||||
* Author: Herve Codina <herve.codina@bootlin.com>
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_FRAMER_H
|
||||
#define __DRIVERS_FRAMER_H
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/**
|
||||
* enum framer_iface - Framer interface
|
||||
* @FRAMER_IFACE_E1: E1 interface
|
||||
* @FRAMER_IFACE_T1: T1 interface
|
||||
*/
|
||||
enum framer_iface {
|
||||
FRAMER_IFACE_E1,
|
||||
FRAMER_IFACE_T1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum framer_clock_type - Framer clock type
|
||||
* @FRAMER_CLOCK_EXT: External clock
|
||||
* @FRAMER_CLOCK_INT: Internal clock
|
||||
*/
|
||||
enum framer_clock_type {
|
||||
FRAMER_CLOCK_EXT,
|
||||
FRAMER_CLOCK_INT,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct framer_config - Framer configuration
|
||||
* @iface: Framer line interface
|
||||
* @clock_type: Framer clock type
|
||||
* @line_clock_rate: Framer line clock rate
|
||||
*/
|
||||
struct framer_config {
|
||||
enum framer_iface iface;
|
||||
enum framer_clock_type clock_type;
|
||||
unsigned long line_clock_rate;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct framer_status - Framer status
|
||||
* @link_is_on: Framer link state. true, the link is on, false, the link is off.
|
||||
*/
|
||||
struct framer_status {
|
||||
bool link_is_on;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum framer_event - Event available for notification
|
||||
* @FRAMER_EVENT_STATUS: Event notified on framer_status changes
|
||||
*/
|
||||
enum framer_event {
|
||||
FRAMER_EVENT_STATUS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct framer - represents the framer device
|
||||
* @dev: framer device
|
||||
* @id: id of the framer device
|
||||
* @ops: function pointers for performing framer operations
|
||||
* @mutex: mutex to protect framer_ops
|
||||
* @init_count: used to protect when the framer is used by multiple consumers
|
||||
* @power_count: used to protect when the framer is used by multiple consumers
|
||||
* @pwr: power regulator associated with the framer
|
||||
* @notify_status_work: work structure used for status notifications
|
||||
* @notifier_list: notifier list used for notifications
|
||||
* @polling_work: delayed work structure used for the polling task
|
||||
* @prev_status: previous read status used by the polling task to detect changes
|
||||
*/
|
||||
struct framer {
|
||||
struct device dev;
|
||||
int id;
|
||||
const struct framer_ops *ops;
|
||||
struct mutex mutex; /* Protect framer */
|
||||
int init_count;
|
||||
int power_count;
|
||||
struct regulator *pwr;
|
||||
struct work_struct notify_status_work;
|
||||
struct blocking_notifier_head notifier_list;
|
||||
struct delayed_work polling_work;
|
||||
struct framer_status prev_status;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_GENERIC_FRAMER)
|
||||
int framer_pm_runtime_get(struct framer *framer);
|
||||
int framer_pm_runtime_get_sync(struct framer *framer);
|
||||
int framer_pm_runtime_put(struct framer *framer);
|
||||
int framer_pm_runtime_put_sync(struct framer *framer);
|
||||
int framer_init(struct framer *framer);
|
||||
int framer_exit(struct framer *framer);
|
||||
int framer_power_on(struct framer *framer);
|
||||
int framer_power_off(struct framer *framer);
|
||||
int framer_get_status(struct framer *framer, struct framer_status *status);
|
||||
int framer_get_config(struct framer *framer, struct framer_config *config);
|
||||
int framer_set_config(struct framer *framer, const struct framer_config *config);
|
||||
int framer_notifier_register(struct framer *framer, struct notifier_block *nb);
|
||||
int framer_notifier_unregister(struct framer *framer, struct notifier_block *nb);
|
||||
|
||||
struct framer *framer_get(struct device *dev, const char *con_id);
|
||||
void framer_put(struct device *dev, struct framer *framer);
|
||||
|
||||
struct framer *devm_framer_get(struct device *dev, const char *con_id);
|
||||
struct framer *devm_framer_optional_get(struct device *dev, const char *con_id);
|
||||
#else
|
||||
static inline int framer_pm_runtime_get(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_pm_runtime_get_sync(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_pm_runtime_put(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_pm_runtime_put_sync(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_init(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_exit(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_power_on(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_power_off(struct framer *framer)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_get_status(struct framer *framer, struct framer_status *status)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_get_config(struct framer *framer, struct framer_config *config)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_set_config(struct framer *framer, const struct framer_config *config)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_notifier_register(struct framer *framer,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int framer_notifier_unregister(struct framer *framer,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
struct framer *framer_get(struct device *dev, const char *con_id)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
void framer_put(struct device *dev, struct framer *framer)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct framer *devm_framer_get(struct device *dev, const char *con_id)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct framer *devm_framer_optional_get(struct device *dev, const char *con_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVERS_FRAMER_H */
|
||||
Reference in New Issue
Block a user