From 1d5f43664d849b1b5eae89b67ff6bce06e295e4b Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Wed, 20 Sep 2023 15:27:12 +0800 Subject: [PATCH] driver/pinctl: add pinctrl framework Signed-off-by: dongjiuzhu1 --- Documentation/components/drivers/index.rst | 4 + .../components/drivers/special/index.rst | 1 + .../components/drivers/special/pinctrl.rst | 38 +++ drivers/Kconfig | 1 + drivers/Makefile | 1 + drivers/pinctrl/CMakeLists.txt | 27 ++ drivers/pinctrl/Kconfig | 15 ++ drivers/pinctrl/Make.defs | 29 ++ drivers/pinctrl/pinctrl.c | 245 +++++++++++++++++ include/nuttx/fs/ioctl.h | 8 + include/nuttx/pinctrl/pinctrl.h | 253 ++++++++++++++++++ 11 files changed, 622 insertions(+) create mode 100644 Documentation/components/drivers/special/pinctrl.rst create mode 100644 drivers/pinctrl/CMakeLists.txt create mode 100644 drivers/pinctrl/Kconfig create mode 100644 drivers/pinctrl/Make.defs create mode 100644 drivers/pinctrl/pinctrl.c create mode 100644 include/nuttx/pinctrl/pinctrl.h diff --git a/Documentation/components/drivers/index.rst b/Documentation/components/drivers/index.rst index 26697f597f..25d8274333 100644 --- a/Documentation/components/drivers/index.rst +++ b/Documentation/components/drivers/index.rst @@ -178,6 +178,10 @@ Subdirectories of ``nuttx/drivers`` Note Driver Support. +* ``pinctrl/`` :doc:`special/pinctrl` + + Configure and manage pin. + * ``pipes/`` :doc:`special/pipes` FIFO and named pipe drivers. diff --git a/Documentation/components/drivers/special/index.rst b/Documentation/components/drivers/special/index.rst index 0682006370..bfb5bd0cdb 100644 --- a/Documentation/components/drivers/special/index.rst +++ b/Documentation/components/drivers/special/index.rst @@ -48,6 +48,7 @@ following section. usrsock.rst mmcsd.rst net/index.rst + pinctrl.rst pipes.rst power/index.rst virtio.rst diff --git a/Documentation/components/drivers/special/pinctrl.rst b/Documentation/components/drivers/special/pinctrl.rst new file mode 100644 index 0000000000..4dd9789dd7 --- /dev/null +++ b/Documentation/components/drivers/special/pinctrl.rst @@ -0,0 +1,38 @@ +====================== +Pinctrl Device Drivers +====================== + +- The Pinctl driver framework allows applications and drivers to flexibly configure + and manage pin parameters such as functionality, strength, driver type, and slewrate + (voltage transition speed). This framework significantly enhances the flexibility + and configurability of the system in terms of hardware interface control. + +- ``include/nuttx/pinctrl/pinctrl.h`` + All structures and APIs needed to work with pinctrl drivers are provided in + this header file. + +- ``struct pinctrl_dev_s`` and ``struct pinctrl_ops_s``. + Each pinctrl device driver must implement an instance of ``struct pinctrl_dev_s``. + And the ``struct pinctrl_ops_s`` defines a call table with the following methods: + + #. **set_function**: Configures the pin's multiplexing (Mux) function, allowing it + to be set as a specific hardware interface (e.g., UART, SPI, I2C) or as a + general-purpose GPIO pin. + #. **set_strength**: Allows the user to configure the pin's drive strength to meet + the requirements of different hardware interfaces. + #. **set_driver**: Controls the pin's driver type, such as push-pull output or + open-drain output. + #. **set_slewrate**: Enables the configuration of pin slew rate, which is crucial + for high-speed digital signal transmission, optimizing signal rise and fall times. + #. **select_gpio**: Configures the pin function as GPIO. + +- Convenience macros are provided to map these operations directly: + ``PINCTRL_SETFUNCTION``,``PINCTRL_SETSTRENGTH``,``PINCTRL_SETDRIVER``,``PINCTRL_SETSLEWRATE``, + ``PINCTRL_SELECTGPIO``. + +- Application developers can configure and control pins by opening /dev/pinctrl0 nodes + and using the ioctl system call. + cmd: PINCTRLC_SETFUNCTION, PINCTRLC_SETSTRENGTH, PINCTRLC_SETDRIVER, PINCTRLC_SETSLEWRATE, + PINCTRLC_SELECTGPIO. + parameters: struct pinctrl_param_s. + diff --git a/drivers/Kconfig b/drivers/Kconfig index 46ddf14cf1..d5e9f18608 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -33,6 +33,7 @@ source "drivers/eeprom/Kconfig" source "drivers/efuse/Kconfig" source "drivers/net/Kconfig" source "drivers/note/Kconfig" +source "drivers/pinctrl/Kconfig" source "drivers/pipes/Kconfig" source "drivers/power/Kconfig" source "drivers/regmap/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 1461e7f223..6dbc5563f0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -52,6 +52,7 @@ include eeprom/Make.defs include efuse/Make.defs include net/Make.defs include note/Make.defs +include pinctrl/Make.defs include pipes/Make.defs include power/Make.defs include regmap/Make.defs diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt new file mode 100644 index 0000000000..cd7e28a62b --- /dev/null +++ b/drivers/pinctrl/CMakeLists.txt @@ -0,0 +1,27 @@ +# ############################################################################## +# drivers/pinctrl/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +set(SRCS) + +if(CONFIG_PINCTRL) + list(APPEND SRCS pinctrl.c) +endif() + +target_sources(drivers PRIVATE ${SRCS}) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig new file mode 100644 index 0000000000..3ce0f90473 --- /dev/null +++ b/drivers/pinctrl/Kconfig @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menu "Pinctrl Support" + +config PINCTRL + bool "PINCTRL Driver Support" + default n + ---help--- + This selection enables selection of common PINCTRL options. This option + should be enabled by all platforms that support PINCTRL interfaces. + See include/nuttx/pinctrl/pinctrl.h for further PINCTRL driver information. +endmenu diff --git a/drivers/pinctrl/Make.defs b/drivers/pinctrl/Make.defs new file mode 100644 index 0000000000..91f9a0dfe3 --- /dev/null +++ b/drivers/pinctrl/Make.defs @@ -0,0 +1,29 @@ +############################################################################ +# drivers/pinctrl/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Don't build anything if there is no PINCTRL support + +ifeq ($(CONFIG_PINCTRL),y) +CSRCS += pinctrl.c + +DEPPATH += --dep-path pinctrl +VPATH += :pinctrl +CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)pinctrl +endif diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c new file mode 100644 index 0000000000..b241be1c26 --- /dev/null +++ b/drivers/pinctrl/pinctrl.c @@ -0,0 +1,245 @@ +/**************************************************************************** + * drivers/pinctrl/pinctrl.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int pinctrl_open(FAR struct file *filep); +static int pinctrl_close(FAR struct file *filep); +static ssize_t pinctrl_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t pinctrl_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int pinctrl_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_pinctrl_drvrops = +{ + pinctrl_open, /* open */ + pinctrl_close, /* close */ + pinctrl_read, /* read */ + pinctrl_write, /* write */ + NULL, /* seek */ + pinctrl_ioctl /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pinctrl_open + * + * Description: + * Standard character driver open method. + * + ****************************************************************************/ + +static int pinctrl_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: pinctrl_close + * + * Description: + * Standard character driver close method. + * + ****************************************************************************/ + +static int pinctrl_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: pinctrl_read + * + * Description: + * Standard character driver read method. + * + ****************************************************************************/ + +static ssize_t pinctrl_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + return 0; +} + +/**************************************************************************** + * Name: pinctrl_write + * + * Description: + * Standard character driver write method. + * + ****************************************************************************/ + +static ssize_t pinctrl_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return buflen; +} + +/**************************************************************************** + * Name: pinctrl_ioctl + * + * Description: + * Standard character driver ioctl method. + * + ****************************************************************************/ + +static int pinctrl_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct pinctrl_dev_s *dev; + FAR struct pinctrl_param_s *param; + int ret; + + DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + inode = filep->f_inode; + DEBUGASSERT(inode->i_private != NULL); + dev = inode->i_private; + + switch (cmd) + { + /* Command: PINCTRLC_SETFUNCTION + * Description: Set the mux function of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_param_s + */ + + case PINCTRLC_SETFUNCTION: + { + param = (FAR struct pinctrl_param_s *)((uintptr_t)arg); + ret = PINCTRL_SETFUNCTION(dev, param->pin, param->para.function); + } + break; + + /* Command: PINCTRLC_SETSTRENGTH + * Description: Set the driver strength of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_param_s + */ + + case PINCTRLC_SETSTRENGTH: + { + param = (FAR struct pinctrl_param_s *)((uintptr_t)arg); + ret = PINCTRL_SETSTRENGTH(dev, param->pin, param->para.strength); + } + break; + + /* Command: PINCTRLC_SETDRIVER + * Description: Set the driver type of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_param_s + */ + + case PINCTRLC_SETDRIVER: + { + param = (FAR struct pinctrl_param_s *)((uintptr_t)arg); + ret = PINCTRL_SETDRIVER(dev, param->pin, param->para.type); + } + break; + + /* Command: PINCTRLC_SETSLEWRATE + * Description: Set slewrate of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_param_s + */ + + case PINCTRLC_SETSLEWRATE: + { + param = (FAR struct pinctrl_param_s *)((uintptr_t)arg); + ret = PINCTRL_SETSLEWRATE(dev, param->pin, param->para.slewrate); + } + break; + + /* Command: PINCTRLC_SELECTGPIO + * Description: Select gpio function of pinctrl pin + * Argument: The uint32_t pinctrl number + */ + + case PINCTRLC_SELECTGPIO: + { + ret = PINCTRL_SELECTGPIO(dev, arg); + } + break; + + /* Unrecognized command */ + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pinctrl_register + * + * Description: + * Register PINCTRL device driver. + * + ****************************************************************************/ + +int pinctrl_register(FAR struct pinctrl_dev_s *dev, int minor) +{ + char devname[32]; + + snprintf(devname, 16, "/dev/pinctrl%u", (unsigned int)minor); + return register_driver(devname, &g_pinctrl_drvrops, 0666, dev); +} + +/**************************************************************************** + * Name: pinctrl_unregister + * + * Description: + * Unregister PINCTRL device driver. + * + ****************************************************************************/ + +void pinctrl_unregister(FAR struct pinctrl_dev_s *dev, int minor) +{ + char devname[32]; + + snprintf(devname, 16, "/dev/pinctrl%u", (unsigned int)minor); + (void)unregister_driver(devname); +} diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index 4b91c2d4f5..4d6c4b4853 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -101,6 +101,7 @@ #define _STEPIOBASE (0x3d00) /* Stepper device ioctl commands */ #define _FPGACFGBASE (0x3e00) /* FPGA configuration ioctl commands */ #define _FFIOCBASE (0x3f00) /* Force feedback ioctl commands */ +#define _PINCTRLBASE (0x4000) /* Pinctrl driver ioctl commands */ #define _PCIBASE (0x4100) /* Pci ioctl commands */ #define _WLIOCBASE (0x8b00) /* Wireless modules ioctl network commands */ @@ -732,6 +733,13 @@ #define _FFIOCVALID(c) (_IOC_TYPE(c)==_FFIOCBASE) #define _FFIOC(nr) _IOC(_FFIOCBASE,nr) +/* Pinctrl driver command definitions ***************************************/ + +/* see nuttx/include/pinctrl/pinctrl.h */ + +#define _PINCTRLIOCVALID(c) (_IOC_TYPE(c)==_PINCTRLBASE) +#define _PINCTRLIOC(nr) _IOC(_PINCTRLBASE,nr) + /**************************************************************************** * Public Type Definitions ****************************************************************************/ diff --git a/include/nuttx/pinctrl/pinctrl.h b/include/nuttx/pinctrl/pinctrl.h new file mode 100644 index 0000000000..8ef6e33914 --- /dev/null +++ b/include/nuttx/pinctrl/pinctrl.h @@ -0,0 +1,253 @@ +/**************************************************************************** + * include/nuttx/pinctrl/pinctrl.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_PINCTRL_PINCTRL_H +#define __INCLUDE_NUTTX_PINCTRL_PINCTRL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Command: PINCTRLC_SETFUNCTION + * Description: Set the mux function of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_iotrans_s + * + * Command: PINCTRLC_SETSTRENGTH + * Description: Set the driver strength of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_iotrans_s + * + * Command: PINCTRLC_SETDRIVER + * Description: Set the driver type of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_iotrans_s + * + * Command: PINCTRLC_SETSLEWRATE + * Description: Set slewrate of the pinctrl pin + * Argument: A pointer to an instance of struct pinctrl_iotrans_s + * + * Command: PINCTRLC_SELECTGPIO + * Description: Select gpio function of pinctrl pin + * Argument: The uint32_t pinctrl number + * + */ + +#define PINCTRLC_SETFUNCTION _PINCTRLIOC(1) +#define PINCTRLC_SETSTRENGTH _PINCTRLIOC(2) +#define PINCTRLC_SETDRIVER _PINCTRLIOC(3) +#define PINCTRLC_SETSLEWRATE _PINCTRLIOC(4) +#define PINCTRLC_SELECTGPIO _PINCTRLIOC(5) + +/* Access macros ************************************************************/ + +/**************************************************************************** + * Name: PINCTRL_SETFUNCTION + * + * Description: + * Set the mux function of the pinctrl pin. + * + * Input Parameters: + * dev - Device-specific state data. + * pin - the pinctrl controller number. + * function - the pinctrl pin function number. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#define PINCTRL_SETFUNCTION(dev, pin, function) ((dev)->ops->set_function(dev, pin, function)) + +/**************************************************************************** + * Name: PINCTRL_SETSTRENGTH + * + * Description: + * Set the driver strength of the pinctrl pin + * + * Input Parameters: + * dev - Device-specific state data. + * pin - the pinctrl controller number. + * strength - the pinctrl pin driver strength number. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#define PINCTRL_SETSTRENGTH(dev, pin, strength) ((dev)->ops->set_strength(dev, pin, strength)) + +/**************************************************************************** + * Name: PINCTRL_SETDRIVER + * + * Description: + * Set the driver type of the pinctrl pin + * + * Input Parameters: + * dev - Device-specific state data. + * pin - the pinctrl controller number. + * driver - the pinctrl_drivertype_e type. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#define PINCTRL_SETDRIVER(dev, pin, driver) ((dev)->ops->set_driver(dev, pin, driver)) + +/**************************************************************************** + * Name: PINCTRL_SETSLEWRATE + * + * Description: + * Set the slewrate of the pinctrl pin + * + * Input Parameters: + * dev - Device-specific state data. + * pin - the pinctrl controller number. + * slewrate - the slewsrate state. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#define PINCTRL_SETSLEWRATE(dev, pin, slewrate) ((dev)->ops->set_slewrate(dev, pin, slewrate)) + +/**************************************************************************** + * Name: PINCTRL_SELECTGPIO + * + * Description: + * Select gpio function the pinctrl pin + * + * Input Parameters: + * dev - Device-specific state data. + * pin - the pinctrl controller number. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#define PINCTRL_SELECTGPIO(dev, pin) ((dev)->ops->select_gpio(dev, pin)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Identifies the type of the pinctrl driver type */ + +enum pinctrl_drivertype_e +{ + BIAS_DISABLE = 0, + BIAS_PULLUP, + BIAS_PULLDOWN, + BIAS_STRONG_PULLDOWN, + BIAS_NDRIVERTYPES +}; + +/**************************************************************************** + * This describes pinctrl ioctl structure in pinctrl command operation. + * the follow command use this structure: + * PINCTRLC_SETFUNCTION, PINCTRLC_SETSTRENGTH, + * PINCTRLC_SETDRIVER, PINCTRLC_SETSLEWRATE. + ****************************************************************************/ + +struct pinctrl_param_s +{ + uint32_t pin; + union + { + uint32_t function; + uint32_t strength; + enum pinctrl_drivertype_e type; + uint32_t slewrate; + } para; +}; + +/* pinctrl interface methods */ + +struct pinctrl_dev_s; +struct pinctrl_ops_s +{ + int (*set_function)(FAR struct pinctrl_dev_s *dev, uint32_t pin, + uint32_t function); + int (*set_strength)(FAR struct pinctrl_dev_s *dev, uint32_t pin, + uint32_t strength); + int (*set_driver)(FAR struct pinctrl_dev_s *dev, uint32_t pin, + enum pinctrl_drivertype_e type); + int (*set_slewrate)(FAR struct pinctrl_dev_s *dev, uint32_t pin, + uint32_t slewrate); + int (*select_gpio)(FAR struct pinctrl_dev_s *dev, uint32_t pin); +}; + +struct pinctrl_dev_s +{ + /* "Lower half" operations provided by the pinctrl lower half */ + + FAR const struct pinctrl_ops_s *ops; + + /* Internal storage used by the pinctrl may (internal to the pinctrl + * implementation). + */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: pinctrl_register + * + * Description: + * Register PINCTRL device driver. + * + ****************************************************************************/ + +int pinctrl_register(FAR struct pinctrl_dev_s *dev, int minor); + +/**************************************************************************** + * Name: pinctrl_unregister + * + * Description: + * Unregister PINCTRL device driver. + * + ****************************************************************************/ + +void pinctrl_unregister(FAR struct pinctrl_dev_s *dev, int minor); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_PINCTRL_PINCTRL_H */