restore lost packages from 0.2.3 + fix overwritten 0.2.4 files
- Restore 29 recipe symlinks (libdrm, qtbase, dbus, sddm, pipewire, etc.) - Restore 33 patches (KDE, libdrm, mesa, pipewire, sddm, wireplumber) - Restore 20+ local/scripts (audit, lint, test, build helpers) - Restore src/cook/scheduler.rs, status.rs, gnu-config/ - Restore scripts/patch-inclusion-gate.sh, run_mini1.sh, validate-collision-log.sh - Recover TLC source from HEAD (was overwritten by 0.2.3 checkout) - Recover 11 local/docs plans from HEAD (were overwritten) - Recover qt6-wayland-smoke symlink from HEAD - Fix MOTD: remove garbled ASCII art, use clean text - Update version: 0.2.0 -> 0.2.4 in os-release, motd, config - Reduce filesystem_size: 1536 -> 512 MiB - Add ABSOLUTE RULE to AGENTS.md: never delete/ignore packages - Reduce pcid scheme log verbosity: info -> debug
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
#ifndef __GPIO_ASPEED_H
|
||||
#define __GPIO_ASPEED_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct gpio_desc;
|
||||
|
||||
struct aspeed_gpio_copro_ops {
|
||||
int (*request_access)(void *data);
|
||||
int (*release_access)(void *data);
|
||||
};
|
||||
|
||||
int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
|
||||
u16 *vreg_offset, u16 *dreg_offset, u8 *bit);
|
||||
int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc);
|
||||
int aspeed_gpio_copro_set_ops(const struct aspeed_gpio_copro_ops *ops, void *data);
|
||||
|
||||
|
||||
#endif /* __GPIO_ASPEED_H */
|
||||
@@ -0,0 +1,738 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LINUX_GPIO_CONSUMER_H
|
||||
#define __LINUX_GPIO_CONSUMER_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
struct acpi_device;
|
||||
struct device;
|
||||
struct fwnode_handle;
|
||||
|
||||
struct gpio_array;
|
||||
struct gpio_desc;
|
||||
|
||||
/**
|
||||
* struct gpio_descs - Struct containing an array of descriptors that can be
|
||||
* obtained using gpiod_get_array()
|
||||
*
|
||||
* @info: Pointer to the opaque gpio_array structure
|
||||
* @ndescs: Number of held descriptors
|
||||
* @desc: Array of pointers to GPIO descriptors
|
||||
*/
|
||||
struct gpio_descs {
|
||||
struct gpio_array *info;
|
||||
unsigned int ndescs;
|
||||
struct gpio_desc *desc[];
|
||||
};
|
||||
|
||||
#define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
|
||||
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
|
||||
#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
|
||||
#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3)
|
||||
/* GPIOD_FLAGS_BIT_NONEXCLUSIVE is DEPRECATED, don't use in new code. */
|
||||
#define GPIOD_FLAGS_BIT_NONEXCLUSIVE BIT(4)
|
||||
|
||||
/**
|
||||
* enum gpiod_flags - Optional flags that can be passed to one of gpiod_* to
|
||||
* configure direction and output value. These values
|
||||
* cannot be OR'd.
|
||||
*
|
||||
* @GPIOD_ASIS: Don't change anything
|
||||
* @GPIOD_IN: Set lines to input mode
|
||||
* @GPIOD_OUT_LOW: Set lines to output and drive them low
|
||||
* @GPIOD_OUT_HIGH: Set lines to output and drive them high
|
||||
* @GPIOD_OUT_LOW_OPEN_DRAIN: Set lines to open-drain output and drive them low
|
||||
* @GPIOD_OUT_HIGH_OPEN_DRAIN: Set lines to open-drain output and drive them high
|
||||
*/
|
||||
enum gpiod_flags {
|
||||
GPIOD_ASIS = 0,
|
||||
GPIOD_IN = GPIOD_FLAGS_BIT_DIR_SET,
|
||||
GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,
|
||||
GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
|
||||
GPIOD_FLAGS_BIT_DIR_VAL,
|
||||
GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_OPEN_DRAIN,
|
||||
GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_OPEN_DRAIN,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
|
||||
/* Return the number of GPIOs associated with a device / function */
|
||||
int gpiod_count(struct device *dev, const char *con_id);
|
||||
|
||||
/* Acquire and dispose GPIOs */
|
||||
struct gpio_desc *__must_check gpiod_get(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int index,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
void gpiod_put(struct gpio_desc *desc);
|
||||
void gpiod_put_array(struct gpio_descs *descs);
|
||||
|
||||
struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_desc *__must_check
|
||||
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
|
||||
unsigned int index, enum gpiod_flags flags);
|
||||
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
struct gpio_descs *__must_check
|
||||
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
|
||||
void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc);
|
||||
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
|
||||
|
||||
int gpiod_get_direction(struct gpio_desc *desc);
|
||||
int gpiod_direction_input(struct gpio_desc *desc);
|
||||
int gpiod_direction_output(struct gpio_desc *desc, int value);
|
||||
int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
|
||||
|
||||
/* Value get/set from non-sleeping context */
|
||||
int gpiod_get_value(const struct gpio_desc *desc);
|
||||
int gpiod_get_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
int gpiod_set_value(struct gpio_desc *desc, int value);
|
||||
int gpiod_set_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
int gpiod_get_raw_value(const struct gpio_desc *desc);
|
||||
int gpiod_get_raw_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
int gpiod_set_raw_value(struct gpio_desc *desc, int value);
|
||||
int gpiod_set_raw_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
|
||||
/* Value get/set from sleeping context */
|
||||
int gpiod_get_value_cansleep(const struct gpio_desc *desc);
|
||||
int gpiod_get_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
int gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
|
||||
int gpiod_set_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc);
|
||||
int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
int gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value);
|
||||
int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
|
||||
int gpiod_set_config(struct gpio_desc *desc, unsigned long config);
|
||||
int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce);
|
||||
void gpiod_toggle_active_low(struct gpio_desc *desc);
|
||||
|
||||
int gpiod_is_active_low(const struct gpio_desc *desc);
|
||||
int gpiod_cansleep(const struct gpio_desc *desc);
|
||||
|
||||
int gpiod_to_irq(const struct gpio_desc *desc);
|
||||
int gpiod_set_consumer_name(struct gpio_desc *desc, const char *name);
|
||||
|
||||
bool gpiod_is_shared(const struct gpio_desc *desc);
|
||||
|
||||
/* Convert between the old gpio_ and new gpiod_ interfaces */
|
||||
struct gpio_desc *gpio_to_desc(unsigned gpio);
|
||||
int desc_to_gpio(const struct gpio_desc *desc);
|
||||
|
||||
int gpiod_hwgpio(const struct gpio_desc *desc);
|
||||
|
||||
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label);
|
||||
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
|
||||
struct fwnode_handle *child,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label);
|
||||
|
||||
bool gpiod_is_equal(const struct gpio_desc *desc,
|
||||
const struct gpio_desc *other);
|
||||
|
||||
#else /* CONFIG_GPIOLIB */
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
static inline int gpiod_count(struct device *dev, const char *con_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
static inline struct gpio_desc *__must_check
|
||||
gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
gpiod_get_optional(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
gpiod_get_index_optional(struct device *dev, const char *con_id,
|
||||
unsigned int index, enum gpiod_flags flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct gpio_descs *__must_check
|
||||
gpiod_get_array(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_descs *__must_check
|
||||
gpiod_get_array_optional(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void gpiod_put(struct gpio_desc *desc)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
}
|
||||
|
||||
static inline void devm_gpiod_unhinge(struct device *dev,
|
||||
struct gpio_desc *desc)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
}
|
||||
|
||||
static inline void gpiod_put_array(struct gpio_descs *descs)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(descs);
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
devm_gpiod_get(struct device *dev,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
static inline
|
||||
struct gpio_desc *__must_check
|
||||
devm_gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
devm_gpiod_get_optional(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
|
||||
unsigned int index, enum gpiod_flags flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct gpio_descs *__must_check
|
||||
devm_gpiod_get_array(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_descs *__must_check
|
||||
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
}
|
||||
|
||||
static inline void devm_gpiod_put_array(struct device *dev,
|
||||
struct gpio_descs *descs)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(descs);
|
||||
}
|
||||
|
||||
|
||||
static inline int gpiod_get_direction(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int gpiod_direction_input(struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int gpiod_get_value(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_get_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_value(struct gpio_desc *desc, int value)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_get_raw_value(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_get_raw_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_raw_value(struct gpio_desc *desc, int value)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_raw_array_value(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_get_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_raw_value_cansleep(struct gpio_desc *desc,
|
||||
int value)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc_array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpiod_set_config(struct gpio_desc *desc, unsigned long config)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void gpiod_toggle_active_low(struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
}
|
||||
|
||||
static inline int gpiod_is_active_low(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
static inline int gpiod_cansleep(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpiod_to_irq(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int gpiod_set_consumer_name(struct gpio_desc *desc,
|
||||
const char *name)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline bool gpiod_is_shared(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int desc_to_gpio(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(desc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
gpiod_is_equal(const struct gpio_desc *desc, const struct gpio_desc *other)
|
||||
{
|
||||
WARN_ON(desc || other);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_HTE)
|
||||
int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags);
|
||||
int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags);
|
||||
#else
|
||||
|
||||
#include <linux/bug.h>
|
||||
|
||||
static inline int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_GPIOLIB))
|
||||
WARN_ON(desc);
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_GPIOLIB))
|
||||
WARN_ON(desc);
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* CONFIG_GPIOLIB && CONFIG_HTE */
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return devm_fwnode_gpiod_get_index(dev, fwnode, con_id, 0,
|
||||
flags, label);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_fwnode_gpiod_get_optional - obtain an optional GPIO from firmware node
|
||||
* @dev: GPIO consumer
|
||||
* @fwnode: handle of the firmware node
|
||||
* @con_id: function within the GPIO consumer
|
||||
* @flags: GPIO initialization flags
|
||||
* @label: label to attach to the requested GPIO
|
||||
*
|
||||
* This function can be used for drivers that get their configuration
|
||||
* from opaque firmware.
|
||||
*
|
||||
* GPIO descriptors returned from this function are automatically disposed on
|
||||
* driver detach.
|
||||
*
|
||||
* Returns:
|
||||
* The GPIO descriptor corresponding to the optional function @con_id of device
|
||||
* dev, NULL if no GPIO has been assigned to the requested function, or
|
||||
* another IS_ERR() code if an error occurred while trying to acquire the GPIO.
|
||||
*/
|
||||
static inline
|
||||
struct gpio_desc *devm_fwnode_gpiod_get_optional(struct device *dev,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
|
||||
desc = devm_fwnode_gpiod_get_index(dev, fwnode, con_id, 0,
|
||||
flags, label);
|
||||
if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
|
||||
return NULL;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
struct acpi_gpio_params {
|
||||
unsigned int crs_entry_index;
|
||||
unsigned short line_index;
|
||||
bool active_low;
|
||||
};
|
||||
|
||||
struct acpi_gpio_mapping {
|
||||
const char *name;
|
||||
const struct acpi_gpio_params *data;
|
||||
unsigned int size;
|
||||
|
||||
/* Ignore IoRestriction field */
|
||||
#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0)
|
||||
/*
|
||||
* When ACPI GPIO mapping table is in use the index parameter inside it
|
||||
* refers to the GPIO resource in _CRS method. That index has no
|
||||
* distinction of actual type of the resource. When consumer wants to
|
||||
* get GpioIo type explicitly, this quirk may be used.
|
||||
*/
|
||||
#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1)
|
||||
/* Use given pin as an absolute GPIO number in the system */
|
||||
#define ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER BIT(2)
|
||||
|
||||
unsigned int quirks;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
|
||||
|
||||
int acpi_dev_add_driver_gpios(struct acpi_device *adev,
|
||||
const struct acpi_gpio_mapping *gpios);
|
||||
void acpi_dev_remove_driver_gpios(struct acpi_device *adev);
|
||||
|
||||
int devm_acpi_dev_add_driver_gpios(struct device *dev,
|
||||
const struct acpi_gpio_mapping *gpios);
|
||||
|
||||
#else /* CONFIG_GPIOLIB && CONFIG_ACPI */
|
||||
|
||||
static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
|
||||
const struct acpi_gpio_mapping *gpios)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {}
|
||||
|
||||
static inline int devm_acpi_dev_add_driver_gpios(struct device *dev,
|
||||
const struct acpi_gpio_mapping *gpios)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GPIOLIB && CONFIG_ACPI */
|
||||
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
|
||||
|
||||
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
|
||||
int gpiod_export_link(struct device *dev, const char *name,
|
||||
struct gpio_desc *desc);
|
||||
void gpiod_unexport(struct gpio_desc *desc);
|
||||
|
||||
#else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
|
||||
|
||||
static inline int gpiod_export(struct gpio_desc *desc,
|
||||
bool direction_may_change)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int gpiod_export_link(struct device *dev, const char *name,
|
||||
struct gpio_desc *desc)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void gpiod_unexport(struct gpio_desc *desc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
|
||||
|
||||
static inline int gpiod_multi_set_value_cansleep(struct gpio_descs *descs,
|
||||
unsigned long *value_bitmap)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(descs))
|
||||
return PTR_ERR_OR_ZERO(descs);
|
||||
|
||||
return gpiod_set_array_value_cansleep(descs->ndescs, descs->desc,
|
||||
descs->info, value_bitmap);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __LINUX_GPIO_DEFS_H
|
||||
#define __LINUX_GPIO_DEFS_H
|
||||
|
||||
#define GPIO_LINE_DIRECTION_IN 1
|
||||
#define GPIO_LINE_DIRECTION_OUT 0
|
||||
|
||||
#endif /* __LINUX_GPIO_DEFS_H */
|
||||
@@ -0,0 +1,911 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LINUX_GPIO_DRIVER_H
|
||||
#define __LINUX_GPIO_DRIVER_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqhandler.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/util_macros.h>
|
||||
|
||||
#ifdef CONFIG_GENERIC_MSI_IRQ
|
||||
#include <asm/msi.h>
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
struct device;
|
||||
struct irq_chip;
|
||||
struct irq_data;
|
||||
struct module;
|
||||
struct of_phandle_args;
|
||||
struct pinctrl_dev;
|
||||
struct seq_file;
|
||||
|
||||
struct gpio_chip;
|
||||
struct gpio_desc;
|
||||
struct gpio_device;
|
||||
|
||||
enum gpio_lookup_flags;
|
||||
enum gpiod_flags;
|
||||
|
||||
union gpio_irq_fwspec {
|
||||
struct irq_fwspec fwspec;
|
||||
#ifdef CONFIG_GENERIC_MSI_IRQ
|
||||
msi_alloc_info_t msiinfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* struct gpio_irq_chip - GPIO interrupt controller
|
||||
*/
|
||||
struct gpio_irq_chip {
|
||||
/**
|
||||
* @chip:
|
||||
*
|
||||
* GPIO IRQ chip implementation, provided by GPIO driver.
|
||||
*/
|
||||
struct irq_chip *chip;
|
||||
|
||||
/**
|
||||
* @domain:
|
||||
*
|
||||
* Interrupt translation domain; responsible for mapping between GPIO
|
||||
* hwirq number and Linux IRQ number.
|
||||
*/
|
||||
struct irq_domain *domain;
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
/**
|
||||
* @fwnode:
|
||||
*
|
||||
* Firmware node corresponding to this gpiochip/irqchip, necessary
|
||||
* for hierarchical irqdomain support.
|
||||
*/
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
/**
|
||||
* @parent_domain:
|
||||
*
|
||||
* If non-NULL, will be set as the parent of this GPIO interrupt
|
||||
* controller's IRQ domain to establish a hierarchical interrupt
|
||||
* domain. The presence of this will activate the hierarchical
|
||||
* interrupt support.
|
||||
*/
|
||||
struct irq_domain *parent_domain;
|
||||
|
||||
/**
|
||||
* @child_to_parent_hwirq:
|
||||
*
|
||||
* This callback translates a child hardware IRQ offset to a parent
|
||||
* hardware IRQ offset on a hierarchical interrupt chip. The child
|
||||
* hardware IRQs correspond to the GPIO index 0..ngpio-1 (see the
|
||||
* ngpio field of struct gpio_chip) and the corresponding parent
|
||||
* hardware IRQ and type (such as IRQ_TYPE_*) shall be returned by
|
||||
* the driver. The driver can calculate this from an offset or using
|
||||
* a lookup table or whatever method is best for this chip. Return
|
||||
* 0 on successful translation in the driver.
|
||||
*
|
||||
* If some ranges of hardware IRQs do not have a corresponding parent
|
||||
* HWIRQ, return -EINVAL, but also make sure to fill in @valid_mask and
|
||||
* @need_valid_mask to make these GPIO lines unavailable for
|
||||
* translation.
|
||||
*/
|
||||
int (*child_to_parent_hwirq)(struct gpio_chip *gc,
|
||||
unsigned int child_hwirq,
|
||||
unsigned int child_type,
|
||||
unsigned int *parent_hwirq,
|
||||
unsigned int *parent_type);
|
||||
|
||||
/**
|
||||
* @populate_parent_alloc_arg :
|
||||
*
|
||||
* This optional callback allocates and populates the specific struct
|
||||
* for the parent's IRQ domain. If this is not specified, then
|
||||
* &gpiochip_populate_parent_fwspec_twocell will be used. A four-cell
|
||||
* variant named &gpiochip_populate_parent_fwspec_fourcell is also
|
||||
* available.
|
||||
*/
|
||||
int (*populate_parent_alloc_arg)(struct gpio_chip *gc,
|
||||
union gpio_irq_fwspec *fwspec,
|
||||
unsigned int parent_hwirq,
|
||||
unsigned int parent_type);
|
||||
|
||||
/**
|
||||
* @child_offset_to_irq:
|
||||
*
|
||||
* This optional callback is used to translate the child's GPIO line
|
||||
* offset on the GPIO chip to an IRQ number for the GPIO to_irq()
|
||||
* callback. If this is not specified, then a default callback will be
|
||||
* provided that returns the line offset.
|
||||
*/
|
||||
unsigned int (*child_offset_to_irq)(struct gpio_chip *gc,
|
||||
unsigned int pin);
|
||||
|
||||
/**
|
||||
* @child_irq_domain_ops:
|
||||
*
|
||||
* The IRQ domain operations that will be used for this GPIO IRQ
|
||||
* chip. If no operations are provided, then default callbacks will
|
||||
* be populated to setup the IRQ hierarchy. Some drivers need to
|
||||
* supply their own translate function.
|
||||
*/
|
||||
struct irq_domain_ops child_irq_domain_ops;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @handler:
|
||||
*
|
||||
* The IRQ handler to use (often a predefined IRQ core function) for
|
||||
* GPIO IRQs, provided by GPIO driver.
|
||||
*/
|
||||
irq_flow_handler_t handler;
|
||||
|
||||
/**
|
||||
* @default_type:
|
||||
*
|
||||
* Default IRQ triggering type applied during GPIO driver
|
||||
* initialization, provided by GPIO driver.
|
||||
*/
|
||||
unsigned int default_type;
|
||||
|
||||
/**
|
||||
* @lock_key:
|
||||
*
|
||||
* Per GPIO IRQ chip lockdep class for IRQ lock.
|
||||
*/
|
||||
struct lock_class_key *lock_key;
|
||||
|
||||
/**
|
||||
* @request_key:
|
||||
*
|
||||
* Per GPIO IRQ chip lockdep class for IRQ request.
|
||||
*/
|
||||
struct lock_class_key *request_key;
|
||||
|
||||
/**
|
||||
* @parent_handler:
|
||||
*
|
||||
* The interrupt handler for the GPIO chip's parent interrupts, may be
|
||||
* NULL if the parent interrupts are nested rather than cascaded.
|
||||
*/
|
||||
irq_flow_handler_t parent_handler;
|
||||
|
||||
union {
|
||||
/**
|
||||
* @parent_handler_data:
|
||||
*
|
||||
* If @per_parent_data is false, @parent_handler_data is a
|
||||
* single pointer used as the data associated with every
|
||||
* parent interrupt.
|
||||
*/
|
||||
void *parent_handler_data;
|
||||
|
||||
/**
|
||||
* @parent_handler_data_array:
|
||||
*
|
||||
* If @per_parent_data is true, @parent_handler_data_array is
|
||||
* an array of @num_parents pointers, and is used to associate
|
||||
* different data for each parent. This cannot be NULL if
|
||||
* @per_parent_data is true.
|
||||
*/
|
||||
void **parent_handler_data_array;
|
||||
};
|
||||
|
||||
/**
|
||||
* @num_parents:
|
||||
*
|
||||
* The number of interrupt parents of a GPIO chip.
|
||||
*/
|
||||
unsigned int num_parents;
|
||||
|
||||
/**
|
||||
* @parents:
|
||||
*
|
||||
* A list of interrupt parents of a GPIO chip. This is owned by the
|
||||
* driver, so the core will only reference this list, not modify it.
|
||||
*/
|
||||
unsigned int *parents;
|
||||
|
||||
/**
|
||||
* @map:
|
||||
*
|
||||
* A list of interrupt parents for each line of a GPIO chip.
|
||||
*/
|
||||
unsigned int *map;
|
||||
|
||||
/**
|
||||
* @threaded:
|
||||
*
|
||||
* True if set the interrupt handling uses nested threads.
|
||||
*/
|
||||
bool threaded;
|
||||
|
||||
/**
|
||||
* @per_parent_data:
|
||||
*
|
||||
* True if parent_handler_data_array describes a @num_parents
|
||||
* sized array to be used as parent data.
|
||||
*/
|
||||
bool per_parent_data;
|
||||
|
||||
/**
|
||||
* @initialized:
|
||||
*
|
||||
* Flag to track GPIO chip irq member's initialization.
|
||||
* This flag will make sure GPIO chip irq members are not used
|
||||
* before they are initialized.
|
||||
*/
|
||||
bool initialized;
|
||||
|
||||
/**
|
||||
* @domain_is_allocated_externally:
|
||||
*
|
||||
* True it the irq_domain was allocated outside of gpiolib, in which
|
||||
* case gpiolib won't free the irq_domain itself.
|
||||
*/
|
||||
bool domain_is_allocated_externally;
|
||||
|
||||
/**
|
||||
* @init_hw: optional routine to initialize hardware before
|
||||
* an IRQ chip will be added. This is quite useful when
|
||||
* a particular driver wants to clear IRQ related registers
|
||||
* in order to avoid undesired events.
|
||||
*/
|
||||
int (*init_hw)(struct gpio_chip *gc);
|
||||
|
||||
/**
|
||||
* @init_valid_mask: optional routine to initialize @valid_mask, to be
|
||||
* used if not all GPIO lines are valid interrupts. Sometimes some
|
||||
* lines just cannot fire interrupts, and this routine, when defined,
|
||||
* is passed a bitmap in "valid_mask" and it will have ngpios
|
||||
* bits from 0..(ngpios-1) set to "1" as in valid. The callback can
|
||||
* then directly set some bits to "0" if they cannot be used for
|
||||
* interrupts.
|
||||
*/
|
||||
void (*init_valid_mask)(struct gpio_chip *gc,
|
||||
unsigned long *valid_mask,
|
||||
unsigned int ngpios);
|
||||
|
||||
/**
|
||||
* @valid_mask:
|
||||
*
|
||||
* If not %NULL, holds bitmask of GPIOs which are valid to be included
|
||||
* in IRQ domain of the chip.
|
||||
*/
|
||||
unsigned long *valid_mask;
|
||||
|
||||
/**
|
||||
* @first:
|
||||
*
|
||||
* Required for static IRQ allocation. If set,
|
||||
* irq_domain_create_simple() will allocate and map all IRQs
|
||||
* during initialization.
|
||||
*/
|
||||
unsigned int first;
|
||||
|
||||
/**
|
||||
* @irq_enable:
|
||||
*
|
||||
* Store old irq_chip irq_enable callback
|
||||
*/
|
||||
void (*irq_enable)(struct irq_data *data);
|
||||
|
||||
/**
|
||||
* @irq_disable:
|
||||
*
|
||||
* Store old irq_chip irq_disable callback
|
||||
*/
|
||||
void (*irq_disable)(struct irq_data *data);
|
||||
/**
|
||||
* @irq_unmask:
|
||||
*
|
||||
* Store old irq_chip irq_unmask callback
|
||||
*/
|
||||
void (*irq_unmask)(struct irq_data *data);
|
||||
|
||||
/**
|
||||
* @irq_mask:
|
||||
*
|
||||
* Store old irq_chip irq_mask callback
|
||||
*/
|
||||
void (*irq_mask)(struct irq_data *data);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct gpio_chip - abstract a GPIO controller
|
||||
* @label: a functional name for the GPIO device, such as a part
|
||||
* number or the name of the SoC IP-block implementing it.
|
||||
* @gpiodev: the internal state holder, opaque struct
|
||||
* @parent: optional parent device providing the GPIOs
|
||||
* @fwnode: optional fwnode providing this controller's properties
|
||||
* @owner: helps prevent removal of modules exporting active GPIOs
|
||||
* @request: optional hook for chip-specific activation, such as
|
||||
* enabling module power and clock; may sleep; must return 0 on success
|
||||
* or negative error number on failure
|
||||
* @free: optional hook for chip-specific deactivation, such as
|
||||
* disabling module power and clock; may sleep
|
||||
* @get_direction: returns direction for signal "offset", 0=out, 1=in,
|
||||
* (same as GPIO_LINE_DIRECTION_OUT / GPIO_LINE_DIRECTION_IN),
|
||||
* or negative error. It is recommended to always implement this
|
||||
* function, even on input-only or output-only gpio chips.
|
||||
* @direction_input: configures signal "offset" as input, returns 0 on success
|
||||
* or a negative error number. This can be omitted on input-only or
|
||||
* output-only gpio chips.
|
||||
* @direction_output: configures signal "offset" as output, returns 0 on
|
||||
* success or a negative error number. This can be omitted on input-only
|
||||
* or output-only gpio chips.
|
||||
* @get: returns value for signal "offset", 0=low, 1=high, or negative error.
|
||||
* the low and high values are defined as physical low on the line
|
||||
* in/out to the connector such as a physical pad, pin or rail. The GPIO
|
||||
* library has internal logic to handle lines that are active low, such
|
||||
* as indicated by overstrike or #name in a schematic, and the driver
|
||||
* should not try to second-guess the logic value of a line.
|
||||
* @get_multiple: reads values for multiple signals defined by "mask" and
|
||||
* stores them in "bits", returns 0 on success or negative error
|
||||
* @set: assigns output value for signal "offset", returns 0 on success or
|
||||
* negative error value. The output value follows the same semantic
|
||||
* rules as for @get.
|
||||
* @set_multiple: assigns output values for multiple signals defined by
|
||||
* "mask", returns 0 on success or negative error value
|
||||
* @set_config: optional hook for all kinds of settings. Uses the same
|
||||
* packed config format as generic pinconf. Must return 0 on success and
|
||||
* a negative error number on failure.
|
||||
* @to_irq: optional hook supporting non-static gpiod_to_irq() mappings;
|
||||
* implementation may not sleep
|
||||
* @dbg_show: optional routine to show contents in debugfs; default code
|
||||
* will be used when this is omitted, but custom code can show extra
|
||||
* state (such as pullup/pulldown configuration).
|
||||
* @init_valid_mask: optional routine to initialize @valid_mask, to be used if
|
||||
* not all GPIOs are valid.
|
||||
* @add_pin_ranges: optional routine to initialize pin ranges, to be used when
|
||||
* requires special mapping of the pins that provides GPIO functionality.
|
||||
* It is called after adding GPIO chip and before adding IRQ chip.
|
||||
* @en_hw_timestamp: Dependent on GPIO chip, an optional routine to
|
||||
* enable hardware timestamp.
|
||||
* @dis_hw_timestamp: Dependent on GPIO chip, an optional routine to
|
||||
* disable hardware timestamp.
|
||||
* @base: identifies the first GPIO number handled by this chip;
|
||||
* or, if negative during registration, requests dynamic ID allocation.
|
||||
* DEPRECATION: providing anything non-negative and nailing the base
|
||||
* offset of GPIO chips is deprecated. Please pass -1 as base to
|
||||
* let gpiolib select the chip base in all possible cases. We want to
|
||||
* get rid of the static GPIO number space in the long run.
|
||||
* @ngpio: the number of GPIOs handled by this controller; the last GPIO
|
||||
* handled is (base + ngpio - 1).
|
||||
* @offset: when multiple gpio chips belong to the same device this
|
||||
* can be used as offset within the device so friendly names can
|
||||
* be properly assigned.
|
||||
* @names: if set, must be an array of strings to use as alternative
|
||||
* names for the GPIOs in this chip. Any entry in the array
|
||||
* may be NULL if there is no alias for the GPIO, however the
|
||||
* array must be @ngpio entries long.
|
||||
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
|
||||
* must while accessing GPIO expander chips over I2C or SPI. This
|
||||
* implies that if the chip supports IRQs, these IRQs need to be threaded
|
||||
* as the chip access may sleep when e.g. reading out the IRQ status
|
||||
* registers.
|
||||
*
|
||||
* A gpio_chip can help platforms abstract various sources of GPIOs so
|
||||
* they can all be accessed through a common programming interface.
|
||||
* Example sources would be SOC controllers, FPGAs, multifunction
|
||||
* chips, dedicated GPIO expanders, and so on.
|
||||
*
|
||||
* Each chip controls a number of signals, identified in method calls
|
||||
* by "offset" values in the range 0..(@ngpio - 1). When those signals
|
||||
* are referenced through calls like gpio_get_value(gpio), the offset
|
||||
* is calculated by subtracting @base from the gpio number.
|
||||
*/
|
||||
struct gpio_chip {
|
||||
const char *label;
|
||||
struct gpio_device *gpiodev;
|
||||
struct device *parent;
|
||||
struct fwnode_handle *fwnode;
|
||||
struct module *owner;
|
||||
|
||||
int (*request)(struct gpio_chip *gc,
|
||||
unsigned int offset);
|
||||
void (*free)(struct gpio_chip *gc,
|
||||
unsigned int offset);
|
||||
int (*get_direction)(struct gpio_chip *gc,
|
||||
unsigned int offset);
|
||||
int (*direction_input)(struct gpio_chip *gc,
|
||||
unsigned int offset);
|
||||
int (*direction_output)(struct gpio_chip *gc,
|
||||
unsigned int offset, int value);
|
||||
int (*get)(struct gpio_chip *gc,
|
||||
unsigned int offset);
|
||||
int (*get_multiple)(struct gpio_chip *gc,
|
||||
unsigned long *mask,
|
||||
unsigned long *bits);
|
||||
int (*set)(struct gpio_chip *gc,
|
||||
unsigned int offset, int value);
|
||||
int (*set_multiple)(struct gpio_chip *gc,
|
||||
unsigned long *mask,
|
||||
unsigned long *bits);
|
||||
int (*set_config)(struct gpio_chip *gc,
|
||||
unsigned int offset,
|
||||
unsigned long config);
|
||||
int (*to_irq)(struct gpio_chip *gc,
|
||||
unsigned int offset);
|
||||
|
||||
void (*dbg_show)(struct seq_file *s,
|
||||
struct gpio_chip *gc);
|
||||
|
||||
int (*init_valid_mask)(struct gpio_chip *gc,
|
||||
unsigned long *valid_mask,
|
||||
unsigned int ngpios);
|
||||
|
||||
int (*add_pin_ranges)(struct gpio_chip *gc);
|
||||
|
||||
int (*en_hw_timestamp)(struct gpio_chip *gc,
|
||||
u32 offset,
|
||||
unsigned long flags);
|
||||
int (*dis_hw_timestamp)(struct gpio_chip *gc,
|
||||
u32 offset,
|
||||
unsigned long flags);
|
||||
int base;
|
||||
u16 ngpio;
|
||||
u16 offset;
|
||||
const char *const *names;
|
||||
bool can_sleep;
|
||||
|
||||
#ifdef CONFIG_GPIOLIB_IRQCHIP
|
||||
/*
|
||||
* With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
|
||||
* to handle IRQs for most practical cases.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @irq:
|
||||
*
|
||||
* Integrates interrupt chip functionality with the GPIO chip. Can be
|
||||
* used to handle IRQs for most practical cases.
|
||||
*/
|
||||
struct gpio_irq_chip irq;
|
||||
#endif /* CONFIG_GPIOLIB_IRQCHIP */
|
||||
|
||||
#if defined(CONFIG_OF_GPIO)
|
||||
/*
|
||||
* If CONFIG_OF_GPIO is enabled, then all GPIO controllers described in
|
||||
* the device tree automatically may have an OF translation
|
||||
*/
|
||||
|
||||
/**
|
||||
* @of_gpio_n_cells:
|
||||
*
|
||||
* Number of cells used to form the GPIO specifier. The standard is 2
|
||||
* cells:
|
||||
*
|
||||
* gpios = <&gpio offset flags>;
|
||||
*
|
||||
* some complex GPIO controllers instantiate more than one chip per
|
||||
* device tree node and have 3 cells:
|
||||
*
|
||||
* gpios = <&gpio instance offset flags>;
|
||||
*
|
||||
* Legacy GPIO controllers may even have 1 cell:
|
||||
*
|
||||
* gpios = <&gpio offset>;
|
||||
*/
|
||||
unsigned int of_gpio_n_cells;
|
||||
|
||||
/**
|
||||
* @of_node_instance_match:
|
||||
*
|
||||
* Determine if a chip is the right instance. Must be implemented by
|
||||
* any driver using more than one gpio_chip per device tree node.
|
||||
* Returns true if gc is the instance indicated by i (which is the
|
||||
* first cell in the phandles for GPIO lines and gpio-ranges).
|
||||
*/
|
||||
bool (*of_node_instance_match)(struct gpio_chip *gc, unsigned int i);
|
||||
|
||||
/**
|
||||
* @of_xlate:
|
||||
*
|
||||
* Callback to translate a device tree GPIO specifier into a chip-
|
||||
* relative GPIO number and flags.
|
||||
*/
|
||||
int (*of_xlate)(struct gpio_chip *gc,
|
||||
const struct of_phandle_args *gpiospec, u32 *flags);
|
||||
#endif /* CONFIG_OF_GPIO */
|
||||
};
|
||||
|
||||
char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset);
|
||||
|
||||
|
||||
struct _gpiochip_for_each_data {
|
||||
const char **label;
|
||||
unsigned int *i;
|
||||
};
|
||||
|
||||
DEFINE_CLASS(_gpiochip_for_each_data,
|
||||
struct _gpiochip_for_each_data,
|
||||
if (*_T.label) kfree(*_T.label),
|
||||
({
|
||||
struct _gpiochip_for_each_data _data = { label, i };
|
||||
*_data.i = 0;
|
||||
_data;
|
||||
}),
|
||||
const char **label, int *i)
|
||||
|
||||
/**
|
||||
* for_each_hwgpio_in_range - Iterates over all GPIOs in a given range
|
||||
* @_chip: Chip to iterate over.
|
||||
* @_i: Loop counter.
|
||||
* @_base: First GPIO in the ranger.
|
||||
* @_size: Amount of GPIOs to check starting from @base.
|
||||
* @_label: Place to store the address of the label if the GPIO is requested.
|
||||
* Set to NULL for unused GPIOs.
|
||||
*/
|
||||
#define for_each_hwgpio_in_range(_chip, _i, _base, _size, _label) \
|
||||
for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \
|
||||
_i < _size; \
|
||||
_i++, kfree(_label), _label = NULL) \
|
||||
for_each_if(!IS_ERR(_label = gpiochip_dup_line_label(_chip, _base + _i)))
|
||||
|
||||
/**
|
||||
* for_each_hwgpio - Iterates over all GPIOs for given chip.
|
||||
* @_chip: Chip to iterate over.
|
||||
* @_i: Loop counter.
|
||||
* @_label: Place to store the address of the label if the GPIO is requested.
|
||||
* Set to NULL for unused GPIOs.
|
||||
*/
|
||||
#define for_each_hwgpio(_chip, _i, _label) \
|
||||
for_each_hwgpio_in_range(_chip, _i, 0, _chip->ngpio, _label)
|
||||
|
||||
/**
|
||||
* for_each_requested_gpio_in_range - iterates over requested GPIOs in a given range
|
||||
* @_chip: the chip to query
|
||||
* @_i: loop variable
|
||||
* @_base: first GPIO in the range
|
||||
* @_size: amount of GPIOs to check starting from @base
|
||||
* @_label: label of current GPIO
|
||||
*/
|
||||
#define for_each_requested_gpio_in_range(_chip, _i, _base, _size, _label) \
|
||||
for_each_hwgpio_in_range(_chip, _i, _base, _size, _label) \
|
||||
for_each_if(_label)
|
||||
|
||||
/* Iterates over all requested GPIO of the given @chip */
|
||||
#define for_each_requested_gpio(chip, i, label) \
|
||||
for_each_requested_gpio_in_range(chip, i, 0, chip->ngpio, label)
|
||||
|
||||
/* add/remove chips */
|
||||
int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
||||
struct lock_class_key *lock_key,
|
||||
struct lock_class_key *request_key);
|
||||
|
||||
/**
|
||||
* gpiochip_add_data() - register a gpio_chip
|
||||
* @gc: the chip to register, with gc->base initialized
|
||||
* @data: driver-private data associated with this chip
|
||||
*
|
||||
* Context: potentially before irqs will work
|
||||
*
|
||||
* When gpiochip_add_data() is called very early during boot, so that GPIOs
|
||||
* can be freely used, the gc->parent device must be registered before
|
||||
* the gpio framework's arch_initcall(). Otherwise sysfs initialization
|
||||
* for GPIOs will fail rudely.
|
||||
*
|
||||
* gpiochip_add_data() must only be called after gpiolib initialization,
|
||||
* i.e. after core_initcall().
|
||||
*
|
||||
* If gc->base is negative, this requests dynamic assignment of
|
||||
* a range of valid GPIOs.
|
||||
*
|
||||
* Returns:
|
||||
* A negative errno if the chip can't be registered, such as because the
|
||||
* gc->base is invalid or already associated with a different chip.
|
||||
* Otherwise it returns zero as a success code.
|
||||
*/
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
#define gpiochip_add_data(gc, data) ({ \
|
||||
static struct lock_class_key lock_key; \
|
||||
static struct lock_class_key request_key; \
|
||||
gpiochip_add_data_with_key(gc, data, &lock_key, \
|
||||
&request_key); \
|
||||
})
|
||||
#define devm_gpiochip_add_data(dev, gc, data) ({ \
|
||||
static struct lock_class_key lock_key; \
|
||||
static struct lock_class_key request_key; \
|
||||
devm_gpiochip_add_data_with_key(dev, gc, data, &lock_key, \
|
||||
&request_key); \
|
||||
})
|
||||
#else
|
||||
#define gpiochip_add_data(gc, data) gpiochip_add_data_with_key(gc, data, NULL, NULL)
|
||||
#define devm_gpiochip_add_data(dev, gc, data) \
|
||||
devm_gpiochip_add_data_with_key(dev, gc, data, NULL, NULL)
|
||||
#endif /* CONFIG_LOCKDEP */
|
||||
|
||||
void gpiochip_remove(struct gpio_chip *gc);
|
||||
int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc,
|
||||
void *data, struct lock_class_key *lock_key,
|
||||
struct lock_class_key *request_key);
|
||||
|
||||
struct gpio_device *gpio_device_find(const void *data,
|
||||
int (*match)(struct gpio_chip *gc,
|
||||
const void *data));
|
||||
|
||||
struct gpio_device *gpio_device_get(struct gpio_device *gdev);
|
||||
void gpio_device_put(struct gpio_device *gdev);
|
||||
|
||||
DEFINE_FREE(gpio_device_put, struct gpio_device *,
|
||||
if (!IS_ERR_OR_NULL(_T)) gpio_device_put(_T))
|
||||
|
||||
struct device *gpio_device_to_device(struct gpio_device *gdev);
|
||||
|
||||
bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset);
|
||||
int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset);
|
||||
void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset);
|
||||
void gpiochip_disable_irq(struct gpio_chip *gc, unsigned int offset);
|
||||
void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset);
|
||||
|
||||
/* irq_data versions of the above */
|
||||
int gpiochip_irq_reqres(struct irq_data *data);
|
||||
void gpiochip_irq_relres(struct irq_data *data);
|
||||
|
||||
/* Paste this in your irq_chip structure */
|
||||
#define GPIOCHIP_IRQ_RESOURCE_HELPERS \
|
||||
.irq_request_resources = gpiochip_irq_reqres, \
|
||||
.irq_release_resources = gpiochip_irq_relres
|
||||
|
||||
static inline void gpio_irq_chip_set_chip(struct gpio_irq_chip *girq,
|
||||
const struct irq_chip *chip)
|
||||
{
|
||||
/* Yes, dropping const is ugly, but it isn't like we have a choice */
|
||||
girq->chip = (struct irq_chip *)chip;
|
||||
}
|
||||
|
||||
/* Line status inquiry for drivers */
|
||||
bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset);
|
||||
bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset);
|
||||
|
||||
/* Sleep persistence inquiry for drivers */
|
||||
bool gpiochip_line_is_persistent(struct gpio_chip *gc, unsigned int offset);
|
||||
bool gpiochip_line_is_valid(const struct gpio_chip *gc, unsigned int offset);
|
||||
const unsigned long *gpiochip_query_valid_mask(const struct gpio_chip *gc);
|
||||
|
||||
/* get driver data */
|
||||
void *gpiochip_get_data(struct gpio_chip *gc);
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
|
||||
int gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc,
|
||||
union gpio_irq_fwspec *gfwspec,
|
||||
unsigned int parent_hwirq,
|
||||
unsigned int parent_type);
|
||||
int gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc,
|
||||
union gpio_irq_fwspec *gfwspec,
|
||||
unsigned int parent_hwirq,
|
||||
unsigned int parent_type);
|
||||
|
||||
#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
|
||||
|
||||
#ifdef CONFIG_GPIOLIB_IRQCHIP
|
||||
int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
|
||||
struct irq_domain *domain);
|
||||
#else
|
||||
|
||||
#include <asm/bug.h>
|
||||
|
||||
static inline int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
|
||||
struct irq_domain *domain)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int gpiochip_generic_request(struct gpio_chip *gc, unsigned int offset);
|
||||
void gpiochip_generic_free(struct gpio_chip *gc, unsigned int offset);
|
||||
int gpiochip_generic_config(struct gpio_chip *gc, unsigned int offset,
|
||||
unsigned long config);
|
||||
|
||||
/**
|
||||
* struct gpio_pin_range - pin range controlled by a gpio chip
|
||||
* @node: list for maintaining set of pin ranges, used internally
|
||||
* @pctldev: pinctrl device which handles corresponding pins
|
||||
* @range: actual range of pins controlled by a gpio controller
|
||||
*/
|
||||
struct gpio_pin_range {
|
||||
struct list_head node;
|
||||
struct pinctrl_dev *pctldev;
|
||||
struct pinctrl_gpio_range range;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
|
||||
int gpiochip_add_pin_range_with_pins(struct gpio_chip *gc,
|
||||
const char *pinctl_name,
|
||||
unsigned int gpio_offset,
|
||||
unsigned int pin_offset,
|
||||
unsigned int const *pins,
|
||||
unsigned int npins);
|
||||
int gpiochip_add_pingroup_range(struct gpio_chip *gc,
|
||||
struct pinctrl_dev *pctldev,
|
||||
unsigned int gpio_offset, const char *pin_group);
|
||||
void gpiochip_remove_pin_ranges(struct gpio_chip *gc);
|
||||
|
||||
static inline int
|
||||
gpiochip_add_pin_range(struct gpio_chip *gc,
|
||||
const char *pinctl_name,
|
||||
unsigned int gpio_offset,
|
||||
unsigned int pin_offset,
|
||||
unsigned int npins)
|
||||
{
|
||||
return gpiochip_add_pin_range_with_pins(gc, pinctl_name, gpio_offset,
|
||||
pin_offset, NULL, npins);
|
||||
}
|
||||
|
||||
static inline int
|
||||
gpiochip_add_sparse_pin_range(struct gpio_chip *gc,
|
||||
const char *pinctl_name,
|
||||
unsigned int gpio_offset,
|
||||
unsigned int const *pins,
|
||||
unsigned int npins)
|
||||
{
|
||||
return gpiochip_add_pin_range_with_pins(gc, pinctl_name, gpio_offset, 0,
|
||||
pins, npins);
|
||||
}
|
||||
#else /* ! CONFIG_PINCTRL */
|
||||
|
||||
static inline int
|
||||
gpiochip_add_pin_range_with_pins(struct gpio_chip *gc,
|
||||
const char *pinctl_name,
|
||||
unsigned int gpio_offset,
|
||||
unsigned int pin_offset,
|
||||
unsigned int npins)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name,
|
||||
unsigned int gpio_offset, unsigned int pin_offset,
|
||||
unsigned int npins)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
gpiochip_add_sparse_pin_range(struct gpio_chip *gc,
|
||||
const char *pinctl_name,
|
||||
unsigned int gpio_offset,
|
||||
unsigned int const *pins,
|
||||
unsigned int npins)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
gpiochip_add_pingroup_range(struct gpio_chip *gc,
|
||||
struct pinctrl_dev *pctldev,
|
||||
unsigned int gpio_offset, const char *pin_group)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gpiochip_remove_pin_ranges(struct gpio_chip *gc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PINCTRL */
|
||||
|
||||
struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
|
||||
unsigned int hwnum,
|
||||
const char *label,
|
||||
enum gpio_lookup_flags lflags,
|
||||
enum gpiod_flags dflags);
|
||||
void gpiochip_free_own_desc(struct gpio_desc *desc);
|
||||
|
||||
struct gpio_desc *
|
||||
gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum);
|
||||
|
||||
struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev);
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
|
||||
/* lock/unlock as IRQ */
|
||||
int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset);
|
||||
void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset);
|
||||
|
||||
struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
|
||||
struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc);
|
||||
|
||||
/* struct gpio_device getters */
|
||||
int gpio_device_get_base(struct gpio_device *gdev);
|
||||
const char *gpio_device_get_label(struct gpio_device *gdev);
|
||||
|
||||
struct gpio_device *gpio_device_find_by_label(const char *label);
|
||||
struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode);
|
||||
|
||||
#else /* CONFIG_GPIOLIB */
|
||||
|
||||
#include <asm/bug.h>
|
||||
|
||||
static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
|
||||
{
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(1);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline int gpio_device_get_base(struct gpio_device *gdev)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline const char *gpio_device_get_label(struct gpio_device *gdev)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct gpio_device *gpio_device_find_by_label(const char *label)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int gpiochip_lock_as_irq(struct gpio_chip *gc,
|
||||
unsigned int offset)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void gpiochip_unlock_as_irq(struct gpio_chip *gc,
|
||||
unsigned int offset)
|
||||
{
|
||||
WARN_ON(1);
|
||||
}
|
||||
#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
#define for_each_gpiochip_node(dev, child) \
|
||||
device_for_each_child_node(dev, child) \
|
||||
for_each_if(fwnode_property_present(child, "gpio-controller"))
|
||||
|
||||
static inline unsigned int gpiochip_node_count(struct device *dev)
|
||||
{
|
||||
struct fwnode_handle *child;
|
||||
unsigned int count = 0;
|
||||
|
||||
for_each_gpiochip_node(dev, child)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline struct fwnode_handle *gpiochip_node_get_first(struct device *dev)
|
||||
{
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
for_each_gpiochip_node(dev, fwnode)
|
||||
return fwnode;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* __LINUX_GPIO_DRIVER_H */
|
||||
@@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LINUX_GPIO_FORWARDER_H
|
||||
#define __LINUX_GPIO_FORWARDER_H
|
||||
|
||||
struct gpio_desc;
|
||||
struct gpio_chip;
|
||||
struct gpiochip_fwd;
|
||||
|
||||
struct gpiochip_fwd *devm_gpiochip_fwd_alloc(struct device *dev,
|
||||
unsigned int ngpios);
|
||||
int gpiochip_fwd_desc_add(struct gpiochip_fwd *fwd,
|
||||
struct gpio_desc *desc, unsigned int offset);
|
||||
void gpiochip_fwd_desc_free(struct gpiochip_fwd *fwd, unsigned int offset);
|
||||
int gpiochip_fwd_register(struct gpiochip_fwd *fwd, void *data);
|
||||
|
||||
struct gpio_chip *gpiochip_fwd_get_gpiochip(struct gpiochip_fwd *fwd);
|
||||
|
||||
void *gpiochip_fwd_get_data(struct gpiochip_fwd *fwd);
|
||||
|
||||
int gpiochip_fwd_gpio_request(struct gpiochip_fwd *fwd, unsigned int offset);
|
||||
int gpiochip_fwd_gpio_get_direction(struct gpiochip_fwd *fwd,
|
||||
unsigned int offset);
|
||||
int gpiochip_fwd_gpio_direction_input(struct gpiochip_fwd *fwd,
|
||||
unsigned int offset);
|
||||
int gpiochip_fwd_gpio_direction_output(struct gpiochip_fwd *fwd,
|
||||
unsigned int offset,
|
||||
int value);
|
||||
int gpiochip_fwd_gpio_get(struct gpiochip_fwd *fwd, unsigned int offset);
|
||||
int gpiochip_fwd_gpio_get_multiple(struct gpiochip_fwd *fwd,
|
||||
unsigned long *mask,
|
||||
unsigned long *bits);
|
||||
int gpiochip_fwd_gpio_set(struct gpiochip_fwd *fwd, unsigned int offset,
|
||||
int value);
|
||||
int gpiochip_fwd_gpio_set_multiple(struct gpiochip_fwd *fwd,
|
||||
unsigned long *mask,
|
||||
unsigned long *bits);
|
||||
int gpiochip_fwd_gpio_set_config(struct gpiochip_fwd *fwd, unsigned int offset,
|
||||
unsigned long config);
|
||||
int gpiochip_fwd_gpio_to_irq(struct gpiochip_fwd *fwd, unsigned int offset);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __LINUX_GPIO_GENERIC_H
|
||||
#define __LINUX_GPIO_GENERIC_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/container_of.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
struct device;
|
||||
|
||||
#define GPIO_GENERIC_BIG_ENDIAN BIT(0)
|
||||
#define GPIO_GENERIC_UNREADABLE_REG_SET BIT(1) /* reg_set is unreadable */
|
||||
#define GPIO_GENERIC_UNREADABLE_REG_DIR BIT(2) /* reg_dir is unreadable */
|
||||
#define GPIO_GENERIC_BIG_ENDIAN_BYTE_ORDER BIT(3)
|
||||
#define GPIO_GENERIC_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */
|
||||
#define GPIO_GENERIC_NO_OUTPUT BIT(5) /* only input */
|
||||
#define GPIO_GENERIC_NO_SET_ON_INPUT BIT(6)
|
||||
#define GPIO_GENERIC_PINCTRL_BACKEND BIT(7) /* Call pinctrl direction setters */
|
||||
#define GPIO_GENERIC_NO_INPUT BIT(8) /* only output */
|
||||
|
||||
/**
|
||||
* struct gpio_generic_chip_config - Generic GPIO chip configuration data
|
||||
* @dev: Parent device of the new GPIO chip (compulsory).
|
||||
* @sz: Size (width) of the MMIO registers in bytes, typically 1, 2 or 4.
|
||||
* @dat: MMIO address for the register to READ the value of the GPIO lines, it
|
||||
* is expected that a 1 in the corresponding bit in this register means
|
||||
* the line is asserted.
|
||||
* @set: MMIO address for the register to SET the value of the GPIO lines, it
|
||||
* is expected that we write the line with 1 in this register to drive
|
||||
* the GPIO line high.
|
||||
* @clr: MMIO address for the register to CLEAR the value of the GPIO lines,
|
||||
* it is expected that we write the line with 1 in this register to
|
||||
* drive the GPIO line low. It is allowed to leave this address as NULL,
|
||||
* in that case the SET register will be assumed to also clear the GPIO
|
||||
* lines, by actively writing the line with 0.
|
||||
* @dirout: MMIO address for the register to set the line as OUTPUT. It is
|
||||
* assumed that setting a line to 1 in this register will turn that
|
||||
* line into an output line. Conversely, setting the line to 0 will
|
||||
* turn that line into an input.
|
||||
* @dirin: MMIO address for the register to set this line as INPUT. It is
|
||||
* assumed that setting a line to 1 in this register will turn that
|
||||
* line into an input line. Conversely, setting the line to 0 will
|
||||
* turn that line into an output.
|
||||
* @flags: Different flags that will affect the behaviour of the device, such
|
||||
* as endianness etc.
|
||||
*/
|
||||
struct gpio_generic_chip_config {
|
||||
struct device *dev;
|
||||
unsigned long sz;
|
||||
void __iomem *dat;
|
||||
void __iomem *set;
|
||||
void __iomem *clr;
|
||||
void __iomem *dirout;
|
||||
void __iomem *dirin;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct gpio_generic_chip - Generic GPIO chip implementation.
|
||||
* @gc: The underlying struct gpio_chip object, implementing low-level GPIO
|
||||
* chip routines.
|
||||
* @read_reg: reader function for generic GPIO
|
||||
* @write_reg: writer function for generic GPIO
|
||||
* @be_bits: if the generic GPIO has big endian bit order (bit 31 is
|
||||
* representing line 0, bit 30 is line 1 ... bit 0 is line 31) this
|
||||
* is set to true by the generic GPIO core. It is for internal
|
||||
* housekeeping only.
|
||||
* @reg_dat: data (in) register for generic GPIO
|
||||
* @reg_set: output set register (out=high) for generic GPIO
|
||||
* @reg_clr: output clear register (out=low) for generic GPIO
|
||||
* @reg_dir_out: direction out setting register for generic GPIO
|
||||
* @reg_dir_in: direction in setting register for generic GPIO
|
||||
* @dir_unreadable: indicates that the direction register(s) cannot be read and
|
||||
* we need to rely on out internal state tracking.
|
||||
* @pinctrl: the generic GPIO uses a pin control backend.
|
||||
* @bits: number of register bits used for a generic GPIO
|
||||
* i.e. <register width> * 8
|
||||
* @lock: used to lock chip->sdata. Also, this is needed to keep
|
||||
* shadowed and real data registers writes together.
|
||||
* @sdata: shadowed data register for generic GPIO to clear/set bits safely.
|
||||
* @sdir: shadowed direction register for generic GPIO to clear/set direction
|
||||
* safely. A "1" in this word means the line is set as output.
|
||||
*/
|
||||
struct gpio_generic_chip {
|
||||
struct gpio_chip gc;
|
||||
unsigned long (*read_reg)(void __iomem *reg);
|
||||
void (*write_reg)(void __iomem *reg, unsigned long data);
|
||||
bool be_bits;
|
||||
void __iomem *reg_dat;
|
||||
void __iomem *reg_set;
|
||||
void __iomem *reg_clr;
|
||||
void __iomem *reg_dir_out;
|
||||
void __iomem *reg_dir_in;
|
||||
bool dir_unreadable;
|
||||
bool pinctrl;
|
||||
int bits;
|
||||
raw_spinlock_t lock;
|
||||
unsigned long sdata;
|
||||
unsigned long sdir;
|
||||
};
|
||||
|
||||
static inline struct gpio_generic_chip *
|
||||
to_gpio_generic_chip(struct gpio_chip *gc)
|
||||
{
|
||||
return container_of(gc, struct gpio_generic_chip, gc);
|
||||
}
|
||||
|
||||
int gpio_generic_chip_init(struct gpio_generic_chip *chip,
|
||||
const struct gpio_generic_chip_config *cfg);
|
||||
|
||||
/**
|
||||
* gpio_generic_chip_set() - Set the GPIO line value of the generic GPIO chip.
|
||||
* @chip: Generic GPIO chip to use.
|
||||
* @offset: Hardware offset of the line to set.
|
||||
* @value: New GPIO line value.
|
||||
*
|
||||
* Some modules using the generic GPIO chip, need to set line values in their
|
||||
* direction setters but they don't have access to the gpio-mmio symbols so
|
||||
* they use the function pointer in struct gpio_chip directly. This is not
|
||||
* optimal and can lead to crashes at run-time in some instances. This wrapper
|
||||
* provides a safe interface for users.
|
||||
*
|
||||
* Returns: 0 on success, negative error number of failure.
|
||||
*/
|
||||
static inline int
|
||||
gpio_generic_chip_set(struct gpio_generic_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
if (WARN_ON(!chip->gc.set))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return chip->gc.set(&chip->gc, offset, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* gpio_generic_read_reg() - Read a register using the underlying callback.
|
||||
* @chip: Generic GPIO chip to use.
|
||||
* @reg: Register to read.
|
||||
*
|
||||
* Returns: value read from register.
|
||||
*/
|
||||
static inline unsigned long
|
||||
gpio_generic_read_reg(struct gpio_generic_chip *chip, void __iomem *reg)
|
||||
{
|
||||
if (WARN_ON(!chip->read_reg))
|
||||
return 0;
|
||||
|
||||
return chip->read_reg(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* gpio_generic_write_reg() - Write a register using the underlying callback.
|
||||
* @chip: Generic GPIO chip to use.
|
||||
* @reg: Register to write to.
|
||||
* @val: New value to write.
|
||||
*/
|
||||
static inline void gpio_generic_write_reg(struct gpio_generic_chip *chip,
|
||||
void __iomem *reg, unsigned long val)
|
||||
{
|
||||
if (WARN_ON(!chip->write_reg))
|
||||
return;
|
||||
|
||||
chip->write_reg(reg, val);
|
||||
}
|
||||
|
||||
#define gpio_generic_chip_lock(gen_gc) \
|
||||
raw_spin_lock(&(gen_gc)->lock)
|
||||
|
||||
#define gpio_generic_chip_unlock(gen_gc) \
|
||||
raw_spin_unlock(&(gen_gc)->lock)
|
||||
|
||||
#define gpio_generic_chip_lock_irqsave(gen_gc, flags) \
|
||||
raw_spin_lock_irqsave(&(gen_gc)->lock, flags)
|
||||
|
||||
#define gpio_generic_chip_unlock_irqrestore(gen_gc, flags) \
|
||||
raw_spin_unlock_irqrestore(&(gen_gc)->lock, flags)
|
||||
|
||||
DEFINE_LOCK_GUARD_1(gpio_generic_lock,
|
||||
struct gpio_generic_chip,
|
||||
gpio_generic_chip_lock(_T->lock),
|
||||
gpio_generic_chip_unlock(_T->lock))
|
||||
|
||||
DEFINE_LOCK_GUARD_1(gpio_generic_lock_irqsave,
|
||||
struct gpio_generic_chip,
|
||||
gpio_generic_chip_lock_irqsave(_T->lock, _T->flags),
|
||||
gpio_generic_chip_unlock_irqrestore(_T->lock, _T->flags),
|
||||
unsigned long flags)
|
||||
|
||||
#endif /* __LINUX_GPIO_GENERIC_H */
|
||||
@@ -0,0 +1,290 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LINUX_GPIO_NOMADIK_H
|
||||
#define __LINUX_GPIO_NOMADIK_H
|
||||
|
||||
struct fwnode_handle;
|
||||
|
||||
/* Package definitions */
|
||||
#define PINCTRL_NMK_STN8815 0
|
||||
#define PINCTRL_NMK_DB8500 1
|
||||
|
||||
#define GPIO_BLOCK_SHIFT 5
|
||||
#define NMK_GPIO_PER_CHIP BIT(GPIO_BLOCK_SHIFT)
|
||||
#define NMK_MAX_BANKS DIV_ROUND_UP(512, NMK_GPIO_PER_CHIP)
|
||||
|
||||
/* Register in the logic block */
|
||||
#define NMK_GPIO_DAT 0x00
|
||||
#define NMK_GPIO_DATS 0x04
|
||||
#define NMK_GPIO_DATC 0x08
|
||||
#define NMK_GPIO_PDIS 0x0c
|
||||
#define NMK_GPIO_DIR 0x10
|
||||
#define NMK_GPIO_DIRS 0x14
|
||||
#define NMK_GPIO_DIRC 0x18
|
||||
#define NMK_GPIO_SLPC 0x1c
|
||||
#define NMK_GPIO_AFSLA 0x20
|
||||
#define NMK_GPIO_AFSLB 0x24
|
||||
#define NMK_GPIO_LOWEMI 0x28
|
||||
|
||||
#define NMK_GPIO_RIMSC 0x40
|
||||
#define NMK_GPIO_FIMSC 0x44
|
||||
#define NMK_GPIO_IS 0x48
|
||||
#define NMK_GPIO_IC 0x4c
|
||||
#define NMK_GPIO_RWIMSC 0x50
|
||||
#define NMK_GPIO_FWIMSC 0x54
|
||||
#define NMK_GPIO_WKS 0x58
|
||||
/* These appear in DB8540 and later ASICs */
|
||||
#define NMK_GPIO_EDGELEVEL 0x5C
|
||||
#define NMK_GPIO_LEVEL 0x60
|
||||
|
||||
/* Pull up/down values */
|
||||
enum nmk_gpio_pull {
|
||||
NMK_GPIO_PULL_NONE,
|
||||
NMK_GPIO_PULL_UP,
|
||||
NMK_GPIO_PULL_DOWN,
|
||||
};
|
||||
|
||||
/* Sleep mode */
|
||||
enum nmk_gpio_slpm {
|
||||
NMK_GPIO_SLPM_INPUT,
|
||||
NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
|
||||
NMK_GPIO_SLPM_NOCHANGE,
|
||||
NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
|
||||
};
|
||||
|
||||
struct nmk_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
void __iomem *addr;
|
||||
struct clk *clk;
|
||||
unsigned int bank;
|
||||
void (*set_ioforce)(bool enable);
|
||||
spinlock_t lock;
|
||||
bool sleepmode;
|
||||
bool is_mobileye_soc;
|
||||
/* Keep track of configured edges */
|
||||
u32 edge_rising;
|
||||
u32 edge_falling;
|
||||
u32 real_wake;
|
||||
u32 rwimsc;
|
||||
u32 fwimsc;
|
||||
u32 rimsc;
|
||||
u32 fimsc;
|
||||
u32 pull_up;
|
||||
u32 lowemi;
|
||||
};
|
||||
|
||||
/* Alternate functions: function C is set in hw by setting both A and B */
|
||||
#define NMK_GPIO_ALT_GPIO 0
|
||||
#define NMK_GPIO_ALT_A 1
|
||||
#define NMK_GPIO_ALT_B 2
|
||||
#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
|
||||
|
||||
#define NMK_GPIO_ALT_CX_SHIFT 2
|
||||
#define NMK_GPIO_ALT_C1 ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
|
||||
#define NMK_GPIO_ALT_C2 ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
|
||||
#define NMK_GPIO_ALT_C3 ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
|
||||
#define NMK_GPIO_ALT_C4 ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
|
||||
|
||||
#define PRCM_GPIOCR_ALTCX(pin_num,\
|
||||
altc1_used, altc1_ri, altc1_cb,\
|
||||
altc2_used, altc2_ri, altc2_cb,\
|
||||
altc3_used, altc3_ri, altc3_cb,\
|
||||
altc4_used, altc4_ri, altc4_cb)\
|
||||
{\
|
||||
.pin = pin_num,\
|
||||
.altcx[PRCM_IDX_GPIOCR_ALTC1] = {\
|
||||
.used = altc1_used,\
|
||||
.reg_index = altc1_ri,\
|
||||
.control_bit = altc1_cb\
|
||||
},\
|
||||
.altcx[PRCM_IDX_GPIOCR_ALTC2] = {\
|
||||
.used = altc2_used,\
|
||||
.reg_index = altc2_ri,\
|
||||
.control_bit = altc2_cb\
|
||||
},\
|
||||
.altcx[PRCM_IDX_GPIOCR_ALTC3] = {\
|
||||
.used = altc3_used,\
|
||||
.reg_index = altc3_ri,\
|
||||
.control_bit = altc3_cb\
|
||||
},\
|
||||
.altcx[PRCM_IDX_GPIOCR_ALTC4] = {\
|
||||
.used = altc4_used,\
|
||||
.reg_index = altc4_ri,\
|
||||
.control_bit = altc4_cb\
|
||||
},\
|
||||
}
|
||||
|
||||
/**
|
||||
* enum prcm_gpiocr_reg_index - Used to reference a PRCM GPIOCR register address.
|
||||
*/
|
||||
enum prcm_gpiocr_reg_index {
|
||||
PRCM_IDX_GPIOCR1,
|
||||
PRCM_IDX_GPIOCR2,
|
||||
PRCM_IDX_GPIOCR3
|
||||
};
|
||||
/**
|
||||
* enum prcm_gpiocr_altcx_index - Used to reference an Other alternate-C function.
|
||||
*/
|
||||
enum prcm_gpiocr_altcx_index {
|
||||
PRCM_IDX_GPIOCR_ALTC1,
|
||||
PRCM_IDX_GPIOCR_ALTC2,
|
||||
PRCM_IDX_GPIOCR_ALTC3,
|
||||
PRCM_IDX_GPIOCR_ALTC4,
|
||||
PRCM_IDX_GPIOCR_ALTC_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct prcm_gpiocr_altcx - Other alternate-C function
|
||||
* @used: other alternate-C function availability
|
||||
* @reg_index: PRCM GPIOCR register index used to control the function
|
||||
* @control_bit: PRCM GPIOCR bit used to control the function
|
||||
*/
|
||||
struct prcm_gpiocr_altcx {
|
||||
bool used:1;
|
||||
u8 reg_index:2;
|
||||
u8 control_bit:5;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct prcm_gpiocr_altcx_pin_desc - Other alternate-C pin
|
||||
* @pin: The pin number
|
||||
* @altcx: array of other alternate-C[1-4] functions
|
||||
*/
|
||||
struct prcm_gpiocr_altcx_pin_desc {
|
||||
unsigned short pin;
|
||||
struct prcm_gpiocr_altcx altcx[PRCM_IDX_GPIOCR_ALTC_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct nmk_function - Nomadik pinctrl mux function
|
||||
* @name: The name of the function, exported to pinctrl core.
|
||||
* @groups: An array of pin groups that may select this function.
|
||||
* @ngroups: The number of entries in @groups.
|
||||
*/
|
||||
struct nmk_function {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
unsigned int ngroups;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct nmk_pingroup - describes a Nomadik pin group
|
||||
* @grp: Generic data of the pin group (name and pins)
|
||||
* @altsetting: the altsetting to apply to all pins in this group to
|
||||
* configure them to be used by a function
|
||||
*/
|
||||
struct nmk_pingroup {
|
||||
struct pingroup grp;
|
||||
int altsetting;
|
||||
};
|
||||
|
||||
#define NMK_PIN_GROUP(a, b) \
|
||||
{ \
|
||||
.grp = PINCTRL_PINGROUP(#a, a##_pins, ARRAY_SIZE(a##_pins)), \
|
||||
.altsetting = b, \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration
|
||||
* @pins: An array describing all pins the pin controller affects.
|
||||
* All pins which are also GPIOs must be listed first within the
|
||||
* array, and be numbered identically to the GPIO controller's
|
||||
* numbering.
|
||||
* @npins: The number of entries in @pins.
|
||||
* @functions: The functions supported on this SoC.
|
||||
* @nfunctions: The number of entries in @functions.
|
||||
* @groups: An array describing all pin groups the pin SoC supports.
|
||||
* @ngroups: The number of entries in @groups.
|
||||
* @altcx_pins: The pins that support Other alternate-C function on this SoC
|
||||
* @npins_altcx: The number of Other alternate-C pins
|
||||
* @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC
|
||||
*/
|
||||
struct nmk_pinctrl_soc_data {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned int npins;
|
||||
const struct nmk_function *functions;
|
||||
unsigned int nfunctions;
|
||||
const struct nmk_pingroup *groups;
|
||||
unsigned int ngroups;
|
||||
const struct prcm_gpiocr_altcx_pin_desc *altcx_pins;
|
||||
unsigned int npins_altcx;
|
||||
const u16 *prcm_gpiocr_registers;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PINCTRL_STN8815
|
||||
|
||||
void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc);
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PINCTRL_DB8500
|
||||
|
||||
void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc);
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PINCTRL_DB8540
|
||||
|
||||
void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc);
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct platform_device;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
/*
|
||||
* Symbols declared in gpio-nomadik used by pinctrl-nomadik. If pinctrl-nomadik
|
||||
* is enabled, then gpio-nomadik is enabled as well; the reverse if not always
|
||||
* true.
|
||||
*/
|
||||
void nmk_gpio_dbg_show_one(struct seq_file *s, struct pinctrl_dev *pctldev,
|
||||
struct gpio_chip *chip, unsigned int offset);
|
||||
|
||||
#else
|
||||
|
||||
static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
|
||||
struct pinctrl_dev *pctldev,
|
||||
struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
|
||||
unsigned int offset, int val);
|
||||
void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, unsigned int offset,
|
||||
enum nmk_gpio_slpm mode);
|
||||
struct nmk_gpio_chip *nmk_gpio_populate_chip(struct fwnode_handle *fwnode,
|
||||
struct platform_device *pdev);
|
||||
|
||||
/* Symbols declared in pinctrl-nomadik used by gpio-nomadik. */
|
||||
#ifdef CONFIG_PINCTRL_NOMADIK
|
||||
extern struct nmk_gpio_chip *nmk_gpio_chips[NMK_MAX_BANKS];
|
||||
extern spinlock_t nmk_gpio_slpm_lock;
|
||||
int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev,
|
||||
int gpio);
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_GPIO_NOMADIK_H */
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef GPIO_REG_H
|
||||
#define GPIO_REG_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
struct irq_domain;
|
||||
|
||||
struct gpio_chip;
|
||||
|
||||
struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg,
|
||||
int base, int num, const char *label, u32 direction, u32 def_out,
|
||||
const char *const *names, struct irq_domain *irqdom, const int *irqs);
|
||||
|
||||
int gpio_reg_resume(struct gpio_chip *gc);
|
||||
|
||||
#endif /* GPIO_REG_H */
|
||||
@@ -0,0 +1,94 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LINUX_GPIO_MACHINE_H
|
||||
#define __LINUX_GPIO_MACHINE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum gpio_lookup_flags {
|
||||
GPIO_ACTIVE_HIGH = (0 << 0),
|
||||
GPIO_ACTIVE_LOW = (1 << 0),
|
||||
GPIO_OPEN_DRAIN = (1 << 1),
|
||||
GPIO_OPEN_SOURCE = (1 << 2),
|
||||
GPIO_PERSISTENT = (0 << 3),
|
||||
GPIO_TRANSITORY = (1 << 3),
|
||||
GPIO_PULL_UP = (1 << 4),
|
||||
GPIO_PULL_DOWN = (1 << 5),
|
||||
GPIO_PULL_DISABLE = (1 << 6),
|
||||
|
||||
GPIO_LOOKUP_FLAGS_DEFAULT = GPIO_ACTIVE_HIGH | GPIO_PERSISTENT,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct gpiod_lookup - lookup table
|
||||
* @key: either the name of the chip the GPIO belongs to, or the GPIO line name
|
||||
* Note that GPIO line names are not guaranteed to be globally unique,
|
||||
* so this will use the first match found!
|
||||
* @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO, or
|
||||
* U16_MAX to indicate that @key is a GPIO line name
|
||||
* @con_id: name of the GPIO from the device's point of view
|
||||
* @idx: index of the GPIO in case several GPIOs share the same name
|
||||
* @flags: bitmask of gpio_lookup_flags GPIO_* values
|
||||
*
|
||||
* gpiod_lookup is a lookup table for associating GPIOs to specific devices and
|
||||
* functions using platform data.
|
||||
*/
|
||||
struct gpiod_lookup {
|
||||
const char *key;
|
||||
u16 chip_hwnum;
|
||||
const char *con_id;
|
||||
unsigned int idx;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct gpiod_lookup_table {
|
||||
struct list_head list;
|
||||
const char *dev_id;
|
||||
struct gpiod_lookup table[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper for lookup tables with just one single lookup for a device.
|
||||
*/
|
||||
#define GPIO_LOOKUP_SINGLE(_name, _dev_id, _key, _chip_hwnum, _con_id, _flags) \
|
||||
static struct gpiod_lookup_table _name = { \
|
||||
.dev_id = _dev_id, \
|
||||
.table = { \
|
||||
GPIO_LOOKUP(_key, _chip_hwnum, _con_id, _flags), \
|
||||
{}, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple definition of a single GPIO under a con_id
|
||||
*/
|
||||
#define GPIO_LOOKUP(_key, _chip_hwnum, _con_id, _flags) \
|
||||
GPIO_LOOKUP_IDX(_key, _chip_hwnum, _con_id, 0, _flags)
|
||||
|
||||
/*
|
||||
* Use this macro if you need to have several GPIOs under the same con_id.
|
||||
* Each GPIO needs to use a different index and can be accessed using
|
||||
* gpiod_get_index()
|
||||
*/
|
||||
#define GPIO_LOOKUP_IDX(_key, _chip_hwnum, _con_id, _idx, _flags) \
|
||||
(struct gpiod_lookup) { \
|
||||
.key = _key, \
|
||||
.chip_hwnum = _chip_hwnum, \
|
||||
.con_id = _con_id, \
|
||||
.idx = _idx, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
|
||||
void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n);
|
||||
void gpiod_remove_lookup_table(struct gpiod_lookup_table *table);
|
||||
#else /* ! CONFIG_GPIOLIB */
|
||||
static inline
|
||||
void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {}
|
||||
static inline
|
||||
void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {}
|
||||
static inline
|
||||
void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {}
|
||||
#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
#endif /* __LINUX_GPIO_MACHINE_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
#ifndef __LINUX_GPIO_PROPERTY_H
|
||||
#define __LINUX_GPIO_PROPERTY_H
|
||||
|
||||
#include <linux/property.h>
|
||||
|
||||
struct software_node;
|
||||
|
||||
#define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \
|
||||
PROPERTY_ENTRY_REF(_name_, _chip_node_, _idx_, _flags_)
|
||||
|
||||
extern const struct software_node swnode_gpio_undefined;
|
||||
|
||||
#endif /* __LINUX_GPIO_PROPERTY_H */
|
||||
@@ -0,0 +1,117 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _LINUX_GPIO_REGMAP_H
|
||||
#define _LINUX_GPIO_REGMAP_H
|
||||
|
||||
struct device;
|
||||
struct fwnode_handle;
|
||||
struct gpio_regmap;
|
||||
struct gpio_chip;
|
||||
struct irq_domain;
|
||||
struct regmap;
|
||||
|
||||
#define GPIO_REGMAP_ADDR_ZERO ((unsigned int)(-1))
|
||||
#define GPIO_REGMAP_ADDR(addr) ((addr) ? : GPIO_REGMAP_ADDR_ZERO)
|
||||
|
||||
/**
|
||||
* struct gpio_regmap_config - Description of a generic regmap gpio_chip.
|
||||
* @parent: The parent device
|
||||
* @regmap: The regmap used to access the registers
|
||||
* given, the name of the device is used
|
||||
* @fwnode: (Optional) The firmware node.
|
||||
* If not given, the fwnode of the parent is used.
|
||||
* @label: (Optional) Descriptive name for GPIO controller.
|
||||
* If not given, the name of the device is used.
|
||||
* @ngpio: (Optional) Number of GPIOs
|
||||
* @names: (Optional) Array of names for gpios
|
||||
* @reg_dat_base: (Optional) (in) register base address
|
||||
* @reg_set_base: (Optional) set register base address
|
||||
* @reg_clr_base: (Optional) clear register base address
|
||||
* @reg_dir_in_base: (Optional) in setting register base address
|
||||
* @reg_dir_out_base: (Optional) out setting register base address
|
||||
* @reg_stride: (Optional) May be set if the registers (of the
|
||||
* same type, dat, set, etc) are not consecutive.
|
||||
* @ngpio_per_reg: (Optional) Number of GPIOs per register
|
||||
* @irq_domain: (Optional) IRQ domain if the controller is
|
||||
* interrupt-capable
|
||||
* @reg_mask_xlate: (Optional) Translates base address and GPIO
|
||||
* offset to a register/bitmask pair. If not
|
||||
* given the default gpio_regmap_simple_xlate()
|
||||
* is used.
|
||||
* @fixed_direction_output:
|
||||
* (Optional) Bitmap representing the fixed direction of
|
||||
* the GPIO lines. Useful when there are GPIO lines with a
|
||||
* fixed direction mixed together in the same register.
|
||||
* @drvdata: (Optional) Pointer to driver specific data which is
|
||||
* not used by gpio-remap but is provided "as is" to the
|
||||
* driver callback(s).
|
||||
* @init_valid_mask: (Optional) Routine to initialize @valid_mask, to be used
|
||||
* if not all GPIOs are valid.
|
||||
* @regmap_irq_chip: (Optional) Pointer on an regmap_irq_chip structure. If
|
||||
* set, a regmap-irq device will be created and the IRQ
|
||||
* domain will be set accordingly.
|
||||
* @regmap_irq_line: (Optional) The IRQ the device uses to signal interrupts.
|
||||
* @regmap_irq_flags: (Optional) The IRQF_ flags to use for the interrupt.
|
||||
*
|
||||
* The ->reg_mask_xlate translates a given base address and GPIO offset to
|
||||
* register and mask pair. The base address is one of the given register
|
||||
* base addresses in this structure.
|
||||
*
|
||||
* Although all register base addresses are marked as optional, there are
|
||||
* several rules:
|
||||
* 1. if you only have @reg_dat_base set, then it is input-only
|
||||
* 2. if you only have @reg_set_base set, then it is output-only
|
||||
* 3. if you have either @reg_dir_in_base or @reg_dir_out_base set, then
|
||||
* you have to set both @reg_dat_base and @reg_set_base
|
||||
* 4. if you have @reg_set_base set, you may also set @reg_clr_base to have
|
||||
* two different registers for setting and clearing the output. This is
|
||||
* also valid for the output-only case.
|
||||
* 5. @reg_dir_in_base and @reg_dir_out_base are exclusive; is there really
|
||||
* hardware which has redundant registers?
|
||||
*
|
||||
* Note: All base addresses may have the special value %GPIO_REGMAP_ADDR_ZERO
|
||||
* which forces the address to the value 0.
|
||||
*/
|
||||
struct gpio_regmap_config {
|
||||
struct device *parent;
|
||||
struct regmap *regmap;
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
const char *label;
|
||||
int ngpio;
|
||||
const char *const *names;
|
||||
|
||||
unsigned int reg_dat_base;
|
||||
unsigned int reg_set_base;
|
||||
unsigned int reg_clr_base;
|
||||
unsigned int reg_dir_in_base;
|
||||
unsigned int reg_dir_out_base;
|
||||
int reg_stride;
|
||||
int ngpio_per_reg;
|
||||
struct irq_domain *irq_domain;
|
||||
unsigned long *fixed_direction_output;
|
||||
|
||||
#ifdef CONFIG_REGMAP_IRQ
|
||||
struct regmap_irq_chip *regmap_irq_chip;
|
||||
int regmap_irq_line;
|
||||
unsigned long regmap_irq_flags;
|
||||
#endif
|
||||
|
||||
int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base,
|
||||
unsigned int offset, unsigned int *reg,
|
||||
unsigned int *mask);
|
||||
|
||||
int (*init_valid_mask)(struct gpio_chip *gc,
|
||||
unsigned long *valid_mask,
|
||||
unsigned int ngpios);
|
||||
|
||||
void *drvdata;
|
||||
};
|
||||
|
||||
struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config);
|
||||
void gpio_regmap_unregister(struct gpio_regmap *gpio);
|
||||
struct gpio_regmap *devm_gpio_regmap_register(struct device *dev,
|
||||
const struct gpio_regmap_config *config);
|
||||
void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio);
|
||||
|
||||
#endif /* _LINUX_GPIO_REGMAP_H */
|
||||
Reference in New Issue
Block a user