/* * 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(…) …;