linux/drivers/pinctrl/pinctrl-single.c

/*
 * Generic device tree based pinctrl driver for one register per pin
 * type pinmux controllers
 *
 * Copyright (C) 2012 Texas Instruments, Inc.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/seq_file.h>

#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>

#include <linux/platform_data/pinctrl-single.h>

#include "core.h"
#include "devicetree.h"
#include "pinconf.h"
#include "pinmux.h"

#define DRIVER_NAME
#define PCS_OFF_DISABLED

/**
 * struct pcs_func_vals - mux function register offset and value pair
 * @reg:	register virtual address
 * @val:	register value
 * @mask:	mask
 */
struct pcs_func_vals {};

/**
 * struct pcs_conf_vals - pinconf parameter, pinconf register offset
 * and value, enable, disable, mask
 * @param:	config parameter
 * @val:	user input bits in the pinconf register
 * @enable:	enable bits in the pinconf register
 * @disable:	disable bits in the pinconf register
 * @mask:	mask bits in the register value
 */
struct pcs_conf_vals {};

/**
 * struct pcs_conf_type - pinconf property name, pinconf param pair
 * @name:	property name in DTS file
 * @param:	config parameter
 */
struct pcs_conf_type {};

/**
 * struct pcs_function - pinctrl function
 * @name:	pinctrl function name
 * @vals:	register and vals array
 * @nvals:	number of entries in vals array
 * @conf:	array of pin configurations
 * @nconfs:	number of pin configurations available
 * @node:	list node
 */
struct pcs_function {};

/**
 * struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
 * @offset:	offset base of pins
 * @npins:	number pins with the same mux value of gpio function
 * @gpiofunc:	mux value of gpio function
 * @node:	list node
 */
struct pcs_gpiofunc_range {};

/**
 * struct pcs_data - wrapper for data needed by pinctrl framework
 * @pa:		pindesc array
 * @cur:	index to current element
 *
 * REVISIT: We should be able to drop this eventually by adding
 * support for registering pins individually in the pinctrl
 * framework for those drivers that don't need a static array.
 */
struct pcs_data {};

/**
 * struct pcs_soc_data - SoC specific settings
 * @flags:	initial SoC specific PCS_FEAT_xxx values
 * @irq:	optional interrupt for the controller
 * @irq_enable_mask:	optional SoC specific interrupt enable mask
 * @irq_status_mask:	optional SoC specific interrupt status mask
 * @rearm:	optional SoC specific wake-up rearm function
 */
struct pcs_soc_data {};

/**
 * struct pcs_device - pinctrl device instance
 * @res:	resources
 * @base:	virtual address of the controller
 * @saved_vals: saved values for the controller
 * @size:	size of the ioremapped area
 * @dev:	device entry
 * @np:		device tree node
 * @pctl:	pin controller device
 * @flags:	mask of PCS_FEAT_xxx values
 * @missing_nr_pinctrl_cells: for legacy binding, may go away
 * @socdata:	soc specific data
 * @lock:	spinlock for register access
 * @mutex:	mutex protecting the lists
 * @width:	bits per mux register
 * @fmask:	function register mask
 * @fshift:	function register shift
 * @foff:	value to turn mux off
 * @fmax:	max number of functions in fmask
 * @bits_per_mux: number of bits per mux
 * @bits_per_pin: number of bits per pin
 * @pins:	physical pins on the SoC
 * @gpiofuncs:	list of gpio functions
 * @irqs:	list of interrupt registers
 * @chip:	chip container for this instance
 * @domain:	IRQ domain for this instance
 * @desc:	pin controller descriptor
 * @read:	register read function to use
 * @write:	register write function to use
 */
struct pcs_device {};

#define PCS_QUIRK_HAS_SHARED_IRQ
#define PCS_HAS_IRQ
#define PCS_HAS_PINCONF

static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
			   unsigned long *config);
static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
			   unsigned long *configs, unsigned num_configs);

