doc: Remove duplicated documentation directory
Commit ad7061ed74 ("doc: Move device tree bindings documentation to
doc/device-tree-bindings") moved all device tree binding documentation
to doc/device-tree-bindings directory.
The current U-Boot project still have two documentation directories:
- doc/
- Documentation/
Move all documentation and sphinx files to doc directory so all content
can be in a common place.
Signed-off-by: Breno Lima <breno.lima@nxp.com>
This commit is contained in:
committed by
Tom Rini
parent
894e235f14
commit
656d8da9d2
124
doc/Makefile
Normal file
124
doc/Makefile
Normal file
@@ -0,0 +1,124 @@
|
||||
# -*- makefile -*-
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
subdir-y :=
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXOPTS =
|
||||
SPHINXDIRS = .
|
||||
_SPHINXDIRS = $(patsubst $(srctree)/doc/%/conf.py,%,$(wildcard $(srctree)/doc/*/conf.py))
|
||||
SPHINX_CONF = conf.py
|
||||
PAPER =
|
||||
BUILDDIR = $(obj)/output
|
||||
PDFLATEX = xelatex
|
||||
LATEXOPTS = -interaction=batchmode
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
|
||||
|
||||
ifeq ($(HAVE_SPHINX),0)
|
||||
|
||||
.DEFAULT:
|
||||
$(warning The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed and in PATH, or set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable.)
|
||||
@echo
|
||||
@./scripts/sphinx-pre-install
|
||||
@echo " SKIP Sphinx $@ target."
|
||||
|
||||
else # HAVE_SPHINX
|
||||
|
||||
# User-friendly check for pdflatex
|
||||
HAVE_PDFLATEX := $(shell if which $(PDFLATEX) >/dev/null 2>&1; then echo 1; else echo 0; fi)
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
KERNELDOC = $(srctree)/scripts/kernel-doc
|
||||
KERNELDOC_CONF = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC)
|
||||
ALLSPHINXOPTS = $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS)
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
# commands; the 'cmd' from scripts/Kbuild.include is not *loopable*
|
||||
loop_cmd = $(echo-cmd) $(cmd_$(1)) || exit;
|
||||
|
||||
# $2 sphinx builder e.g. "html"
|
||||
# $3 name of the build subfolder / e.g. "media", used as:
|
||||
# * dest folder relative to $(BUILDDIR) and
|
||||
# * cache folder relative to $(BUILDDIR)/.doctrees
|
||||
# $4 dest subfolder e.g. "man" for man pages at media/man
|
||||
# $5 reST source folder relative to $(srctree)/$(src),
|
||||
# e.g. "media" for the linux-tv book-set at ./doc/media
|
||||
|
||||
quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
|
||||
cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=doc/media $2 && \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
|
||||
$(SPHINXBUILD) \
|
||||
-b $2 \
|
||||
-c $(abspath $(srctree)/$(src)) \
|
||||
-d $(abspath $(BUILDDIR)/.doctrees/$3) \
|
||||
-D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) \
|
||||
$(ALLSPHINXOPTS) \
|
||||
$(abspath $(srctree)/$(src)/$5) \
|
||||
$(abspath $(BUILDDIR)/$3/$4)
|
||||
|
||||
htmldocs:
|
||||
@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
|
||||
|
||||
linkcheckdocs:
|
||||
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var)))
|
||||
|
||||
latexdocs:
|
||||
@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
|
||||
|
||||
ifeq ($(HAVE_PDFLATEX),0)
|
||||
|
||||
pdfdocs:
|
||||
$(warning The '$(PDFLATEX)' command was not found. Make sure you have it installed and in PATH to produce PDF output.)
|
||||
@echo " SKIP Sphinx $@ target."
|
||||
|
||||
else # HAVE_PDFLATEX
|
||||
|
||||
pdfdocs: latexdocs
|
||||
$(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex || exit;)
|
||||
|
||||
endif # HAVE_PDFLATEX
|
||||
|
||||
epubdocs:
|
||||
@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,epub,$(var),epub,$(var)))
|
||||
|
||||
xmldocs:
|
||||
@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,xml,$(var),xml,$(var)))
|
||||
|
||||
endif # HAVE_SPHINX
|
||||
|
||||
# The following targets are independent of HAVE_SPHINX, and the rules should
|
||||
# work or silently pass without Sphinx.
|
||||
|
||||
refcheckdocs:
|
||||
$(Q)cd $(srctree);scripts/documentation-file-ref-check
|
||||
|
||||
cleandocs:
|
||||
$(Q)rm -rf $(BUILDDIR)
|
||||
$(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=doc/media clean
|
||||
|
||||
dochelp:
|
||||
@echo ' Linux kernel internal documentation in different formats from ReST:'
|
||||
@echo ' htmldocs - HTML'
|
||||
@echo ' latexdocs - LaTeX'
|
||||
@echo ' pdfdocs - PDF'
|
||||
@echo ' epubdocs - EPUB'
|
||||
@echo ' xmldocs - XML'
|
||||
@echo ' linkcheckdocs - check for broken external links (will connect to external hosts)'
|
||||
@echo ' refcheckdocs - check for references to non-existing files under Documentation'
|
||||
@echo ' cleandocs - clean all generated files'
|
||||
@echo
|
||||
@echo ' make SPHINXDIRS="s1 s2" [target] Generate only docs of folder s1, s2'
|
||||
@echo ' valid values for SPHINXDIRS are: $(_SPHINXDIRS)'
|
||||
@echo
|
||||
@echo ' make SPHINX_CONF={conf-file} [target] use *additional* sphinx-build'
|
||||
@echo ' configuration. This is e.g. useful to build with nit-picking config.'
|
||||
@echo
|
||||
@echo ' Default location for the generated documents is doc/output'
|
||||
528
doc/conf.py
Normal file
528
doc/conf.py
Normal file
@@ -0,0 +1,528 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# The U-Boot documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Feb 12 13:51:46 2016.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import sphinx
|
||||
|
||||
# Get Sphinx version
|
||||
major, minor, patch = sphinx.version_info[:3]
|
||||
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('sphinx'))
|
||||
from load_config import loadConfig
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
needs_sphinx = '1.3'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure']
|
||||
|
||||
# The name of the math extension changed on Sphinx 1.4
|
||||
if major == 1 and minor > 3:
|
||||
extensions.append("sphinx.ext.imgmath")
|
||||
else:
|
||||
extensions.append("sphinx.ext.pngmath")
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'Das U-Boot'
|
||||
copyright = 'The U-Boot development community'
|
||||
author = 'The U-Boot development community'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# In a normal build, version and release are are set to KERNELVERSION and
|
||||
# KERNELRELEASE, respectively, from the Makefile via Sphinx command line
|
||||
# arguments.
|
||||
#
|
||||
# The following code tries to extract the information by reading the Makefile,
|
||||
# when Sphinx is run directly (e.g. by Read the Docs).
|
||||
try:
|
||||
makefile_version = None
|
||||
makefile_patchlevel = None
|
||||
for line in open('../Makefile'):
|
||||
key, val = [x.strip() for x in line.split('=', 2)]
|
||||
if key == 'VERSION':
|
||||
makefile_version = val
|
||||
elif key == 'PATCHLEVEL':
|
||||
makefile_patchlevel = val
|
||||
if makefile_version and makefile_patchlevel:
|
||||
break
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
if makefile_version and makefile_patchlevel:
|
||||
version = release = makefile_version + '.' + makefile_patchlevel
|
||||
else:
|
||||
version = release = "unknown version"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['output']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
primary_domain = 'c'
|
||||
highlight_language = 'none'
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
|
||||
# The Read the Docs theme is available from
|
||||
# - https://github.com/snide/sphinx_rtd_theme
|
||||
# - https://pypi.python.org/pypi/sphinx_rtd_theme
|
||||
# - python-sphinx-rtd-theme package (on Debian)
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
except ImportError:
|
||||
sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n')
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
|
||||
html_static_path = ['sphinx-static']
|
||||
|
||||
html_context = {
|
||||
'css_files': [
|
||||
'_static/theme_overrides.css',
|
||||
],
|
||||
}
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Language to be used for generating the HTML full-text search index.
|
||||
# Sphinx supports the following languages:
|
||||
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
|
||||
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
|
||||
#html_search_language = 'en'
|
||||
|
||||
# A dictionary with options for the search language support, empty by default.
|
||||
# Now only 'ja' uses this config value
|
||||
#html_search_options = {'type': 'default'}
|
||||
|
||||
# The name of a javascript file (relative to the configuration directory) that
|
||||
# implements a search results scorer. If empty, the default will be used.
|
||||
#html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'TheUBootdoc'
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
'papersize': 'a4paper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
'pointsize': '8pt',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#'figure_align': 'htbp',
|
||||
|
||||
# Don't mangle with UTF-8 chars
|
||||
'inputenc': '',
|
||||
'utf8extra': '',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
'preamble': '''
|
||||
% Use some font with UTF-8 support with XeLaTeX
|
||||
\\usepackage{fontspec}
|
||||
\\setsansfont{DejaVu Serif}
|
||||
\\setromanfont{DejaVu Sans}
|
||||
\\setmonofont{DejaVu Sans Mono}
|
||||
|
||||
'''
|
||||
}
|
||||
|
||||
# Fix reference escape troubles with Sphinx 1.4.x
|
||||
if major == 1 and minor > 3:
|
||||
latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
|
||||
|
||||
if major == 1 and minor <= 4:
|
||||
latex_elements['preamble'] += '\\usepackage[margin=0.5in, top=1in, bottom=1in]{geometry}'
|
||||
elif major == 1 and (minor > 5 or (minor == 5 and patch >= 3)):
|
||||
latex_elements['sphinxsetup'] = 'hmargin=0.5in, vmargin=1in'
|
||||
latex_elements['preamble'] += '\\fvset{fontsize=auto}\n'
|
||||
|
||||
# Customize notice background colors on Sphinx < 1.6:
|
||||
if major == 1 and minor < 6:
|
||||
latex_elements['preamble'] += '''
|
||||
\\usepackage{ifthen}
|
||||
|
||||
% Put notes in color and let them be inside a table
|
||||
\\definecolor{NoteColor}{RGB}{204,255,255}
|
||||
\\definecolor{WarningColor}{RGB}{255,204,204}
|
||||
\\definecolor{AttentionColor}{RGB}{255,255,204}
|
||||
\\definecolor{ImportantColor}{RGB}{192,255,204}
|
||||
\\definecolor{OtherColor}{RGB}{204,204,204}
|
||||
\\newlength{\\mynoticelength}
|
||||
\\makeatletter\\newenvironment{coloredbox}[1]{%
|
||||
\\setlength{\\fboxrule}{1pt}
|
||||
\\setlength{\\fboxsep}{7pt}
|
||||
\\setlength{\\mynoticelength}{\\linewidth}
|
||||
\\addtolength{\\mynoticelength}{-2\\fboxsep}
|
||||
\\addtolength{\\mynoticelength}{-2\\fboxrule}
|
||||
\\begin{lrbox}{\\@tempboxa}\\begin{minipage}{\\mynoticelength}}{\\end{minipage}\\end{lrbox}%
|
||||
\\ifthenelse%
|
||||
{\\equal{\\py@noticetype}{note}}%
|
||||
{\\colorbox{NoteColor}{\\usebox{\\@tempboxa}}}%
|
||||
{%
|
||||
\\ifthenelse%
|
||||
{\\equal{\\py@noticetype}{warning}}%
|
||||
{\\colorbox{WarningColor}{\\usebox{\\@tempboxa}}}%
|
||||
{%
|
||||
\\ifthenelse%
|
||||
{\\equal{\\py@noticetype}{attention}}%
|
||||
{\\colorbox{AttentionColor}{\\usebox{\\@tempboxa}}}%
|
||||
{%
|
||||
\\ifthenelse%
|
||||
{\\equal{\\py@noticetype}{important}}%
|
||||
{\\colorbox{ImportantColor}{\\usebox{\\@tempboxa}}}%
|
||||
{\\colorbox{OtherColor}{\\usebox{\\@tempboxa}}}%
|
||||
}%
|
||||
}%
|
||||
}%
|
||||
}\\makeatother
|
||||
|
||||
\\makeatletter
|
||||
\\renewenvironment{notice}[2]{%
|
||||
\\def\\py@noticetype{#1}
|
||||
\\begin{coloredbox}{#1}
|
||||
\\bf\\it
|
||||
\\par\\strong{#2}
|
||||
\\csname py@noticestart@#1\\endcsname
|
||||
}
|
||||
{
|
||||
\\csname py@noticeend@\\py@noticetype\\endcsname
|
||||
\\end{coloredbox}
|
||||
}
|
||||
\\makeatother
|
||||
|
||||
'''
|
||||
|
||||
# With Sphinx 1.6, it is possible to change the Bg color directly
|
||||
# by using:
|
||||
# \definecolor{sphinxnoteBgColor}{RGB}{204,255,255}
|
||||
# \definecolor{sphinxwarningBgColor}{RGB}{255,204,204}
|
||||
# \definecolor{sphinxattentionBgColor}{RGB}{255,255,204}
|
||||
# \definecolor{sphinximportantBgColor}{RGB}{192,255,204}
|
||||
#
|
||||
# However, it require to use sphinx heavy box with:
|
||||
#
|
||||
# \renewenvironment{sphinxlightbox} {%
|
||||
# \\begin{sphinxheavybox}
|
||||
# }
|
||||
# \\end{sphinxheavybox}
|
||||
# }
|
||||
#
|
||||
# Unfortunately, the implementation is buggy: if a note is inside a
|
||||
# table, it isn't displayed well. So, for now, let's use boring
|
||||
# black and white notes.
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
# Sorted in alphabetical order
|
||||
latex_documents = [
|
||||
('index', 'u-boot-hacker-manual.tex', 'U-Boot Hacker Manual',
|
||||
'The U-Boot development community', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'dasuboot', 'The U-Boot Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'DasUBoot', 'The U-Boot Documentation',
|
||||
author, 'DasUBoot', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# -- Options for Epub output ----------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
epub_author = author
|
||||
epub_publisher = author
|
||||
epub_copyright = copyright
|
||||
|
||||
# The basename for the epub file. It defaults to the project name.
|
||||
#epub_basename = project
|
||||
|
||||
# The HTML theme for the epub output. Since the default themes are not
|
||||
# optimized for small screen space, using the same theme for HTML and epub
|
||||
# output is usually not wise. This defaults to 'epub', a theme designed to save
|
||||
# visual space.
|
||||
#epub_theme = 'epub'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or 'en' if the language is not set.
|
||||
#epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
#epub_cover = ()
|
||||
|
||||
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
|
||||
#epub_guide = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
|
||||
# HTML files that should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
|
||||
# Choose between 'default' and 'includehidden'.
|
||||
#epub_tocscope = 'default'
|
||||
|
||||
# Fix unsupported image types using the Pillow.
|
||||
#epub_fix_images = False
|
||||
|
||||
# Scale large images.
|
||||
#epub_max_image_width = 0
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#epub_show_urls = 'inline'
|
||||
|
||||
# If false, no index is generated.
|
||||
#epub_use_index = True
|
||||
|
||||
#=======
|
||||
# rst2pdf
|
||||
#
|
||||
# Grouping the document tree into PDF files. List of tuples
|
||||
# (source start file, target name, title, author, options).
|
||||
#
|
||||
# See the Sphinx chapter of http://ralsina.me/static/manual.pdf
|
||||
#
|
||||
# FIXME: Do not add the index file here; the result will be too big. Adding
|
||||
# multiple PDF files here actually tries to get the cross-referencing right
|
||||
# *between* PDF files.
|
||||
pdf_documents = [
|
||||
('uboot-documentation', u'U-Boot', u'U-Boot', u'J. Random Bozo'),
|
||||
]
|
||||
|
||||
# kernel-doc extension configuration for running Sphinx directly (e.g. by Read
|
||||
# the Docs). In a normal build, these are supplied from the Makefile via command
|
||||
# line arguments.
|
||||
kerneldoc_bin = '../scripts/kernel-doc'
|
||||
kerneldoc_srctree = '..'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Since loadConfig overwrites settings from the global namespace, it has to be
|
||||
# the last statement in the conf.py file
|
||||
# ------------------------------------------------------------------------------
|
||||
loadConfig(globals())
|
||||
114
doc/device-tree-bindings/arm/l2c2x0.txt
Normal file
114
doc/device-tree-bindings/arm/l2c2x0.txt
Normal file
@@ -0,0 +1,114 @@
|
||||
* ARM L2 Cache Controller
|
||||
|
||||
ARM cores often have a separate L2C210/L2C220/L2C310 (also known as PL210/PL220/
|
||||
PL310 and variants) based level 2 cache controller. All these various implementations
|
||||
of the L2 cache controller have compatible programming models (Note 1).
|
||||
Some of the properties that are just prefixed "cache-*" are taken from section
|
||||
3.7.3 of the Devicetree Specification which can be found at:
|
||||
https://www.devicetree.org/specifications/
|
||||
|
||||
The ARM L2 cache representation in the device tree should be done as follows:
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be one of:
|
||||
"arm,pl310-cache"
|
||||
"arm,l220-cache"
|
||||
"arm,l210-cache"
|
||||
"bcm,bcm11351-a2-pl310-cache": DEPRECATED by "brcm,bcm11351-a2-pl310-cache"
|
||||
"brcm,bcm11351-a2-pl310-cache": For Broadcom bcm11351 chipset where an
|
||||
offset needs to be added to the address before passing down to the L2
|
||||
cache controller
|
||||
"marvell,aurora-system-cache": Marvell Controller designed to be
|
||||
compatible with the ARM one, with system cache mode (meaning
|
||||
maintenance operations on L1 are broadcasted to the L2 and L2
|
||||
performs the same operation).
|
||||
"marvell,aurora-outer-cache": Marvell Controller designed to be
|
||||
compatible with the ARM one with outer cache mode.
|
||||
"marvell,tauros3-cache": Marvell Tauros3 cache controller, compatible
|
||||
with arm,pl310-cache controller.
|
||||
- cache-unified : Specifies the cache is a unified cache.
|
||||
- cache-level : Should be set to 2 for a level 2 cache.
|
||||
- reg : Physical base address and size of cache controller's memory mapped
|
||||
registers.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- arm,data-latency : Cycles of latency for Data RAM accesses. Specifies 3 cells of
|
||||
read, write and setup latencies. Minimum valid values are 1. Controllers
|
||||
without setup latency control should use a value of 0.
|
||||
- arm,tag-latency : Cycles of latency for Tag RAM accesses. Specifies 3 cells of
|
||||
read, write and setup latencies. Controllers without setup latency control
|
||||
should use 0. Controllers without separate read and write Tag RAM latency
|
||||
values should only use the first cell.
|
||||
- arm,dirty-latency : Cycles of latency for Dirty RAMs. This is a single cell.
|
||||
- arm,filter-ranges : <start length> Starting address and length of window to
|
||||
filter. Addresses in the filter window are directed to the M1 port. Other
|
||||
addresses will go to the M0 port.
|
||||
- arm,io-coherent : indicates that the system is operating in an hardware
|
||||
I/O coherent mode. Valid only when the arm,pl310-cache compatible
|
||||
string is used.
|
||||
- interrupts : 1 combined interrupt.
|
||||
- cache-size : specifies the size in bytes of the cache
|
||||
- cache-sets : specifies the number of associativity sets of the cache
|
||||
- cache-block-size : specifies the size in bytes of a cache block
|
||||
- cache-line-size : specifies the size in bytes of a line in the cache,
|
||||
if this is not specified, the line size is assumed to be equal to the
|
||||
cache block size
|
||||
- cache-id-part: cache id part number to be used if it is not present
|
||||
on hardware
|
||||
- wt-override: If present then L2 is forced to Write through mode
|
||||
- arm,double-linefill : Override double linefill enable setting. Enable if
|
||||
non-zero, disable if zero.
|
||||
- arm,double-linefill-incr : Override double linefill on INCR read. Enable
|
||||
if non-zero, disable if zero.
|
||||
- arm,double-linefill-wrap : Override double linefill on WRAP read. Enable
|
||||
if non-zero, disable if zero.
|
||||
- arm,prefetch-drop : Override prefetch drop enable setting. Enable if non-zero,
|
||||
disable if zero.
|
||||
- arm,prefetch-offset : Override prefetch offset value. Valid values are
|
||||
0-7, 15, 23, and 31.
|
||||
- arm,shared-override : The default behavior of the L220 or PL310 cache
|
||||
controllers with respect to the shareable attribute is to transform "normal
|
||||
memory non-cacheable transactions" into "cacheable no allocate" (for reads)
|
||||
or "write through no write allocate" (for writes).
|
||||
On systems where this may cause DMA buffer corruption, this property must be
|
||||
specified to indicate that such transforms are precluded.
|
||||
- arm,parity-enable : enable parity checking on the L2 cache (L220 or PL310).
|
||||
- arm,parity-disable : disable parity checking on the L2 cache (L220 or PL310).
|
||||
- arm,outer-sync-disable : disable the outer sync operation on the L2 cache.
|
||||
Some core tiles, especially ARM PB11MPCore have a faulty L220 cache that
|
||||
will randomly hang unless outer sync operations are disabled.
|
||||
- prefetch-data : Data prefetch. Value: <0> (forcibly disable), <1>
|
||||
(forcibly enable), property absent (retain settings set by firmware)
|
||||
- prefetch-instr : Instruction prefetch. Value: <0> (forcibly disable),
|
||||
<1> (forcibly enable), property absent (retain settings set by
|
||||
firmware)
|
||||
- arm,dynamic-clock-gating : L2 dynamic clock gating. Value: <0> (forcibly
|
||||
disable), <1> (forcibly enable), property absent (OS specific behavior,
|
||||
preferably retain firmware settings)
|
||||
- arm,standby-mode: L2 standby mode enable. Value <0> (forcibly disable),
|
||||
<1> (forcibly enable), property absent (OS specific behavior,
|
||||
preferably retain firmware settings)
|
||||
- arm,early-bresp-disable : Disable the CA9 optimization Early BRESP (PL310)
|
||||
- arm,full-line-zero-disable : Disable the CA9 optimization Full line of zero
|
||||
write (PL310)
|
||||
|
||||
Example:
|
||||
|
||||
L2: cache-controller {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0xfff12000 0x1000>;
|
||||
arm,data-latency = <1 1 1>;
|
||||
arm,tag-latency = <2 2 2>;
|
||||
arm,filter-ranges = <0x80000000 0x8000000>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
interrupts = <45>;
|
||||
};
|
||||
|
||||
Note 1: The description in this document doesn't apply to integrated L2
|
||||
cache controllers as found in e.g. Cortex-A15/A7/A57/A53. These
|
||||
integrated L2 controllers are assumed to be all preconfigured by
|
||||
early secure boot code. Thus no need to deal with their configuration
|
||||
in the kernel at all.
|
||||
22
doc/device-tree-bindings/axi/gdsys,ihs_axi.txt
Normal file
22
doc/device-tree-bindings/axi/gdsys,ihs_axi.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
gdsys AXI busses of IHS FPGA devices
|
||||
|
||||
Certain gdsys IHS FPGAs offer a interface to their built-in AXI bus with which
|
||||
the connected devices (usually IP cores) can be controlled via software.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "gdsys,ihs_axi"
|
||||
- reg: describes the address and length of the AXI bus's register map (within
|
||||
the FPGA's register space)
|
||||
|
||||
Example:
|
||||
|
||||
fpga0_axi_video0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "gdsys,ihs_axi";
|
||||
reg = <0x170 0x10>;
|
||||
|
||||
axi_dev_1 {
|
||||
...
|
||||
};
|
||||
};
|
||||
46
doc/device-tree-bindings/board/gdsys,board_gazerbeam.txt
Normal file
46
doc/device-tree-bindings/board/gdsys,board_gazerbeam.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
gdsys Gazerbeam board driver
|
||||
|
||||
This driver provides capabilities to access the gdsys Gazerbeam board's device
|
||||
information. Furthermore, phandles to some internal devices are provided for
|
||||
the board files.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "gdsys,board_gazerbeam"
|
||||
- csb: phandle to the board's coherent system bus (CSB) device node
|
||||
- rxaui[0-3]: phandles to the rxaui control device nodes
|
||||
- fpga[0-1]: phandles to the board's gdsys FPGA device nodes
|
||||
- ioep[0-1]: phandles to the board's IO endpoint device nodes
|
||||
- ver-gpios: GPIO list to read the hardware version from
|
||||
- var-gpios: GPIO list to read the hardware variant information from
|
||||
- reset-gpios: GPIO list for the board's reset GPIOs
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
board {
|
||||
compatible = "gdsys,board_gazerbeam";
|
||||
csb = <&board_soc>;
|
||||
serdes = <&SERDES>;
|
||||
rxaui0 = <&RXAUI0>;
|
||||
rxaui1 = <&RXAUI1>;
|
||||
rxaui2 = <&RXAUI2>;
|
||||
rxaui3 = <&RXAUI3>;
|
||||
fpga0 = <&FPGA0>;
|
||||
fpga1 = <&FPGA1>;
|
||||
ioep0 = <&IOEP0>;
|
||||
ioep1 = <&IOEP1>;
|
||||
|
||||
ver-gpios = <&PPCPCA 12 0
|
||||
&PPCPCA 13 0
|
||||
&PPCPCA 14 0
|
||||
&PPCPCA 15 0>;
|
||||
|
||||
/* MC2/SC-Board */
|
||||
var-gpios-mc2 = <&GPIO_VB0 0 0 /* VAR-MC_SC */
|
||||
&GPIO_VB0 11 0>; /* VAR-CON */
|
||||
/* MC4-Board */
|
||||
var-gpios-mc4 = <&GPIO_VB1 0 0 /* VAR-MC_SC */
|
||||
&GPIO_VB1 11 0>; /* VAR-CON */
|
||||
|
||||
reset-gpios = <&gpio0 1 0 &gpio0 2 1>;
|
||||
};
|
||||
23
doc/device-tree-bindings/clock/fsl,mpc83xx-clk.txt
Normal file
23
doc/device-tree-bindings/clock/fsl,mpc83xx-clk.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
MPC83xx system clock devices
|
||||
|
||||
MPC83xx SoCs supply a variety of clocks to drive various components of a
|
||||
system.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be one of "fsl,mpc8308-clk",
|
||||
"fsl,mpc8309-clk",
|
||||
"fsl,mpc8313-clk",
|
||||
"fsl,mpc8315-clk",
|
||||
"fsl,mpc832x-clk",
|
||||
"fsl,mpc8349-clk",
|
||||
"fsl,mpc8360-clk",
|
||||
"fsl,mpc8379-clk"
|
||||
depending on which SoC is employed
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
Example:
|
||||
|
||||
socclocks: clocks {
|
||||
compatible = "fsl,mpc832x-clk";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
34
doc/device-tree-bindings/cpu/fsl,mpc83xx.txt
Normal file
34
doc/device-tree-bindings/cpu/fsl,mpc83xx.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
MPC83xx CPU devices
|
||||
|
||||
MPC83xx SoCs contain a e300 core as their main processor.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be one of "fsl,mpc83xx",
|
||||
"fsl,mpc8308",
|
||||
"fsl,mpc8309",
|
||||
"fsl,mpc8313",
|
||||
"fsl,mpc8315",
|
||||
"fsl,mpc832x",
|
||||
"fsl,mpc8349",
|
||||
"fsl,mpc8360",
|
||||
"fsl,mpc8379"
|
||||
- clocks: has to have two entries, which must be the core clock at index 0 and
|
||||
the CSB (Coherent System Bus) clock at index 1. Both are given by a suitable
|
||||
"fsl,mpc83xx-clk" device
|
||||
|
||||
Example:
|
||||
|
||||
socclocks: clocks {
|
||||
compatible = "fsl,mpc8315-clk";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
compatible = "cpu_bus";
|
||||
|
||||
PowerPC,8315@0 {
|
||||
compatible = "fsl,mpc8315";
|
||||
clocks = <&socclocks MPC83XX_CLK_CORE
|
||||
&socclocks MPC83XX_CLK_CSB>;
|
||||
};
|
||||
};
|
||||
24
doc/device-tree-bindings/misc/misc/fsl,mpc83xx-serdes.txt
Normal file
24
doc/device-tree-bindings/misc/misc/fsl,mpc83xx-serdes.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
MPC83xx SerDes controller devices
|
||||
|
||||
MPC83xx SoCs contain a built-in SerDes controller that determines which
|
||||
protocols (SATA, PCI Express, SGMII, ...) are used on the system's serdes lines
|
||||
and how the lines are configured.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "fsl,mpc83xx-serdes"
|
||||
- reg: must point to the serdes controller's register map
|
||||
- proto: selects for which protocol the serdes lines are configured. One of
|
||||
"sata", "pex", "pex-x2", "sgmii"
|
||||
- serdes-clk: determines the frequency the serdes lines are configured for. One
|
||||
of 100, 125, 150.
|
||||
- vdd: determines whether 1.0V core VDD is used or not
|
||||
|
||||
Example:
|
||||
|
||||
SERDES: serdes@e3000 {
|
||||
reg = <0xe3000 0x200>;
|
||||
compatible = "fsl,mpc83xx-serdes";
|
||||
proto = "pex";
|
||||
serdes-clk = <100>;
|
||||
vdd;
|
||||
};
|
||||
20
doc/device-tree-bindings/misc/misc/gdsys,io-endpoint.txt
Normal file
20
doc/device-tree-bindings/misc/misc/gdsys,io-endpoint.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
gdsys IO endpoint of IHS FPGA devices
|
||||
|
||||
The IO endpoint of IHS FPGA devices is a packet-based transmission interface
|
||||
that allows interconnected gdsys devices to send and receive data over the
|
||||
FPGA's main ethernet connection.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "gdsys,io-endpoint"
|
||||
- reg: describes the address and length of the endpoint's register map (within
|
||||
the FPGA's register space)
|
||||
|
||||
Example:
|
||||
|
||||
fpga0_ep0 {
|
||||
compatible = "gdsys,io-endpoint";
|
||||
reg = <0x020 0x10
|
||||
0x320 0x10
|
||||
0x340 0x10
|
||||
0x360 0x10>;
|
||||
};
|
||||
19
doc/device-tree-bindings/misc/misc/gdsys,iocon_fpga.txt
Normal file
19
doc/device-tree-bindings/misc/misc/gdsys,iocon_fpga.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
gdsys IHS FPGA for CON devices
|
||||
|
||||
The gdsys IHS FPGA is the main FPGA on gdsys CON devices. This driver provides
|
||||
support for enabling and starting the FPGA, as well as verifying working bus
|
||||
communication.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "gdsys,iocon_fpga"
|
||||
- reset-gpios: List of GPIOs controlling the FPGA's reset
|
||||
- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
|
||||
done
|
||||
|
||||
Example:
|
||||
|
||||
FPGA0 {
|
||||
compatible = "gdsys,iocon_fpga";
|
||||
reset-gpios = <&PPCPCA 26 0>;
|
||||
done-gpios = <&GPIO_VB0 19 0>;
|
||||
};
|
||||
19
doc/device-tree-bindings/misc/misc/gdsys,iocpu_fpga.txt
Normal file
19
doc/device-tree-bindings/misc/misc/gdsys,iocpu_fpga.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
gdsys IHS FPGA for CPU devices
|
||||
|
||||
The gdsys IHS FPGA is the main FPGA on gdsys CPU devices. This driver provides
|
||||
support for enabling and starting the FPGA, as well as verifying working bus
|
||||
communication.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "gdsys,iocpu_fpga"
|
||||
- reset-gpios: List of GPIOs controlling the FPGA's reset
|
||||
- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
|
||||
done
|
||||
|
||||
Example:
|
||||
|
||||
FPGA0 {
|
||||
compatible = "gdsys,iocpu_fpga";
|
||||
reset-gpios = <&PPCPCA 26 0>;
|
||||
done-gpios = <&GPIO_VB0 19 0>;
|
||||
};
|
||||
16
doc/device-tree-bindings/misc/misc/gdsys,soc.txt
Normal file
16
doc/device-tree-bindings/misc/misc/gdsys,soc.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
gdsys soc bus driver
|
||||
|
||||
This driver provides a simple interface for the busses associated with gdsys
|
||||
IHS FPGAs. The bus itself contains devices whose register maps are contained
|
||||
within the FPGA's register space.
|
||||
|
||||
Required properties:
|
||||
- fpga: A phandle to the controlling IHS FPGA
|
||||
|
||||
Example:
|
||||
|
||||
FPGA0BUS: fpga0bus {
|
||||
compatible = "gdsys,soc";
|
||||
ranges = <0x0 0xe0600000 0x00004000>;
|
||||
fpga = <&FPGA0>;
|
||||
};
|
||||
314
doc/device-tree-bindings/ram/fsl,mpc83xx-mem-controller.txt
Normal file
314
doc/device-tree-bindings/ram/fsl,mpc83xx-mem-controller.txt
Normal file
@@ -0,0 +1,314 @@
|
||||
MPC83xx RAM controller
|
||||
|
||||
This driver supplies support for the embedded RAM controller on MCP83xx-series
|
||||
SoCs.
|
||||
|
||||
For static configuration mode, each controller node should have child nodes
|
||||
describing the actual RAM modules installed.
|
||||
|
||||
Controller node
|
||||
===============
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "fsl,mpc83xx-mem-controller"
|
||||
- reg: The address of the RAM controller's register space
|
||||
- #address-cells: Must be 2
|
||||
- #size-cells: Must be 1
|
||||
- driver_software_override: DDR driver software override is enabled (1) or
|
||||
disabled (0)
|
||||
- p_impedance_override: DDR driver software p-impedance override; possible
|
||||
values:
|
||||
* DSO_P_IMPEDANCE_HIGHEST_Z
|
||||
* DSO_P_IMPEDANCE_MUCH_HIGHER_Z
|
||||
* DSO_P_IMPEDANCE_HIGHER_Z
|
||||
* DSO_P_IMPEDANCE_NOMINAL
|
||||
* DSO_P_IMPEDANCE_LOWER_Z
|
||||
- n_impedance_override: DDR driver software n-impedance override; possible
|
||||
values:
|
||||
* DSO_N_IMPEDANCE_HIGHEST_Z
|
||||
* DSO_N_IMPEDANCE_MUCH_HIGHER_Z
|
||||
* DSO_N_IMPEDANCE_HIGHER_Z
|
||||
* DSO_N_IMPEDANCE_NOMINAL
|
||||
* DSO_N_IMPEDANCE_LOWER_Z
|
||||
- odt_termination_value: ODT termination value for I/Os; possible values:
|
||||
* ODT_TERMINATION_75_OHM
|
||||
* ODT_TERMINATION_150_OHM
|
||||
- ddr_type: Selects voltage level for DDR pads; possible
|
||||
values:
|
||||
* DDR_TYPE_DDR2_1_8_VOLT
|
||||
* DDR_TYPE_DDR1_2_5_VOLT
|
||||
- mvref_sel: Determine where MVREF_SEL signal is generated;
|
||||
possible values:
|
||||
* MVREF_SEL_EXTERNAL
|
||||
* MVREF_SEL_INTERNAL_GVDD
|
||||
- m_odr: Disable memory transaction reordering; possible
|
||||
values:
|
||||
* M_ODR_ENABLE
|
||||
* M_ODR_DISABLE
|
||||
- clock_adjust: Clock adjust; possible values:
|
||||
* CLOCK_ADJUST_025
|
||||
* CLOCK_ADJUST_05
|
||||
* CLOCK_ADJUST_075
|
||||
* CLOCK_ADJUST_1
|
||||
- ext_refresh_rec: Extended refresh recovery time; possible values:
|
||||
0, 16, 32, 48, 64, 80, 96, 112
|
||||
- read_to_write: Read-to-write turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- write_to_read: Write-to-read turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- read_to_read: Read-to-read turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- write_to_write: Write-to-write turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- active_powerdown_exit: Active powerdown exit timing; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- precharge_powerdown_exit: Precharge powerdown exit timing; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- odt_powerdown_exit: ODT powerdown exit timing; possible values:
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15
|
||||
- mode_reg_set_cycle: Mode register set cycle time; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
||||
- precharge_to_activate: Precharge-to-acitvate interval; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- activate_to_precharge: Activate to precharge interval; possible values:
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19
|
||||
- activate_to_readwrite: Activate to read/write interval for SDRAM;
|
||||
possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- mcas_latency: MCAS latency from READ command; possible values:
|
||||
* CASLAT_20
|
||||
* CASLAT_25
|
||||
* CASLAT_30
|
||||
* CASLAT_35
|
||||
* CASLAT_40
|
||||
* CASLAT_45
|
||||
* CASLAT_50
|
||||
* CASLAT_55
|
||||
* CASLAT_60
|
||||
* CASLAT_65
|
||||
* CASLAT_70
|
||||
* CASLAT_75
|
||||
* CASLAT_80
|
||||
- refresh_recovery: Refresh recovery time; possible values:
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23
|
||||
- last_data_to_precharge: Last data to precharge minimum interval; possible
|
||||
values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- activate_to_activate: Activate-to-activate interval; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- last_write_data_to_read: Last write data pair to read command issue
|
||||
interval; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- additive_latency: Additive latency; possible values:
|
||||
0, 1, 2, 3, 4, 5
|
||||
- mcas_to_preamble_override: MCAS-to-preamble-override; possible values:
|
||||
* READ_LAT
|
||||
* READ_LAT_PLUS_1_4
|
||||
* READ_LAT_PLUS_1_2
|
||||
* READ_LAT_PLUS_3_4
|
||||
* READ_LAT_PLUS_1
|
||||
* READ_LAT_PLUS_5_4
|
||||
* READ_LAT_PLUS_3_2
|
||||
* READ_LAT_PLUS_7_4
|
||||
* READ_LAT_PLUS_2
|
||||
* READ_LAT_PLUS_9_4
|
||||
* READ_LAT_PLUS_5_2
|
||||
* READ_LAT_PLUS_11_4
|
||||
* READ_LAT_PLUS_3
|
||||
* READ_LAT_PLUS_13_4
|
||||
* READ_LAT_PLUS_7_2
|
||||
* READ_LAT_PLUS_15_4
|
||||
* READ_LAT_PLUS_4
|
||||
* READ_LAT_PLUS_17_4
|
||||
* READ_LAT_PLUS_9_2
|
||||
* READ_LAT_PLUS_19_4
|
||||
- write_latency: Write latency; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- read_to_precharge: Read to precharge; possible values:
|
||||
1, 2, 3, 4
|
||||
- write_cmd_to_write_data: Write command to write data strobe timing
|
||||
adjustment; possible values:
|
||||
* CLOCK_DELAY_0
|
||||
* CLOCK_DELAY_1_4
|
||||
* CLOCK_DELAY_1_2
|
||||
* CLOCK_DELAY_3_4
|
||||
* CLOCK_DELAY_1
|
||||
* CLOCK_DELAY_5_4
|
||||
* CLOCK_DELAY_3_2
|
||||
- minimum_cke_pulse_width: Minimum CKE pulse width; possible values:
|
||||
1, 2, 3, 4
|
||||
- four_activates_window: Window for four activates; possible values:
|
||||
1, 2, 3, 4 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19
|
||||
- self_refresh: Self refresh (during sleep); possible values:
|
||||
* SREN_DISABLE
|
||||
* SREN_ENABLE
|
||||
- ecc: Support for ECC; possible values:
|
||||
* ECC_DISABLE
|
||||
* ECC_ENABLE
|
||||
- registered_dram: Support for registered DRAM; possible values:
|
||||
* RD_DISABLE
|
||||
* RD_ENABLE
|
||||
- sdram_type: Type of SDRAM device to be used; possible values:
|
||||
* TYPE_DDR1
|
||||
* TYPE_DDR2
|
||||
- dynamic_power_management: Dynamic power management mode; possible values:
|
||||
* DYN_PWR_DISABLE
|
||||
* DYN_PWR_ENABLE
|
||||
- databus_width: DRAM data bus width; possible values
|
||||
* DATA_BUS_WIDTH_16
|
||||
* DATA_BUS_WIDTH_32
|
||||
- nc_auto_precharge: Non-concurrent auto-precharge; possible values:
|
||||
* NCAP_DISABLE
|
||||
* NCAP_ENABLE
|
||||
- timing_2t: 2T timing; possible values:
|
||||
* TIMING_1T
|
||||
* TIMING_2T
|
||||
- bank_interleaving_ctrl: Bank (chip select) interleaving control; possible
|
||||
values:
|
||||
* INTERLEAVE_NONE
|
||||
* INTERLEAVE_1_AND_2
|
||||
- precharge_bit_8: Precharge bin 8; possible values
|
||||
* PRECHARGE_MA_10
|
||||
* PRECHARGE_MA_8
|
||||
- half_strength: Global half-strength override; possible values:
|
||||
* STRENGTH_FULL
|
||||
* STRENGTH_HALF
|
||||
- bypass_initialization: Bypass initialization; possible values:
|
||||
* INITIALIZATION_DONT_BYPASS
|
||||
* INITIALIZATION_BYPASS
|
||||
- force_self_refresh: Force self refresh; possible values:
|
||||
* MODE_NORMAL
|
||||
* MODE_REFRESH
|
||||
- dll_reset: DLL reset; possible values:
|
||||
* DLL_RESET_ENABLE
|
||||
* DLL_RESET_DISABLE
|
||||
- dqs_config: DQS configuration; possible values:
|
||||
* DQS_TRUE
|
||||
- odt_config: ODT configuration; possible values:
|
||||
* ODT_ASSERT_NEVER
|
||||
* ODT_ASSERT_WRITES
|
||||
* ODT_ASSERT_READS
|
||||
* ODT_ASSERT_ALWAYS
|
||||
- posted_refreshes: Number of posted refreshes
|
||||
1, 2, 3, 4, 5, 6, 7, 8
|
||||
- sdmode: Initial value loaded into the DDR SDRAM mode
|
||||
register
|
||||
- esdmode: Initial value loaded into the DDR SDRAM extended
|
||||
mode register
|
||||
- esdmode2: Initial value loaded into the DDR SDRAM extended
|
||||
mode 2 register
|
||||
- esdmode3: Initial value loaded into the DDR SDRAM extended
|
||||
mode 3 register
|
||||
- refresh_interval: Refresh interval; possible values:
|
||||
0 - 65535
|
||||
- precharge_interval: Precharge interval; possible values:
|
||||
0 - 16383
|
||||
|
||||
RAM module node:
|
||||
================
|
||||
|
||||
Required properties:
|
||||
- reg: A triple <cs addr size>, which consists of:
|
||||
* cs - the chipselect used to drive this RAM module
|
||||
* addr - the address where this RAM module's memory is map
|
||||
to in the global memory space
|
||||
* size - the size of the RAM module's memory in bytes
|
||||
- auto_precharge: Chip select auto-precharge; possible values:
|
||||
* AUTO_PRECHARGE_ENABLE
|
||||
* AUTO_PRECHARGE_DISABLE
|
||||
- odt_rd_cfg: ODT for reads configuration; possible values:
|
||||
* ODT_RD_NEVER
|
||||
* ODT_RD_ONLY_CURRENT
|
||||
* ODT_RD_ONLY_OTHER_CS
|
||||
* ODT_RD_ONLY_OTHER_DIMM
|
||||
* ODT_RD_ALL
|
||||
- odt_wr_cfg: ODT for writes configuration; possible values:
|
||||
* ODT_WR_NEVER
|
||||
* ODT_WR_ONLY_CURRENT
|
||||
* ODT_WR_ONLY_OTHER_CS
|
||||
* ODT_WR_ONLY_OTHER_DIMM
|
||||
* ODT_WR_ALL
|
||||
- bank_bits: Number of bank bits for SDRAM on chip select; possible
|
||||
values:
|
||||
2, 3
|
||||
- row_bits: Number of row bits for SDRAM on chip select; possible values:
|
||||
12, 13, 14
|
||||
- col_bits: Number of column bits for SDRAM on chip select; possible
|
||||
values:
|
||||
8, 9, 10, 11
|
||||
|
||||
Example:
|
||||
|
||||
memory@2000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc83xx-mem-controller";
|
||||
reg = <0x2000 0x1000>;
|
||||
device_type = "memory";
|
||||
u-boot,dm-pre-reloc;
|
||||
|
||||
driver_software_override = <DSO_ENABLE>;
|
||||
p_impedance_override = <DSO_P_IMPEDANCE_NOMINAL>;
|
||||
n_impedance_override = <DSO_N_IMPEDANCE_NOMINAL>;
|
||||
odt_termination_value = <ODT_TERMINATION_150_OHM>;
|
||||
ddr_type = <DDR_TYPE_DDR2_1_8_VOLT>;
|
||||
|
||||
clock_adjust = <CLOCK_ADJUST_05>;
|
||||
|
||||
read_to_write = <0>;
|
||||
write_to_read = <0>;
|
||||
read_to_read = <0>;
|
||||
write_to_write = <0>;
|
||||
active_powerdown_exit = <2>;
|
||||
precharge_powerdown_exit = <6>;
|
||||
odt_powerdown_exit = <8>;
|
||||
mode_reg_set_cycle = <2>;
|
||||
|
||||
precharge_to_activate = <2>;
|
||||
activate_to_precharge = <6>;
|
||||
activate_to_readwrite = <2>;
|
||||
mcas_latency = <CASLAT_40>;
|
||||
refresh_recovery = <17>;
|
||||
last_data_to_precharge = <2>;
|
||||
activate_to_activate = <2>;
|
||||
last_write_data_to_read = <2>;
|
||||
|
||||
additive_latency = <0>;
|
||||
mcas_to_preamble_override = <READ_LAT_PLUS_1_2>;
|
||||
write_latency = <3>;
|
||||
read_to_precharge = <2>;
|
||||
write_cmd_to_write_data = <CLOCK_DELAY_1_2>;
|
||||
minimum_cke_pulse_width = <3>;
|
||||
four_activates_window = <5>;
|
||||
|
||||
self_refresh = <SREN_ENABLE>;
|
||||
sdram_type = <TYPE_DDR2>;
|
||||
databus_width = <DATA_BUS_WIDTH_32>;
|
||||
|
||||
force_self_refresh = <MODE_NORMAL>;
|
||||
dll_reset = <DLL_RESET_ENABLE>;
|
||||
dqs_config = <DQS_TRUE>;
|
||||
odt_config = <ODT_ASSERT_READS>;
|
||||
posted_refreshes = <1>;
|
||||
|
||||
refresh_interval = <2084>;
|
||||
precharge_interval = <256>;
|
||||
|
||||
sdmode = <0x0242>;
|
||||
esdmode = <0x0440>;
|
||||
|
||||
ram@0 {
|
||||
reg = <0x0 0x0 0x8000000>;
|
||||
compatible = "nanya,nt5tu64m16hg";
|
||||
|
||||
odt_rd_cfg = <ODT_RD_NEVER>;
|
||||
odt_wr_cfg = <ODT_WR_ONLY_CURRENT>;
|
||||
bank_bits = <3>;
|
||||
row_bits = <13>;
|
||||
col_bits = <10>;
|
||||
};
|
||||
};
|
||||
136
doc/device-tree-bindings/reserved-memory/reserved-memory.txt
Normal file
136
doc/device-tree-bindings/reserved-memory/reserved-memory.txt
Normal file
@@ -0,0 +1,136 @@
|
||||
*** Reserved memory regions ***
|
||||
|
||||
Reserved memory is specified as a node under the /reserved-memory node.
|
||||
The operating system shall exclude reserved memory from normal usage
|
||||
one can create child nodes describing particular reserved (excluded from
|
||||
normal use) memory regions. Such memory regions are usually designed for
|
||||
the special usage by various device drivers.
|
||||
|
||||
Parameters for each memory region can be encoded into the device tree
|
||||
with the following nodes:
|
||||
|
||||
/reserved-memory node
|
||||
---------------------
|
||||
#address-cells, #size-cells (required) - standard definition
|
||||
- Should use the same values as the root node
|
||||
ranges (required) - standard definition
|
||||
- Should be empty
|
||||
|
||||
/reserved-memory/ child nodes
|
||||
-----------------------------
|
||||
Each child of the reserved-memory node specifies one or more regions of
|
||||
reserved memory. Each child node may either use a 'reg' property to
|
||||
specify a specific range of reserved memory, or a 'size' property with
|
||||
optional constraints to request a dynamically allocated block of memory.
|
||||
|
||||
Following the generic-names recommended practice, node names should
|
||||
reflect the purpose of the node (ie. "framebuffer" or "dma-pool"). Unit
|
||||
address (@<address>) should be appended to the name if the node is a
|
||||
static allocation.
|
||||
|
||||
Properties:
|
||||
Requires either a) or b) below.
|
||||
a) static allocation
|
||||
reg (required) - standard definition
|
||||
b) dynamic allocation
|
||||
size (required) - length based on parent's #size-cells
|
||||
- Size in bytes of memory to reserve.
|
||||
alignment (optional) - length based on parent's #size-cells
|
||||
- Address boundary for alignment of allocation.
|
||||
alloc-ranges (optional) - prop-encoded-array (address, length pairs).
|
||||
- Specifies regions of memory that are
|
||||
acceptable to allocate from.
|
||||
|
||||
If both reg and size are present, then the reg property takes precedence
|
||||
and size is ignored.
|
||||
|
||||
Additional properties:
|
||||
compatible (optional) - standard definition
|
||||
- may contain the following strings:
|
||||
- shared-dma-pool: This indicates a region of memory meant to be
|
||||
used as a shared pool of DMA buffers for a set of devices. It can
|
||||
be used by an operating system to instantiate the necessary pool
|
||||
management subsystem if necessary.
|
||||
- vendor specific string in the form <vendor>,[<device>-]<usage>
|
||||
no-map (optional) - empty property
|
||||
- Indicates the operating system must not create a virtual mapping
|
||||
of the region as part of its standard mapping of system memory,
|
||||
nor permit speculative access to it under any circumstances other
|
||||
than under the control of the device driver using the region.
|
||||
reusable (optional) - empty property
|
||||
- The operating system can use the memory in this region with the
|
||||
limitation that the device driver(s) owning the region need to be
|
||||
able to reclaim it back. Typically that means that the operating
|
||||
system can use that region to store volatile or cached data that
|
||||
can be otherwise regenerated or migrated elsewhere.
|
||||
|
||||
Linux implementation note:
|
||||
- If a "linux,cma-default" property is present, then Linux will use the
|
||||
region for the default pool of the contiguous memory allocator.
|
||||
|
||||
- If a "linux,dma-default" property is present, then Linux will use the
|
||||
region for the default pool of the consistent DMA allocator.
|
||||
|
||||
Device node references to reserved memory
|
||||
-----------------------------------------
|
||||
Regions in the /reserved-memory node may be referenced by other device
|
||||
nodes by adding a memory-region property to the device node.
|
||||
|
||||
memory-region (optional) - phandle, specifier pairs to children of /reserved-memory
|
||||
|
||||
Example
|
||||
-------
|
||||
This example defines 3 contiguous regions are defined for Linux kernel:
|
||||
one default of all device drivers (named linux,cma@72000000 and 64MiB in size),
|
||||
one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and
|
||||
one for multimedia processing (named multimedia-memory@77000000, 64MiB).
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
memory {
|
||||
reg = <0x40000000 0x40000000>;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
/* global autoconfigured region for contiguous allocations */
|
||||
linux,cma {
|
||||
compatible = "shared-dma-pool";
|
||||
reusable;
|
||||
size = <0x4000000>;
|
||||
alignment = <0x2000>;
|
||||
linux,cma-default;
|
||||
};
|
||||
|
||||
display_reserved: framebuffer@78000000 {
|
||||
reg = <0x78000000 0x800000>;
|
||||
};
|
||||
|
||||
multimedia_reserved: multimedia@77000000 {
|
||||
compatible = "acme,multimedia-memory";
|
||||
reg = <0x77000000 0x4000000>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ... */
|
||||
|
||||
fb0: video@12300000 {
|
||||
memory-region = <&display_reserved>;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
scaler: scaler@12500000 {
|
||||
memory-region = <&multimedia_reserved>;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
codec: codec@12600000 {
|
||||
memory-region = <&multimedia_reserved>;
|
||||
/* ... */
|
||||
};
|
||||
};
|
||||
21
doc/device-tree-bindings/timer/fsl,mpc83xx-timer.txt
Normal file
21
doc/device-tree-bindings/timer/fsl,mpc83xx-timer.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
MPC83xx timer devices
|
||||
|
||||
MPC83xx SoCs offer a decrementer interrupt that can be used to implement delay
|
||||
functionality, and periodically triggered actions.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "fsl,mpc83xx-timer"
|
||||
- clocks: must be a reference to the system's CSB (coherent system bus) clock,
|
||||
provided by one of the "fsl,mpc83xx-clk" devices
|
||||
|
||||
Example:
|
||||
|
||||
socclocks: clocks {
|
||||
compatible = "fsl,mpc832x-clk";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
timer {
|
||||
compatible = "fsl,mpc83xx-timer";
|
||||
clocks = <&socclocks MPC83XX_CLK_CSB>;
|
||||
};
|
||||
22
doc/efi.rst
Normal file
22
doc/efi.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
EFI subsystem
|
||||
=============
|
||||
|
||||
Boot services
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: lib/efi_loader/efi_boottime.c
|
||||
:internal:
|
||||
|
||||
Image relocation
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: lib/efi_loader/efi_image_loader.c
|
||||
:internal:
|
||||
|
||||
Runtime services
|
||||
----------------
|
||||
|
||||
.. kernel-doc:: lib/efi_loader/efi_runtime.c
|
||||
:internal:
|
||||
11
doc/index.rst
Normal file
11
doc/index.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#######################
|
||||
U-Boot Developer Manual
|
||||
#######################
|
||||
|
||||
.. toctree::
|
||||
|
||||
efi
|
||||
linker_lists
|
||||
serial
|
||||
100
doc/linker_lists.rst
Normal file
100
doc/linker_lists.rst
Normal file
@@ -0,0 +1,100 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Linker-Generated Arrays
|
||||
=======================
|
||||
|
||||
A linker list is constructed by grouping together linker input
|
||||
sections, each containing one entry of the list. Each input section
|
||||
contains a constant initialized variable which holds the entry's
|
||||
content. Linker list input sections are constructed from the list
|
||||
and entry names, plus a prefix which allows grouping all lists
|
||||
together. Assuming _list and _entry are the list and entry names,
|
||||
then the corresponding input section name is
|
||||
|
||||
::
|
||||
|
||||
.u_boot_list_ + 2_ + @_list + _2_ + @_entry
|
||||
|
||||
and the C variable name is
|
||||
|
||||
::
|
||||
|
||||
_u_boot_list + _2_ + @_list + _2_ + @_entry
|
||||
|
||||
This ensures uniqueness for both input section and C variable name.
|
||||
|
||||
Note that the names differ only in the first character, "." for the
|
||||
section and "_" for the variable, so that the linker cannot confuse
|
||||
section and symbol names. From now on, both names will be referred
|
||||
to as
|
||||
|
||||
::
|
||||
|
||||
%u_boot_list_ + 2_ + @_list + _2_ + @_entry
|
||||
|
||||
Entry variables need never be referred to directly.
|
||||
|
||||
The naming scheme for input sections allows grouping all linker lists
|
||||
into a single linker output section and grouping all entries for a
|
||||
single list.
|
||||
|
||||
Note the two '_2_' constant components in the names: their presence
|
||||
allows putting a start and end symbols around a list, by mapping
|
||||
these symbols to sections names with components "1" (before) and
|
||||
"3" (after) instead of "2" (within).
|
||||
Start and end symbols for a list can generally be defined as
|
||||
|
||||
::
|
||||
|
||||
%u_boot_list_2_ + @_list + _1_...
|
||||
%u_boot_list_2_ + @_list + _3_...
|
||||
|
||||
Start and end symbols for the whole of the linker lists area can be
|
||||
defined as
|
||||
|
||||
::
|
||||
|
||||
%u_boot_list_1_...
|
||||
%u_boot_list_3_...
|
||||
|
||||
Here is an example of the sorted sections which result from a list
|
||||
"array" made up of three entries : "first", "second" and "third",
|
||||
iterated at least once.
|
||||
|
||||
::
|
||||
|
||||
.u_boot_list_2_array_1
|
||||
.u_boot_list_2_array_2_first
|
||||
.u_boot_list_2_array_2_second
|
||||
.u_boot_list_2_array_2_third
|
||||
.u_boot_list_2_array_3
|
||||
|
||||
If lists must be divided into sublists (e.g. for iterating only on
|
||||
part of a list), one can simply give the list a name of the form
|
||||
'outer_2_inner', where 'outer' is the global list name and 'inner'
|
||||
is the sub-list name. Iterators for the whole list should use the
|
||||
global list name ("outer"); iterators for only a sub-list should use
|
||||
the full sub-list name ("outer_2_inner").
|
||||
|
||||
Here is an example of the sections generated from a global list
|
||||
named "drivers", two sub-lists named "i2c" and "pci", and iterators
|
||||
defined for the whole list and each sub-list:
|
||||
|
||||
::
|
||||
|
||||
%u_boot_list_2_drivers_1
|
||||
%u_boot_list_2_drivers_2_i2c_1
|
||||
%u_boot_list_2_drivers_2_i2c_2_first
|
||||
%u_boot_list_2_drivers_2_i2c_2_first
|
||||
%u_boot_list_2_drivers_2_i2c_2_second
|
||||
%u_boot_list_2_drivers_2_i2c_2_third
|
||||
%u_boot_list_2_drivers_2_i2c_3
|
||||
%u_boot_list_2_drivers_2_pci_1
|
||||
%u_boot_list_2_drivers_2_pci_2_first
|
||||
%u_boot_list_2_drivers_2_pci_2_second
|
||||
%u_boot_list_2_drivers_2_pci_2_third
|
||||
%u_boot_list_2_drivers_2_pci_3
|
||||
%u_boot_list_2_drivers_3
|
||||
|
||||
.. kernel-doc:: include/linker_lists.h
|
||||
:internal:
|
||||
38
doc/media/Makefile
Normal file
38
doc/media/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
# Rules to convert a .h file to inline RST documentation
|
||||
|
||||
SRC_DIR=$(srctree)/doc/media
|
||||
PARSER = $(srctree)/doc/sphinx/parse-headers.pl
|
||||
API = $(srctree)/include
|
||||
|
||||
FILES = linker_lists.h.rst
|
||||
|
||||
TARGETS := $(addprefix $(BUILDDIR)/, $(FILES))
|
||||
|
||||
gen_rst = \
|
||||
echo ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions; \
|
||||
${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
|
||||
|
||||
quiet_gen_rst = echo ' PARSE $(patsubst $(srctree)/%,%,$<)'; \
|
||||
${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
|
||||
|
||||
silent_gen_rst = ${gen_rst}
|
||||
|
||||
$(BUILDDIR)/linker_lists.h.rst: ${API}/linker_lists.h ${PARSER} $(SRC_DIR)/linker_lists.h.rst.exceptions
|
||||
@$($(quiet)gen_rst)
|
||||
|
||||
# Media build rules
|
||||
|
||||
.PHONY: all html epub xml latex
|
||||
|
||||
all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
|
||||
html: all
|
||||
epub: all
|
||||
xml: all
|
||||
latex: $(IMGPDF) all
|
||||
linkcheck:
|
||||
|
||||
clean:
|
||||
-rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null
|
||||
|
||||
$(BUILDDIR):
|
||||
$(Q)mkdir -p $@
|
||||
0
doc/media/linker_lists.h.rst.exceptions
Normal file
0
doc/media/linker_lists.h.rst.exceptions
Normal file
7
doc/serial.rst
Normal file
7
doc/serial.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Serial system
|
||||
=============
|
||||
|
||||
.. kernel-doc:: drivers/serial/serial.c
|
||||
:internal:
|
||||
89
doc/sphinx-static/theme_overrides.css
Normal file
89
doc/sphinx-static/theme_overrides.css
Normal file
@@ -0,0 +1,89 @@
|
||||
/* -*- coding: utf-8; mode: css -*-
|
||||
*
|
||||
* Sphinx HTML theme customization: read the doc
|
||||
*
|
||||
*/
|
||||
|
||||
/* Interim: Code-blocks with line nos - lines and line numbers don't line up.
|
||||
* see: https://github.com/rtfd/sphinx_rtd_theme/issues/419
|
||||
*/
|
||||
|
||||
div[class^="highlight"] pre {
|
||||
line-height: normal;
|
||||
}
|
||||
.rst-content .highlight > pre {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
|
||||
/* content column
|
||||
*
|
||||
* RTD theme's default is 800px as max width for the content, but we have
|
||||
* tables with tons of columns, which need the full width of the view-port.
|
||||
*/
|
||||
|
||||
.wy-nav-content{max-width: none; }
|
||||
|
||||
/* table:
|
||||
*
|
||||
* - Sequences of whitespace should collapse into a single whitespace.
|
||||
* - make the overflow auto (scrollbar if needed)
|
||||
* - align caption "left" ("center" is unsuitable on vast tables)
|
||||
*/
|
||||
|
||||
.wy-table-responsive table td { white-space: normal; }
|
||||
.wy-table-responsive { overflow: auto; }
|
||||
.rst-content table.docutils caption { text-align: left; font-size: 100%; }
|
||||
|
||||
/* captions:
|
||||
*
|
||||
* - captions should have 100% (not 85%) font size
|
||||
* - hide the permalink symbol as long as link is not hovered
|
||||
*/
|
||||
|
||||
.toc-title {
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
caption, .wy-table caption, .rst-content table.field-list caption {
|
||||
font-size: 100%;
|
||||
}
|
||||
caption a.headerlink { opacity: 0; }
|
||||
caption a.headerlink:hover { opacity: 1; }
|
||||
|
||||
/* Menu selection and keystrokes */
|
||||
|
||||
span.menuselection {
|
||||
color: blue;
|
||||
font-family: "Courier New", Courier, monospace
|
||||
}
|
||||
|
||||
code.kbd, code.kbd span {
|
||||
color: white;
|
||||
background-color: darkblue;
|
||||
font-weight: bold;
|
||||
font-family: "Courier New", Courier, monospace
|
||||
}
|
||||
|
||||
/* fix bottom margin of lists items */
|
||||
|
||||
.rst-content .section ul li:last-child, .rst-content .section ul li p:last-child {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
/* inline literal: drop the borderbox, padding and red color */
|
||||
|
||||
code, .rst-content tt, .rst-content code {
|
||||
color: inherit;
|
||||
border: none;
|
||||
padding: unset;
|
||||
background: inherit;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
165
doc/sphinx/cdomain.py
Normal file
165
doc/sphinx/cdomain.py
Normal file
@@ -0,0 +1,165 @@
|
||||
# -*- coding: utf-8; mode: python -*-
|
||||
# pylint: disable=W0141,C0113,C0103,C0325
|
||||
u"""
|
||||
cdomain
|
||||
~~~~~~~
|
||||
|
||||
Replacement for the sphinx c-domain.
|
||||
|
||||
:copyright: Copyright (C) 2016 Markus Heiser
|
||||
:license: GPL Version 2, June 1991 see Linux/COPYING for details.
|
||||
|
||||
List of customizations:
|
||||
|
||||
* Moved the *duplicate C object description* warnings for function
|
||||
declarations in the nitpicky mode. See Sphinx documentation for
|
||||
the config values for ``nitpick`` and ``nitpick_ignore``.
|
||||
|
||||
* Add option 'name' to the "c:function:" directive. With option 'name' the
|
||||
ref-name of a function can be modified. E.g.::
|
||||
|
||||
.. c:function:: int ioctl( int fd, int request )
|
||||
:name: VIDIOC_LOG_STATUS
|
||||
|
||||
The func-name (e.g. ioctl) remains in the output but the ref-name changed
|
||||
from 'ioctl' to 'VIDIOC_LOG_STATUS'. The function is referenced by::
|
||||
|
||||
* :c:func:`VIDIOC_LOG_STATUS` or
|
||||
* :any:`VIDIOC_LOG_STATUS` (``:any:`` needs sphinx 1.3)
|
||||
|
||||
* Handle signatures of function-like macros well. Don't try to deduce
|
||||
arguments types of function-like macros.
|
||||
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
|
||||
import sphinx
|
||||
from sphinx import addnodes
|
||||
from sphinx.domains.c import c_funcptr_sig_re, c_sig_re
|
||||
from sphinx.domains.c import CObject as Base_CObject
|
||||
from sphinx.domains.c import CDomain as Base_CDomain
|
||||
|
||||
__version__ = '1.0'
|
||||
|
||||
# Get Sphinx version
|
||||
major, minor, patch = sphinx.version_info[:3]
|
||||
|
||||
def setup(app):
|
||||
|
||||
app.override_domain(CDomain)
|
||||
|
||||
return dict(
|
||||
version = __version__,
|
||||
parallel_read_safe = True,
|
||||
parallel_write_safe = True
|
||||
)
|
||||
|
||||
class CObject(Base_CObject):
|
||||
|
||||
"""
|
||||
Description of a C language object.
|
||||
"""
|
||||
option_spec = {
|
||||
"name" : directives.unchanged
|
||||
}
|
||||
|
||||
def handle_func_like_macro(self, sig, signode):
|
||||
u"""Handles signatures of function-like macros.
|
||||
|
||||
If the objtype is 'function' and the the signature ``sig`` is a
|
||||
function-like macro, the name of the macro is returned. Otherwise
|
||||
``False`` is returned. """
|
||||
|
||||
if not self.objtype == 'function':
|
||||
return False
|
||||
|
||||
m = c_funcptr_sig_re.match(sig)
|
||||
if m is None:
|
||||
m = c_sig_re.match(sig)
|
||||
if m is None:
|
||||
raise ValueError('no match')
|
||||
|
||||
rettype, fullname, arglist, _const = m.groups()
|
||||
arglist = arglist.strip()
|
||||
if rettype or not arglist:
|
||||
return False
|
||||
|
||||
arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
|
||||
arglist = [a.strip() for a in arglist.split(",")]
|
||||
|
||||
# has the first argument a type?
|
||||
if len(arglist[0].split(" ")) > 1:
|
||||
return False
|
||||
|
||||
# This is a function-like macro, it's arguments are typeless!
|
||||
signode += addnodes.desc_name(fullname, fullname)
|
||||
paramlist = addnodes.desc_parameterlist()
|
||||
signode += paramlist
|
||||
|
||||
for argname in arglist:
|
||||
param = addnodes.desc_parameter('', '', noemph=True)
|
||||
# separate by non-breaking space in the output
|
||||
param += nodes.emphasis(argname, argname)
|
||||
paramlist += param
|
||||
|
||||
return fullname
|
||||
|
||||
def handle_signature(self, sig, signode):
|
||||
"""Transform a C signature into RST nodes."""
|
||||
|
||||
fullname = self.handle_func_like_macro(sig, signode)
|
||||
if not fullname:
|
||||
fullname = super(CObject, self).handle_signature(sig, signode)
|
||||
|
||||
if "name" in self.options:
|
||||
if self.objtype == 'function':
|
||||
fullname = self.options["name"]
|
||||
else:
|
||||
# FIXME: handle :name: value of other declaration types?
|
||||
pass
|
||||
return fullname
|
||||
|
||||
def add_target_and_index(self, name, sig, signode):
|
||||
# for C API items we add a prefix since names are usually not qualified
|
||||
# by a module name and so easily clash with e.g. section titles
|
||||
targetname = 'c.' + name
|
||||
if targetname not in self.state.document.ids:
|
||||
signode['names'].append(targetname)
|
||||
signode['ids'].append(targetname)
|
||||
signode['first'] = (not self.names)
|
||||
self.state.document.note_explicit_target(signode)
|
||||
inv = self.env.domaindata['c']['objects']
|
||||
if (name in inv and self.env.config.nitpicky):
|
||||
if self.objtype == 'function':
|
||||
if ('c:func', name) not in self.env.config.nitpick_ignore:
|
||||
self.state_machine.reporter.warning(
|
||||
'duplicate C object description of %s, ' % name +
|
||||
'other instance in ' + self.env.doc2path(inv[name][0]),
|
||||
line=self.lineno)
|
||||
inv[name] = (self.env.docname, self.objtype)
|
||||
|
||||
indextext = self.get_index_text(name)
|
||||
if indextext:
|
||||
if major == 1 and minor < 4:
|
||||
# indexnode's tuple changed in 1.4
|
||||
# https://github.com/sphinx-doc/sphinx/commit/e6a5a3a92e938fcd75866b4227db9e0524d58f7c
|
||||
self.indexnode['entries'].append(
|
||||
('single', indextext, targetname, ''))
|
||||
else:
|
||||
self.indexnode['entries'].append(
|
||||
('single', indextext, targetname, '', None))
|
||||
|
||||
class CDomain(Base_CDomain):
|
||||
|
||||
"""C language domain."""
|
||||
name = 'c'
|
||||
label = 'C'
|
||||
directives = {
|
||||
'function': CObject,
|
||||
'member': CObject,
|
||||
'macro': CObject,
|
||||
'type': CObject,
|
||||
'var': CObject,
|
||||
}
|
||||
190
doc/sphinx/kernel_include.py
Executable file
190
doc/sphinx/kernel_include.py
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8; mode: python -*-
|
||||
# pylint: disable=R0903, C0330, R0914, R0912, E0401
|
||||
|
||||
u"""
|
||||
kernel-include
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Implementation of the ``kernel-include`` reST-directive.
|
||||
|
||||
:copyright: Copyright (C) 2016 Markus Heiser
|
||||
:license: GPL Version 2, June 1991 see linux/COPYING for details.
|
||||
|
||||
The ``kernel-include`` reST-directive is a replacement for the ``include``
|
||||
directive. The ``kernel-include`` directive expand environment variables in
|
||||
the path name and allows to include files from arbitrary locations.
|
||||
|
||||
.. hint::
|
||||
|
||||
Including files from arbitrary locations (e.g. from ``/etc``) is a
|
||||
security risk for builders. This is why the ``include`` directive from
|
||||
docutils *prohibit* pathnames pointing to locations *above* the filesystem
|
||||
tree where the reST document with the include directive is placed.
|
||||
|
||||
Substrings of the form $name or ${name} are replaced by the value of
|
||||
environment variable name. Malformed variable names and references to
|
||||
non-existing variables are left unchanged.
|
||||
"""
|
||||
|
||||
# ==============================================================================
|
||||
# imports
|
||||
# ==============================================================================
|
||||
|
||||
import os.path
|
||||
|
||||
from docutils import io, nodes, statemachine
|
||||
from docutils.utils.error_reporting import SafeString, ErrorString
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives.body import CodeBlock, NumberLines
|
||||
from docutils.parsers.rst.directives.misc import Include
|
||||
|
||||
__version__ = '1.0'
|
||||
|
||||
# ==============================================================================
|
||||
def setup(app):
|
||||
# ==============================================================================
|
||||
|
||||
app.add_directive("kernel-include", KernelInclude)
|
||||
return dict(
|
||||
version = __version__,
|
||||
parallel_read_safe = True,
|
||||
parallel_write_safe = True
|
||||
)
|
||||
|
||||
# ==============================================================================
|
||||
class KernelInclude(Include):
|
||||
# ==============================================================================
|
||||
|
||||
u"""KernelInclude (``kernel-include``) directive"""
|
||||
|
||||
def run(self):
|
||||
path = os.path.realpath(
|
||||
os.path.expandvars(self.arguments[0]))
|
||||
|
||||
# to get a bit security back, prohibit /etc:
|
||||
if path.startswith(os.sep + "etc"):
|
||||
raise self.severe(
|
||||
'Problems with "%s" directive, prohibited path: %s'
|
||||
% (self.name, path))
|
||||
|
||||
self.arguments[0] = path
|
||||
|
||||
#return super(KernelInclude, self).run() # won't work, see HINTs in _run()
|
||||
return self._run()
|
||||
|
||||
def _run(self):
|
||||
"""Include a file as part of the content of this reST file."""
|
||||
|
||||
# HINT: I had to copy&paste the whole Include.run method. I'am not happy
|
||||
# with this, but due to security reasons, the Include.run method does
|
||||
# not allow absolute or relative pathnames pointing to locations *above*
|
||||
# the filesystem tree where the reST document is placed.
|
||||
|
||||
if not self.state.document.settings.file_insertion_enabled:
|
||||
raise self.warning('"%s" directive disabled.' % self.name)
|
||||
source = self.state_machine.input_lines.source(
|
||||
self.lineno - self.state_machine.input_offset - 1)
|
||||
source_dir = os.path.dirname(os.path.abspath(source))
|
||||
path = directives.path(self.arguments[0])
|
||||
if path.startswith('<') and path.endswith('>'):
|
||||
path = os.path.join(self.standard_include_path, path[1:-1])
|
||||
path = os.path.normpath(os.path.join(source_dir, path))
|
||||
|
||||
# HINT: this is the only line I had to change / commented out:
|
||||
#path = utils.relative_path(None, path)
|
||||
|
||||
path = nodes.reprunicode(path)
|
||||
encoding = self.options.get(
|
||||
'encoding', self.state.document.settings.input_encoding)
|
||||
e_handler=self.state.document.settings.input_encoding_error_handler
|
||||
tab_width = self.options.get(
|
||||
'tab-width', self.state.document.settings.tab_width)
|
||||
try:
|
||||
self.state.document.settings.record_dependencies.add(path)
|
||||
include_file = io.FileInput(source_path=path,
|
||||
encoding=encoding,
|
||||
error_handler=e_handler)
|
||||
except UnicodeEncodeError as error:
|
||||
raise self.severe('Problems with "%s" directive path:\n'
|
||||
'Cannot encode input file path "%s" '
|
||||
'(wrong locale?).' %
|
||||
(self.name, SafeString(path)))
|
||||
except IOError as error:
|
||||
raise self.severe('Problems with "%s" directive path:\n%s.' %
|
||||
(self.name, ErrorString(error)))
|
||||
startline = self.options.get('start-line', None)
|
||||
endline = self.options.get('end-line', None)
|
||||
try:
|
||||
if startline or (endline is not None):
|
||||
lines = include_file.readlines()
|
||||
rawtext = ''.join(lines[startline:endline])
|
||||
else:
|
||||
rawtext = include_file.read()
|
||||
except UnicodeError as error:
|
||||
raise self.severe('Problem with "%s" directive:\n%s' %
|
||||
(self.name, ErrorString(error)))
|
||||
# start-after/end-before: no restrictions on newlines in match-text,
|
||||
# and no restrictions on matching inside lines vs. line boundaries
|
||||
after_text = self.options.get('start-after', None)
|
||||
if after_text:
|
||||
# skip content in rawtext before *and incl.* a matching text
|
||||
after_index = rawtext.find(after_text)
|
||||
if after_index < 0:
|
||||
raise self.severe('Problem with "start-after" option of "%s" '
|
||||
'directive:\nText not found.' % self.name)
|
||||
rawtext = rawtext[after_index + len(after_text):]
|
||||
before_text = self.options.get('end-before', None)
|
||||
if before_text:
|
||||
# skip content in rawtext after *and incl.* a matching text
|
||||
before_index = rawtext.find(before_text)
|
||||
if before_index < 0:
|
||||
raise self.severe('Problem with "end-before" option of "%s" '
|
||||
'directive:\nText not found.' % self.name)
|
||||
rawtext = rawtext[:before_index]
|
||||
|
||||
include_lines = statemachine.string2lines(rawtext, tab_width,
|
||||
convert_whitespace=True)
|
||||
if 'literal' in self.options:
|
||||
# Convert tabs to spaces, if `tab_width` is positive.
|
||||
if tab_width >= 0:
|
||||
text = rawtext.expandtabs(tab_width)
|
||||
else:
|
||||
text = rawtext
|
||||
literal_block = nodes.literal_block(rawtext, source=path,
|
||||
classes=self.options.get('class', []))
|
||||
literal_block.line = 1
|
||||
self.add_name(literal_block)
|
||||
if 'number-lines' in self.options:
|
||||
try:
|
||||
startline = int(self.options['number-lines'] or 1)
|
||||
except ValueError:
|
||||
raise self.error(':number-lines: with non-integer '
|
||||
'start value')
|
||||
endline = startline + len(include_lines)
|
||||
if text.endswith('\n'):
|
||||
text = text[:-1]
|
||||
tokens = NumberLines([([], text)], startline, endline)
|
||||
for classes, value in tokens:
|
||||
if classes:
|
||||
literal_block += nodes.inline(value, value,
|
||||
classes=classes)
|
||||
else:
|
||||
literal_block += nodes.Text(value, value)
|
||||
else:
|
||||
literal_block += nodes.Text(text, text)
|
||||
return [literal_block]
|
||||
if 'code' in self.options:
|
||||
self.options['source'] = path
|
||||
codeblock = CodeBlock(self.name,
|
||||
[self.options.pop('code')], # arguments
|
||||
self.options,
|
||||
include_lines, # content
|
||||
self.lineno,
|
||||
self.content_offset,
|
||||
self.block_text,
|
||||
self.state,
|
||||
self.state_machine)
|
||||
return codeblock.run()
|
||||
self.state_machine.insert_input(include_lines, path)
|
||||
return []
|
||||
146
doc/sphinx/kerneldoc.py
Normal file
146
doc/sphinx/kerneldoc.py
Normal file
@@ -0,0 +1,146 @@
|
||||
# coding=utf-8
|
||||
#
|
||||
# Copyright © 2016 Intel Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
#
|
||||
# Authors:
|
||||
# Jani Nikula <jani.nikula@intel.com>
|
||||
#
|
||||
# Please make sure this works on both python2 and python3.
|
||||
#
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
import glob
|
||||
|
||||
from docutils import nodes, statemachine
|
||||
from docutils.statemachine import ViewList
|
||||
from docutils.parsers.rst import directives, Directive
|
||||
from sphinx.ext.autodoc import AutodocReporter
|
||||
|
||||
__version__ = '1.0'
|
||||
|
||||
class KernelDocDirective(Directive):
|
||||
"""Extract kernel-doc comments from the specified file"""
|
||||
required_argument = 1
|
||||
optional_arguments = 4
|
||||
option_spec = {
|
||||
'doc': directives.unchanged_required,
|
||||
'functions': directives.unchanged_required,
|
||||
'export': directives.unchanged,
|
||||
'internal': directives.unchanged,
|
||||
}
|
||||
has_content = False
|
||||
|
||||
def run(self):
|
||||
env = self.state.document.settings.env
|
||||
cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
|
||||
|
||||
filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
|
||||
export_file_patterns = []
|
||||
|
||||
# Tell sphinx of the dependency
|
||||
env.note_dependency(os.path.abspath(filename))
|
||||
|
||||
tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
|
||||
|
||||
# FIXME: make this nicer and more robust against errors
|
||||
if 'export' in self.options:
|
||||
cmd += ['-export']
|
||||
export_file_patterns = str(self.options.get('export')).split()
|
||||
elif 'internal' in self.options:
|
||||
cmd += ['-internal']
|
||||
export_file_patterns = str(self.options.get('internal')).split()
|
||||
elif 'doc' in self.options:
|
||||
cmd += ['-function', str(self.options.get('doc'))]
|
||||
elif 'functions' in self.options:
|
||||
for f in str(self.options.get('functions')).split():
|
||||
cmd += ['-function', f]
|
||||
|
||||
for pattern in export_file_patterns:
|
||||
for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
|
||||
env.note_dependency(os.path.abspath(f))
|
||||
cmd += ['-export-file', f]
|
||||
|
||||
cmd += [filename]
|
||||
|
||||
try:
|
||||
env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd)))
|
||||
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = p.communicate()
|
||||
|
||||
out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
|
||||
|
||||
if p.returncode != 0:
|
||||
sys.stderr.write(err)
|
||||
|
||||
env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
|
||||
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
|
||||
elif env.config.kerneldoc_verbosity > 0:
|
||||
sys.stderr.write(err)
|
||||
|
||||
lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
|
||||
result = ViewList()
|
||||
|
||||
lineoffset = 0;
|
||||
line_regex = re.compile("^#define LINENO ([0-9]+)$")
|
||||
for line in lines:
|
||||
match = line_regex.search(line)
|
||||
if match:
|
||||
# sphinx counts lines from 0
|
||||
lineoffset = int(match.group(1)) - 1
|
||||
# we must eat our comments since the upset the markup
|
||||
else:
|
||||
result.append(line, filename, lineoffset)
|
||||
lineoffset += 1
|
||||
|
||||
node = nodes.section()
|
||||
buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
|
||||
self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
|
||||
self.state.memo.title_styles, self.state.memo.section_level = [], 0
|
||||
try:
|
||||
self.state.nested_parse(result, 0, node, match_titles=1)
|
||||
finally:
|
||||
self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
|
||||
|
||||
return node.children
|
||||
|
||||
except Exception as e: # pylint: disable=W0703
|
||||
env.app.warn('kernel-doc \'%s\' processing failed with: %s' %
|
||||
(" ".join(cmd), str(e)))
|
||||
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('kerneldoc_bin', None, 'env')
|
||||
app.add_config_value('kerneldoc_srctree', None, 'env')
|
||||
app.add_config_value('kerneldoc_verbosity', 1, 'env')
|
||||
|
||||
app.add_directive('kernel-doc', KernelDocDirective)
|
||||
|
||||
return dict(
|
||||
version = __version__,
|
||||
parallel_read_safe = True,
|
||||
parallel_write_safe = True
|
||||
)
|
||||
551
doc/sphinx/kfigure.py
Normal file
551
doc/sphinx/kfigure.py
Normal file
@@ -0,0 +1,551 @@
|
||||
# -*- coding: utf-8; mode: python -*-
|
||||
# pylint: disable=C0103, R0903, R0912, R0915
|
||||
u"""
|
||||
scalable figure and image handling
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sphinx extension which implements scalable image handling.
|
||||
|
||||
:copyright: Copyright (C) 2016 Markus Heiser
|
||||
:license: GPL Version 2, June 1991 see Linux/COPYING for details.
|
||||
|
||||
The build for image formats depend on image's source format and output's
|
||||
destination format. This extension implement methods to simplify image
|
||||
handling from the author's POV. Directives like ``kernel-figure`` implement
|
||||
methods *to* always get the best output-format even if some tools are not
|
||||
installed. For more details take a look at ``convert_image(...)`` which is
|
||||
the core of all conversions.
|
||||
|
||||
* ``.. kernel-image``: for image handling / a ``.. image::`` replacement
|
||||
|
||||
* ``.. kernel-figure``: for figure handling / a ``.. figure::`` replacement
|
||||
|
||||
* ``.. kernel-render``: for render markup / a concept to embed *render*
|
||||
markups (or languages). Supported markups (see ``RENDER_MARKUP_EXT``)
|
||||
|
||||
- ``DOT``: render embedded Graphviz's **DOC**
|
||||
- ``SVG``: render embedded Scalable Vector Graphics (**SVG**)
|
||||
- ... *developable*
|
||||
|
||||
Used tools:
|
||||
|
||||
* ``dot(1)``: Graphviz (http://www.graphviz.org). If Graphviz is not
|
||||
available, the DOT language is inserted as literal-block.
|
||||
|
||||
* SVG to PDF: To generate PDF, you need at least one of this tools:
|
||||
|
||||
- ``convert(1)``: ImageMagick (https://www.imagemagick.org)
|
||||
|
||||
List of customizations:
|
||||
|
||||
* generate PDF from SVG / used by PDF (LaTeX) builder
|
||||
|
||||
* generate SVG (html-builder) and PDF (latex-builder) from DOT files.
|
||||
DOT: see http://www.graphviz.org/content/dot-language
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from os import path
|
||||
import subprocess
|
||||
from hashlib import sha1
|
||||
import sys
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.statemachine import ViewList
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives import images
|
||||
import sphinx
|
||||
|
||||
from sphinx.util.nodes import clean_astext
|
||||
from six import iteritems
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
_unicode = str
|
||||
else:
|
||||
_unicode = unicode
|
||||
|
||||
# Get Sphinx version
|
||||
major, minor, patch = sphinx.version_info[:3]
|
||||
if major == 1 and minor > 3:
|
||||
# patches.Figure only landed in Sphinx 1.4
|
||||
from sphinx.directives.patches import Figure # pylint: disable=C0413
|
||||
else:
|
||||
Figure = images.Figure
|
||||
|
||||
__version__ = '1.0.0'
|
||||
|
||||
# simple helper
|
||||
# -------------
|
||||
|
||||
def which(cmd):
|
||||
"""Searches the ``cmd`` in the ``PATH`` environment.
|
||||
|
||||
This *which* searches the PATH for executable ``cmd`` . First match is
|
||||
returned, if nothing is found, ``None` is returned.
|
||||
"""
|
||||
envpath = os.environ.get('PATH', None) or os.defpath
|
||||
for folder in envpath.split(os.pathsep):
|
||||
fname = folder + os.sep + cmd
|
||||
if path.isfile(fname):
|
||||
return fname
|
||||
|
||||
def mkdir(folder, mode=0o775):
|
||||
if not path.isdir(folder):
|
||||
os.makedirs(folder, mode)
|
||||
|
||||
def file2literal(fname):
|
||||
with open(fname, "r") as src:
|
||||
data = src.read()
|
||||
node = nodes.literal_block(data, data)
|
||||
return node
|
||||
|
||||
def isNewer(path1, path2):
|
||||
"""Returns True if ``path1`` is newer than ``path2``
|
||||
|
||||
If ``path1`` exists and is newer than ``path2`` the function returns
|
||||
``True`` is returned otherwise ``False``
|
||||
"""
|
||||
return (path.exists(path1)
|
||||
and os.stat(path1).st_ctime > os.stat(path2).st_ctime)
|
||||
|
||||
def pass_handle(self, node): # pylint: disable=W0613
|
||||
pass
|
||||
|
||||
# setup conversion tools and sphinx extension
|
||||
# -------------------------------------------
|
||||
|
||||
# Graphviz's dot(1) support
|
||||
dot_cmd = None
|
||||
|
||||
# ImageMagick' convert(1) support
|
||||
convert_cmd = None
|
||||
|
||||
|
||||
def setup(app):
|
||||
# check toolchain first
|
||||
app.connect('builder-inited', setupTools)
|
||||
|
||||
# image handling
|
||||
app.add_directive("kernel-image", KernelImage)
|
||||
app.add_node(kernel_image,
|
||||
html = (visit_kernel_image, pass_handle),
|
||||
latex = (visit_kernel_image, pass_handle),
|
||||
texinfo = (visit_kernel_image, pass_handle),
|
||||
text = (visit_kernel_image, pass_handle),
|
||||
man = (visit_kernel_image, pass_handle), )
|
||||
|
||||
# figure handling
|
||||
app.add_directive("kernel-figure", KernelFigure)
|
||||
app.add_node(kernel_figure,
|
||||
html = (visit_kernel_figure, pass_handle),
|
||||
latex = (visit_kernel_figure, pass_handle),
|
||||
texinfo = (visit_kernel_figure, pass_handle),
|
||||
text = (visit_kernel_figure, pass_handle),
|
||||
man = (visit_kernel_figure, pass_handle), )
|
||||
|
||||
# render handling
|
||||
app.add_directive('kernel-render', KernelRender)
|
||||
app.add_node(kernel_render,
|
||||
html = (visit_kernel_render, pass_handle),
|
||||
latex = (visit_kernel_render, pass_handle),
|
||||
texinfo = (visit_kernel_render, pass_handle),
|
||||
text = (visit_kernel_render, pass_handle),
|
||||
man = (visit_kernel_render, pass_handle), )
|
||||
|
||||
app.connect('doctree-read', add_kernel_figure_to_std_domain)
|
||||
|
||||
return dict(
|
||||
version = __version__,
|
||||
parallel_read_safe = True,
|
||||
parallel_write_safe = True
|
||||
)
|
||||
|
||||
|
||||
def setupTools(app):
|
||||
u"""
|
||||
Check available build tools and log some *verbose* messages.
|
||||
|
||||
This function is called once, when the builder is initiated.
|
||||
"""
|
||||
global dot_cmd, convert_cmd # pylint: disable=W0603
|
||||
app.verbose("kfigure: check installed tools ...")
|
||||
|
||||
dot_cmd = which('dot')
|
||||
convert_cmd = which('convert')
|
||||
|
||||
if dot_cmd:
|
||||
app.verbose("use dot(1) from: " + dot_cmd)
|
||||
else:
|
||||
app.warn("dot(1) not found, for better output quality install "
|
||||
"graphviz from http://www.graphviz.org")
|
||||
if convert_cmd:
|
||||
app.verbose("use convert(1) from: " + convert_cmd)
|
||||
else:
|
||||
app.warn(
|
||||
"convert(1) not found, for SVG to PDF conversion install "
|
||||
"ImageMagick (https://www.imagemagick.org)")
|
||||
|
||||
|
||||
# integrate conversion tools
|
||||
# --------------------------
|
||||
|
||||
RENDER_MARKUP_EXT = {
|
||||
# The '.ext' must be handled by convert_image(..) function's *in_ext* input.
|
||||
# <name> : <.ext>
|
||||
'DOT' : '.dot',
|
||||
'SVG' : '.svg'
|
||||
}
|
||||
|
||||
def convert_image(img_node, translator, src_fname=None):
|
||||
"""Convert a image node for the builder.
|
||||
|
||||
Different builder prefer different image formats, e.g. *latex* builder
|
||||
prefer PDF while *html* builder prefer SVG format for images.
|
||||
|
||||
This function handles output image formats in dependence of source the
|
||||
format (of the image) and the translator's output format.
|
||||
"""
|
||||
app = translator.builder.app
|
||||
|
||||
fname, in_ext = path.splitext(path.basename(img_node['uri']))
|
||||
if src_fname is None:
|
||||
src_fname = path.join(translator.builder.srcdir, img_node['uri'])
|
||||
if not path.exists(src_fname):
|
||||
src_fname = path.join(translator.builder.outdir, img_node['uri'])
|
||||
|
||||
dst_fname = None
|
||||
|
||||
# in kernel builds, use 'make SPHINXOPTS=-v' to see verbose messages
|
||||
|
||||
app.verbose('assert best format for: ' + img_node['uri'])
|
||||
|
||||
if in_ext == '.dot':
|
||||
|
||||
if not dot_cmd:
|
||||
app.verbose("dot from graphviz not available / include DOT raw.")
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
|
||||
elif translator.builder.format == 'latex':
|
||||
dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
|
||||
img_node['uri'] = fname + '.pdf'
|
||||
img_node['candidates'] = {'*': fname + '.pdf'}
|
||||
|
||||
|
||||
elif translator.builder.format == 'html':
|
||||
dst_fname = path.join(
|
||||
translator.builder.outdir,
|
||||
translator.builder.imagedir,
|
||||
fname + '.svg')
|
||||
img_node['uri'] = path.join(
|
||||
translator.builder.imgpath, fname + '.svg')
|
||||
img_node['candidates'] = {
|
||||
'*': path.join(translator.builder.imgpath, fname + '.svg')}
|
||||
|
||||
else:
|
||||
# all other builder formats will include DOT as raw
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
|
||||
elif in_ext == '.svg':
|
||||
|
||||
if translator.builder.format == 'latex':
|
||||
if convert_cmd is None:
|
||||
app.verbose("no SVG to PDF conversion available / include SVG raw.")
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
else:
|
||||
dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
|
||||
img_node['uri'] = fname + '.pdf'
|
||||
img_node['candidates'] = {'*': fname + '.pdf'}
|
||||
|
||||
if dst_fname:
|
||||
# the builder needs not to copy one more time, so pop it if exists.
|
||||
translator.builder.images.pop(img_node['uri'], None)
|
||||
_name = dst_fname[len(translator.builder.outdir) + 1:]
|
||||
|
||||
if isNewer(dst_fname, src_fname):
|
||||
app.verbose("convert: {out}/%s already exists and is newer" % _name)
|
||||
|
||||
else:
|
||||
ok = False
|
||||
mkdir(path.dirname(dst_fname))
|
||||
|
||||
if in_ext == '.dot':
|
||||
app.verbose('convert DOT to: {out}/' + _name)
|
||||
ok = dot2format(app, src_fname, dst_fname)
|
||||
|
||||
elif in_ext == '.svg':
|
||||
app.verbose('convert SVG to: {out}/' + _name)
|
||||
ok = svg2pdf(app, src_fname, dst_fname)
|
||||
|
||||
if not ok:
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
|
||||
|
||||
def dot2format(app, dot_fname, out_fname):
|
||||
"""Converts DOT file to ``out_fname`` using ``dot(1)``.
|
||||
|
||||
* ``dot_fname`` pathname of the input DOT file, including extension ``.dot``
|
||||
* ``out_fname`` pathname of the output file, including format extension
|
||||
|
||||
The *format extension* depends on the ``dot`` command (see ``man dot``
|
||||
option ``-Txxx``). Normally you will use one of the following extensions:
|
||||
|
||||
- ``.ps`` for PostScript,
|
||||
- ``.svg`` or ``svgz`` for Structured Vector Graphics,
|
||||
- ``.fig`` for XFIG graphics and
|
||||
- ``.png`` or ``gif`` for common bitmap graphics.
|
||||
|
||||
"""
|
||||
out_format = path.splitext(out_fname)[1][1:]
|
||||
cmd = [dot_cmd, '-T%s' % out_format, dot_fname]
|
||||
exit_code = 42
|
||||
|
||||
with open(out_fname, "w") as out:
|
||||
exit_code = subprocess.call(cmd, stdout = out)
|
||||
if exit_code != 0:
|
||||
app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
|
||||
return bool(exit_code == 0)
|
||||
|
||||
def svg2pdf(app, svg_fname, pdf_fname):
|
||||
"""Converts SVG to PDF with ``convert(1)`` command.
|
||||
|
||||
Uses ``convert(1)`` from ImageMagick (https://www.imagemagick.org) for
|
||||
conversion. Returns ``True`` on success and ``False`` if an error occurred.
|
||||
|
||||
* ``svg_fname`` pathname of the input SVG file with extension (``.svg``)
|
||||
* ``pdf_name`` pathname of the output PDF file with extension (``.pdf``)
|
||||
|
||||
"""
|
||||
cmd = [convert_cmd, svg_fname, pdf_fname]
|
||||
# use stdout and stderr from parent
|
||||
exit_code = subprocess.call(cmd)
|
||||
if exit_code != 0:
|
||||
app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
|
||||
return bool(exit_code == 0)
|
||||
|
||||
|
||||
# image handling
|
||||
# ---------------------
|
||||
|
||||
def visit_kernel_image(self, node): # pylint: disable=W0613
|
||||
"""Visitor of the ``kernel_image`` Node.
|
||||
|
||||
Handles the ``image`` child-node with the ``convert_image(...)``.
|
||||
"""
|
||||
img_node = node[0]
|
||||
convert_image(img_node, self)
|
||||
|
||||
class kernel_image(nodes.image):
|
||||
"""Node for ``kernel-image`` directive."""
|
||||
pass
|
||||
|
||||
class KernelImage(images.Image):
|
||||
u"""KernelImage directive
|
||||
|
||||
Earns everything from ``.. image::`` directive, except *remote URI* and
|
||||
*glob* pattern. The KernelImage wraps a image node into a
|
||||
kernel_image node. See ``visit_kernel_image``.
|
||||
"""
|
||||
|
||||
def run(self):
|
||||
uri = self.arguments[0]
|
||||
if uri.endswith('.*') or uri.find('://') != -1:
|
||||
raise self.severe(
|
||||
'Error in "%s: %s": glob pattern and remote images are not allowed'
|
||||
% (self.name, uri))
|
||||
result = images.Image.run(self)
|
||||
if len(result) == 2 or isinstance(result[0], nodes.system_message):
|
||||
return result
|
||||
(image_node,) = result
|
||||
# wrap image node into a kernel_image node / see visitors
|
||||
node = kernel_image('', image_node)
|
||||
return [node]
|
||||
|
||||
# figure handling
|
||||
# ---------------------
|
||||
|
||||
def visit_kernel_figure(self, node): # pylint: disable=W0613
|
||||
"""Visitor of the ``kernel_figure`` Node.
|
||||
|
||||
Handles the ``image`` child-node with the ``convert_image(...)``.
|
||||
"""
|
||||
img_node = node[0][0]
|
||||
convert_image(img_node, self)
|
||||
|
||||
class kernel_figure(nodes.figure):
|
||||
"""Node for ``kernel-figure`` directive."""
|
||||
|
||||
class KernelFigure(Figure):
|
||||
u"""KernelImage directive
|
||||
|
||||
Earns everything from ``.. figure::`` directive, except *remote URI* and
|
||||
*glob* pattern. The KernelFigure wraps a figure node into a kernel_figure
|
||||
node. See ``visit_kernel_figure``.
|
||||
"""
|
||||
|
||||
def run(self):
|
||||
uri = self.arguments[0]
|
||||
if uri.endswith('.*') or uri.find('://') != -1:
|
||||
raise self.severe(
|
||||
'Error in "%s: %s":'
|
||||
' glob pattern and remote images are not allowed'
|
||||
% (self.name, uri))
|
||||
result = Figure.run(self)
|
||||
if len(result) == 2 or isinstance(result[0], nodes.system_message):
|
||||
return result
|
||||
(figure_node,) = result
|
||||
# wrap figure node into a kernel_figure node / see visitors
|
||||
node = kernel_figure('', figure_node)
|
||||
return [node]
|
||||
|
||||
|
||||
# render handling
|
||||
# ---------------------
|
||||
|
||||
def visit_kernel_render(self, node):
|
||||
"""Visitor of the ``kernel_render`` Node.
|
||||
|
||||
If rendering tools available, save the markup of the ``literal_block`` child
|
||||
node into a file and replace the ``literal_block`` node with a new created
|
||||
``image`` node, pointing to the saved markup file. Afterwards, handle the
|
||||
image child-node with the ``convert_image(...)``.
|
||||
"""
|
||||
app = self.builder.app
|
||||
srclang = node.get('srclang')
|
||||
|
||||
app.verbose('visit kernel-render node lang: "%s"' % (srclang))
|
||||
|
||||
tmp_ext = RENDER_MARKUP_EXT.get(srclang, None)
|
||||
if tmp_ext is None:
|
||||
app.warn('kernel-render: "%s" unknown / include raw.' % (srclang))
|
||||
return
|
||||
|
||||
if not dot_cmd and tmp_ext == '.dot':
|
||||
app.verbose("dot from graphviz not available / include raw.")
|
||||
return
|
||||
|
||||
literal_block = node[0]
|
||||
|
||||
code = literal_block.astext()
|
||||
hashobj = code.encode('utf-8') # str(node.attributes)
|
||||
fname = path.join('%s-%s' % (srclang, sha1(hashobj).hexdigest()))
|
||||
|
||||
tmp_fname = path.join(
|
||||
self.builder.outdir, self.builder.imagedir, fname + tmp_ext)
|
||||
|
||||
if not path.isfile(tmp_fname):
|
||||
mkdir(path.dirname(tmp_fname))
|
||||
with open(tmp_fname, "w") as out:
|
||||
out.write(code)
|
||||
|
||||
img_node = nodes.image(node.rawsource, **node.attributes)
|
||||
img_node['uri'] = path.join(self.builder.imgpath, fname + tmp_ext)
|
||||
img_node['candidates'] = {
|
||||
'*': path.join(self.builder.imgpath, fname + tmp_ext)}
|
||||
|
||||
literal_block.replace_self(img_node)
|
||||
convert_image(img_node, self, tmp_fname)
|
||||
|
||||
|
||||
class kernel_render(nodes.General, nodes.Inline, nodes.Element):
|
||||
"""Node for ``kernel-render`` directive."""
|
||||
pass
|
||||
|
||||
class KernelRender(Figure):
|
||||
u"""KernelRender directive
|
||||
|
||||
Render content by external tool. Has all the options known from the
|
||||
*figure* directive, plus option ``caption``. If ``caption`` has a
|
||||
value, a figure node with the *caption* is inserted. If not, a image node is
|
||||
inserted.
|
||||
|
||||
The KernelRender directive wraps the text of the directive into a
|
||||
literal_block node and wraps it into a kernel_render node. See
|
||||
``visit_kernel_render``.
|
||||
"""
|
||||
has_content = True
|
||||
required_arguments = 1
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = False
|
||||
|
||||
# earn options from 'figure'
|
||||
option_spec = Figure.option_spec.copy()
|
||||
option_spec['caption'] = directives.unchanged
|
||||
|
||||
def run(self):
|
||||
return [self.build_node()]
|
||||
|
||||
def build_node(self):
|
||||
|
||||
srclang = self.arguments[0].strip()
|
||||
if srclang not in RENDER_MARKUP_EXT.keys():
|
||||
return [self.state_machine.reporter.warning(
|
||||
'Unknown source language "%s", use one of: %s.' % (
|
||||
srclang, ",".join(RENDER_MARKUP_EXT.keys())),
|
||||
line=self.lineno)]
|
||||
|
||||
code = '\n'.join(self.content)
|
||||
if not code.strip():
|
||||
return [self.state_machine.reporter.warning(
|
||||
'Ignoring "%s" directive without content.' % (
|
||||
self.name),
|
||||
line=self.lineno)]
|
||||
|
||||
node = kernel_render()
|
||||
node['alt'] = self.options.get('alt','')
|
||||
node['srclang'] = srclang
|
||||
literal_node = nodes.literal_block(code, code)
|
||||
node += literal_node
|
||||
|
||||
caption = self.options.get('caption')
|
||||
if caption:
|
||||
# parse caption's content
|
||||
parsed = nodes.Element()
|
||||
self.state.nested_parse(
|
||||
ViewList([caption], source=''), self.content_offset, parsed)
|
||||
caption_node = nodes.caption(
|
||||
parsed[0].rawsource, '', *parsed[0].children)
|
||||
caption_node.source = parsed[0].source
|
||||
caption_node.line = parsed[0].line
|
||||
|
||||
figure_node = nodes.figure('', node)
|
||||
for k,v in self.options.items():
|
||||
figure_node[k] = v
|
||||
figure_node += caption_node
|
||||
|
||||
node = figure_node
|
||||
|
||||
return node
|
||||
|
||||
def add_kernel_figure_to_std_domain(app, doctree):
|
||||
"""Add kernel-figure anchors to 'std' domain.
|
||||
|
||||
The ``StandardDomain.process_doc(..)`` method does not know how to resolve
|
||||
the caption (label) of ``kernel-figure`` directive (it only knows about
|
||||
standard nodes, e.g. table, figure etc.). Without any additional handling
|
||||
this will result in a 'undefined label' for kernel-figures.
|
||||
|
||||
This handle adds labels of kernel-figure to the 'std' domain labels.
|
||||
"""
|
||||
|
||||
std = app.env.domains["std"]
|
||||
docname = app.env.docname
|
||||
labels = std.data["labels"]
|
||||
|
||||
for name, explicit in iteritems(doctree.nametypes):
|
||||
if not explicit:
|
||||
continue
|
||||
labelid = doctree.nameids[name]
|
||||
if labelid is None:
|
||||
continue
|
||||
node = doctree.ids[labelid]
|
||||
|
||||
if node.tagname == 'kernel_figure':
|
||||
for n in node.next_node():
|
||||
if n.tagname == 'caption':
|
||||
sectname = clean_astext(n)
|
||||
# add label to std domain
|
||||
labels[name] = docname, labelid, sectname
|
||||
break
|
||||
32
doc/sphinx/load_config.py
Normal file
32
doc/sphinx/load_config.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8; mode: python -*-
|
||||
# pylint: disable=R0903, C0330, R0914, R0912, E0401
|
||||
|
||||
import os
|
||||
import sys
|
||||
from sphinx.util.pycompat import execfile_
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
def loadConfig(namespace):
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
u"""Load an additional configuration file into *namespace*.
|
||||
|
||||
The name of the configuration file is taken from the environment
|
||||
``SPHINX_CONF``. The external configuration file extends (or overwrites) the
|
||||
configuration values from the origin ``conf.py``. With this you are able to
|
||||
maintain *build themes*. """
|
||||
|
||||
config_file = os.environ.get("SPHINX_CONF", None)
|
||||
if (config_file is not None
|
||||
and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ):
|
||||
config_file = os.path.abspath(config_file)
|
||||
|
||||
if os.path.isfile(config_file):
|
||||
sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
|
||||
config = namespace.copy()
|
||||
config['__file__'] = config_file
|
||||
execfile_(config_file, config)
|
||||
del config['__file__']
|
||||
namespace.update(config)
|
||||
else:
|
||||
sys.stderr.write("WARNING: additional sphinx-config not found: %s\n" % config_file)
|
||||
401
doc/sphinx/parse-headers.pl
Executable file
401
doc/sphinx/parse-headers.pl
Executable file
@@ -0,0 +1,401 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use Text::Tabs;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
|
||||
my $debug;
|
||||
my $help;
|
||||
my $man;
|
||||
|
||||
GetOptions(
|
||||
"debug" => \$debug,
|
||||
'usage|?' => \$help,
|
||||
'help' => \$man
|
||||
) or pod2usage(2);
|
||||
|
||||
pod2usage(1) if $help;
|
||||
pod2usage(-exitstatus => 0, -verbose => 2) if $man;
|
||||
pod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3);
|
||||
|
||||
my ($file_in, $file_out, $file_exceptions) = @ARGV;
|
||||
|
||||
my $data;
|
||||
my %ioctls;
|
||||
my %defines;
|
||||
my %typedefs;
|
||||
my %enums;
|
||||
my %enum_symbols;
|
||||
my %structs;
|
||||
|
||||
require Data::Dumper if ($debug);
|
||||
|
||||
#
|
||||
# read the file and get identifiers
|
||||
#
|
||||
|
||||
my $is_enum = 0;
|
||||
my $is_comment = 0;
|
||||
open IN, $file_in or die "Can't open $file_in";
|
||||
while (<IN>) {
|
||||
$data .= $_;
|
||||
|
||||
my $ln = $_;
|
||||
if (!$is_comment) {
|
||||
$ln =~ s,/\*.*(\*/),,g;
|
||||
|
||||
$is_comment = 1 if ($ln =~ s,/\*.*,,);
|
||||
} else {
|
||||
if ($ln =~ s,^(.*\*/),,) {
|
||||
$is_comment = 0;
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_enum && $ln =~ m/^\s*([_\w][\w\d_]+)\s*[\,=]?/) {
|
||||
my $s = $1;
|
||||
my $n = $1;
|
||||
$n =~ tr/A-Z/a-z/;
|
||||
$n =~ tr/_/-/;
|
||||
|
||||
$enum_symbols{$s} = "\\ :ref:`$s <$n>`\\ ";
|
||||
|
||||
$is_enum = 0 if ($is_enum && m/\}/);
|
||||
next;
|
||||
}
|
||||
$is_enum = 0 if ($is_enum && m/\}/);
|
||||
|
||||
if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+_IO/) {
|
||||
my $s = $1;
|
||||
my $n = $1;
|
||||
$n =~ tr/A-Z/a-z/;
|
||||
|
||||
$ioctls{$s} = "\\ :ref:`$s <$n>`\\ ";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+/) {
|
||||
my $s = $1;
|
||||
my $n = $1;
|
||||
$n =~ tr/A-Z/a-z/;
|
||||
$n =~ tr/_/-/;
|
||||
|
||||
$defines{$s} = "\\ :ref:`$s <$n>`\\ ";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($ln =~ m/^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);/) {
|
||||
my $s = $2;
|
||||
my $n = $3;
|
||||
|
||||
$typedefs{$n} = "\\ :c:type:`$n <$s>`\\ ";
|
||||
next;
|
||||
}
|
||||
if ($ln =~ m/^\s*enum\s+([_\w][\w\d_]+)\s+\{/
|
||||
|| $ln =~ m/^\s*enum\s+([_\w][\w\d_]+)$/
|
||||
|| $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)\s+\{/
|
||||
|| $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)$/) {
|
||||
my $s = $1;
|
||||
|
||||
$enums{$s} = "enum :c:type:`$s`\\ ";
|
||||
|
||||
$is_enum = $1;
|
||||
next;
|
||||
}
|
||||
if ($ln =~ m/^\s*struct\s+([_\w][\w\d_]+)\s+\{/
|
||||
|| $ln =~ m/^\s*struct\s+([[_\w][\w\d_]+)$/
|
||||
|| $ln =~ m/^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s+\{/
|
||||
|| $ln =~ m/^\s*typedef\s*struct\s+([[_\w][\w\d_]+)$/
|
||||
) {
|
||||
my $s = $1;
|
||||
|
||||
$structs{$s} = "struct :c:type:`$s`\\ ";
|
||||
next;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
#
|
||||
# Handle multi-line typedefs
|
||||
#
|
||||
|
||||
my @matches = ($data =~ m/typedef\s+struct\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,
|
||||
$data =~ m/typedef\s+enum\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,);
|
||||
foreach my $m (@matches) {
|
||||
my $s = $m;
|
||||
|
||||
$typedefs{$s} = "\\ :c:type:`$s`\\ ";
|
||||
next;
|
||||
}
|
||||
|
||||
#
|
||||
# Handle exceptions, if any
|
||||
#
|
||||
|
||||
my %def_reftype = (
|
||||
"ioctl" => ":ref",
|
||||
"define" => ":ref",
|
||||
"symbol" => ":ref",
|
||||
"typedef" => ":c:type",
|
||||
"enum" => ":c:type",
|
||||
"struct" => ":c:type",
|
||||
);
|
||||
|
||||
if ($file_exceptions) {
|
||||
open IN, $file_exceptions or die "Can't read $file_exceptions";
|
||||
while (<IN>) {
|
||||
next if (m/^\s*$/ || m/^\s*#/);
|
||||
|
||||
# Parsers to ignore a symbol
|
||||
|
||||
if (m/^ignore\s+ioctl\s+(\S+)/) {
|
||||
delete $ioctls{$1} if (exists($ioctls{$1}));
|
||||
next;
|
||||
}
|
||||
if (m/^ignore\s+define\s+(\S+)/) {
|
||||
delete $defines{$1} if (exists($defines{$1}));
|
||||
next;
|
||||
}
|
||||
if (m/^ignore\s+typedef\s+(\S+)/) {
|
||||
delete $typedefs{$1} if (exists($typedefs{$1}));
|
||||
next;
|
||||
}
|
||||
if (m/^ignore\s+enum\s+(\S+)/) {
|
||||
delete $enums{$1} if (exists($enums{$1}));
|
||||
next;
|
||||
}
|
||||
if (m/^ignore\s+struct\s+(\S+)/) {
|
||||
delete $structs{$1} if (exists($structs{$1}));
|
||||
next;
|
||||
}
|
||||
if (m/^ignore\s+symbol\s+(\S+)/) {
|
||||
delete $enum_symbols{$1} if (exists($enum_symbols{$1}));
|
||||
next;
|
||||
}
|
||||
|
||||
# Parsers to replace a symbol
|
||||
my ($type, $old, $new, $reftype);
|
||||
|
||||
if (m/^replace\s+(\S+)\s+(\S+)\s+(\S+)/) {
|
||||
$type = $1;
|
||||
$old = $2;
|
||||
$new = $3;
|
||||
} else {
|
||||
die "Can't parse $file_exceptions: $_";
|
||||
}
|
||||
|
||||
if ($new =~ m/^\:c\:(data|func|macro|type)\:\`(.+)\`/) {
|
||||
$reftype = ":c:$1";
|
||||
$new = $2;
|
||||
} elsif ($new =~ m/\:ref\:\`(.+)\`/) {
|
||||
$reftype = ":ref";
|
||||
$new = $1;
|
||||
} else {
|
||||
$reftype = $def_reftype{$type};
|
||||
}
|
||||
$new = "$reftype:`$old <$new>`";
|
||||
|
||||
if ($type eq "ioctl") {
|
||||
$ioctls{$old} = $new if (exists($ioctls{$old}));
|
||||
next;
|
||||
}
|
||||
if ($type eq "define") {
|
||||
$defines{$old} = $new if (exists($defines{$old}));
|
||||
next;
|
||||
}
|
||||
if ($type eq "symbol") {
|
||||
$enum_symbols{$old} = $new if (exists($enum_symbols{$old}));
|
||||
next;
|
||||
}
|
||||
if ($type eq "typedef") {
|
||||
$typedefs{$old} = $new if (exists($typedefs{$old}));
|
||||
next;
|
||||
}
|
||||
if ($type eq "enum") {
|
||||
$enums{$old} = $new if (exists($enums{$old}));
|
||||
next;
|
||||
}
|
||||
if ($type eq "struct") {
|
||||
$structs{$old} = $new if (exists($structs{$old}));
|
||||
next;
|
||||
}
|
||||
|
||||
die "Can't parse $file_exceptions: $_";
|
||||
}
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls);
|
||||
print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs);
|
||||
print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums);
|
||||
print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs);
|
||||
print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines);
|
||||
print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols);
|
||||
}
|
||||
|
||||
#
|
||||
# Align block
|
||||
#
|
||||
$data = expand($data);
|
||||
$data = " " . $data;
|
||||
$data =~ s/\n/\n /g;
|
||||
$data =~ s/\n\s+$/\n/g;
|
||||
$data =~ s/\n\s+\n/\n\n/g;
|
||||
|
||||
#
|
||||
# Add escape codes for special characters
|
||||
#
|
||||
$data =~ s,([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^]),\\$1,g;
|
||||
|
||||
$data =~ s,DEPRECATED,**DEPRECATED**,g;
|
||||
|
||||
#
|
||||
# Add references
|
||||
#
|
||||
|
||||
my $start_delim = "[ \n\t\(\=\*\@]";
|
||||
my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)";
|
||||
|
||||
foreach my $r (keys %ioctls) {
|
||||
my $s = $ioctls{$r};
|
||||
|
||||
$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
|
||||
|
||||
print "$r -> $s\n" if ($debug);
|
||||
|
||||
$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
|
||||
}
|
||||
|
||||
foreach my $r (keys %defines) {
|
||||
my $s = $defines{$r};
|
||||
|
||||
$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
|
||||
|
||||
print "$r -> $s\n" if ($debug);
|
||||
|
||||
$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
|
||||
}
|
||||
|
||||
foreach my $r (keys %enum_symbols) {
|
||||
my $s = $enum_symbols{$r};
|
||||
|
||||
$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
|
||||
|
||||
print "$r -> $s\n" if ($debug);
|
||||
|
||||
$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
|
||||
}
|
||||
|
||||
foreach my $r (keys %enums) {
|
||||
my $s = $enums{$r};
|
||||
|
||||
$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
|
||||
|
||||
print "$r -> $s\n" if ($debug);
|
||||
|
||||
$data =~ s/enum\s+($r)$end_delim/$s$2/g;
|
||||
}
|
||||
|
||||
foreach my $r (keys %structs) {
|
||||
my $s = $structs{$r};
|
||||
|
||||
$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
|
||||
|
||||
print "$r -> $s\n" if ($debug);
|
||||
|
||||
$data =~ s/struct\s+($r)$end_delim/$s$2/g;
|
||||
}
|
||||
|
||||
foreach my $r (keys %typedefs) {
|
||||
my $s = $typedefs{$r};
|
||||
|
||||
$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
|
||||
|
||||
print "$r -> $s\n" if ($debug);
|
||||
$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
|
||||
}
|
||||
|
||||
$data =~ s/\\ ([\n\s])/\1/g;
|
||||
|
||||
#
|
||||
# Generate output file
|
||||
#
|
||||
|
||||
my $title = $file_in;
|
||||
$title =~ s,.*/,,;
|
||||
|
||||
open OUT, "> $file_out" or die "Can't open $file_out";
|
||||
print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n";
|
||||
print OUT "$title\n";
|
||||
print OUT "=" x length($title);
|
||||
print OUT "\n\n.. parsed-literal::\n\n";
|
||||
print OUT $data;
|
||||
close OUT;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
parse_headers.pl - parse a C file, in order to identify functions, structs,
|
||||
enums and defines and create cross-references to a Sphinx book.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
|
||||
|
||||
Where <options> can be: --debug, --help or --man.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--debug>
|
||||
|
||||
Put the script in verbose mode, useful for debugging.
|
||||
|
||||
=item B<--usage>
|
||||
|
||||
Prints a brief help message and exits.
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Prints a more detailed help message and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Convert a C header or source file (C_FILE), into a ReStructured Text
|
||||
included via ..parsed-literal block with cross-references for the
|
||||
documentation files that describe the API. It accepts an optional
|
||||
EXCEPTIONS_FILE with describes what elements will be either ignored or
|
||||
be pointed to a non-default reference.
|
||||
|
||||
The output is written at the (OUT_FILE).
|
||||
|
||||
It is capable of identifying defines, functions, structs, typedefs,
|
||||
enums and enum symbols and create cross-references for all of them.
|
||||
It is also capable of distinguish #define used for specifying a Linux
|
||||
ioctl.
|
||||
|
||||
The EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or
|
||||
to replace the default references by a custom one.
|
||||
|
||||
Please read doc/doc-guide/parse-headers.rst at the Kernel's
|
||||
tree for more details.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
Report bugs to Mauro Carvalho Chehab <mchehab@kernel.org>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
|
||||
|
||||
License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
|
||||
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
|
||||
=cut
|
||||
3
doc/sphinx/requirements.txt
Normal file
3
doc/sphinx/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
docutils==0.12
|
||||
Sphinx==1.4.9
|
||||
sphinx_rtd_theme
|
||||
376
doc/sphinx/rstFlatTable.py
Executable file
376
doc/sphinx/rstFlatTable.py
Executable file
@@ -0,0 +1,376 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8; mode: python -*-
|
||||
# pylint: disable=C0330, R0903, R0912
|
||||
|
||||
u"""
|
||||
flat-table
|
||||
~~~~~~~~~~
|
||||
|
||||
Implementation of the ``flat-table`` reST-directive.
|
||||
|
||||
:copyright: Copyright (C) 2016 Markus Heiser
|
||||
:license: GPL Version 2, June 1991 see linux/COPYING for details.
|
||||
|
||||
The ``flat-table`` (:py:class:`FlatTable`) is a double-stage list similar to
|
||||
the ``list-table`` with some additional features:
|
||||
|
||||
* *column-span*: with the role ``cspan`` a cell can be extended through
|
||||
additional columns
|
||||
|
||||
* *row-span*: with the role ``rspan`` a cell can be extended through
|
||||
additional rows
|
||||
|
||||
* *auto span* rightmost cell of a table row over the missing cells on the
|
||||
right side of that table-row. With Option ``:fill-cells:`` this behavior
|
||||
can changed from *auto span* to *auto fill*, which automaticly inserts
|
||||
(empty) cells instead of spanning the last cell.
|
||||
|
||||
Options:
|
||||
|
||||
* header-rows: [int] count of header rows
|
||||
* stub-columns: [int] count of stub columns
|
||||
* widths: [[int] [int] ... ] widths of columns
|
||||
* fill-cells: instead of autospann missing cells, insert missing cells
|
||||
|
||||
roles:
|
||||
|
||||
* cspan: [int] additionale columns (*morecols*)
|
||||
* rspan: [int] additionale rows (*morerows*)
|
||||
"""
|
||||
|
||||
# ==============================================================================
|
||||
# imports
|
||||
# ==============================================================================
|
||||
|
||||
import sys
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives, roles
|
||||
from docutils.parsers.rst.directives.tables import Table
|
||||
from docutils.utils import SystemMessagePropagation
|
||||
|
||||
# ==============================================================================
|
||||
# common globals
|
||||
# ==============================================================================
|
||||
|
||||
# The version numbering follows numbering of the specification
|
||||
# (doc/books/kernel-doc-HOWTO).
|
||||
__version__ = '1.0'
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
PY2 = sys.version_info[0] == 2
|
||||
|
||||
if PY3:
|
||||
# pylint: disable=C0103, W0622
|
||||
unicode = str
|
||||
basestring = str
|
||||
|
||||
# ==============================================================================
|
||||
def setup(app):
|
||||
# ==============================================================================
|
||||
|
||||
app.add_directive("flat-table", FlatTable)
|
||||
roles.register_local_role('cspan', c_span)
|
||||
roles.register_local_role('rspan', r_span)
|
||||
|
||||
return dict(
|
||||
version = __version__,
|
||||
parallel_read_safe = True,
|
||||
parallel_write_safe = True
|
||||
)
|
||||
|
||||
# ==============================================================================
|
||||
def c_span(name, rawtext, text, lineno, inliner, options=None, content=None):
|
||||
# ==============================================================================
|
||||
# pylint: disable=W0613
|
||||
|
||||
options = options if options is not None else {}
|
||||
content = content if content is not None else []
|
||||
nodelist = [colSpan(span=int(text))]
|
||||
msglist = []
|
||||
return nodelist, msglist
|
||||
|
||||
# ==============================================================================
|
||||
def r_span(name, rawtext, text, lineno, inliner, options=None, content=None):
|
||||
# ==============================================================================
|
||||
# pylint: disable=W0613
|
||||
|
||||
options = options if options is not None else {}
|
||||
content = content if content is not None else []
|
||||
nodelist = [rowSpan(span=int(text))]
|
||||
msglist = []
|
||||
return nodelist, msglist
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
class rowSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321
|
||||
class colSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321
|
||||
# ==============================================================================
|
||||
|
||||
# ==============================================================================
|
||||
class FlatTable(Table):
|
||||
# ==============================================================================
|
||||
|
||||
u"""FlatTable (``flat-table``) directive"""
|
||||
|
||||
option_spec = {
|
||||
'name': directives.unchanged
|
||||
, 'class': directives.class_option
|
||||
, 'header-rows': directives.nonnegative_int
|
||||
, 'stub-columns': directives.nonnegative_int
|
||||
, 'widths': directives.positive_int_list
|
||||
, 'fill-cells' : directives.flag }
|
||||
|
||||
def run(self):
|
||||
|
||||
if not self.content:
|
||||
error = self.state_machine.reporter.error(
|
||||
'The "%s" directive is empty; content required.' % self.name,
|
||||
nodes.literal_block(self.block_text, self.block_text),
|
||||
line=self.lineno)
|
||||
return [error]
|
||||
|
||||
title, messages = self.make_title()
|
||||
node = nodes.Element() # anonymous container for parsing
|
||||
self.state.nested_parse(self.content, self.content_offset, node)
|
||||
|
||||
tableBuilder = ListTableBuilder(self)
|
||||
tableBuilder.parseFlatTableNode(node)
|
||||
tableNode = tableBuilder.buildTableNode()
|
||||
# SDK.CONSOLE() # print --> tableNode.asdom().toprettyxml()
|
||||
if title:
|
||||
tableNode.insert(0, title)
|
||||
return [tableNode] + messages
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
class ListTableBuilder(object):
|
||||
# ==============================================================================
|
||||
|
||||
u"""Builds a table from a double-stage list"""
|
||||
|
||||
def __init__(self, directive):
|
||||
self.directive = directive
|
||||
self.rows = []
|
||||
self.max_cols = 0
|
||||
|
||||
def buildTableNode(self):
|
||||
|
||||
colwidths = self.directive.get_column_widths(self.max_cols)
|
||||
if isinstance(colwidths, tuple):
|
||||
# Since docutils 0.13, get_column_widths returns a (widths,
|
||||
# colwidths) tuple, where widths is a string (i.e. 'auto').
|
||||
# See https://sourceforge.net/p/docutils/patches/120/.
|
||||
colwidths = colwidths[1]
|
||||
stub_columns = self.directive.options.get('stub-columns', 0)
|
||||
header_rows = self.directive.options.get('header-rows', 0)
|
||||
|
||||
table = nodes.table()
|
||||
tgroup = nodes.tgroup(cols=len(colwidths))
|
||||
table += tgroup
|
||||
|
||||
|
||||
for colwidth in colwidths:
|
||||
colspec = nodes.colspec(colwidth=colwidth)
|
||||
# FIXME: It seems, that the stub method only works well in the
|
||||
# absence of rowspan (observed by the html buidler, the docutils-xml
|
||||
# build seems OK). This is not extraordinary, because there exists
|
||||
# no table directive (except *this* flat-table) which allows to
|
||||
# define coexistent of rowspan and stubs (there was no use-case
|
||||
# before flat-table). This should be reviewed (later).
|
||||
if stub_columns:
|
||||
colspec.attributes['stub'] = 1
|
||||
stub_columns -= 1
|
||||
tgroup += colspec
|
||||
stub_columns = self.directive.options.get('stub-columns', 0)
|
||||
|
||||
if header_rows:
|
||||
thead = nodes.thead()
|
||||
tgroup += thead
|
||||
for row in self.rows[:header_rows]:
|
||||
thead += self.buildTableRowNode(row)
|
||||
|
||||
tbody = nodes.tbody()
|
||||
tgroup += tbody
|
||||
|
||||
for row in self.rows[header_rows:]:
|
||||
tbody += self.buildTableRowNode(row)
|
||||
return table
|
||||
|
||||
def buildTableRowNode(self, row_data, classes=None):
|
||||
classes = [] if classes is None else classes
|
||||
row = nodes.row()
|
||||
for cell in row_data:
|
||||
if cell is None:
|
||||
continue
|
||||
cspan, rspan, cellElements = cell
|
||||
|
||||
attributes = {"classes" : classes}
|
||||
if rspan:
|
||||
attributes['morerows'] = rspan
|
||||
if cspan:
|
||||
attributes['morecols'] = cspan
|
||||
entry = nodes.entry(**attributes)
|
||||
entry.extend(cellElements)
|
||||
row += entry
|
||||
return row
|
||||
|
||||
def raiseError(self, msg):
|
||||
error = self.directive.state_machine.reporter.error(
|
||||
msg
|
||||
, nodes.literal_block(self.directive.block_text
|
||||
, self.directive.block_text)
|
||||
, line = self.directive.lineno )
|
||||
raise SystemMessagePropagation(error)
|
||||
|
||||
def parseFlatTableNode(self, node):
|
||||
u"""parses the node from a :py:class:`FlatTable` directive's body"""
|
||||
|
||||
if len(node) != 1 or not isinstance(node[0], nodes.bullet_list):
|
||||
self.raiseError(
|
||||
'Error parsing content block for the "%s" directive: '
|
||||
'exactly one bullet list expected.' % self.directive.name )
|
||||
|
||||
for rowNum, rowItem in enumerate(node[0]):
|
||||
row = self.parseRowItem(rowItem, rowNum)
|
||||
self.rows.append(row)
|
||||
self.roundOffTableDefinition()
|
||||
|
||||
def roundOffTableDefinition(self):
|
||||
u"""Round off the table definition.
|
||||
|
||||
This method rounds off the table definition in :py:member:`rows`.
|
||||
|
||||
* This method inserts the needed ``None`` values for the missing cells
|
||||
arising from spanning cells over rows and/or columns.
|
||||
|
||||
* recount the :py:member:`max_cols`
|
||||
|
||||
* Autospan or fill (option ``fill-cells``) missing cells on the right
|
||||
side of the table-row
|
||||
"""
|
||||
|
||||
y = 0
|
||||
while y < len(self.rows):
|
||||
x = 0
|
||||
|
||||
while x < len(self.rows[y]):
|
||||
cell = self.rows[y][x]
|
||||
if cell is None:
|
||||
x += 1
|
||||
continue
|
||||
cspan, rspan = cell[:2]
|
||||
# handle colspan in current row
|
||||
for c in range(cspan):
|
||||
try:
|
||||
self.rows[y].insert(x+c+1, None)
|
||||
except: # pylint: disable=W0702
|
||||
# the user sets ambiguous rowspans
|
||||
pass # SDK.CONSOLE()
|
||||
# handle colspan in spanned rows
|
||||
for r in range(rspan):
|
||||
for c in range(cspan + 1):
|
||||
try:
|
||||
self.rows[y+r+1].insert(x+c, None)
|
||||
except: # pylint: disable=W0702
|
||||
# the user sets ambiguous rowspans
|
||||
pass # SDK.CONSOLE()
|
||||
x += 1
|
||||
y += 1
|
||||
|
||||
# Insert the missing cells on the right side. For this, first
|
||||
# re-calculate the max columns.
|
||||
|
||||
for row in self.rows:
|
||||
if self.max_cols < len(row):
|
||||
self.max_cols = len(row)
|
||||
|
||||
# fill with empty cells or cellspan?
|
||||
|
||||
fill_cells = False
|
||||
if 'fill-cells' in self.directive.options:
|
||||
fill_cells = True
|
||||
|
||||
for row in self.rows:
|
||||
x = self.max_cols - len(row)
|
||||
if x and not fill_cells:
|
||||
if row[-1] is None:
|
||||
row.append( ( x - 1, 0, []) )
|
||||
else:
|
||||
cspan, rspan, content = row[-1]
|
||||
row[-1] = (cspan + x, rspan, content)
|
||||
elif x and fill_cells:
|
||||
for i in range(x):
|
||||
row.append( (0, 0, nodes.comment()) )
|
||||
|
||||
def pprint(self):
|
||||
# for debugging
|
||||
retVal = "[ "
|
||||
for row in self.rows:
|
||||
retVal += "[ "
|
||||
for col in row:
|
||||
if col is None:
|
||||
retVal += ('%r' % col)
|
||||
retVal += "\n , "
|
||||
else:
|
||||
content = col[2][0].astext()
|
||||
if len (content) > 30:
|
||||
content = content[:30] + "..."
|
||||
retVal += ('(cspan=%s, rspan=%s, %r)'
|
||||
% (col[0], col[1], content))
|
||||
retVal += "]\n , "
|
||||
retVal = retVal[:-2]
|
||||
retVal += "]\n , "
|
||||
retVal = retVal[:-2]
|
||||
return retVal + "]"
|
||||
|
||||
def parseRowItem(self, rowItem, rowNum):
|
||||
row = []
|
||||
childNo = 0
|
||||
error = False
|
||||
cell = None
|
||||
target = None
|
||||
|
||||
for child in rowItem:
|
||||
if (isinstance(child , nodes.comment)
|
||||
or isinstance(child, nodes.system_message)):
|
||||
pass
|
||||
elif isinstance(child , nodes.target):
|
||||
target = child
|
||||
elif isinstance(child, nodes.bullet_list):
|
||||
childNo += 1
|
||||
cell = child
|
||||
else:
|
||||
error = True
|
||||
break
|
||||
|
||||
if childNo != 1 or error:
|
||||
self.raiseError(
|
||||
'Error parsing content block for the "%s" directive: '
|
||||
'two-level bullet list expected, but row %s does not '
|
||||
'contain a second-level bullet list.'
|
||||
% (self.directive.name, rowNum + 1))
|
||||
|
||||
for cellItem in cell:
|
||||
cspan, rspan, cellElements = self.parseCellItem(cellItem)
|
||||
if target is not None:
|
||||
cellElements.insert(0, target)
|
||||
row.append( (cspan, rspan, cellElements) )
|
||||
return row
|
||||
|
||||
def parseCellItem(self, cellItem):
|
||||
# search and remove cspan, rspan colspec from the first element in
|
||||
# this listItem (field).
|
||||
cspan = rspan = 0
|
||||
if not len(cellItem):
|
||||
return cspan, rspan, []
|
||||
for elem in cellItem[0]:
|
||||
if isinstance(elem, colSpan):
|
||||
cspan = elem.get("span")
|
||||
elem.parent.remove(elem)
|
||||
continue
|
||||
if isinstance(elem, rowSpan):
|
||||
rspan = elem.get("span")
|
||||
elem.parent.remove(elem)
|
||||
continue
|
||||
return cspan, rspan, cellItem[:]
|
||||
Reference in New Issue
Block a user