/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Generic framer profider header file
*
* Copyright 2023 CS GROUP France
*
* Author: Herve Codina <[email protected]>
*/
#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
* @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,
const 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,
const 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,
const 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,
const 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,
const 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,
const 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,
const 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 */