static enum pin_config_param pcs_bias[] =;

/*
 * This lock class tells lockdep that irqchip core that this single
 * pinctrl can be in a different category than its parents, so it won't
 * report false recursion.
 */
static struct lock_class_key pcs_lock_class;

/* Class for the IRQ request mutex */
static struct lock_class_key pcs_request_class;

/*
 * REVISIT: Reads and writes could eventually use regmap or something
 * generic. But at least on omaps, some mux registers are performance
 * critical as they may need to be remuxed every time before and after
 * idle. Adding tests for register access width for every read and
 * write like regmap is doing is not desired, and caching the registers
 * does not help in this case.
 */

static unsigned int pcs_readb(void __iomem *reg)
{}

static unsigned int pcs_readw(void __iomem *reg)
{}

static unsigned int pcs_readl(void __iomem *reg)
{}

static void pcs_writeb(unsigned int val, void __iomem *reg)
{}

static void pcs_writew(unsigned int val, void __iomem *reg)
{}

static void pcs_writel(unsigned int val, void __iomem *reg)
{}

static unsigned int pcs_pin_reg_offset_get(struct pcs_device *pcs,
					   unsigned int pin)
{}

static unsigned int pcs_pin_shift_reg_get(struct pcs_device *pcs,
					  unsigned int pin)
{}

static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
					struct seq_file *s,
					unsigned pin)
{}

static void pcs_dt_free_map(struct pinctrl_dev *pctldev,
				struct pinctrl_map *map, unsigned num_maps)
{}

static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
				struct device_node *np_config,
				struct pinctrl_map **map, unsigned *num_maps);

static const struct pinctrl_ops pcs_pinctrl_ops =;

static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
			    struct pcs_function **func)
{}

static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
	unsigned group)
{}

static int pcs_request_gpio(struct pinctrl_dev *pctldev,
			    struct pinctrl_gpio_range *range, unsigned pin)
{}

static const struct pinmux_ops pcs_pinmux_ops =;

/* Clear BIAS value */
static void pcs_pinconf_clear_bias(struct pinctrl_dev *pctldev, unsigned pin)
{}

/*
 * Check whether PIN_CONFIG_BIAS_DISABLE is valid.
 * It's depend on that PULL_DOWN & PULL_UP configs are all invalid.
 */
static bool pcs_pinconf_bias_disable(struct pinctrl_dev *pctldev, unsigned pin)
{}

static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
				unsigned pin, unsigned long *config)
{}

static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
				unsigned pin, unsigned long *configs,
				unsigned num_configs)
{}

static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
				unsigned group, unsigned long *config)
{}

static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
				unsigned group, unsigned long *configs,
				unsigned num_configs)
{}

static void pcs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
				struct seq_file *s, unsigned pin)
{}

static void pcs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
				struct seq_file *s, unsigned selector)
{}

static void pcs_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
					struct seq_file *s,
					unsigned long config)
{}

static const struct pinconf_ops pcs_pinconf_ops =;

/**
 * pcs_add_pin() - add a pin to the static per controller pin array
 * @pcs: pcs driver instance
 * @offset: register offset from base
 */
static int pcs_add_pin(struct pcs_device *pcs, unsigned int offset)
{}

/**
 * pcs_allocate_pin_table() - adds all the pins for the pinctrl driver
 * @pcs: pcs driver instance
 *
 * In case of errors, resources are freed in pcs_free_resources.
 *
 * If your hardware needs holes in the address space, then just set
 * up multiple driver instances.
 */
static int pcs_allocate_pin_table(struct pcs_device *pcs)
{}

/**
 * pcs_add_function() - adds a new function to the function list
 * @pcs: pcs driver instance
 * @fcn: new function allocated
 * @name: name of the function
 * @vals: array of mux register value pairs used by the function
 * @nvals: number of mux register value pairs
 * @pgnames: array of pingroup names for the function
 * @npgnames: number of pingroup names
 *
 * Caller must take care of locking.
 */
