This is an automated email from the ASF dual-hosted git repository. btashton pushed a commit to branch pci in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 0d4e050b04d6cad5c72c8ffb0d5196366d4e3116 Author: Yang Chung-Fan <sonic.tw...@gmail.com> AuthorDate: Mon May 4 18:44:11 2020 +0900 pcie: add framework --- Kconfig | 35 +++++ drivers/Kconfig | 1 + drivers/Makefile | 1 + drivers/pcie/Kconfig | 11 ++ drivers/pcie/Make.defs | 32 +++++ drivers/pcie/pcie_root.c | 354 ++++++++++++++++++++++++++++++++++++++++++++++ include/debug.h | 18 +++ include/nuttx/pcie/pcie.h | 324 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 776 insertions(+) diff --git a/Kconfig b/Kconfig index a9e4cb0..24019ba 100644 --- a/Kconfig +++ b/Kconfig @@ -1661,6 +1661,41 @@ config DEBUG_WATCHDOG_INFO Enable watchdog time informational output to SYSLOG. endif # DEBUG_WATCHDOG + +config DEBUG_PCIE + bool "PCI-E Debug Features" + default n + depends on PCIE + ---help--- + Enable PCIE driver debug features. + + Support for this debug option is architecture-specific and may not + be available for some MCUs. + +if DEBUG_PCIE + +config DEBUG_PCIE_ERROR + bool "PCI-E Error Output" + default n + depends on DEBUG_ERROR + ---help--- + Enable PCI-E driver error output to SYSLOG. + +config DEBUG_PCIE_WARN + bool "PCI-E Warnings Output" + default n + depends on DEBUG_WARN + ---help--- + Enable PCI-E driver warning output to SYSLOG. + +config DEBUG_PCIE_INFO + bool "PCI-E Informational Output" + default n + depends on DEBUG_INFO + ---help--- + Enable PCI-E driver informational output to SYSLOG. + +endif # DEBUG_PCIE endif # DEBUG_FEATURES config ARCH_HAVE_STACKCHECK diff --git a/drivers/Kconfig b/drivers/Kconfig index 5220a94..513d3ea 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -107,3 +107,4 @@ source drivers/1wire/Kconfig source drivers/syslog/Kconfig source drivers/platform/Kconfig source drivers/rf/Kconfig +source drivers/pcie/Kconfig diff --git a/drivers/Makefile b/drivers/Makefile index 3e355c5..4a2e9eb 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -83,6 +83,7 @@ include wireless$(DELIM)Make.defs include contactless$(DELIM)Make.defs include 1wire$(DELIM)Make.defs include rf$(DELIM)Make.defs +include pcie$(DELIM)Make.defs ifeq ($(CONFIG_SPECIFIC_DRIVERS),y) include platform$(DELIM)Make.defs diff --git a/drivers/pcie/Kconfig b/drivers/pcie/Kconfig new file mode 100644 index 0000000..d4138ff --- /dev/null +++ b/drivers/pcie/Kconfig @@ -0,0 +1,11 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config PCIE + bool "Support for PCI-E Bus" + default n + ---help--- + Enables support for the PCI-E bus. + Backend bust be provided by per-arch or per-board implementation.. diff --git a/drivers/pcie/Make.defs b/drivers/pcie/Make.defs new file mode 100644 index 0000000..68efee8 --- /dev/null +++ b/drivers/pcie/Make.defs @@ -0,0 +1,32 @@ +############################################################################ +# drivers/pcie/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 CAN support + +ifeq ($(CONFIG_PCIE),y) + +CSRCS += pcie_root.c + +# Include PCIE device driver build support + +DEPPATH += --dep-path pcie +VPATH += :pcie +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)pcie} +endif diff --git a/drivers/pcie/pcie_root.c b/drivers/pcie/pcie_root.c new file mode 100644 index 0000000..8764492 --- /dev/null +++ b/drivers/pcie/pcie_root.c @@ -0,0 +1,354 @@ +/**************************************************************************** + * nuttx/drivers/pcie/pcie_root.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 <nuttx/config.h> + +#include <assert.h> +#include <errno.h> +#include <debug.h> + +#include <nuttx/pcie/pcie.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +struct pcie_dev_type_s *pci_device_types[] = +{ + NULL, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pcie_initialize + * + * Description: + * Initialize the PCI-E bus and enumerate the devices with give devices + * type array + * + * Input Parameters: + * bus - An PCIE bus + * types - A array of PCIE device types + * num - Number of device types + * + * Returned Value: + * OK if the driver was successfully register; A negated errno value is + * returned on any failure. + * + ****************************************************************************/ + +int pcie_initialize(FAR struct pcie_bus_s *bus) +{ + return bus->ops->pcie_enumerate(bus, pci_device_types); +} + +/**************************************************************************** + * Name: pci_enable_device + * + * Description: + * Enable device with flags + * + * Input Parameters: + * bdf - device BDF + * flags - device ability to be enabled + * + * Return value: + * -EINVAL: error + * OK: OK + * + ****************************************************************************/ + +int pci_enable_device(FAR struct pcie_dev_s *dev, uint32_t flags) +{ + uint16_t old_cmd; + uint16_t cmd; + + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_COMMAND, &old_cmd, 2); + + cmd = old_cmd | flags; + + dev->bus->ops->pci_cfg_write(dev, PCI_CFG_COMMAND, &cmd, 2); + + pciinfo("%02x:%02x.%x, CMD: %x -> %x\n", + dev->bdf >> 8, (dev->bdf >> 3) & 0x1f, dev->bdf & 0x3, + old_cmd, cmd); + + return OK; +} + +/**************************************************************************** + * Name: pci_find_cap + * + * Description: + * Search through the PCI-e device capability list to find given capability. + * + * Input Parameters: + * dev - Device + * cap - Bitmask of capability + * + * Returned Value: + * -1: Capability not supported + * other: the offset in PCI configuration space to the capability structure + * + ****************************************************************************/ + +int pci_find_cap(FAR struct pcie_dev_s *dev, uint16_t cap) +{ + uint8_t pos = PCI_CFG_CAP_PTR - 1; + uint16_t status; + uint8_t rcap; + + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_STATUS, &status, 2); + + if (!(status & PCI_STS_CAPS)) + return -EINVAL; + + while (1) + { + dev->bus->ops->pci_cfg_read(dev, pos + 1, &pos, 1); + if (pos == 0) + return -EINVAL; + + dev->bus->ops->pci_cfg_read(dev, pos, &rcap, 1); + + if (rcap == cap) + return pos; + } +} + +/**************************************************************************** + * Name: pci_get_bar + * + * Description: + * Get a 32 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * ret - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_get_bar(FAR struct pcie_dev_s *dev, uint32_t bar, + uint32_t *ret) +{ + if (bar > 5) + return -EINVAL; + + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, ret, 4); + + return OK; +} + +/**************************************************************************** + * Name: pci_get_bar64 + * + * Description: + * Get a 64 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * ret - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_get_bar64(FAR struct pcie_dev_s *dev, uint32_t bar, + uint64_t *ret) +{ + if (bar > 5 || ((bar % 2) != 0)) + return -EINVAL; + + uint32_t barmem1; + uint32_t barmem2; + + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4); + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4); + + *ret = ((uint64_t)barmem2 << 32) | barmem1; + + return OK; +} + +/**************************************************************************** + * Name: pci_set_bar + * + * Description: + * Set a 32 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * val - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_set_bar(FAR struct pcie_dev_s *dev, uint32_t bar, + uint32_t val) +{ + if (bar > 5) + return -EINVAL; + + dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4, &val, 4); + + return OK; +} + +/**************************************************************************** + * Name: pci_set_bar64 + * + * Description: + * Set a 64 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * val - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_set_bar64(FAR struct pcie_dev_s *dev, uint32_t bar, + uint64_t val) +{ + if (bar > 5 || ((bar % 2) != 0)) + return -EINVAL; + + uint32_t barmem1 = (uint32_t)val; + uint32_t barmem2 = (uint32_t)(val >> 32); + + dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4); + dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4); + + return OK; +} + +/**************************************************************************** + * Name: pci_map_bar + * + * Description: + * Map address in a 32 bits bar in the flat memory address space + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * length - Map length, multiple of PAGE_SIZE + * ret - Bar Content if not NULL + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t bar, + unsigned long length, uint32_t *ret) +{ + if (bar > 5) + return -EINVAL; + + uint32_t barmem; + + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem, 4); + + if (((bar % 2) == 0 && + (barmem & PCI_BAR_64BIT) == PCI_BAR_64BIT) || + (barmem & PCI_BAR_IO) == PCI_BAR_IO) + return -EINVAL; + + if (!dev->bus->ops->pci_map_bar) + return -EINVAL; + + dev->bus->ops->pci_map_bar(dev, barmem, length); + + if (ret) + *ret = barmem; + + return OK; +} + +/**************************************************************************** + * Name: pci_map_bar64 + * + * Description: + * Map address in a 64 bits bar in the flat memory address space + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * length - Map length, multiple of PAGE_SIZE + * ret - Bar Content if not NULL + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_map_bar64(FAR struct pcie_dev_s *dev, uint32_t bar, + unsigned long length, uint64_t *ret) +{ + if (bar > 5 || ((bar % 2) != 0)) + return -EINVAL; + + uint32_t barmem1; + uint32_t barmem2; + uint64_t barmem; + + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4); + + if ((barmem1 & PCI_BAR_64BIT) != PCI_BAR_64BIT || + (barmem1 & PCI_BAR_IO) == PCI_BAR_IO) + return -EINVAL; + + dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4); + + barmem = ((uint64_t)barmem2 << 32) | barmem1; + + if (!dev->bus->ops->pci_map_bar64) + return -EINVAL; + + dev->bus->ops->pci_map_bar64(dev, barmem, length); + + if (ret) + *ret = barmem; + + return OK; +} diff --git a/include/debug.h b/include/debug.h index f4bc4d3..07a83b2 100644 --- a/include/debug.h +++ b/include/debug.h @@ -721,6 +721,24 @@ # define wdinfo _none #endif +#ifdef CONFIG_DEBUG_PCIE_ERROR +# define pcierr _err +#else +# define pcierr _none +#endif + +#ifdef CONFIG_DEBUG_PCIE_WARN +# define pciwarn _warn +#else +# define pciwarn _none +#endif + +#ifdef CONFIG_DEBUG_PCIE_INFO +# define pciinfo _info +#else +# define pciinfo _none +#endif + /* Buffer dumping macros do not depend on varargs */ #ifdef CONFIG_DEBUG_ERROR diff --git a/include/nuttx/pcie/pcie.h b/include/nuttx/pcie/pcie.h new file mode 100644 index 0000000..62adbb7 --- /dev/null +++ b/include/nuttx/pcie/pcie.h @@ -0,0 +1,324 @@ +/**************************************************************************** + * include/nuttx/pcie/pcie.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_PCIE_PCIE_H +#define __INCLUDE_NUTTX_PCIE_PCIE_H + +#ifdef CONFIG_PCIE + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <stdint.h> + +#include <nuttx/fs/ioctl.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PCI_CFG_VENDOR_ID 0x000 +#define PCI_CFG_DEVICE_ID 0x002 +#define PCI_CFG_COMMAND 0x004 +# define PCI_CMD_IO (1 << 0) +# define PCI_CMD_MEM (1 << 1) +# define PCI_CMD_MASTER (1 << 2) +# define PCI_CMD_INTX_OFF (1 << 10) +#define PCI_CFG_STATUS 0x006 +# define PCI_STS_INT (1 << 3) +# define PCI_STS_CAPS (1 << 4) +#define PCI_CFG_REVERSION 0x008 +#define PCI_CFG_BAR 0x010 +# define PCI_BAR_IO 0x1 +# define PCI_BAR_1M 0x2 +# define PCI_BAR_64BIT 0x4 +#define PCI_CFG_CAP_PTR 0x034 + +#define PCI_ID_ANY 0xffff +#define PCI_DEV_CLASS_OTHER 0xff + +#define PCI_CAP_PM 0x01 +#define PCI_CAP_MSI 0x05 +#define PCI_CAP_MSIX 0x11 +# define MSIX_CTRL_ENABLE 0x8000 +# define MSIX_CTRL_FMASK 0x4000 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The PCIE driver interface */ + +struct pcie_bus_s; +struct pcie_dev_type_s; +struct pcie_dev_s; + +/* Bus related operations */ + +struct pcie_bus_ops_s +{ + CODE int (*pcie_enumerate)(FAR struct pcie_bus_s *bus, + FAR struct pcie_dev_type_s **types); + + CODE int (*pci_cfg_write)(FAR struct pcie_dev_s *dev, uintptr_t addr, + FAR const void *buffer, unsigned int size); + + CODE int (*pci_cfg_read)(FAR struct pcie_dev_s *dev, uintptr_t addr, + FAR void *buffer, unsigned int size); + + CODE int (*pci_map_bar)(FAR struct pcie_dev_s *dev, uint32_t addr, + unsigned long length); + + CODE int (*pci_map_bar64)(FAR struct pcie_dev_s *dev, uint64_t addr, + unsigned long length); + + CODE int (*pci_msi_register)(FAR struct pcie_dev_s *dev, + uint16_t vector); + + CODE int (*pci_msix_register)(FAR struct pcie_dev_s *dev, + uint32_t vector, uint32_t index); +}; + +/* PCIE bus private data. */ + +struct pcie_bus_s +{ + FAR const struct pcie_bus_ops_s *ops; /* operations */ +}; + +/* PCIE device type, defines by vendor ID and device ID */ + +struct pcie_dev_type_s +{ + uint16_t vendor; /* Device vendor ID */ + uint16_t device; /* Device ID */ + uint32_t class_rev; /* Device reversion */ + const char *name; /* Human readable name */ + + /* Call back function when a device is probed */ + + CODE int (*probe)(FAR struct pcie_bus_s *bus, + FAR struct pcie_dev_type_s *type, uint16_t bdf); +}; + +/* PCIE device private data. */ + +struct pcie_dev_s +{ + FAR struct pcie_bus_s *bus; + FAR struct pcie_dev_type_s *type; + uint16_t bdf; +}; + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: pcie_initialize + * + * Description: + * Initialize the PCI-E bus and enumerate the devices with give devices + * type array + * + * Input Parameters: + * bus - An PCIE bus + * types - A array of PCIE device types + * num - Number of device types + * + * Returned Value: + * OK if the driver was successfully register; A negated errno value is + * returned on any failure. + * + ****************************************************************************/ + +int pcie_initialize(FAR struct pcie_bus_s *bus); + +/**************************************************************************** + * Name: pci_enable_device + * + * Description: + * Enable device with flags + * + * Input Parameters: + * dev - device + * flags - device ability to be enabled + * + * Return value: + * -EINVAL: error + * OK: OK + * + ****************************************************************************/ + +int pci_enable_device(FAR struct pcie_dev_s *dev, uint32_t flags); + +/**************************************************************************** + * Name: pci_find_cap + * + * Description: + * Search through the PCI-e device capability list to find given capability. + * + * Input Parameters: + * dev - Device + * cap - Bitmask of capability + * + * Returned Value: + * -1: Capability not supported + * other: the offset in PCI configuration space to the capability structure + * + ****************************************************************************/ + +int pci_find_cap(FAR struct pcie_dev_s *dev, uint16_t cap); + +/**************************************************************************** + * Name: pci_map_bar + * + * Description: + * Map address in a 32 bits bar in the flat memory address space + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * length - Map length, multiple of PAGE_SIZE + * ret - Bar Contentif not NULL + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t bar, + unsigned long length, uint32_t *ret); + +/**************************************************************************** + * Name: pci_map_bar64 + * + * Description: + * Map address in a 64 bits bar in the flat memory address space + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * length - Map length, multiple of PAGE_SIZE + * ret - Bar Content if not NULL + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_map_bar64(FAR struct pcie_dev_s *dev, uint32_t bar, + unsigned long length, uint64_t *ret); + +/**************************************************************************** + * Name: pci_get_bar + * + * Description: + * Get a 32 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * ret - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_get_bar(FAR struct pcie_dev_s *dev, uint32_t bar, + uint32_t *ret); + +/**************************************************************************** + * Name: pci_get_bar64 + * + * Description: + * Get a 64 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * ret - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_get_bar64(FAR struct pcie_dev_s *dev, uint32_t bar, + uint64_t *ret); + +/**************************************************************************** + * Name: pci_set_bar + * + * Description: + * Set a 32 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * val - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_set_bar(FAR struct pcie_dev_s *dev, uint32_t bar, + uint32_t val); + +/**************************************************************************** + * Name: pci_set_bar64 + * + * Description: + * Set a 64 bits bar + * + * Input Parameters: + * dev - Device private data + * bar - Bar number + * val - Bar Content + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +int pci_set_bar64(FAR struct pcie_dev_s *dev, uint32_t bar, + uint64_t val); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif +#endif /* __INCLUDE_NUTTX_I2C_I2C_MASTER_H */