static int pcs_add_function(struct pcs_device *pcs,
			    struct pcs_function **fcn,
			    const char *name,
			    struct pcs_func_vals *vals,
			    unsigned int nvals,
			    const char **pgnames,
			    unsigned int npgnames)
{}

/**
 * pcs_get_pin_by_offset() - get a pin index based on the register offset
 * @pcs: pcs driver instance
 * @offset: register offset from the base
 *
 * Note that this is OK as long as the pins are in a static array.
 */
static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
{}

/*
 * check whether data matches enable bits or disable bits
 * Return value: 1 for matching enable bits, 0 for matching disable bits,
 *               and negative value for matching failure.
 */
static int pcs_config_match(unsigned data, unsigned enable, unsigned disable)
{}

static void add_config(struct pcs_conf_vals **conf, enum pin_config_param param,
		       unsigned value, unsigned enable, unsigned disable,
		       unsigned mask)
{}

static void add_setting(unsigned long **setting, enum pin_config_param param,
			unsigned arg)
{}

/* add pinconf setting with 2 parameters */
static void pcs_add_conf2(struct pcs_device *pcs, struct device_node *np,
			  const char *name, enum pin_config_param param,
			  struct pcs_conf_vals **conf, unsigned long **settings)
{}

/* add pinconf setting with 4 parameters */
static void pcs_add_conf4(struct pcs_device *pcs, struct device_node *np,
			  const char *name, enum pin_config_param param,
			  struct pcs_conf_vals **conf, unsigned long **settings)
{}

static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
			     struct pcs_function *func,
			     struct pinctrl_map **map)

{}

/**
 * pcs_parse_one_pinctrl_entry() - parses a device tree mux entry
 * @pcs: pinctrl driver instance
 * @np: device node of the mux entry
 * @map: map entry
 * @num_maps: number of map
 * @pgnames: pingroup names
 *
 * Note that this binding currently supports only sets of one register + value.
 *
 * Also note that this driver tries to avoid understanding pin and function
 * names because of the extra bloat they would cause especially in the case of
 * a large number of pins. This driver just sets what is specified for the board
 * in the .dts file. Further user space debugging tools can be developed to
 * decipher the pin and function names using debugfs.
 *
 * If you are concerned about the boot time, set up the static pins in
 * the bootloader, and only set up selected pins as device tree entries.
 */
static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
						struct device_node *np,
						struct pinctrl_map **map,
						unsigned *num_maps,
						const char **pgnames)
{}

static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
						struct device_node *np,
						struct pinctrl_map **map,
						unsigned *num_maps,
						const char **pgnames)
{}
/**
 * pcs_dt_node_to_map() - allocates and parses pinctrl maps
 * @pctldev: pinctrl instance
 * @np_config: device tree pinmux entry
 * @map: array of map entries
 * @num_maps: number of maps
 */
static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
				struct device_node *np_config,
				struct pinctrl_map **map, unsigned *num_maps)
{}

/**
 * pcs_irq_free() - free interrupt
 * @pcs: pcs driver instance
 */
static void pcs_irq_free(struct pcs_device *pcs)
{}

/**
 * pcs_free_resources() - free memory used by this driver
 * @pcs: pcs driver instance
 */
static void pcs_free_resources(struct pcs_device *pcs)
{}

static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
{}

/**
 * struct pcs_interrupt
 * @reg:	virtual address of interrupt register
 * @hwirq:	hardware irq number
 * @irq:	virtual irq number
 * @node:	list node
 */
struct pcs_interrupt {};

/**
 * pcs_irq_set() - enables or disables an interrupt
 * @pcs_soc: SoC specific settings
 * @irq: interrupt
 * @enable: enable or disable the interrupt
 *
 * Note that this currently assumes one interrupt per pinctrl
 * register that is typically used for wake-up events.
 */
static inline void pcs_irq_set(struct pcs_soc_data *pcs_soc,
			       int irq, const bool enable)
{}

/**
 * pcs_irq_mask() - mask pinctrl interrupt
 * @d: interrupt data
 */
static void pcs_irq_mask(struct irq_data *d)
{}

/**
 * pcs_irq_unmask() - unmask pinctrl interrupt
 * @d: interrupt data
 */
static void pcs_irq_unmask(struct irq_data *d)
{}

/**
 * pcs_irq_set_wake() - toggle the suspend and resume wake up
 * @d: interrupt data
 * @state: wake-up state
 *
 * Note that this should be called only for suspend and resume.
 * For runtime PM, the wake-up events should be enabled by default.
 */
static int pcs_irq_set_wake(struct irq_data *d, unsigned int state)
{}

/**
 * pcs_irq_handle() - common interrupt handler
 * @pcs_soc: SoC specific settings
 *
 * Note that this currently assumes we have one interrupt bit per
 * mux register. This interrupt is typically used for wake-up events.
 * For more complex interrupts different handlers can be specified.
 */
static int pcs_irq_handle(struct pcs_soc_data *pcs_soc)
{}

/**
 * pcs_irq_handler() - handler for the shared interrupt case
 * @irq: interrupt
 * @d: data
 *
 * Use this for cases where multiple instances of
 * pinctrl-single share a single interrupt like on omaps.
 */
static irqreturn_t pcs_irq_handler(int irq, void *d)
{}

/**
 * pcs_irq_chain_handler() - handler for the dedicated chained interrupt case
 * @desc: interrupt descriptor
 *
 * Use this if you have a separate interrupt for each
 * pinctrl-single instance.
 */
static void pcs_irq_chain_handler(struct irq_desc *desc)
{}

static int pcs_irqdomain_map(struct irq_domain *d, unsigned int irq,
			     irq_hw_number_t hwirq)
{}

static const struct irq_domain_ops pcs_irqdomain_ops =;

/**
 * pcs_irq_init_chained_handler() - set up a chained interrupt handler
 * @pcs: pcs driver instance
 * @np: device node pointer
 */
static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
					struct device_node *np)
{}

static int pcs_save_context(struct pcs_device *pcs)
{}

static void pcs_restore_context(struct pcs_device *pcs)
{}

static int pinctrl_single_suspend_noirq(struct device *dev)
{}

static int pinctrl_single_resume_noirq(struct device *dev)
{}

static DEFINE_NOIRQ_DEV_PM_OPS(pinctrl_single_pm_ops,
			       pinctrl_single_suspend_noirq,
			       pinctrl_single_resume_noirq);

/**
 * pcs_quirk_missing_pinctrl_cells - handle legacy binding
 * @pcs: pinctrl driver instance
 * @np: device tree node
 * @cells: number of cells
 *
 * Handle legacy binding with no #pinctrl-cells. This should be
 * always two pinctrl-single,bit-per-mux and one for others.
 * At some point we may want to consider removing this.
 */
static int pcs_quirk_missing_pinctrl_cells(struct pcs_device *pcs,
					   struct device_node *np,
					   int cells)
{}

static int pcs_probe(struct platform_device *pdev)
{}

static void pcs_remove(struct platform_device *pdev)
{}

static const struct pcs_soc_data pinctrl_single_omap_wkup =;

static const struct pcs_soc_data pinctrl_single_dra7 =;

static const struct pcs_soc_data pinctrl_single_am437x =;

static const struct pcs_soc_data pinctrl_single_am654 =;

static const struct pcs_soc_data pinctrl_single_j7200 =;

static const struct pcs_soc_data pinctrl_single =;

static const struct pcs_soc_data pinconf_single =;

static const struct of_device_id pcs_of_match[] =;
MODULE_DEVICE_TABLE(of, pcs_of_match);

static struct platform_driver pcs_driver =;

module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();