--- /dev/null
+# Shakti M-Class Libre SoC
+
+This SoC is a propsed libre design that draws in expertise from mass-volume
+SoCs of the past six years and beyond, and is being designed to cover just
+as wide a range of target embedded / low-power / industrial markets as those
+SoCs. Pincount is to be kept low in order to reduce cost as well as increase
+yields.
+
+* See <http://rise.cse.iitm.ac.in/shakti.html> M-Class for top-level
+* See [[pinouts]] for auto-generated table of pinouts (including mux)
+* See [[peripheralschematics]] for example Reference Layouts
+* See [[ramanalysis]] for a comprehensive analysis of why DDR3 is to be used.
+
+## Rough specification.
+
+Quad-core 28nm RISC-V 64-bit (RISCV64GC core with Vector SIMD Media / 3D
+extensions), 300-pin 15x15mm BGA 0.8mm pitch, 32-bit DDR3/DDR3L/LPDDR3
+memory interface and libre / open interfaces and accelerated hardware
+functions suitable for the higher-end, low-power, embedded, industrial
+and mobile space.
+
+A 0.8mm pitch BGA allows relatively large (low-cost) VIA drill sizes
+to be used (8-10mil) and 4-5mil tracks with 4mil clearance. For
+details see
+<http://processors.wiki.ti.com/index.php/General_hardware_design/BGA_PCB_design>
+
+## Targetting full Libre Licensing to the bedrock.
+
+The only barrier to being able to replicate the masks from scratch
+is the proprietary cells (e.g. memory cells) designed by the Foundries:
+there is a potential long-term strategy in place to deal with that issue.
+
+The only proprietary interface utilised in the entire SoC is the DDR3
+PHY plus Controller, which will be replaced in a future revision, making
+the entire SoC exclusively designed and made from fully libre-licensed
+BSD and LGPL openly and freely accessible VLSI and VHDL source.
+
+In addition, no proprietary firmware whatsoever will be required to
+operate or boot the device right from the bedrock: the entire software
+stack will also be libre-licensed (even for programming the initial
+proprietary DDR3 PHY+Controller)
+
+# Inspiration from several sources
+
+The design of this SoC is drawn from at least the following SoCs, which
+have significant multiplexing for pinouts, reducing pincount whilst at
+the same time permitting the SoC to be utilised across a very wide range
+of markets:
+
+* A10/A20 EVB <http://hands.com/~lkcl/eoma/A10-EVB-V1-2-20110726.pdf>
+* RK3288 T-Firefly <http://www.t-firefly.com/download/firefly-rk3288/hardware/FR_RK3288_0930.pdf>
+* Ingenic JZ4760B <ftp://ftp.ingenic.cn/SOC/JZ4760B/JZ4760B_DS_REVISION.PDF>
+ LEPUS Board <ftp://ftp.ingenic.cn/DevSupport/Hardware/RD4760B_LEPUS/RD4760B_LEPUS_V1.3.2.PDF>
+* GPL-violating CT-PC89e <http://hands.com/~lkcl/seatron/>,
+ and <http://lkcl.net/arm_systems/CT-PC89E/> this was an 8.9in netbook
+ weighing only 0.72kg and having a 3 HOUR battery life on a single 2100mAh
+ cell, its casework alone inspired a decade of copycat china clone
+ netbooks as it was slowly morphed from its original 8.9in up to (currently)
+ an 11in form-factor almost a decade later in 2017.
+* A64 Reference Designs for example this: <http://linux-sunxi.org/images/3/32/Banana_pi_BPI-M64-V1_1-Release_201609.pdf>
+
+TI Boards such as the BeagleXXXX Series, or the Freescale iMX6
+WandBoard etc., are, whilst interesting, have a different kind of focus
+and "feel" about them, as they are typically designed by Western firms
+with less access or knowledge of the kinds of low-cost tricks deployed
+to ingenious and successful effect by Chinese Design Houses. Not only
+that but they typically know the best components to buy. Western-designed
+PCBs typically source exclusively from Digikey, AVNet, Mouser etc. and
+the prices are often two to **TEN** times more costly as a result.
+
+The TI and Freescale (now NXP) series SoCs themselves are also just as
+interesting to study, but again have a subtly different focus: cost of
+manufacture of PCBs utilising them not being one of those primary focii.
+Freescale's iMX6 is well-known for its awesome intended lifespan and support:
+**ninteen** years. That does however have some unintended knock-on effects
+on its pricing.
+
+Instead, the primary input is taken from Chinese-designed SoCs, where cost
+and ease of production, manufacturing and design of a PCB using the planned
+SoC, as well as support for high-volume mass-produced peripherals is
+firmly a priority focus.
+
+# Target Markets
+
+* EOMA68 Computer Card form-factor (general-purpose, eco-conscious)
+* Smartphone / Tablet (basically the same thing, different LCD/CTP size)
+* Low-end (ChromeOS style) laptop
+* Industrial uses when augmented by a suitable MCU (for ADC/DAC/CAN etc.)
+
+## Common Peripherals to majority of target markets
+
+* SPI or 8080 or RGB/TTL or LVDS LCD display. SPI: 320x240. LVDS: 1440x900.
+* LCD Backlight, requires GPIO power-control plus PWM for brightness control
+* USB-OTG Port (OTG-Host, OTG Client, Charging capability)
+* Baseband Modem (GSM / GPRS / 3G / LTE) requiring USB, UART, and PCM audio
+* Bluetooth, requires either full UART or SD/MMC or USB, plus control GPIO
+* WIFI, requires either USB (but with power penalties) or better SD/MMC
+* SD/MMC for external MicroSD
+* SD/MMC for on-PCB eMMC (care needed on power/boot sequence)
+* NAND Flash (not recommended), requires 8080/ATI-style Bus with dedicated CS#
+* Optional 4-wire SPI NAND/NOR for boot (XIP - Execute In-place - recommended).
+* Audio over I2S (5-pin: 4 for output, 1 for input), fall-back to USB Audio
+* Some additional SPI peripherals, e.g. connection to low-power MCU.
+* GPIO (EINT-capable, with wakeup) for buttons, power, volume etc.
+* Camera(s) either by CSI-1 (parallel CSI) or better by USB
+* I2C sensors: accelerometer, compass, etc. Each requires EINT and RST GPIO.
+* Capacitive Touchpanel (I2C and also requiring EINT and RST GPIO)
+* Real-time Clock (usually an I2C device but may be on-board a support MCU)
+
+## Peripherals unique to laptop market
+
+* Keyboard (USB or keyboard-matrix managed by MCU)
+* USB, I2C or SPI Mouse-trackpad (plus button GPIO, EINT capable)
+
+## Peripherals common to laptop and Industrial Market
+
+* Ethernet (RGMII or better 8080-style XT/AT/ATI MCU bus)
+
+## Augmentation by an embedded MCU
+
+Some functions, particularly analog, are particularly tricky to implement
+in an early SoC. In addition, CAN is still patented. For unusual, patented
+or analog functionality such as CAN, RTC, ADC, DAC, SPDIF, One-wire Bus
+and so on it is easier and simpler to deploy an ultra-low-cost low-speed
+companion Micro-Controller such as the crystal-less STMS8003 ($0.24) or
+the crystal-less STM32F072 or other suitable MCU, depending on requirements.
+For high-speed interconnect it may be wired up as an SPI device, and for
+lower-speed communication UART would be the simplest and easiest means of
+two-way communication.
+
+This technique can be deployed in all scenarios (phone, tablet, laptop,
+industrial), and is an extremely low-cost way of getting RTC functionality
+for example. The cost of, for example, dedicated I2C sensors that provide
+RTC functionality, or ADC or DAC or "Digipot", are actually incredibly
+high, relatively speaking. Some very simple software and a general-purpose
+MCU does the exact same job. In particularly cost-sensitive applications,
+DAC may be substituted by a PWM, an RC circuit, and an optional feedback
+loop into an ADC pin to monitor situations where changing load on the RC
+circuit alters the output voltage. All done entirely in the MCU's software.
+
+An MCU may even be used to emulate SPI "XIP" (Execute in-place) NAND
+memory, such that there is no longer a need to deploy a dedicated SPI
+NOR bootloader IC (which are really quite expensive). By emulating
+an SPI XIP device the SoC may boot from the NAND Flash storage built-in
+to the embedded MCU, or may even feed the SoC data from a USB-OTG
+or other interface. This makes for an extremely flexible bootloader
+capability, without the need for totally redoing the SoC masks just to
+add extra BOOTROM functions.
+
+## Common Internal (on-board) acceleration and hardware functions
+
+* 2D accelerated display
+* 3D accelerated graphics
+* Video encode / decode
+* Image encode / decode
+* Crypto functions (SHA, Rijndael, DES, etc., Diffie-Hellman, RSA)
+* Cryptographically-secure PRNG (hard to get right)
+
+### 2D acceleration
+
+The ORSOC GPU contains basic primitives for 2D: rectangles, sprites,
+image acceleration, scalable fonts, and Z-buffering and much more.
+
+<https://opencores.org/project,orsoc_graphics_accelerator>
+
+### 3D acceleration
+
+* MIAOW: ATI-compatible shader engine <http://miaowgpu.org/>
+* ORSOC GPU contains some primitives that can be used
+* SIMD RISC-V extensions can obviate the need for a "full" separate GPU
+
+### Video encode / decode
+
+* video primitives <https://opencores.org/project,video_systems>
+* MPEG decoder <https://opencores.org/project,mpeg2fpga>
+* Google make free VP8 and VP9 hard macros available for production use only
+
+### Image encode / decode
+
+partially covered by the ORSOC GPU
+
+### Crypto functions
+
+TBD
+
+### Cryptographically-secure PRNG
+
+TBD
+
+# Proposed Interfaces
+
+* RGB/TTL up to 1440x900 @ 60fps, 24-bit colour
+* 2x 1-lane SPI
+* 1x 4-lane (quad) SPI
+* 4x SD/MMC (1x 1/2/4/8-bit, 3x 1/2/4-bit)
+* 2x full UART incl. CTS/RTS
+* 3x UART (TX/RX only)
+* 3x I2C (in case of address clashes between peripherals)
+* 8080-style AT/XT/ATI MCU Bus Interface, with multiple (8x CS#) lines
+* 3x PWM-capable GPIO
+* 32x EINT-cable GPIO with full edge-triggered and low/high IRQ capability
+* 1x I2S audio with 4-wire output and 1-wire input.
+* 3x USB2 (ULPI for reduced pincount) each capable of USB-OTG support
+* DDR3/DDR3L/LPDDR3 32-bit-wide memory controller
+
+Some interfaces at:
+
+* <https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/>
+ includes GPIO, SPI, UART, JTAG, I2C, PinCtrl, UART and PWM. Also included
+ is a Watchdog Timer and others.
+* <https://github.com/sifive/freedom/blob/master/src/main/scala/everywhere/e300artydevkit/Platform.scala>
+ Pinmux ("IOF") for multiplexing several I/O functions onto a single pin
+
+## I2S
+
+<https://github.com/skristiansson/i2s>
+
+## FlexBus
+
+FlexBus is capable of emulating the 8080-style / ATI MCU Bus, as well as
+providing support for access to SRAM. It is extremely likely that it will
+provide access to MCU-style Ethernet PHY ICs such as the DM9000, the
+AX88180 (gigabit ethernet but an enormous number of pins), the AX88796A
+(8/16-bit 80186 or MC68k).
+
+## RGB/TTL interface
+
+<https://opencores.org/project,vga_lcd> full linux kernel driver also available
+
+## SPI
+
+* APB to SPI <https://opencores.org/project,apb2spi>
+* ASIC-proven <https://opencores.org/project,spi_master_slave>
+* Wishbone-compliant <https://opencores.org/project,simple_spi>
+
+## SD/MMC (including eMMC)
+
+* <https://opencores.org/project,sd_mmc_emulator>
+* (needs work) <https://opencores.org/project,sdcard_mass_storage_controller>
+
+# Pin Multiplexing
+
+Complex! Covered in [[pinouts]]. The general idea is to target several
+distinct applications and, by trial-and-error, create a pinmux table that
+successfully covers all the target scenarios by providing absolutely all
+required functions for each and every target. A few general rules:
+
+* Different functions (SPI, I2C) which overlap on the same pins on one
+ bank should also be duplicated on completely different banks, both from
+ each other and also the bank on which they overlap. With each bank having
+ separate Power Domains this strategy increases the chances of being able
+ to place low-power and high-power peripherals and sensors on separate
+ GPIO banks without needing external level-shifters.
+* Functions which have optional bus-widths (eMMC: 1/2/4/8) may have more
+ functions overlapping them than would otherwise normally be considered.
+* Then the same overlapped high-order bus pins can also be mapped onto
+ other pins. This particularly applies to the very large buses, such
+ as FlexBus (over 50 pins). However if the overlapped pins are on a
+ different bank it becomes necessary to have both banks run in the same
+ GPIO Power Domain.
+* All functions should really be pin-muxed at least twice, preferably
+ three times. Four or more times on average makes it pointless to
+ even have four-way pinmuxing at all, so this should be avoided.
+ The only exceptions (functions which have not been pinmuxed multiple
+ times) are the RGB/TTL LCD channel, and both ULPI interfaces.
+
+## GPIO Pinmux Power Domains
+
+Of particular importance is the Power Domains for the GPIO. Realistically
+it has to be flexible (simplest option: recommended to be between
+1.8v and 3.3v) as the majority of low-cost mass-produced sensors and
+peripherals on I2C, SPI, UART and SD/MMC are at or are compatible with
+this voltage range. Long-tail (older / stable / low-cost / mass-produced)
+peripherals in particular tend to be 3.3v, whereas newer ones with a
+particular focus on Mobile tend to be 1.2v to 1.8v.
+
+A large percentage of sensors and peripherals have separate IO voltage
+domains from their main supply voltage: a good example is the SN75LVDS83b
+which has one power domain for the RGB/TTL I/O, one for the LVDS output,
+and one for the internal logic controller (typical deployments tend not
+to notice the different power-domain capability, as they usually supply all
+three voltages at 3.3v).
+
+Relying on this capability, however, by selecting a fixed voltage for
+the entire SoC's GPIO domain, is simply not a good idea: all sensors
+and peripherals which do not have a variable (VREF) capability for the
+logic side, or coincidentally are not at the exact same fixed voltage,
+will simply not be compatible if they are high-speed CMOS-level push-push
+driven. Open-Drain on the other hand can be handled with a MOSFET for
+two-way or even a diode for one-way depending on the levels, but this means
+significant numbers of external components if the number of lines is large.
+
+So, selecting a fixed voltage (such as 1.8v or 3.3v) results in a bit of a
+problem: external level-shifting is required on pretty much absolutely every
+single pin, particularly the high-speed (CMOS) push-push I/O. An example: the
+DM9000 is best run at 3.3v. A fixed 1.8v FlexBus would
+require a whopping 18 pins (possibly even 24 for a 16-bit-wide bus)
+worth of level-shifting, which is not just costly
+but also a huge amount of PCB space: bear in mind that for level-shifting, an
+IC with **double** the number of pins being level-shifted is required.
+
+Given that level-shifting is an unavoidable necessity, and external
+level-shifting has such high cost(s), the workable solution is to
+actually include GPIO-group level-shifting actually on the SoC die,
+after the pin-muxer at the front-end (on the I/O pads of the die),
+on a per-bank basis. This is an extremely common technique that is
+deployed across a very wide range of mass-volume SoCs.
+
+One very useful side-effect for example of a variable Power Domain voltage
+on a GPIO bank containing SD/MMC functionality is to be able to change the
+bank's voltage from 3.3v to 1.8v, to match an SD Card's capabilities, as
+permitted under the SD/MMC Specification. The alternative is to be forced to
+deploy an external level-shifter IC (if PCB space and BOM target allows) or to
+fix the voltage at 3.3v and thus lose access to the low-power and higher-speed
+capabilities of modern SD Cards.
+
+In summary: putting level shifters right at the I/O pads of the SoC, after
+the pin-mux (so that the core logic remains at the core voltage) is a
+cost-effective solution that can have additional unintended side-benefits
+and cost savings beyond simply saving on external level-shifting components
+and board space.
+
+# Items requiring clarification, or proposals TBD
+
+## Core Voltage Domains from the PMIC
+
+See [[peripheralschematics]] - what default (start-up) voltage can the
+core of the proposed 28nm SoC cope with for short durations? The AXP209
+PMIC defaults to a 1.25v CPU core voltage, and 1.2v for the logic. It
+can be changed by the SoC by communicating over I2C but the start-up
+voltage of the PMIC may not be changed. What is the maximum voltage
+that the SoC can run at, for short durations at a greatly-reduced clock rate?
+
+## 3.3v tolerance
+
+Can the GPIO be made at least 3.3v tolerant?
+
+## Shakti Flexbus implementation: 32-bit word-aligned access
+
+The FlexBus implementation may only make accesses onto the back-end
+AXI bus on 32-bit word-aligned boundaries. How this affects FlexBus
+memory accesses (read and write) on 8-bit and 16-bit boundaries is
+yet to be determined. It is particularly relevant e.g. for 24-bit
+pixel accesses on 8080 (MCU) style LCD controllers that have their
+own on-board SRAM.
+
+## Confirmation of GPIO Power Domains
+
+The proposed plan is to stick with a fixed 1.8v GPIO level across all
+GPIO banks. However as outlined in the section above, this has some
+distinct disadvantages, particularly for e.g. SRAM access over FlexBus:
+that would often require a 50-way bi-directional level-shifter Bus IC,
+with over 100 pins!
+
+## Proposal / Concept to include "Minion Cores" on a 7-way pinmux
+
+The lowRISC team first came up with the idea, instead of having a pinmux,
+to effectively bit-bang pretty much all GPIO using **multiple** 32-bit
+RISC-V non-SMP integer-only cores each with a tiny instruction and data
+cache (or, simpler, access to their own independent on-die SRAM).
+The reasoning behind this is: if it's a dedicated core, it's not really
+bit-banging any more. The technique is very commonly deployed, typically
+using an 8051 MCU engine, as it means that a mass-produced peripheral may
+be firmware-updated in the field for example if a Standard has unanticipated
+flaws or otherwise requires updating.
+
+The proposal here is to add four extra pin-mux selectors (an extra bit
+to what is currently a 2-bit mux per pin), and for each GPIO bank to map to
+one of four such ultra-small "Minion Cores". For each pin, Pin-mux 4 would
+select the first Minion core, Pin-mux 5 would select the second and so on.
+The sizes of the GPIO banks are as follows:
+
+* Bank A: 16
+* Bank B: 28
+* Bank C: 24
+* Bank D: 24
+* Bank E: 24
+* Bank F: 10
+
+Therefore, it is proposed that each Minion Core have 28 EINT-capable
+GPIOs, and that all but Bank A and F map their GPIO number (minus the
+Bank Designation letter) direct to the Minion Core GPIOs. For Banks
+A and F, the numbering is proposed to be concatenated, so that A0 through
+A15 maps to a Minion Core's GPIO 0 to 15, and F0 to F10 map to a Minion
+Core's GPIO 16 to 25 (another alternative idea would be to split Banks
+A and F to complete B through E, taking them up to 32 I/O per Minion core).
+
+With careful selection from different banks it should be possible to map
+unused spare pins to a complete, contiguous, sequential set of any given
+Minion Core, such that the Minion Core could then bit-bang anything up to
+a 28-bit-wide Bus. Theoretically this could make up a second RGB/TTL
+LCD interface with up to 24 bits per pixel.
+
+For low-speed interfaces, particularly those with an independent clock
+that the interface takes into account that the clock changes on a different
+time-cycle from the data, this should work perfectly fine. Whether the
+idea is practical for higher-speed interfaces or or not will critically
+depend on whether the Minion Core can do mask-spread atomic
+reads/writes from a register to/from memory-addressed GPIO or not,
+and faster I/O streams will almost certainly require some form of
+serialiser/de-serialiser hardware-assist, and definitely each their
+own DMA Engine.
+
+If the idea proves successful it would be extremely nice to have a
+future version that has direct access to generic LVDS lines, plus
+S8/10 ECC hardware-assist engines. If the voltage may be set externally
+and accurate PLL clock timing provided, it may become possible to bit-bang
+and software-emulate high-speed interfaces such as SATA, HDMI, PCIe and
+many more.
+
+# Research (to investigate)
+
+* <https://level42.ca/projects/ultra64/Documentation/man/pro-man/pro25/index25.1.html>
+* <http://n64devkit.square7.ch/qa/graphics/ucode.htm>
+* <https://dac.com/media-center/exhibitor-news/synopsys%E2%80%99-designware-universal-ddr-memory-controller-delivers-30-percent> 110nm DDR3 PHY
+[[!tag cpus]]
+
--- /dev/null
+# Goal
+
+The goal is to create, test and document a working pinmux (switchbox),
+with extended goals, time permitting, to add actual multiplexed peripherals
+to a pre-existing working core (lowRISC, ZipCPU, OR1k) and a further goal
+to get actual linux kernel drivers up and running. This could be part
+of an existing team, or a single-person project, or a team project.
+All communication will be carried out on a public mailing list at all
+times, as part of the goal is to allow absolutely anyone to help if they
+feel so inclined.
+
+# Details
+
+Starting from a known-good working pre-existing SoC running well on
+a standard FPGA platform and having a few pre-existing proven
+peripherals working, the idea is to add a multiplexer so that the actual I/O
+pins can switch to different functions, just like any Embedded STM32F,
+or any Texas Instruments OMAP Series processor.
+
+A pre-existing multiplexer already exists which may provide a good starting
+point: https://github.com/wallento/pmod_switchbox. Another exists
+in the form of the SiFive "IOF":
+https://github.com/sifive/freedom/blob/master/src/main/scala/everywhere/e300artydevkit/Platform.scala
+
+Additional peripherals
+in the form of PWM, UART, I2C, SPI, SD/MMC and RGB/TTL already exist on
+http://opencores.org so there will be no need to develop those.
+
+If RISC-V is chosen (for example the lowRISC ethernet-0.5 branch
+https://github.com/lowRISC/lowrisc-chip/tree/ethernet-v0.5) then the
+first task will be to move the MicroSD and Ethernet peripherals aside
+and place the GPIO pinmux in between. This should be a relatively
+straightforward task that on its own is a significant contribution,
+and the project could be declared to be a success even if this was the
+only task that was completed.
+
+The next phase, where it gets interesting, would be to track down a suitable
+linux kernel driver for GPIO and rewrite it (or the pmod switchbox VHDL) to
+match precisely a pre-existing memory-mapped linux kernel GPIO driver.
+This would then need to be tested, demonstrating that the pins formerly
+used for MicroSD for example can now be switched to Input or Output.
+
+The next phase after that, again if time permits, would be to incorporate
+further peripherals such as PWM, I2C, UART, SPI and others, as desired.
+Recommended priority here will be on saving time by tracking down code
+that already has pre-existing linux kernel drivers that match up with
+the associated Verilog / VHDL, so that time is not spent exclusively writing
+c code or exclusively writing Verilog / VHDL.
+
+This project is therefore primarily about cross-skill integration and
+communication, and learning to work and collaborate "in the public eye",
+which takes either quite a lot of confidence, or just a particularly
+honest and open mind-set.
+
+Skill level: varies from Beginner to Advanced.
+
+Language / Tool: varied. VHDL/Verilog/Chisel essential, c optional,
+ git, mailing lists, wikis, good written communication
+ skills in English absolutely essential.
+
+Mentor: Luke Kenneth Casson Leighton, Stefan Wallentowitz.
+
+# Notes
+
+## <https://lists.librecores.org/pipermail/discussion/2018-January/000406.html>
+
+Some additional considerations:
+
+Glitchless muxing:: Pads must never glitch when switched.
+
+Request/Grant handshake:: Multiple requests can occur at the same time and control goes to the highest priority.
+A grant signal notifies the winner and losing input pads are driven to a specified value (1,0 ,other signal)
+
+Fast path for main function:: The pads main function is the most important signal but it only controls the pad when no one
+else wants it. You want it one mux level from the pad and must not have to go through a bunch of muxes.
+
+Jtag mode:: Boundary scan must test mission mode signals going to pad
+
+
+Test mode:: For any and all scan,mbist or test signals. Must not go through jtag Boundary scan.
+
+Reset mode: Forces pad into reset state during power on reset
+
--- /dev/null
+# Example Reference Schematics for Peripherals
+
+# Selection of a suitable PMIC
+
+Selecting a PMIC is tricky. Corporations such as Intel have gotten themselves
+into a lot of trouble by supplying an SoC under NDA, then forgetting that
+it's ultra-important to supply an easily-accessible PMIC that doesn't
+additionally require a totally separate NDA just to gain access to it!
+Total madness: cartelling by accident or by design (literally).
+
+Allwinner's solution was to actually buy a PMIC company (X-Powers), and
+for every new SoC they actually designed a corresponding companion PMIC,
+often selling it along-side the SoC at a combined price. Ingenic, as
+a smaller company, picks off-the-shelf PMICs from Actions Semi (typically
+the ACT8600 or similar). Rockchip also picked Actions Semi PMICs for
+the RK3288 designs but unlike the majority of X-Powers (AXP) offerings,
+none of these cover battery charging or OTG Power-switching.
+
+DCin, battery and OTG "Charging" is a **three-way** power-routing problem
+that, due to the amounts of current involved, and the possibility of
+blowing up lithium cells and causing people's houses to catch fire, is
+somthing that has to be taken very very seriously.
+Not blowing up devices by getting into a current bun-fight over who is
+going to supply 5.0v (battery, main power, DCin or the USB charger) is
+really quite complicated, and the AXP209 in conjunction with SY6280
+current-limiter ICs per USB port can take care of that, easily enough.
+
+Without this integrated capacity to route power it actually becomes
+extremely hair-raising and requires something like 60 discrete components
+and ICs to replicate (see jz4760 reference schematics "LEPUS Board"
+for an example). Alternatives for higher power (up to 4.5A) but not
+the same level of integration as the AXP209, include the bq2419x series
+from TI. Using anything from the bq24193 series still requires external
+components for 3-way power protection, as well as an external high-current
+efficient power-regulator to drop the input DC down to a stable 5V supply.
+
+Alternatives which do not have the same OTG Power provision
+but are lower cost and around the same current include the ACT8600 (2A),
+and the ACT8846 which can handle around 3A but requires companion
+ICs (SYR627 and SYR628) for the SoC core domain supply (see below).
+Another option would be something like the AXP803, however this PMIC
+requires a rather large companion MOSFET to handle / switch the battery
+and charging current, where the AXP209, by being less power-hungry,
+has that same MOSFET integrated.
+
+A critical aspect of PMIC selection is that the default output voltages
+at power-up are compatible with the SoC. Supply voltages **need** to be set
+so that during low clock rate operation the amount of power consumed is
+greatly reduced, however at higher clockrates the current draw of flipping
+1s to 0s and vice-versa causes a voltage drop that takes 1s and 0s outside
+of their "definitions". The solution: increase the voltage supply.
+
+The AXP209's main "core voltage" DCDC converter
+defaults to 1.2v for example, and the
+DCDC converter that is used for supplying the
+DRAM typically defaults to 1.5v. **These voltages are typically hard-wired
+into the PMIC's firmware**.
+Some PMICs may be re-programmed manually (at the factory) i.e have
+an on-board EEPROM, but this adds considerable complexity to manufacturing,
+as the PMIC must be pre-programmed **before** it can be safely connected
+to the SoC.
+
+So to avoid cartel scenarios and also to avoid custom-ordering of (minimum
+10k-50k PMICs), and to avoid the manufacturing and design complexity of
+re-programming the PMIC before it can be connected to the SoC, the best
+course of action is to analyse some available and extremely common PMICs,
+find out what their default outputs are, and then **arrange the SoC and
+the DRAM to be compatible with them** rather than the other way round.
+Primarily it is the core CPU voltage that, if exceeded, could damage the
+processor: the PMICs below default to between 1.0 and 1.25v; the DRAM
+voltage also typically defaults to 1.5v, meaning that DRAM ICs selected
+for the application will need to be rated for that. During the first
+second or so of startup, the boot firmware will need to get the SoC to
+communicate with the PMIC and set more suitable voltages before carrying
+on with the boot process. This is a Standard Operational Procedure
+which is encoded into either the BIOS or into u-boot.
+
+## AXP209
+
+An extremely well-supported, very simple-to-deploy and very comprehensive
+PMIC that includes support for USB OTG power flipping as well as battery
+charging. It copes with up to around a 2A power provision.
+
+Control Signals for the AXP209 are as follows:
+
+* NMI# - Non-maskable Interrupt. connect to main SoC. absolutely critical.
+* PWRON - Power On. Press-and-hold style, generates IRQ for SoC to shut down.
+* I2C SDA/SCL - for being able to manage the PMIC, change voltage output levels
+* GPIO1-3 - spare GPIO accessible over the I2C Bus
+* VBUSEN# - for controlling (enabling) the VBUS power.
+
+This latter signal - VBUSEN# - is absolutely critical. The AXP209 can cut
+the power when needed (when an OTG charger is plugged in), or it can do so as
+directed by the SoC, which detects incoming power or there is the required
+OTG "ID" negotiated.
+
+Power outputs are roughly as follows:
+
+* IPSOUT - basically either the battery or the 5V DC mains input. Needs
+ to be boosted (e.g. SY7208) to provide a stable 5.0v
+* DCDC outputs - the exact voltages are under I2C control. They're high
+ current, usually used for the DDR3 main supply, core SoC supply and so on.
+* LDO outputs - again controlled through I2C. Typically used for Camera,
+ Analog 3.3v and so on (around 200-300mA). One of them is suitable for a
+ RTC supply, when the rest of the board (and the PMIC) are in shut-down mode.
+
+Note that for the CPU and DDR3, the SoC has to either be designed to cope
+with the default pre-set voltages (1.2v for the CPU core for example and
+1.5v for DDR3) and to run for a very short while on those whilst the CPU gets
+a chance to change them by communicating over the I2C Bus to the PMIC, or it
+is necessary to **custom-order** a very special PMIC with preset voltages
+from a PMIC Manufacturer, which means a MOQ of 10k to 50k units.
+
+Honestly it is simpler to just design the SoC to cope with the higher voltage.
+
+[[!img AXP209.jpg]]
+
+# ACT8846 with SYR827 and SYR828 companion ICs
+
+This PMIC is used typically in conjunction with the 28nm Rockchip RK3288,
+and full schematics may be found by searching for "T-Firefly" and also
+"EOMA68-RK3288". Like the AXP209 it is an integrated PMIC but it does **not**
+handle battery charging or VBUS detection and OTG triple-way power switching.
+
+It does however, in combination with the SYR827 and SYR828, handle a lot
+more power than the AXP209 (2.8A for two of its DC-DC converters). The SYR827
+and SYR828 are used on the RK3288 to provide the SoC core domain power and
+the GPU core power, respectively. The default voltage is 1.0 volts and may
+be reduced or increased under I2C control as needed.
+
+[[!img ACT8846.jpg]]
+
+[[!img SYR827.828.jpg]]
+
+# AXP803 and companion MOSFET for Battery
+
+The AXP803 handles a lot more current and has a lot more options than the
+AXP209: it's a bit larger, a bit more expensive, but is specifically designed
+for modern quad-core SoCs. It can also handle a lot more current for charging
+because the battery MOSFET is an external IC.
+
+The A64 for which this PMIC was first deployed is a 40nm quad-core SoC, so
+the default power domains are designed specifically for that SoC.
+
+Control Signals include:
+
+* I2C for control, access to GPIO and selection of voltages on all outputs
+* 2 GPIOs which may be switched to an additional pair of LDOs
+* NMI# - Non-Maskable Interrupt. Critical to be connected to the SoC.
+* RESET# - a reset signal
+* PWR-ON - press or press-and-hold, used for hard power-cycling of the device
+* USB-DM/DP - this is to detect the presence of an OTG device in a clean way
+* USBVBUSEN - just as with the AXP209 this controls power to the OTG port.
+
+The AXP803 has additional capability to detect whether a USB 3.0 OTG Charger
+has been connected (so that additional current may be negotiated). This is
+most likely the reason why the USB+/- lines have to be connected to the PMIC.
+
+Outputs include:
+
+* 6 DC-DC converters
+* 3 ELDOs (extremely low-dropout outputs, for high-stability)
+* 4 DLDOs (digital LDOs)
+* 3 ALDOs (separate LDOs for Analog supply)
+* 2 FLDOs (no idea what these are: refer to the datasheet)
+* Dedicated RTC VCC supply
+
+Overall it is an extremely sophisticated PMIC which has the advantage of being
+mass-produced, proven (just like the AXP209 before it), and significant
+linux kernel driver support that is well-understood.
+
+[[!img AXP803.jpg]]
+
+# Ingenic JZ4760 PMIC Approach: Discrete ICs
+
+The team that did the Ingenic JZ4760 LEPUS Reference Design decided to take
+a different approach to Power Management: multiple discrete ICs for each
+power domain. They selected multiple RT8008 ICs and used different resistors
+to set the required current (which is then not adjustable, but the jz4760 is
+so low power anyway that this doesn't really matter), and used RT9169 and other
+3-pin LDOs for the RTC and low-power 1.2v supply.
+
+Of particular interest is how they did battery charging and the USB OTG
+power-switching. For the battery charging including being able to charge
+from either a 5V DCin or the OTG VBUS, they selected the RT9502. A MOSFET
+protects against power input from VBUS fighting with DCIN, and a Schottky
+Diode protects against current fights. A **second** MOSFET and Schottky
+Diode allows power-selection of either battery or DCin to the RT9502.
+All in all it's quite a sophisticated and clever circuit.
+
+[[!img RT9502.jpg]]
+
+USB Power Switching - selecting between either 5V or VBUS to go in (or out)
+of the OTG Port without blowing anything up - is done with a matched pair
+of RT9711A and RT9711B ICs. A SY6280 has not been deployed, so it is not
+precisely clear which IC does the current-provision / over-current protection
+on the OTG port.
+
+In addition to these discrete ICs for power provision, there is the usual
+step-up converter (an RT9266) which converts the 3.8-4.2v battery directly
+into a stable +5V supply. This is fairly normal, and can be seen in
+pretty much every design (whether using the AXP209, AXP803, ACT8600, ACT8846
+and so on). It is very interesting in this case however to note that
+the DCin is wired (via the two MOSFETs and Schottky Diodes) directly to
+BAT-V (and thus supplies the +5V rail) but that, thanks to those MOSFETs
+and Schottkys, if either VBUS powers up or the battery powers up, they
+**replace** the power stream to BAT-V in a priority-cascade.
+
+This example is included to show that power-provision **can** be done without
+a dedicated PMIC (but also demonstrating quite how many components it
+actually needs, to do so). Perhaps it might even still be a viable solution,
+by replacing some of the discrete (fixed) SY8008 LDOs with SYR828 and SYR829
+I2C-controllable high-current voltage regulators.
+
+[[!img RT9711.jpg]]
+
+[[!img Vregs.jpg]]
+
+# USB-OTG and USB-Host Ports
+
+This section covers how to set up an OTG port and a plain USB2 Host port.
+The USB Host is quite straightforward: protect the power with a SY6280 which
+performs current-limiting and also stops over-voltage from the USB port
+bleeding back down into the 5V supply (if someone does something silly like
+connect a 5.5v or 6v PSU to the USB port), and that's basically it, apart
+from one note-worthy fact that the SY6280 may be enabled/disabled under the
+control of the SoC in order to save power or to carry out a hard-reset on USB
+devices.
+
+The OTG port is slightly different. Note that there are 2 power lines and
+3 I/O signals involved:
+
+* VCC-5V input - for when power is **supplied** to the USB port (OTG Host)
+* USBVBUS - for when power is supplied **by** the USB port
+ (OTG Client aka usually "OTG Charging")
+* USB-ID - for OTG negotiation of which end is to be Client and which Host
+* VBUSDET - a resistor-divider bridge allowing the SoC to detect USBVBUS on/off
+* USB-DRV - enables or disables the VCC-5V power **supply** (but does not
+ affect, involve, or otherwise stop VBUS - outgoing or incoming)
+
+It is a good idea to place the USB-DRV under the control of the PMIC, so that
+it may detect when a charger is plugged in, even if the main SoC is powered
+down. Bear in mind that this all is a cooperative arrangement where the SoC
+and the PMIC must collaborate to prevent power-loss and current bun-fights.
+VBUSDET must be arranged so that the resistor-divider bridge creates just
+enough of a voltage to trigger an EINT-capable GPIO on the SoC with a "HIGH"
+or "LOW" digital level (not an ADC in other words).
+
+[[!img USBports.jpg]]
+
+# Level-shifted MicroSD
+
+For instances where the GPIO voltage of the SoC's I/O is not 3.3v, the
+deployment of a level-shifter is needed. Note the inclusion of ESD protection
+(which needs to be very close to the SD card slot) and the 47k pull-up
+resistors. Strictly speaking the Card Detect line (which is an Open Drain)
+need not be routed through the level-shifter, whereas the SDcard signals,
+which are push-push high-speed, definitely do. Many "Arduino-style"
+amateur-deployed level shifting techniques are in fact Open-Drain style and
+really do not work properly as they rely on the internal capacitance of
+pins and tracks to drop towards Ground levels: this simply doesn't happen
+quickly enough, corrupting the signal integrity and is why push-push was
+invented in the first place.
+
+This schematic could actually be dynamically converted to adjustable 3.3v/1.8v
+by replacing the level-shifter VCC-3V3 input power (U2, VCCB) with a power
+source that is under the control of the SoC. When the SoC detects
+that the inserted card has 1.8v capability, the SoC could then drop the
+level-shifter's B side down from 3.3v signal levels to 1.8v levels... all
+without having to adjust the actual SoC GPIO levels. The down-side:
+level-shifter ICs are around USD $1, take up a lot of board space relatively
+speaking, and require double the number of pins as I/O signals.
+
+[[!img LevelShiftedMicroSD.jpg]]
+
+# Power-domain-controlled MicroSD
+
+This second circuit is much simpler in principle yet may still adjust the
+SD/MMC power levels from 3.3v to 1.8v as required. Also note that the
+SD Card itself may be powered down under the control of a GPIO signal
+(named SDMMC-PWR) from the SoC.
+
+The level-shifting trick however in this case relies on the capability of the
+SoC and requires the cooperation of the PMIC. A specific LDO output from the
+PMIC is dedicated to this **one** SD card, and the **entire** power domain
+for this particular GPIO-bank (which happens only to have SD/MMC on it)
+is flipped from 3.3v down to 1.8v if needed.
+
+Note that whilst this GPIO voltage domain power-drop occurs the actual SD
+card itself is still supplied by 3.3v. Also note that in this circuit
+the SD-Det is still powered from SDIO (3.3v) so the SoC GPIO will need
+to be 3.3v tolerant even when it is dropped to 1.8v signalling levels.
+
+The alternative scheme would be to have an on-board level-shifter where the
+SD/MMC signal levels (only) are shifted between 3.3v and 1.8v levels, whilst
+leaving the rest of the entire GPIO bank's voltage levels alone. This seems
+inordinately overcomplex.
+
+[[!img PowerDomainMicroSD.jpg]]
+
+# AC97-compliant (I2S) Audio
+
+Under certain circumstances, USB Audio may be preferred over I2S (the
+CM108AH is a very good low-cost choice that is still mass-produced and
+has full schematics and no NDAs required). However USB bulk audio
+framing introduces latency that may prove intolerable under certain
+high-end circumstances (Media Centre for example). I2S was designed
+for low-latency and high-quality Digital Audio, send and receive.
+
+An example AC97-compliant Audio IC is the ES8323. In this instance it
+is a very low-cost one (around $0.50 for single quanties from multiple
+vendors on taobao.com), that only has a single stereo earphone output and
+a single mono microphone input. For ultra-low-cost applications this
+is perfectly fine, considering the price and high availability. Also,
+using the right type of stereo headphone jack (a PJ-0345 6-pin) it
+becomes possible to hard-switch (and detect - using another of the
+precious EINT lines to the SoC) stereo headphone jack insertion and to
+route both outputs, via the headphone jack, back to a pair of low-cost
+audio amplifier ICS (TDA2822), the important thing being that this
+requires **no** additional signals or involvement or wires to/from the
+AC97 Audio IC. It's crude but effective: the only thing needed to watch
+out for is to make sure that the jack insertion (or removal) is properly
+detected and that the audio volume level adjusted in sufficient time
+(if needed). Careful inclusion of the right resistor-divider bridges
+etc. can mitigate even against needing to do that.
+
+Control signals to the ES8323 are:
+
+* 5-pin I2S: this includes, in this example, only one DO and only one DI.
+* I2C: used to control the ES8323 (volume, configuration)
+
+Audio signals are:
+
+* Mono Microphone input
+* Stereo Headphone
+
+Many more sophisticated examples exist, which include 5-lane I2S (4 output,
+1 input) for Dolby 5.1 and 7 Surround Sound, multiple audio paths including
+Line-out, Line-in, Car Stereo, etc. etc. - one obsolete one that was extremely
+good was the Akai AK4641 used in the HTC Universal clamshell / micro-laptop
+smartphone. All in all it just depends on the application but the actual
+signals / buses involved remains pretty much the same in all cases: I2S for
+Audio data, I2C for control of the IC (AC97 volumes and routing etc.) and
+optional GPIO for detection e.g. of physical insertion of headphone and
+other jacks. That's about it.
+
+[[!img ES8323.jpg]]
+
+[[!img TDA2822.jpg]]
+
+# 802.11 WIFI and BT
+
+**WARNING: there are *NO* low-power embedded WIFI ICs that are RYF-Endorseable.
+*ALL* firmware for *ALL* embedded (SD/MMC) WIFI SIP modules and ICs are
+proprietary and cannot in any way be trusted not to compromise a machine
+through *built-in* factory-installed spying, or hardware level malicious
+hacking (this is not a theoretical concept: it has been successfully
+demonstrated by Security Researchers, numerous times on numerous chipsets
+and numerous architectures and OSes). If you include a hard-wired
+SD/MMC embedded WIFI SIP module hard-soldered to a PCB it is a sure-fire
+*GUARANTEED* way to 100 percent *FAIL* RYF Endorsement and Certification.
+If RYF Endorsement and the safety and privacy of end-users is important,
+ensure that the WIFI module may be *REMOVED* (physically by the user
+or simply not installed at the factory) and USB-based WIFI such as the
+ThinkPenguin TP150N, a small 802.11abgn WIFI dongle, inserted into the
+device instead (either internally or externally) with the end-user having
+the right to remove it.**
+
+With that huge warning out of the way, we can move on to describe the signals
+required for an example 802.11a/b/g/n/ac WIFI and BT 4.0 SIP Module. These
+are:
+
+* 4-lane SD/MMC for the WIFI data. This is standard for low-power SIP WIFI
+* 4-wire UART for Bluetooth, including TX/RX as well as CTS/RTS.
+* Quite a lot of IRQ and communication lines: up to five EINTs and GPIO in
+ the case of this particular SoC.
+
+The GPIO lines particularly EINTs are critical for WIFI and Bluetooth,
+particularly as applications may be adversely affected by clashes of these
+two protocols sharing the same 2.4ghz frequency bands. So the OS needs to
+know when a clash is detected, immediately: that requires an EINT-capable
+GPIO, on its own. Also, BT or WIFI (separately) may be used to wake up a
+host that has been placed into low-power sleep mode: again, that requires
+two separate and distinct EINT-capable GPIO lines.
+
+This particular WIFI SIP module also takes a 32.768kHz RTC input signal
+(which may be generated by the SoC or by a companion MCU), and it is also
+recommended to dedicate an additional GPIO to a MOSFET or other means to
+hard-kill the entire WIFI module.
+
+So on the face of it, it seems very straightforward, just route SD/MMC
+and UART, but it's actually quite involved. It would seem, then, that
+deploying a USB WIFI module would be a much simpler idea, especially
+given that USB2 is only 2 wires (plus power) and things like "wakeup"
+and "signalling" etc. are typically handled (with the common exception
+of protocol-clashing) via the provision of features built-in to the
+USB Bus Protocol. The down-side: most USB2 WIFI dongles, modules and
+chipsets are simply not designed for low-power scenarios, not at the
+hardware level and certainly not at the firmware level.
+
+Only one (modern) USB chipset - which only supports 802.11abgn and not ac -
+has full firmware source code available under Libre Licensing, thanks to
+ThinkPenguin's tireless efforts: the Atheros AR9271 USB Chipset. ThinkPenguin
+spent two years walking Atheros through the process of releasing the full
+firmware source code, and it is the only chipset where peer-to-peer mesh
+networking has been added by the Free Software Community, and it is the
+only chipset that could be considered for adjusting the firmware to reduce
+power consumption. Time however is running out for this chip because
+Qualcomm subequently bought Atheros, and Qualcomm replaced the entire
+management with people who completely fail to comprehend what made the
+AR9271 so very successful.
+
+Bottom line: WIFI and Bluetooth are an ethical minefield as far as
+user privacy, rights, and hardware-level remote hacking are concerend,
+and it starts right at the early design phase: component selection.
+A good way to ensure that users have control over their own devices is
+to add hardware (physical) kill-switches to the power lines, and/or
+to allow them to actually physically and completely remove the WIFI /
+BT module without invalidating the warranty.
+
+Datasheet: <http://www.t-firefly.com/download/firefly-rk3288/hardware/AP6335%20datasheet_V1.3_02102014.pdf>
+
+[[!img AP6335.jpg]]
+
+# I2C Sensors
+
+I2C sensors appear on the face of it to be quite straightforward: wire them
+up to the 2-line I2C bus and it's done, right? It's not that simple: I2C
+is a **master** bus only, meaning that if the peripheral has important data,
+it has to have some way of letting the SoC know that something's happened.
+This requires an EINT-capable IRQ line on the SoC in order to wake up the
+SoC from tasks or low-power mode(s). In addition, it's often the case
+that the sensor may need an occasional (or a definitive, on start-up)
+RESET. In particular it's a good idea to reset sensors after power-on due
+to potential problems caused by in-rush current instability: often this is
+covered in the datasheet as being **required**.
+
+So typically for each sensor, two extra GPIO lines are required: one EINT
+and one not. If the amount of GPIO begins to run out (EINTs are usually a
+finite resource) then it is technically possible to share SoC EINT lines
+using logic gates (one for a group of sensors), board-space permitting.
+The other technique is to use a companion MCU for EINT aggregation, and
+even, if pins are particularly sparse, to use the fact that the USB Bus
+has built-in wake-up capability to the SoC. A signal (or the actual data
+if the sensor is directly connected to the MCU instead) can be sent over
+USB. Typically in this instance it's a good idea to use the MCU to convert
+to a more standard format such as presenting one or more USB-HID endpoints
+(for CTP, Trackpad and mouse-like sensors), otherwise a special linux kernel
+driver needs to be written.
+
+Other than that, sensors are pretty straightforward. Most already have a
+linux kernel driver already available. If they don't, they're best avoided:
+pick another one that does, as it's a sure-fire sign that the sensor has not
+seen mass-volume production deployment, or if it has, there's been zero
+opportunity to do a security review of the source code and/or it'll be
+GPL-violating.
+
+[[!img I2CSensors.jpg]]
+
+# Ethernet PHY IC
+
+The normal standard for Ethernet PHYs is MII (10/100) and its variants, GMII
+(10/100/1000 Ethernet), RGMII and so on. There is however a different
+approach: MCU-based interfaces. In this particular instance, the Shakti
+team have already created a FlexBus implementation, which can be used
+to emulate the required SRAM / 8080-style micro-controller interface needed.
+A number of MCU-based Ethernet PHY ICs exist, including the AX88180
+(which is a Gigabit MCU-to-RGMII converter), the AX88796A (a 10/100
+PHY which supports 8080 as well as MC68k-style interfaces), and the
+low-cost and well-established 10/100 DM9000 PHY. It requires the
+following signals:
+
+* 16-bit Data/Address Bus
+* CMD select (Changes bus from Data to Address lines)
+* PWRST# (Power-on Reset)
+* IRQ (Interrupt indicator from DM9000 to SoC)
+* IOR# (Read Ready)
+* IOW# (Write Ready)
+* CS# (Chip Select)
+
+This comes to a total of 22 GPIO lines, which is a significant amount.
+However it is also possible to run the DM9000 bus at a reduced 8-bit
+width (with a slightly different pin arrangement for the top 8 bit pins:
+see datasheet for details), for a total 14 pincount. In addition,
+as a general-purpose shared memory bus it's possible to connect other
+peripherals simultaneously, mitigating the high pincount issue, requiring
+only one Chip Select line per peripheral. For example, if two Ethernet
+PHY ICs are required they may be placed on the exact same Bus: only one
+extra CS# line is required, and the pincount is now 15 pins for two
+Ethernet PHY ICs: a much better average pincount ratio than would be
+achieved from using two RGMII PHYs.
+
+Other important details: the AX88180, AX88796A and the DM9000 all have
+had linux kernel and u-boot driver source code available for many years.
+
+Datasheet: <https://www.heyrick.co.uk/blog/files/datasheets/dm9000aep.pdf>
+
+[[!img DM9000.jpg]]
+
+# USB-based Camera IC or Bit-banging CSI
+
+Low-cost Cameras typically require either a MIPI interface (CSI-2) or
+a Parallel Bus-style interface (CSI-1). Theoretically it is possible
+to bit-bang the CSI-1 interface, using a PWM for generating the clock,
+reading the HSYNC and VSYNC signals and the 8 to 12-bit data, and even
+using DMA to optimise the process. For an example implementation of this
+techique see
+<https://www.nxp.com/docs/en/application-note/AN4627.pdf>
+
+However the DMA / bit-banging technique takes up at least 12 pins,
+14 if the I2C interface is included, and many sensors require a minimum
+clockrate (data-rate) of 12 mhz before they will respond. A way to greatly
+reduce pincount is to use a USB-based IC, such as the low-cost, mass
+produced VC0345 from VIMicro.
+
+The VC0345 can do up to VGA @ 30fps, and can take still pictures up to 3M-pixels
+so is not exactly the fastest bunny on the block, but it has the distinct
+advantage of not requiring an NDA to gain access to either the datasheet or
+the app notes, and it is so commonly available that approaching the
+manufacturer is not actually necessary: it can be obtained directly from
+Shenzhen Markets. Also as it is a UVC-video compliant device, linux kernel
+driver support is automatic.
+
+An alternative approach to using an off-the-shelf CSI-to-USB Camera IC is
+to use a companion MCU: after all, the VC0345 is just a general-purpose
+8051 MCU. A student achieved this with an ultra-low-cost
+Camera Sensor (QVGA) and an STM32F103 back in 2010:
+<https://github.com/adamgreig/negativeacknowledge/blob/master/content/from-wordpress/robot2-an-arm-based-colour-tracking-robot.md>
+
+However for coping with larger sensors, care has to be taken: not least,
+it is not possible to fit an entire sensor frame into the SRAM of a small
+MCU, so there has to be some care taken to avoid loss of data. Also,
+the MCU must have 480mbit/sec USB2 capability, as beyond around
+640x480 even at 15fps a USB 1.1 11mbit/sec bus becomes completely saturated.
+Also to watch out for is whether the MCU's USB hardware supports enough
+simultaneous endpoints, particularly if USB-HID for keyboard (matrix to
+USB-HID keyboard) and/or USB-HID trackpad (mouse) or other devices are
+to be managed by the same MCU. Those caveats in mind: it is actually
+achievable.
+
+* Datasheet: <http://hands.com/~lkcl/eoma/kde_tablet/VC0345TLNA-1102-V10-EN.pdf>
+* VC0345 App Note: <http://hands.com/~lkcl/eoma/kde_tablet/VC0345_app_notes.pdf>
+
+# USB-Based 3G / UMTS/HSDPA Modem
+
+GSM / GPRS / EDGE Modems are typically slow enough to be able to use a UART
+at 115200 baud data rates. 3G on the other hand is fast enough to warrant the
+use of a USB connection. Depending on the firmware, some 3G USB-based Modems
+offer multiple endpoints, some of which can transfer audio data. Others
+offer two-way duplex digital audio over a standard four-wire "PCM" arrangement.
+The MU509 also (as previously mentioned in relation to the HTC Universal)
+has GPIO pins which may be accessed over an AT command-set. Using these
+becomes extra-complex as far as software is concerned, so should only really
+be used as a last resort.
+
+Connectivity for this particular 3G Modem is as follows, which will give
+the minimum functionality:
+
+* USB2 (+/-)
+* 3G Power Enable (to an LDO to cut/enable power to the entire Modem)
+* RESET#
+* PWRON
+* WAKEUPIN# (to wake up the 3G Modem)
+* WAKEUPOUT# (for the 3G Modem to wake up the SoC: requires EINT-capable pin)
+* SIM Card (connected to the MU509, not the SoC)
+
+This is a minimum of 5 GPIO plus 2 USB lines. Optional extras include:
+
+* Full UART (TX/RX, CTS/RTS, DTR/DCD/DSR, RING)
+* PCM 4-wire audio (standard WAV format, supported by many Audio HW CODECs)
+* Twin Mics
+* Speaker Out
+* Headset Out
+* 12 pins GPIO
+
+Note also in the example schematic that MMBT3904 transistors have been deployed
+for simple level-shifting and also convenient inversion of the control
+signals. Care needs to be taken in reading the datasheet to ensure that the
+voltage levels of the GPIO match the GPIO Power Domain of the SoC GPIO Bank
+to which the control signals of the MU509 are connected (and level-shifting
+deployed if needed).
+
+Also, special attention must be paid to the power supply: GSM and 3G Modems,
+particularly the "M2M" ones, require an enormous amount of current: 2 to 2.5
+**AMPS** is not unusual. M2M modules are also typically designed to operate
+off of a direct Lithium battery voltage and are **not** to be run off of
+a 3.3v or 5.0v supply. Hence in the example schematic below an LP6362
+high-current LDO is used. This however requires an additional GPIO, which
+is utilised to control the power supply of the 3G Modem.
+
+Deploying hard-power-kill switches (physical and/or under SoC GPIO-control)
+is generally a good idea with USB-based 3G and GSM Modems. During long-term
+operation, these modems, which are basically yet another ARM Processor and
+their own DDR and NAND storage with a full Software Stack (often linux kernel
+based) inside an enclosed metal box, are pretty much guaranteed to crash so
+hard that they become completely unrecoverable and unresponsive, and have
+even been known to cause the USB Host Endpoints that they are connected to
+to hard-crash as well. The only way to deal with that is to hard power-cycle
+the Modem module in order to do a full reset of its USB PHY.
+
+The other reason for considering deployment of a hard (physical) kill-switch
+is for respecting user privacy and safety. Also, it is worth ensuring that
+the 3G Modem does not require its firmware to be uploaded each and every time
+it is powered up: it's much better to select a Modem that has its own
+independent on-board NAND Flash (fortunately, unlike with the WIFI
+module industry which is the total opposite, it is standard practice to
+include on-board NAND on GSM/3G Modems). The hassle of getting a Modem Hardware
+Manufacturer to provide the exact and correct firmware per country per
+Cell-Operator (the FCC is particularly strict about this in the USA, and
+even requires FCC Re-Certification **per Operating System** at a cost of
+USD $50,000 per modem, per cell-operator, per firmware release, **per OS
+release**),
+all of which of course will require an NDA (for binaries??), and require
+MOQs of 100k units or above just to get them to answer enquiries: it's
+just not worth the hassle and the cost "savings" of not having NAND
+Flash on the actual Modem module.
+
+Plus, uploading of software (firmware) from main OS Storage to a peripheral
+is something that instantly terminates any possibility of obtaining RYF
+Hardware-Endorsement Certification. To make that clear: as long as all
+peripherals (such as a 3G Modem) that run proprietary software are
+fully-functional from the moment they leave the factory, i.e. they do
+not **require** software to be uploaded to them via the main OS in order
+to do their **full** job, RYF Certification can be sought. Ath5k and
+Ath9k WIFI modules are another example of peripherals that have on-board
+NAND and are fully-functional from the factory, so do not stop RYF
+Certification.
+
+[[!img MU509.jpg]]
+
+# SimCOM SIM7600 / SIM7100 USB-based GSM/EDGE/3G/4G/LTE Penta-band Modem
+
+An up-to-date low-cost Modem example is one from SimCOM. SimCOM are best
+known for their low-cost SIM800 and SIM900 "workhorse" GSM modems, which
+are extremely popular in the Shenzhen Markets. SimCom also have some
+LTE multi-band modems, the 7100 and 7600 Series. Full technical documents can
+be obtained by registering and then logging in to their website
+(or instead by simply searching online without registration).
+The SIM7600E is here: <http://simcomm2m.com/En/module/detail.aspx?id=178>.
+Checking pricing and availability, it actually seems that the SIM7100C
+is more popular. has lots of developer kits available, some MiniPCIe
+designs, bare modules, and, importantly, plenty of suppliers which is
+a good sign.
+
+The pinouts are pretty much exactly the same as the Huawei MU509,
+with the addition of two SD Card interfaces, two ADCs, and an SPI interface
+for running a display. This module, it seems, is actually designed for
+use as a stand-alone, fully-functioning actual phone, not even requiring
+a companion SoC or MCU at all. The SIM7100 also supports sending and
+reading of Audio data over USB. The Application Notes are **significant**
+which makes it an extremely good choice. There is even advice on how
+to design an interoperable PCB that supports the low-cost SIM800C, the
+SIM5360 and the SIM7100, all of which are in the same footprint and are
+nearly 100% pin-compatible. Documents can be obtained without
+NDA from here: <http://simcomm2m.com/En/module/detail.aspx?id=85>
+
+[[!img SIM7600.jpg]]
+
--- /dev/null
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] None None
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] None None
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] None None
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] None None
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] None None
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] None None
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] None 2
+['CMD', 'CLK', 'D0', 'D1', 'D2', 'D3'] 2 None
+# Pinouts (PinMux)
+
+auto-generated by [[pinouts.py]]
+
+[[!toc ]]
+
+| Pin | Mux0 | Mux1 | Mux2 | Mux3 |
+| --- | ----------- | ----------- | ----------- | ----------- |
+| 0 | A GPIOA0 | A MMCCMD | A UART1_TX | A SPI1_CLK |
+| 1 | A GPIOA1 | A MMCCLK | A UART1_RX | A SPI1_NSS |
+| 2 | A GPIOA2 | A MMCD0 | A UART1_CTS | A SPI1_MOSI |
+| 3 | A GPIOA3 | A MMCD1 | A UART1_RTS | A SPI1_MISO |
+| 4 | A GPIOA4 | A MMCD2 | A TWI1_SDA | A EINT0 |
+| 5 | A GPIOA5 | A MMCD3 | A TWI1_SCL | A EINT1 |
+| 6 | A GPIOA6 | A MMCD4 | A SPI2_CLK | A EINT2 |
+| 7 | A GPIOA7 | A MMCD5 | A SPI2_NSS | A EINT3 |
+| 8 | A GPIOA8 | A MMCD6 | A SPI2_MOSI | A EINT4 |
+| 9 | A GPIOA9 | A MMCD7 | A SPI2_MISO | A EINT5 |
+| 10 | A GPIOA10 | A EINT0 | A SD1_CMD | A JTAG1_MS |
+| 11 | A GPIOA11 | A EINT1 | A SD1_CLK | A JTAG1_DI |
+| 12 | A GPIOA12 | A EINT2 | A SD1_D0 | A JTAG1_DO |
+| 13 | A GPIOA13 | A EINT3 | A SD1_D1 | A JTAG1_CK |
+| 14 | A GPIOA14 | A EINT4 | A SD1_D2 | A UART2_TX |
+| 15 | A GPIOA15 | A EINT5 | A SD1_D3 | A UART2_RX |
+| 16 | B GPIOB0 | B LCDCK_0 | B TWI1_SDA | B EINT6 |
+| 17 | B GPIOB1 | B LCDDE_0 | B TWI1_SCL | B EINT7 |
+| 18 | B GPIOB2 | B LCDHS_0 | B UART2_TX | B EINT8 |
+| 19 | B GPIOB3 | B LCDVS_0 | B UART2_RX | B EINT9 |
+| 20 | B GPIOB4 | B LCD0_0 | B SPI3_CK | B FB_AD8 |
+| 21 | B GPIOB5 | B LCD1_0 | B SPI3_NSS | B FB_AD9 |
+| 22 | B GPIOB6 | B LCD2_0 | B SPI3_IO0 | B FB_AD10 |
+| 23 | B GPIOB7 | B LCD3_0 | B SPI3_IO1 | B FB_AD11 |
+| 24 | B GPIOB8 | B LCD4_0 | | B FB_AD12 |
+| 25 | B GPIOB9 | B LCD5_0 | B PWM_0 | B FB_AD13 |
+| 26 | B GPIOB10 | B LCD6_0 | B UART4_TX | B FB_AD14 |
+| 27 | B GPIOB11 | B LCD7_0 | B UART4_RX | B FB_AD15 |
+| 28 | B GPIOB12 | B LCD8_0 | B SPI1_CLK | B FB_AD16 |
+| 29 | B GPIOB13 | B LCD9_0 | B SPI1_NSS | B FB_AD17 |
+| 30 | B GPIOB14 | B LCD10_0 | B SPI1_MOSI | B FB_AD18 |
+| 31 | B GPIOB15 | B LCD11_0 | B SPI1_MISO | B FB_AD19 |
+| 32 | B GPIOB16 | B LCD12_0 | B UART3_TX | B FB_AD20 |
+| 33 | B GPIOB17 | B LCD13_0 | B UART3_RX | B FB_AD21 |
+| 34 | B GPIOB18 | B LCD14_0 | B TWI3_SDA | B FB_AD22 |
+| 35 | B GPIOB19 | B LCD15_0 | B TWI3_SCL | B FB_AD23 |
+| 36 | B GPIOB20 | B LCD16_0 | B PWM_1 | B FB_AD24 |
+| 37 | B GPIOB21 | B LCD17_0 | B PWM_2 | B FB_AD25 |
+| 38 | B GPIOB22 | B LCD18_0 | B SD1_CMD | B FB_AD26 |
+| 39 | B GPIOB23 | B LCD19_0 | B SD1_CLK | B FB_AD27 |
+| 40 | B GPIOB24 | B LCD20_0 | B SD1_D0 | B FB_AD28 |
+| 41 | B GPIOB25 | B LCD21_0 | B SD1_D1 | B FB_AD29 |
+| 42 | B GPIOB26 | B LCD22_0 | B SD1_D2 | B FB_AD30 |
+| 43 | B GPIOB27 | B LCD23_0 | B SD1_D3 | B FB_AD31 |
+| 44 | C GPIOC0 | C ULPI1_CK | | C EINT10 |
+| 45 | C GPIOC1 | C ULPI1_DIR | | C EINT11 |
+| 46 | C GPIOC2 | C ULPI1_STP | | C EINT12 |
+| 47 | C GPIOC3 | C ULPI1_NXT | | C EINT13 |
+| 48 | C GPIOC4 | C ULPI1_D0 | | C EINT14 |
+| 49 | C GPIOC5 | C ULPI1_D1 | | C EINT15 |
+| 50 | C GPIOC6 | C ULPI1_D2 | | C EINT16 |
+| 51 | C GPIOC7 | C ULPI1_D3 | | C EINT17 |
+| 52 | C GPIOC8 | C ULPI1_D4 | C SPI2_CLK | C JTAG2_MS |
+| 53 | C GPIOC9 | C ULPI1_D5 | C SPI2_NSS | C JTAG2_DI |
+| 54 | C GPIOC10 | C ULPI1_D6 | C SPI2_MOSI | C JTAG2_DO |
+| 55 | C GPIOC11 | C ULPI1_D7 | C SPI2_MISO | C JTAG2_CK |
+| 56 | C GPIOC12 | C ULPI2_CK | C SPI2_NSS | C EINT22 |
+| 57 | C GPIOC13 | C ULPI2_DIR | C IISMCK | C EINT23 |
+| 58 | C GPIOC14 | C ULPI2_STP | C IISBCK | C EINT24 |
+| 59 | C GPIOC15 | C ULPI2_NXT | C IISLRCK | C EINT25 |
+| 60 | C GPIOC16 | C ULPI2_D0 | C IISDI | C EINT26 |
+| 61 | C GPIOC17 | C ULPI2_D1 | C IISDO0 | C EINT27 |
+| 62 | C GPIOC18 | C ULPI2_D2 | C IISDO1 | C EINT28 |
+| 63 | C GPIOC19 | C ULPI2_D3 | C IISDO2 | C EINT29 |
+| 64 | C GPIOC20 | C ULPI2_D4 | C IISDO3 | C UART0_TX |
+| 65 | C GPIOC21 | C ULPI2_D5 | C PWM_2 | C UART0_RX |
+| 66 | C GPIOC22 | C ULPI2_D6 | C UART2_TX | C UART0_CTS |
+| 67 | C GPIOC23 | C ULPI2_D7 | C UART2_RX | C UART0_RTS |
+| 68 | D GPIOD0 | D FB_AD0 | D UART0_TX | D EINT30 |
+| 69 | D GPIOD1 | D FB_AD1 | D UART0_RX | D EINT31 |
+| 70 | D GPIOD2 | D FB_AD2 | D UART0_CTS | D TWI2_SDA |
+| 71 | D GPIOD3 | D FB_AD3 | D UART0_RTS | D TWI2_SCL |
+| 72 | D GPIOD4 | D FB_AD4 | D SD2_CMD | |
+| 73 | D GPIOD5 | D FB_AD5 | D SD2_CLK | |
+| 74 | D GPIOD6 | D FB_AD6 | D SD2_D0 | |
+| 75 | D GPIOD7 | D FB_AD7 | D SD2_D1 | |
+| 76 | D GPIOD8 | D FB_CS0 | D SD2_D2 | |
+| 77 | D GPIOD9 | D FB_CS1 | D SD2_D3 | |
+| 78 | D GPIOD10 | D FB_ALE | D FB_TS | D TWI1_SDA |
+| 79 | D GPIOD11 | D FB_OE | D FB_TBST | D TWI1_SCL |
+| 80 | D GPIOD12 | D FB_RW | | |
+| 81 | D GPIOD13 | D FB_TA | D UART4_TX | D EINT5 |
+| 82 | D GPIOD14 | D FB_CLK | D UART4_RX | D EINT6 |
+| 83 | D GPIOD15 | D FB_BWE0 | D FB_TSIZ0 | D EINT7 |
+| 84 | D GPIOD16 | D FB_BWE1 | D FB_TSIZ1 | D EINT8 |
+| 85 | D GPIOD17 | D FB_BWE2 | D TWI2_SDA | D FB_A0 |
+| 86 | D GPIOD18 | D FB_BWE3 | D TWI2_SCL | D FB_A1 |
+| 87 | D GPIOD19 | D FB_CS4 | D TWI3_SDA | D EINT18 |
+| 88 | D GPIOD20 | D FB_CS5 | D TWI3_SCL | D EINT19 |
+| 89 | D GPIOD21 | D PWM_0 | D UART3_TX | D EINT20 |
+| 90 | D GPIOD22 | D PWM_1 | D UART3_RX | D EINT21 |
+| 91 | D GPIOD23 | D PWM_2 | | D EINT9 |
+| 92 | E GPIOE0 | E FB_AD8 | E SD2_CMD | E EINT10 |
+| 93 | E GPIOE1 | E FB_AD9 | E SD2_CLK | E EINT11 |
+| 94 | E GPIOE2 | E FB_AD10 | E SD2_D0 | E EINT12 |
+| 95 | E GPIOE3 | E FB_AD11 | E SD2_D1 | E EINT13 |
+| 96 | E GPIOE4 | E FB_AD12 | E SD2_D2 | E EINT14 |
+| 97 | E GPIOE5 | E FB_AD13 | E SD2_D3 | E EINT15 |
+| 98 | E GPIOE6 | E FB_AD14 | E TWI2_SDA | E EINT16 |
+| 99 | E GPIOE7 | E FB_AD15 | E TWI2_SCL | E EINT17 |
+| 100 | E GPIOE8 | E FB_AD16 | E SD3_CMD | E EINT22 |
+| 101 | E GPIOE9 | E FB_AD17 | E SD3_CLK | E EINT23 |
+| 102 | E GPIOE10 | E FB_AD18 | E SD3_D0 | E EINT24 |
+| 103 | E GPIOE11 | E FB_AD19 | E SD3_D1 | E EINT25 |
+| 104 | E GPIOE12 | E FB_AD20 | E SD3_D2 | E EINT26 |
+| 105 | E GPIOE13 | E FB_AD21 | E SD3_D3 | E EINT27 |
+| 106 | E GPIOE14 | E FB_AD22 | E UART1_TX | E MMCCMD |
+| 107 | E GPIOE15 | E FB_AD23 | E UART1_RX | E MMCCLK |
+| 108 | E GPIOE16 | E FB_AD24 | E UART1_CTS | E MMCD0 |
+| 109 | E GPIOE17 | E FB_AD25 | E UART1_RTS | E MMCD1 |
+| 110 | E GPIOE18 | E FB_AD26 | E SPI3_CK | E MMCD2 |
+| 111 | E GPIOE19 | E FB_AD27 | E SPI3_NSS | E MMCD3 |
+| 112 | E GPIOE20 | E FB_AD28 | E SPI3_IO0 | E MMCD4 |
+| 113 | E GPIOE21 | E FB_AD29 | E SPI3_IO1 | E MMCD5 |
+| 114 | E GPIOE22 | E FB_AD30 | E SPI3_IO2 | E MMCD6 |
+| 115 | E GPIOE23 | E FB_AD31 | E SPI3_IO3 | E MMCD7 |
+| 116 | F GPIOF0 | F IISMCK | F SD3_CMD | F EINT18 |
+| 117 | F GPIOF1 | F IISBCK | F SD3_CLK | F EINT19 |
+| 118 | F GPIOF2 | F IISLRCK | F SD3_D0 | F EINT20 |
+| 119 | F GPIOF3 | F IISDI | F SD3_D1 | F EINT21 |
+| 120 | F GPIOF4 | F IISDO0 | F SD3_D2 | F PWM_2 |
+| 121 | F GPIOF5 | F IISDO1 | F SD3_D3 | F EINT7 |
+| 122 | F GPIOF6 | F IISDO2 | F TWI1_SDA | F EINT28 |
+| 123 | F GPIOF7 | F IISDO3 | F TWI1_SCL | F EINT29 |
+| 124 | F GPIOF8 | F UART4_TX | F PWM_0 | F EINT30 |
+| 125 | F GPIOF9 | F UART4_RX | F PWM_1 | F EINT31 |
+| 126 | G GPIOG0 | G RG_ERXD0 | G LCDCK_1 | G FB_AD8 |
+| 127 | G GPIOG1 | G RG_ERXD1 | G LCDDE_1 | G FB_AD9 |
+| 128 | G GPIOG2 | G RG_ERXD2 | G LCDHS_1 | G FB_AD10 |
+| 129 | G GPIOG3 | G RG_ETXD0 | G LCDVS_1 | G FB_AD11 |
+| 130 | G GPIOG4 | G RG_ETXD1 | G LCD0_1 | G FB_AD12 |
+| 131 | G GPIOG5 | G RG_ETXD2 | G LCD1_1 | G FB_AD13 |
+| 132 | G GPIOG6 | G RG_FB_CS0 | G LCD2_1 | G FB_AD14 |
+| 133 | G GPIOG7 | G RG_FB_CS1 | G LCD3_1 | G FB_AD15 |
+| 134 | G GPIOG8 | G RG_ERXCK | G LCD4_1 | G FB_AD16 |
+| 135 | G GPIOG9 | G RG_ERXERR | G LCD5_1 | G FB_AD17 |
+| 136 | G GPIOG10 | G RG_ERXDV | G LCD6_1 | G FB_AD18 |
+| 137 | G GPIOG11 | G RG_EMDC | G LCD7_1 | G FB_AD19 |
+| 138 | G GPIOG12 | G RG_EMDIO | G LCD8_1 | G FB_AD20 |
+| 139 | G GPIOG13 | G RG_ETXEN | G LCD9_1 | G FB_AD21 |
+| 140 | G GPIOG14 | G RG_ETXCK | G LCD10_1 | G FB_AD22 |
+| 141 | G GPIOG15 | G RG_ECRS | G LCD11_1 | G FB_AD23 |
+| 142 | G GPIOG16 | G RG_ECOL | G LCD12_1 | G FB_AD24 |
+| 143 | G GPIOG17 | G RG_ETXERR | G LCD13_1 | G FB_AD25 |
+| 144 | G GPIOG18 | G ULPI3_CK | G LCD14_1 | G FB_AD26 |
+| 145 | G GPIOG19 | G ULPI3_DIR | G LCD15_1 | G FB_AD27 |
+| 146 | G GPIOG20 | G ULPI3_STP | G LCD16_1 | G FB_AD28 |
+| 147 | G GPIOG21 | G ULPI3_NXT | G LCD17_1 | G FB_AD29 |
+| 148 | G GPIOG22 | G ULPI3_D0 | G LCD18_1 | G FB_AD30 |
+| 149 | G GPIOG23 | G ULPI3_D1 | G LCD19_1 | G FB_AD31 |
+| 150 | G GPIOG24 | G ULPI3_D2 | G LCD20_1 | G SD2_CMD |
+| 151 | G GPIOG25 | G ULPI3_D3 | G LCD21_1 | G SD2_CLK |
+| 152 | G GPIOG26 | G ULPI3_D4 | G LCD22_1 | G SPI3_CK |
+| 153 | G GPIOG27 | G ULPI3_D5 | G LCD23_1 | G SPI3_NSS |
+| 154 | G GPIOG28 | G ULPI3_D6 | G SD2_D0 | G SPI3_IO0 |
+| 155 | G GPIOG29 | G ULPI3_D7 | G SD2_D1 | G SPI3_IO1 |
+| 156 | G GPIOG30 | | G SD2_D2 | G SPI3_IO2 |
+| 157 | G GPIOG31 | | G SD2_D3 | G SPI3_IO3 |
+
+# Pinouts (Fixed function)
+
+## CTRL_SYS
+
+* 158: 0 TEST
+* 159: 0 JTAG_SEL
+* 160: 0 UBOOT_SEL
+* 161: 0 NMI#
+* 162: 0 RESET#
+* 163: 0 CLK24M_IN CLK24M_OUT
+* 165: 0 PLLTEST PLLREGIO PLLVP25 PLLDV
+* 169: 0 PLLVREG PLLGND
+
+## DDR3
+
+* 171: 1 SDQ0 SDQ1 SDQ2 SDQ3
+* 175: 1 SDQ4 SDQ5 SDQ6 SDQ7
+* 179: 1 SDQ8 SDQ9 SDQ10 SDQ11
+* 183: 1 SDQ12 SDQ13 SDQ14 SDQ15
+* 187: 1 SDQ16 SDQ17 SDQ18 SDQ19
+* 191: 1 SDQ20 SDQ21 SDQ22 SDQ23
+* 195: 1 SDQ24 SDQ25 SDQ26 SDQ27
+* 199: 1 SDQ28 SDQ29 SDQ30 SDQ31
+* 203: 1 SVREF0 SVREF1 SVREF2 SVREF3
+* 207: 1 SDQS0 SDQS0# SDQS1 SDQS1#
+* 211: 1 SDQS2 SDQS2# SDQS3 SDQS3#
+* 215: 1 SDQM0 SDQM1 SDQM2 SDQM3
+* 219: 1 SCK# SCK SCKE0 SCKE1
+* 223: 1 SA0 SA1 SA2 SA3
+* 227: 1 SA4 SA5 SA6 SA7
+* 231: 1 SA8 SA9 SA10 SA11
+* 235: 1 SA12 SA13 SA14
+* 238: 1 SBA0 SBA1 SBA2
+* 241: 1 SWE
+* 242: 1 SCAS
+* 243: 1 SRAS
+* 244: 1 SCS0 SCS1
+* 246: 1 SZQ
+* 247: 1 SRST
+* 248: 1 SDBG0 SDBG1
+* 250: 1 ADBG
+* 251: 1 ODT0 ODT1
+
+## POWER_CPU
+
+* 253: 2 VDD0_CPU VDD1_CPU VDD2_CPU VDD3_CPU
+* 257: 2 VDD4_CPU VDD5_CPU
+* 259: 2 GND0_CPU GND1_CPU GND2_CPU GND3_CPU
+* 263: 2 GND4_CPU GND5_CPU
+
+## POWER_DLL
+
+* 265: 3 VDD0_DLL VDD1_DLL VDD2_DLL
+* 268: 3 GND0_DLL GND1_DLL GND2_DLL
+
+## POWER_DRAM
+
+* 271: 4 VCC0_DRAM VCC1_DRAM VCC2_DRAM VCC3_DRAM
+* 275: 4 VCC4_DRAM VCC5_DRAM VCC6_DRAM VCC7_DRAM
+* 279: 4 VCC8_DRAM VCC9_DRAM
+* 281: 4 GND0_DRAM GND1_DRAM GND2_DRAM GND3_DRAM
+* 285: 4 GND4_DRAM GND5_DRAM GND6_DRAM GND7_DRAM
+* 289: 4 GND8_DRAM GND9_DRAM
+
+## POWER_GPIO
+
+* 291: 5 VDD_GPIOA VDD_GPIOB VDD_GPIOC VDD_GPIOD
+* 295: 5 VDD_GPIOE VDD_GPIOF VDD_GPIOG
+* 298: 5 GND_GPIOA GND_GPIOB GND_GPIOC GND_GPIOD
+* 302: 5 GND_GPIOE GND_GPIOF GND_GPIOG
+
+## POWER_INT
+
+* 305: 6 VDD0_INT VDD1_INT VDD2_INT VDD3_INT
+* 309: 6 VDD4_INT VDD5_INT VDD6_INT VDD7_INT
+* 313: 6 VDD8_INT VDD9_INT
+* 315: 6 GND0_INT GND1_INT GND2_INT GND3_INT
+* 319: 6 GND4_INT GND5_INT GND6_INT GND7_INT
+* 323: 6 GND8_INT GND9_INT
+
+# Functions (PinMux)
+
+auto-generated by [[pinouts.py]]
+
+## EINT
+
+External Interrupt
+
+* EINT0 : A4/3 A10/1
+* EINT1 : A5/3 A11/1
+* EINT2 : A6/3 A12/1
+* EINT3 : A7/3 A13/1
+* EINT4 : A8/3 A14/1
+* EINT5 : A9/3 A15/1 D13/3
+* EINT6 : B0/3 D14/3
+* EINT7 : B1/3 D15/3 F5/3
+* EINT8 : B2/3 D16/3
+* EINT9 : B3/3 D23/3
+* EINT10 : C0/3 E0/3
+* EINT11 : C1/3 E1/3
+* EINT12 : C2/3 E2/3
+* EINT13 : C3/3 E3/3
+* EINT14 : C4/3 E4/3
+* EINT15 : C5/3 E5/3
+* EINT16 : C6/3 E6/3
+* EINT17 : C7/3 E7/3
+* EINT18 : D19/3 F0/3
+* EINT19 : D20/3 F1/3
+* EINT20 : D21/3 F2/3
+* EINT21 : D22/3 F3/3
+* EINT22 : C12/3 E8/3
+* EINT23 : C13/3 E9/3
+* EINT24 : C14/3 E10/3
+* EINT25 : C15/3 E11/3
+* EINT26 : C16/3 E12/3
+* EINT27 : C17/3 E13/3
+* EINT28 : C18/3 F6/3
+* EINT29 : C19/3 F7/3
+* EINT30 : D0/3 F8/3
+* EINT31 : D1/3 F9/3
+
+## FB
+
+MC68k FlexBus
+
+* FB_A0 : D17/3
+* FB_A1 : D18/3
+* FB_AD0 : D0/1
+* FB_AD1 : D1/1
+* FB_AD2 : D2/1
+* FB_AD3 : D3/1
+* FB_AD4 : D4/1
+* FB_AD5 : D5/1
+* FB_AD6 : D6/1
+* FB_AD7 : D7/1
+* FB_AD8 : B4/3 E0/1 G0/3
+* FB_AD9 : B5/3 E1/1 G1/3
+* FB_AD10 : B6/3 E2/1 G2/3
+* FB_AD11 : B7/3 E3/1 G3/3
+* FB_AD12 : B8/3 E4/1 G4/3
+* FB_AD13 : B9/3 E5/1 G5/3
+* FB_AD14 : B10/3 E6/1 G6/3
+* FB_AD15 : B11/3 E7/1 G7/3
+* FB_AD16 : B12/3 E8/1 G8/3
+* FB_AD17 : B13/3 E9/1 G9/3
+* FB_AD18 : B14/3 E10/1 G10/3
+* FB_AD19 : B15/3 E11/1 G11/3
+* FB_AD20 : B16/3 E12/1 G12/3
+* FB_AD21 : B17/3 E13/1 G13/3
+* FB_AD22 : B18/3 E14/1 G14/3
+* FB_AD23 : B19/3 E15/1 G15/3
+* FB_AD24 : B20/3 E16/1 G16/3
+* FB_AD25 : B21/3 E17/1 G17/3
+* FB_AD26 : B22/3 E18/1 G18/3
+* FB_AD27 : B23/3 E19/1 G19/3
+* FB_AD28 : B24/3 E20/1 G20/3
+* FB_AD29 : B25/3 E21/1 G21/3
+* FB_AD30 : B26/3 E22/1 G22/3
+* FB_AD31 : B27/3 E23/1 G23/3
+* FB_ALE : D10/1
+* FB_BWE0 : D15/1
+* FB_BWE1 : D16/1
+* FB_BWE2 : D17/1
+* FB_BWE3 : D18/1
+* FB_CLK : D14/1
+* FB_CS0 : D8/1
+* FB_CS1 : D9/1
+* FB_CS4 : D19/1
+* FB_CS5 : D20/1
+* FB_OE : D11/1
+* FB_RW : D12/1
+* FB_TA : D13/1
+* FB_TBST : D11/2
+* FB_TS : D10/2
+* FB_TSIZ0 : D15/2
+* FB_TSIZ1 : D16/2
+
+## IIS
+
+I2S Audio
+
+* IISBCK : C14/2 F1/1
+* IISDI : C16/2 F3/1
+* IISDO0 : C17/2 F4/1
+* IISDO1 : C18/2 F5/1
+* IISDO2 : C19/2 F6/1
+* IISDO3 : C20/2 F7/1
+* IISLRCK : C15/2 F2/1
+* IISMCK : C13/2 F0/1
+
+## JTAG1
+
+JTAG (same as JTAG2, JTAG_SEL=LOW)
+
+* JTAG1_CK : A13/3
+* JTAG1_DI : A11/3
+* JTAG1_DO : A12/3
+* JTAG1_MS : A10/3
+
+## JTAG2
+
+JTAG (same as JTAG1, JTAG_SEL=HIGH)
+
+* JTAG2_CK : C11/3
+* JTAG2_DI : C9/3
+* JTAG2_DO : C10/3
+* JTAG2_MS : C8/3
+
+## LCD
+
+24-pin RGB/TTL LCD
+
+* LCD0_0 : B4/1
+* LCD0_1 : G4/2
+* LCD1_0 : B5/1
+* LCD1_1 : G5/2
+* LCD10_0 : B14/1
+* LCD10_1 : G14/2
+* LCD11_0 : B15/1
+* LCD11_1 : G15/2
+* LCD12_0 : B16/1
+* LCD12_1 : G16/2
+* LCD13_0 : B17/1
+* LCD13_1 : G17/2
+* LCD14_0 : B18/1
+* LCD14_1 : G18/2
+* LCD15_0 : B19/1
+* LCD15_1 : G19/2
+* LCD16_0 : B20/1
+* LCD16_1 : G20/2
+* LCD17_0 : B21/1
+* LCD17_1 : G21/2
+* LCD18_0 : B22/1
+* LCD18_1 : G22/2
+* LCD19_0 : B23/1
+* LCD19_1 : G23/2
+* LCD2_0 : B6/1
+* LCD2_1 : G6/2
+* LCD20_0 : B24/1
+* LCD20_1 : G24/2
+* LCD21_0 : B25/1
+* LCD21_1 : G25/2
+* LCD22_0 : B26/1
+* LCD22_1 : G26/2
+* LCD23_0 : B27/1
+* LCD23_1 : G27/2
+* LCD3_0 : B7/1
+* LCD3_1 : G7/2
+* LCD4_0 : B8/1
+* LCD4_1 : G8/2
+* LCD5_0 : B9/1
+* LCD5_1 : G9/2
+* LCD6_0 : B10/1
+* LCD6_1 : G10/2
+* LCD7_0 : B11/1
+* LCD7_1 : G11/2
+* LCD8_0 : B12/1
+* LCD8_1 : G12/2
+* LCD9_0 : B13/1
+* LCD9_1 : G13/2
+* LCDCK_0 : B0/1
+* LCDCK_1 : G0/2
+* LCDDE_0 : B1/1
+* LCDDE_1 : G1/2
+* LCDHS_0 : B2/1
+* LCDHS_1 : G2/2
+* LCDVS_0 : B3/1
+* LCDVS_1 : G3/2
+
+## MMC
+
+eMMC 1/2/4/8 pin
+
+* MMCCLK : A1/1 E15/3
+* MMCCMD : A0/1 E14/3
+* MMCD0 : A2/1 E16/3
+* MMCD1 : A3/1 E17/3
+* MMCD2 : A4/1 E18/3
+* MMCD3 : A5/1 E19/3
+* MMCD4 : A6/1 E20/3
+* MMCD5 : A7/1 E21/3
+* MMCD6 : A8/1 E22/3
+* MMCD7 : A9/1 E23/3
+
+## PWM
+
+PWM (pulse-width modulation)
+
+* PWM_0 : B9/2 D21/1 F8/2
+* PWM_1 : B20/2 D22/1 F9/2
+* PWM_2 : B21/2 C21/2 D23/1 F4/3
+
+## RG
+
+RGMII Ethernet
+
+* RG_ECOL : G16/1
+* RG_ECRS : G15/1
+* RG_EMDC : G11/1
+* RG_EMDIO : G12/1
+* RG_ERXCK : G8/1
+* RG_ERXD0 : G0/1
+* RG_ERXD1 : G1/1
+* RG_ERXD2 : G2/1
+* RG_ERXDV : G10/1
+* RG_ERXERR : G9/1
+* RG_ETXCK : G14/1
+* RG_ETXD0 : G3/1
+* RG_ETXD1 : G4/1
+* RG_ETXD2 : G5/1
+* RG_ETXEN : G13/1
+* RG_ETXERR : G17/1
+* RG_FB_CS0 : G6/1
+* RG_FB_CS1 : G7/1
+
+## SD1
+
+SD/MMC 1
+
+* SD1_CLK : A11/2 B23/2
+* SD1_CMD : A10/2 B22/2
+* SD1_D0 : A12/2 B24/2
+* SD1_D1 : A13/2 B25/2
+* SD1_D2 : A14/2 B26/2
+* SD1_D3 : A15/2 B27/2
+
+## SD2
+
+SD/MMC 2
+
+* SD2_CLK : D5/2 E1/2 G25/3
+* SD2_CMD : D4/2 E0/2 G24/3
+* SD2_D0 : D6/2 E2/2 G28/2
+* SD2_D1 : D7/2 E3/2 G29/2
+* SD2_D2 : D8/2 E4/2 G30/2
+* SD2_D3 : D9/2 E5/2 G31/2
+
+## SD3
+
+SD/MMC 3
+
+* SD3_CLK : E9/2 F1/2
+* SD3_CMD : E8/2 F0/2
+* SD3_D0 : E10/2 F2/2
+* SD3_D1 : E11/2 F3/2
+* SD3_D2 : E12/2 F4/2
+* SD3_D3 : E13/2 F5/2
+
+## SPI1
+
+SPI (Serial Peripheral Interface) 1
+
+* SPI1_CLK : A0/3 B12/2
+* SPI1_MISO : A3/3 B15/2
+* SPI1_MOSI : A2/3 B14/2
+* SPI1_NSS : A1/3 B13/2
+
+## SPI2
+
+SPI (Serial Peripheral Interface) 2
+
+* SPI2_CLK : A6/2 C8/2
+* SPI2_MISO : A9/2 C11/2
+* SPI2_MOSI : A8/2 C10/2
+* SPI2_NSS : A7/2 C9/2 C12/2
+
+## SPI3
+
+Quad SPI (Serial Peripheral Interface) 3
+
+* SPI3_CK : B4/2 E18/2 G26/3
+* SPI3_IO0 : B6/2 E20/2 G28/3
+* SPI3_IO1 : B7/2 E21/2 G29/3
+* SPI3_IO2 : E22/2 G30/3
+* SPI3_IO3 : E23/2 G31/3
+* SPI3_NSS : B5/2 E19/2 G27/3
+
+## TWI1
+
+I2C 1
+
+* TWI1_SCL : A5/2 B1/2 D11/3 F7/2
+* TWI1_SDA : A4/2 B0/2 D10/3 F6/2
+
+## TWI2
+
+I2C 2
+
+* TWI2_SCL : D3/3 D18/2 E7/2
+* TWI2_SDA : D2/3 D17/2 E6/2
+
+## TWI3
+
+I2C 3
+
+* TWI3_SCL : B19/2 D20/2
+* TWI3_SDA : B18/2 D19/2
+
+## UART0
+
+UART (TX/RX/CTS/RTS) 0
+
+* UART0_CTS : C22/3 D2/2
+* UART0_RTS : C23/3 D3/2
+* UART0_RX : C21/3 D1/2
+* UART0_TX : C20/3 D0/2
+
+## UART1
+
+UART (TX/RX/CTS/RTS) 1
+
+* UART1_CTS : A2/2 E16/2
+* UART1_RTS : A3/2 E17/2
+* UART1_RX : A1/2 E15/2
+* UART1_TX : A0/2 E14/2
+
+## UART2
+
+UART (TX/RX) 2
+
+* UART2_RX : A15/3 B3/2 C23/2
+* UART2_TX : A14/3 B2/2 C22/2
+
+## UART3
+
+UART (TX/RX) 3
+
+* UART3_RX : B17/2 D22/2
+* UART3_TX : B16/2 D21/2
+
+## UART4
+
+UART (TX/RX) 4
+
+* UART4_RX : B11/2 D14/2 F9/1
+* UART4_TX : B10/2 D13/2 F8/1
+
+## ULPI1
+
+ULPI (USB Low Pin-count) 1
+
+* ULPI1_CK : C0/1
+* ULPI1_D0 : C4/1
+* ULPI1_D1 : C5/1
+* ULPI1_D2 : C6/1
+* ULPI1_D3 : C7/1
+* ULPI1_D4 : C8/1
+* ULPI1_D5 : C9/1
+* ULPI1_D6 : C10/1
+* ULPI1_D7 : C11/1
+* ULPI1_DIR : C1/1
+* ULPI1_NXT : C3/1
+* ULPI1_STP : C2/1
+
+## ULPI2
+
+ULPI (USB Low Pin-count) 2
+
+* ULPI2_CK : C12/1
+* ULPI2_D0 : C16/1
+* ULPI2_D1 : C17/1
+* ULPI2_D2 : C18/1
+* ULPI2_D3 : C19/1
+* ULPI2_D4 : C20/1
+* ULPI2_D5 : C21/1
+* ULPI2_D6 : C22/1
+* ULPI2_D7 : C23/1
+* ULPI2_DIR : C13/1
+* ULPI2_NXT : C15/1
+* ULPI2_STP : C14/1
+
+## ULPI3
+
+ULPI (USB Low Pin-count) 3
+
+* ULPI3_CK : G18/1
+* ULPI3_D0 : G22/1
+* ULPI3_D1 : G23/1
+* ULPI3_D2 : G24/1
+* ULPI3_D3 : G25/1
+* ULPI3_D4 : G26/1
+* ULPI3_D5 : G27/1
+* ULPI3_D6 : G28/1
+* ULPI3_D7 : G29/1
+* ULPI3_DIR : G19/1
+* ULPI3_NXT : G21/1
+* ULPI3_STP : G20/1
+
+# Pinmap for EOMA68
+
+## B1:LCD/22
+
+EOMA68-compliance, 18-bit RGB/TTL LCD
+
+* LCDCK_0 16 B0/1
+* LCDDE_0 17 B1/1
+* LCDHS_0 18 B2/1
+* LCDVS_0 19 B3/1
+* LCD0_0 20 B4/1
+* LCD1_0 21 B5/1
+* LCD2_0 22 B6/1
+* LCD3_0 23 B7/1
+* LCD4_0 24 B8/1
+* LCD5_0 25 B9/1
+* LCD6_0 26 B10/1
+* LCD7_0 27 B11/1
+* LCD8_0 28 B12/1
+* LCD9_0 29 B13/1
+* LCD10_0 30 B14/1
+* LCD11_0 31 B15/1
+* LCD12_0 32 B16/1
+* LCD13_0 33 B17/1
+* LCD14_0 34 B18/1
+* LCD15_0 35 B19/1
+* LCD16_0 36 B20/1
+* LCD17_0 37 B21/1
+
+## ULPI1/8
+
+user-facing: internal (on Card), USB-OTG ULPI PHY
+
+* ULPI1_CK 44 C0/1
+* ULPI1_DIR 45 C1/1
+* ULPI1_STP 46 C2/1
+* ULPI1_NXT 47 C3/1
+* ULPI1_D0 48 C4/1
+* ULPI1_D1 49 C5/1
+* ULPI1_D2 50 C6/1
+* ULPI1_D3 51 C7/1
+
+## ULPI2
+
+EOMA68-compliance: dual USB2 Host ULPI PHY
+
+* ULPI2_CK 56 C12/1
+* ULPI2_DIR 57 C13/1
+* ULPI2_STP 58 C14/1
+* ULPI2_NXT 59 C15/1
+* ULPI2_D0 60 C16/1
+* ULPI2_D1 61 C17/1
+* ULPI2_D2 62 C18/1
+* ULPI2_D3 63 C19/1
+* ULPI2_D4 64 C20/1
+* ULPI2_D5 65 C21/1
+* ULPI2_D6 66 C22/1
+* ULPI2_D7 67 C23/1
+
+## MMC
+
+internal (on Card)
+
+* MMCCMD 0 A0/1
+* MMCCLK 1 A1/1
+* MMCD0 2 A2/1
+* MMCD1 3 A3/1
+* MMCD2 4 A4/1
+* MMCD3 5 A5/1
+* MMCD4 6 A6/1
+* MMCD5 7 A7/1
+* MMCD6 8 A8/1
+* MMCD7 9 A9/1
+
+## SD1
+
+user-facing: internal (on Card), multiplexed with JTAG1
+and UART2, for debug purposes
+
+* SD1_CMD 10 A10/2
+* SD1_CLK 11 A11/2
+* SD1_D0 12 A12/2
+* SD1_D1 13 A13/2
+* SD1_D2 14 A14/2
+* SD1_D3 15 A15/2
+
+## UART3
+
+EOMA68-compliance
+
+* UART3_TX 89 D21/2
+* UART3_RX 90 D22/2
+
+## TWI3
+
+EOMA68-compliance: must be entirely free of devices.
+Address 0x51 used (externally) for EOMA68 EEPROM Id
+
+* TWI3_SDA 87 D19/2
+* TWI3_SCL 88 D20/2
+
+## SPI2
+
+EOMA68-compliance
+
+* SPI2_CLK 52 C8/2
+* SPI2_NSS 53 C9/2
+* SPI2_MOSI 54 C10/2
+* SPI2_MISO 55 C11/2
+
+## E2:SD2
+
+EOMA68-compliance
+
+* SD2_CMD 92 E0/2
+* SD2_CLK 93 E1/2
+* SD2_D0 94 E2/2
+* SD2_D1 95 E3/2
+* SD2_D2 96 E4/2
+* SD2_D3 97 E5/2
+
+## EINT
+
+* EINT16 98 E6/3
+* EINT17 99 E7/3
+* EINT18 116 F0/3
+* EINT19 117 F1/3
+
+## PWM
+
+* PWM_2 91 D23/1
+
+## Unused Pinouts (spare as GPIO) for 'EOMA68'
+
+| Pin | Mux0 | Mux1 | Mux2 | Mux3 |
+| --- | ----------- | ----------- | ----------- | ----------- |
+| 38 | B GPIOB22 | B LCD18_0 | B SD1_CMD | B FB_AD26 |
+| 39 | B GPIOB23 | B LCD19_0 | B SD1_CLK | B FB_AD27 |
+| 40 | B GPIOB24 | B LCD20_0 | B SD1_D0 | B FB_AD28 |
+| 41 | B GPIOB25 | B LCD21_0 | B SD1_D1 | B FB_AD29 |
+| 42 | B GPIOB26 | B LCD22_0 | B SD1_D2 | B FB_AD30 |
+| 43 | B GPIOB27 | B LCD23_0 | B SD1_D3 | B FB_AD31 |
+| 68 | D GPIOD0 | D FB_AD0 | D UART0_TX | D EINT30 |
+| 69 | D GPIOD1 | D FB_AD1 | D UART0_RX | D EINT31 |
+| 70 | D GPIOD2 | D FB_AD2 | D UART0_CTS | D TWI2_SDA |
+| 71 | D GPIOD3 | D FB_AD3 | D UART0_RTS | D TWI2_SCL |
+| 72 | D GPIOD4 | D FB_AD4 | D SD2_CMD | |
+| 73 | D GPIOD5 | D FB_AD5 | D SD2_CLK | |
+| 74 | D GPIOD6 | D FB_AD6 | D SD2_D0 | |
+| 75 | D GPIOD7 | D FB_AD7 | D SD2_D1 | |
+| 76 | D GPIOD8 | D FB_CS0 | D SD2_D2 | |
+| 77 | D GPIOD9 | D FB_CS1 | D SD2_D3 | |
+| 78 | D GPIOD10 | D FB_ALE | D FB_TS | D TWI1_SDA |
+| 79 | D GPIOD11 | D FB_OE | D FB_TBST | D TWI1_SCL |
+| 80 | D GPIOD12 | D FB_RW | | |
+| 81 | D GPIOD13 | D FB_TA | D UART4_TX | D EINT5 |
+| 82 | D GPIOD14 | D FB_CLK | D UART4_RX | D EINT6 |
+| 83 | D GPIOD15 | D FB_BWE0 | D FB_TSIZ0 | D EINT7 |
+| 84 | D GPIOD16 | D FB_BWE1 | D FB_TSIZ1 | D EINT8 |
+| 85 | D GPIOD17 | D FB_BWE2 | D TWI2_SDA | D FB_A0 |
+| 86 | D GPIOD18 | D FB_BWE3 | D TWI2_SCL | D FB_A1 |
+| 100 | E GPIOE8 | E FB_AD16 | E SD3_CMD | E EINT22 |
+| 101 | E GPIOE9 | E FB_AD17 | E SD3_CLK | E EINT23 |
+| 102 | E GPIOE10 | E FB_AD18 | E SD3_D0 | E EINT24 |
+| 103 | E GPIOE11 | E FB_AD19 | E SD3_D1 | E EINT25 |
+| 104 | E GPIOE12 | E FB_AD20 | E SD3_D2 | E EINT26 |
+| 105 | E GPIOE13 | E FB_AD21 | E SD3_D3 | E EINT27 |
+| 106 | E GPIOE14 | E FB_AD22 | E UART1_TX | E MMCCMD |
+| 107 | E GPIOE15 | E FB_AD23 | E UART1_RX | E MMCCLK |
+| 108 | E GPIOE16 | E FB_AD24 | E UART1_CTS | E MMCD0 |
+| 109 | E GPIOE17 | E FB_AD25 | E UART1_RTS | E MMCD1 |
+| 110 | E GPIOE18 | E FB_AD26 | E SPI3_CK | E MMCD2 |
+| 111 | E GPIOE19 | E FB_AD27 | E SPI3_NSS | E MMCD3 |
+| 112 | E GPIOE20 | E FB_AD28 | E SPI3_IO0 | E MMCD4 |
+| 113 | E GPIOE21 | E FB_AD29 | E SPI3_IO1 | E MMCD5 |
+| 114 | E GPIOE22 | E FB_AD30 | E SPI3_IO2 | E MMCD6 |
+| 115 | E GPIOE23 | E FB_AD31 | E SPI3_IO3 | E MMCD7 |
+| 118 | F GPIOF2 | F IISLRCK | F SD3_D0 | F EINT20 |
+| 119 | F GPIOF3 | F IISDI | F SD3_D1 | F EINT21 |
+| 120 | F GPIOF4 | F IISDO0 | F SD3_D2 | F PWM_2 |
+| 121 | F GPIOF5 | F IISDO1 | F SD3_D3 | F EINT7 |
+| 122 | F GPIOF6 | F IISDO2 | F TWI1_SDA | F EINT28 |
+| 123 | F GPIOF7 | F IISDO3 | F TWI1_SCL | F EINT29 |
+| 124 | F GPIOF8 | F UART4_TX | F PWM_0 | F EINT30 |
+| 125 | F GPIOF9 | F UART4_RX | F PWM_1 | F EINT31 |
+| 126 | G GPIOG0 | G RG_ERXD0 | G LCDCK_1 | G FB_AD8 |
+| 127 | G GPIOG1 | G RG_ERXD1 | G LCDDE_1 | G FB_AD9 |
+| 128 | G GPIOG2 | G RG_ERXD2 | G LCDHS_1 | G FB_AD10 |
+| 129 | G GPIOG3 | G RG_ETXD0 | G LCDVS_1 | G FB_AD11 |
+| 130 | G GPIOG4 | G RG_ETXD1 | G LCD0_1 | G FB_AD12 |
+| 131 | G GPIOG5 | G RG_ETXD2 | G LCD1_1 | G FB_AD13 |
+| 132 | G GPIOG6 | G RG_FB_CS0 | G LCD2_1 | G FB_AD14 |
+| 133 | G GPIOG7 | G RG_FB_CS1 | G LCD3_1 | G FB_AD15 |
+| 134 | G GPIOG8 | G RG_ERXCK | G LCD4_1 | G FB_AD16 |
+| 135 | G GPIOG9 | G RG_ERXERR | G LCD5_1 | G FB_AD17 |
+| 136 | G GPIOG10 | G RG_ERXDV | G LCD6_1 | G FB_AD18 |
+| 137 | G GPIOG11 | G RG_EMDC | G LCD7_1 | G FB_AD19 |
+| 138 | G GPIOG12 | G RG_EMDIO | G LCD8_1 | G FB_AD20 |
+| 139 | G GPIOG13 | G RG_ETXEN | G LCD9_1 | G FB_AD21 |
+| 140 | G GPIOG14 | G RG_ETXCK | G LCD10_1 | G FB_AD22 |
+| 141 | G GPIOG15 | G RG_ECRS | G LCD11_1 | G FB_AD23 |
+| 142 | G GPIOG16 | G RG_ECOL | G LCD12_1 | G FB_AD24 |
+| 143 | G GPIOG17 | G RG_ETXERR | G LCD13_1 | G FB_AD25 |
+| 144 | G GPIOG18 | G ULPI3_CK | G LCD14_1 | G FB_AD26 |
+| 145 | G GPIOG19 | G ULPI3_DIR | G LCD15_1 | G FB_AD27 |
+| 146 | G GPIOG20 | G ULPI3_STP | G LCD16_1 | G FB_AD28 |
+| 147 | G GPIOG21 | G ULPI3_NXT | G LCD17_1 | G FB_AD29 |
+| 148 | G GPIOG22 | G ULPI3_D0 | G LCD18_1 | G FB_AD30 |
+| 149 | G GPIOG23 | G ULPI3_D1 | G LCD19_1 | G FB_AD31 |
+| 150 | G GPIOG24 | G ULPI3_D2 | G LCD20_1 | G SD2_CMD |
+| 151 | G GPIOG25 | G ULPI3_D3 | G LCD21_1 | G SD2_CLK |
+| 152 | G GPIOG26 | G ULPI3_D4 | G LCD22_1 | G SPI3_CK |
+| 153 | G GPIOG27 | G ULPI3_D5 | G LCD23_1 | G SPI3_NSS |
+| 154 | G GPIOG28 | G ULPI3_D6 | G SD2_D0 | G SPI3_IO0 |
+| 155 | G GPIOG29 | G ULPI3_D7 | G SD2_D1 | G SPI3_IO1 |
+| 156 | G GPIOG30 | | G SD2_D2 | G SPI3_IO2 |
+| 157 | G GPIOG31 | | G SD2_D3 | G SPI3_IO3 |
+
+# Pinmap for Industrial
+
+## D1:FB/17
+
+* FB_AD0 68 D0/1
+* FB_AD1 69 D1/1
+* FB_AD2 70 D2/1
+* FB_AD3 71 D3/1
+* FB_AD4 72 D4/1
+* FB_AD5 73 D5/1
+* FB_AD6 74 D6/1
+* FB_AD7 75 D7/1
+* FB_CS0 76 D8/1
+* FB_CS1 77 D9/1
+* FB_ALE 78 D10/1
+* FB_OE 79 D11/1
+* FB_RW 80 D12/1
+* FB_TA 81 D13/1
+* FB_CLK 82 D14/1
+* FB_BWE0 83 D15/1
+* FB_BWE1 84 D16/1
+
+## E1:FB/8
+
+* FB_AD8 92 E0/1
+* FB_AD9 93 E1/1
+* FB_AD10 94 E2/1
+* FB_AD11 95 E3/1
+* FB_AD12 96 E4/1
+* FB_AD13 97 E5/1
+* FB_AD14 98 E6/1
+* FB_AD15 99 E7/1
+
+## B1:LCD/22
+
+* LCDCK_0 16 B0/1
+* LCDDE_0 17 B1/1
+* LCDHS_0 18 B2/1
+* LCDVS_0 19 B3/1
+* LCD0_0 20 B4/1
+* LCD1_0 21 B5/1
+* LCD2_0 22 B6/1
+* LCD3_0 23 B7/1
+* LCD4_0 24 B8/1
+* LCD5_0 25 B9/1
+* LCD6_0 26 B10/1
+* LCD7_0 27 B11/1
+* LCD8_0 28 B12/1
+* LCD9_0 29 B13/1
+* LCD10_0 30 B14/1
+* LCD11_0 31 B15/1
+* LCD12_0 32 B16/1
+* LCD13_0 33 B17/1
+* LCD14_0 34 B18/1
+* LCD15_0 35 B19/1
+* LCD16_0 36 B20/1
+* LCD17_0 37 B21/1
+
+## ULPI1/8
+
+* ULPI1_CK 44 C0/1
+* ULPI1_DIR 45 C1/1
+* ULPI1_STP 46 C2/1
+* ULPI1_NXT 47 C3/1
+* ULPI1_D0 48 C4/1
+* ULPI1_D1 49 C5/1
+* ULPI1_D2 50 C6/1
+* ULPI1_D3 51 C7/1
+
+## ULPI2/8
+
+* ULPI2_CK 56 C12/1
+* ULPI2_DIR 57 C13/1
+* ULPI2_STP 58 C14/1
+* ULPI2_NXT 59 C15/1
+* ULPI2_D0 60 C16/1
+* ULPI2_D1 61 C17/1
+* ULPI2_D2 62 C18/1
+* ULPI2_D3 63 C19/1
+
+## MMC
+
+* MMCCMD 0 A0/1
+* MMCCLK 1 A1/1
+* MMCD0 2 A2/1
+* MMCD1 3 A3/1
+* MMCD2 4 A4/1
+* MMCD3 5 A5/1
+* MMCD4 6 A6/1
+* MMCD5 7 A7/1
+* MMCD6 8 A8/1
+* MMCD7 9 A9/1
+
+## B2:SD1
+
+* SD1_CMD 38 B22/2
+* SD1_CLK 39 B23/2
+* SD1_D0 40 B24/2
+* SD1_D1 41 B25/2
+* SD1_D2 42 B26/2
+* SD1_D3 43 B27/2
+
+## JTAG1
+
+* JTAG1_MS 10 A10/3
+* JTAG1_DI 11 A11/3
+* JTAG1_DO 12 A12/3
+* JTAG1_CK 13 A13/3
+
+## A3:UART2
+
+* UART2_TX 14 A14/3
+* UART2_RX 15 A15/3
+
+## E2:UART1
+
+* UART1_TX 106 E14/2
+* UART1_RX 107 E15/2
+* UART1_CTS 108 E16/2
+* UART1_RTS 109 E17/2
+
+## C3:UART0
+
+* UART0_TX 64 C20/3
+* UART0_RX 65 C21/3
+* UART0_CTS 66 C22/3
+* UART0_RTS 67 C23/3
+
+## F2:TWI1
+
+* TWI1_SDA 122 F6/2
+* TWI1_SCL 123 F7/2
+
+## D2:TWI2
+
+* TWI2_SDA 85 D17/2
+* TWI2_SCL 86 D18/2
+
+## D2:TWI3
+
+* TWI3_SDA 87 D19/2
+* TWI3_SCL 88 D20/2
+
+## SPI2
+
+* SPI2_CLK 52 C8/2
+* SPI2_NSS 53 C9/2
+* SPI2_MOSI 54 C10/2
+* SPI2_MISO 55 C11/2
+
+## SPI3
+
+* SPI3_CK 110 E18/2
+* SPI3_NSS 111 E19/2
+* SPI3_IO0 112 E20/2
+* SPI3_IO1 113 E21/2
+* SPI3_IO2 114 E22/2
+* SPI3_IO3 115 E23/2
+
+## F2:SD3
+
+* SD3_CMD 116 F0/2
+* SD3_CLK 117 F1/2
+* SD3_D0 118 F2/2
+* SD3_D1 119 F3/2
+* SD3_D2 120 F4/2
+* SD3_D3 121 F5/2
+
+## EINT
+
+* EINT24 102 E10/3
+* EINT25 103 E11/3
+* EINT26 104 E12/3
+* EINT27 105 E13/3
+* EINT20 89 D21/3
+* EINT21 90 D22/3
+* EINT22 100 E8/3
+* EINT23 101 E9/3
+
+## PWM
+
+* PWM_0 124 F8/2
+* PWM_1 125 F9/2
+* PWM_2 91 D23/1
+
+## Unused Pinouts (spare as GPIO) for 'Industrial'
+
+| Pin | Mux0 | Mux1 | Mux2 | Mux3 |
+| --- | ----------- | ----------- | ----------- | ----------- |
+| 126 | G GPIOG0 | G RG_ERXD0 | G LCDCK_1 | G FB_AD8 |
+| 127 | G GPIOG1 | G RG_ERXD1 | G LCDDE_1 | G FB_AD9 |
+| 128 | G GPIOG2 | G RG_ERXD2 | G LCDHS_1 | G FB_AD10 |
+| 129 | G GPIOG3 | G RG_ETXD0 | G LCDVS_1 | G FB_AD11 |
+| 130 | G GPIOG4 | G RG_ETXD1 | G LCD0_1 | G FB_AD12 |
+| 131 | G GPIOG5 | G RG_ETXD2 | G LCD1_1 | G FB_AD13 |
+| 132 | G GPIOG6 | G RG_FB_CS0 | G LCD2_1 | G FB_AD14 |
+| 133 | G GPIOG7 | G RG_FB_CS1 | G LCD3_1 | G FB_AD15 |
+| 134 | G GPIOG8 | G RG_ERXCK | G LCD4_1 | G FB_AD16 |
+| 135 | G GPIOG9 | G RG_ERXERR | G LCD5_1 | G FB_AD17 |
+| 136 | G GPIOG10 | G RG_ERXDV | G LCD6_1 | G FB_AD18 |
+| 137 | G GPIOG11 | G RG_EMDC | G LCD7_1 | G FB_AD19 |
+| 138 | G GPIOG12 | G RG_EMDIO | G LCD8_1 | G FB_AD20 |
+| 139 | G GPIOG13 | G RG_ETXEN | G LCD9_1 | G FB_AD21 |
+| 140 | G GPIOG14 | G RG_ETXCK | G LCD10_1 | G FB_AD22 |
+| 141 | G GPIOG15 | G RG_ECRS | G LCD11_1 | G FB_AD23 |
+| 142 | G GPIOG16 | G RG_ECOL | G LCD12_1 | G FB_AD24 |
+| 143 | G GPIOG17 | G RG_ETXERR | G LCD13_1 | G FB_AD25 |
+| 144 | G GPIOG18 | G ULPI3_CK | G LCD14_1 | G FB_AD26 |
+| 145 | G GPIOG19 | G ULPI3_DIR | G LCD15_1 | G FB_AD27 |
+| 146 | G GPIOG20 | G ULPI3_STP | G LCD16_1 | G FB_AD28 |
+| 147 | G GPIOG21 | G ULPI3_NXT | G LCD17_1 | G FB_AD29 |
+| 148 | G GPIOG22 | G ULPI3_D0 | G LCD18_1 | G FB_AD30 |
+| 149 | G GPIOG23 | G ULPI3_D1 | G LCD19_1 | G FB_AD31 |
+| 150 | G GPIOG24 | G ULPI3_D2 | G LCD20_1 | G SD2_CMD |
+| 151 | G GPIOG25 | G ULPI3_D3 | G LCD21_1 | G SD2_CLK |
+| 152 | G GPIOG26 | G ULPI3_D4 | G LCD22_1 | G SPI3_CK |
+| 153 | G GPIOG27 | G ULPI3_D5 | G LCD23_1 | G SPI3_NSS |
+| 154 | G GPIOG28 | G ULPI3_D6 | G SD2_D0 | G SPI3_IO0 |
+| 155 | G GPIOG29 | G ULPI3_D7 | G SD2_D1 | G SPI3_IO1 |
+| 156 | G GPIOG30 | | G SD2_D2 | G SPI3_IO2 |
+| 157 | G GPIOG31 | | G SD2_D3 | G SPI3_IO3 |
+
+# Pinmap for Industrial with SPI-LCD
+
+## D1:FB/17
+
+* FB_AD0 68 D0/1
+* FB_AD1 69 D1/1
+* FB_AD2 70 D2/1
+* FB_AD3 71 D3/1
+* FB_AD4 72 D4/1
+* FB_AD5 73 D5/1
+* FB_AD6 74 D6/1
+* FB_AD7 75 D7/1
+* FB_CS0 76 D8/1
+* FB_CS1 77 D9/1
+* FB_ALE 78 D10/1
+* FB_OE 79 D11/1
+* FB_RW 80 D12/1
+* FB_TA 81 D13/1
+* FB_CLK 82 D14/1
+* FB_BWE0 83 D15/1
+* FB_BWE1 84 D16/1
+
+## E1:FB/8
+
+* FB_AD8 92 E0/1
+* FB_AD9 93 E1/1
+* FB_AD10 94 E2/1
+* FB_AD11 95 E3/1
+* FB_AD12 96 E4/1
+* FB_AD13 97 E5/1
+* FB_AD14 98 E6/1
+* FB_AD15 99 E7/1
+
+## B2:SPI1
+
+Used for 320x240 or 640x480 etc. SPI-based LCD.
+Frees up large numbers of GPIO from RGB/TTL bank
+
+* SPI1_CLK 28 B12/2
+* SPI1_NSS 29 B13/2
+* SPI1_MOSI 30 B14/2
+* SPI1_MISO 31 B15/2
+
+## ULPI1/8
+
+* ULPI1_CK 44 C0/1
+* ULPI1_DIR 45 C1/1
+* ULPI1_STP 46 C2/1
+* ULPI1_NXT 47 C3/1
+* ULPI1_D0 48 C4/1
+* ULPI1_D1 49 C5/1
+* ULPI1_D2 50 C6/1
+* ULPI1_D3 51 C7/1
+
+## ULPI2/8
+
+* ULPI2_CK 56 C12/1
+* ULPI2_DIR 57 C13/1
+* ULPI2_STP 58 C14/1
+* ULPI2_NXT 59 C15/1
+* ULPI2_D0 60 C16/1
+* ULPI2_D1 61 C17/1
+* ULPI2_D2 62 C18/1
+* ULPI2_D3 63 C19/1
+
+## MMC
+
+* MMCCMD 0 A0/1
+* MMCCLK 1 A1/1
+* MMCD0 2 A2/1
+* MMCD1 3 A3/1
+* MMCD2 4 A4/1
+* MMCD3 5 A5/1
+* MMCD4 6 A6/1
+* MMCD5 7 A7/1
+* MMCD6 8 A8/1
+* MMCD7 9 A9/1
+
+## B2:SD1
+
+* SD1_CMD 38 B22/2
+* SD1_CLK 39 B23/2
+* SD1_D0 40 B24/2
+* SD1_D1 41 B25/2
+* SD1_D2 42 B26/2
+* SD1_D3 43 B27/2
+
+## JTAG1
+
+* JTAG1_MS 10 A10/3
+* JTAG1_DI 11 A11/3
+* JTAG1_DO 12 A12/3
+* JTAG1_CK 13 A13/3
+
+## A3:UART2
+
+* UART2_TX 14 A14/3
+* UART2_RX 15 A15/3
+
+## E2:UART1
+
+* UART1_TX 106 E14/2
+* UART1_RX 107 E15/2
+* UART1_CTS 108 E16/2
+* UART1_RTS 109 E17/2
+
+## C3:UART0
+
+* UART0_TX 64 C20/3
+* UART0_RX 65 C21/3
+* UART0_CTS 66 C22/3
+* UART0_RTS 67 C23/3
+
+## B2:UART4
+
+* UART4_TX 26 B10/2
+* UART4_RX 27 B11/2
+
+## B2:UART3
+
+* UART3_TX 32 B16/2
+* UART3_RX 33 B17/2
+
+## F2:TWI1
+
+* TWI1_SDA 122 F6/2
+* TWI1_SCL 123 F7/2
+
+## D2:TWI2
+
+* TWI2_SDA 85 D17/2
+* TWI2_SCL 86 D18/2
+
+## D2:TWI3
+
+* TWI3_SDA 87 D19/2
+* TWI3_SCL 88 D20/2
+
+## SPI2
+
+* SPI2_CLK 52 C8/2
+* SPI2_NSS 53 C9/2
+* SPI2_MOSI 54 C10/2
+* SPI2_MISO 55 C11/2
+
+## SPI3
+
+* SPI3_CK 20 B4/2
+* SPI3_NSS 21 B5/2
+* SPI3_IO0 22 B6/2
+* SPI3_IO1 23 B7/2
+* SPI3_IO2 114 E22/2
+* SPI3_IO3 115 E23/2
+
+## F2:SD3
+
+* SD3_CMD 116 F0/2
+* SD3_CLK 117 F1/2
+* SD3_D0 118 F2/2
+* SD3_D1 119 F3/2
+* SD3_D2 120 F4/2
+* SD3_D3 121 F5/2
+
+## EINT
+
+* EINT24 102 E10/3
+* EINT25 103 E11/3
+* EINT26 104 E12/3
+* EINT27 105 E13/3
+* EINT20 89 D21/3
+* EINT21 90 D22/3
+* EINT22 100 E8/3
+* EINT23 101 E9/3
+
+## PWM
+
+* PWM_0 124 F8/2
+* PWM_1 125 F9/2
+* PWM_2 91 D23/1
+
+## Unused Pinouts (spare as GPIO) for 'Industrial with SPI-LCD'
+
+| Pin | Mux0 | Mux1 | Mux2 | Mux3 |
+| --- | ----------- | ----------- | ----------- | ----------- |
+| 16 | B GPIOB0 | B LCDCK_0 | B TWI1_SDA | B EINT6 |
+| 17 | B GPIOB1 | B LCDDE_0 | B TWI1_SCL | B EINT7 |
+| 18 | B GPIOB2 | B LCDHS_0 | B UART2_TX | B EINT8 |
+| 19 | B GPIOB3 | B LCDVS_0 | B UART2_RX | B EINT9 |
+| 24 | B GPIOB8 | B LCD4_0 | | B FB_AD12 |
+| 25 | B GPIOB9 | B LCD5_0 | B PWM_0 | B FB_AD13 |
+| 34 | B GPIOB18 | B LCD14_0 | B TWI3_SDA | B FB_AD22 |
+| 35 | B GPIOB19 | B LCD15_0 | B TWI3_SCL | B FB_AD23 |
+| 36 | B GPIOB20 | B LCD16_0 | B PWM_1 | B FB_AD24 |
+| 37 | B GPIOB21 | B LCD17_0 | B PWM_2 | B FB_AD25 |
+| 110 | E GPIOE18 | E FB_AD26 | E SPI3_CK | E MMCD2 |
+| 111 | E GPIOE19 | E FB_AD27 | E SPI3_NSS | E MMCD3 |
+| 112 | E GPIOE20 | E FB_AD28 | E SPI3_IO0 | E MMCD4 |
+| 113 | E GPIOE21 | E FB_AD29 | E SPI3_IO1 | E MMCD5 |
+| 126 | G GPIOG0 | G RG_ERXD0 | G LCDCK_1 | G FB_AD8 |
+| 127 | G GPIOG1 | G RG_ERXD1 | G LCDDE_1 | G FB_AD9 |
+| 128 | G GPIOG2 | G RG_ERXD2 | G LCDHS_1 | G FB_AD10 |
+| 129 | G GPIOG3 | G RG_ETXD0 | G LCDVS_1 | G FB_AD11 |
+| 130 | G GPIOG4 | G RG_ETXD1 | G LCD0_1 | G FB_AD12 |
+| 131 | G GPIOG5 | G RG_ETXD2 | G LCD1_1 | G FB_AD13 |
+| 132 | G GPIOG6 | G RG_FB_CS0 | G LCD2_1 | G FB_AD14 |
+| 133 | G GPIOG7 | G RG_FB_CS1 | G LCD3_1 | G FB_AD15 |
+| 134 | G GPIOG8 | G RG_ERXCK | G LCD4_1 | G FB_AD16 |
+| 135 | G GPIOG9 | G RG_ERXERR | G LCD5_1 | G FB_AD17 |
+| 136 | G GPIOG10 | G RG_ERXDV | G LCD6_1 | G FB_AD18 |
+| 137 | G GPIOG11 | G RG_EMDC | G LCD7_1 | G FB_AD19 |
+| 138 | G GPIOG12 | G RG_EMDIO | G LCD8_1 | G FB_AD20 |
+| 139 | G GPIOG13 | G RG_ETXEN | G LCD9_1 | G FB_AD21 |
+| 140 | G GPIOG14 | G RG_ETXCK | G LCD10_1 | G FB_AD22 |
+| 141 | G GPIOG15 | G RG_ECRS | G LCD11_1 | G FB_AD23 |
+| 142 | G GPIOG16 | G RG_ECOL | G LCD12_1 | G FB_AD24 |
+| 143 | G GPIOG17 | G RG_ETXERR | G LCD13_1 | G FB_AD25 |
+| 144 | G GPIOG18 | G ULPI3_CK | G LCD14_1 | G FB_AD26 |
+| 145 | G GPIOG19 | G ULPI3_DIR | G LCD15_1 | G FB_AD27 |
+| 146 | G GPIOG20 | G ULPI3_STP | G LCD16_1 | G FB_AD28 |
+| 147 | G GPIOG21 | G ULPI3_NXT | G LCD17_1 | G FB_AD29 |
+| 148 | G GPIOG22 | G ULPI3_D0 | G LCD18_1 | G FB_AD30 |
+| 149 | G GPIOG23 | G ULPI3_D1 | G LCD19_1 | G FB_AD31 |
+| 150 | G GPIOG24 | G ULPI3_D2 | G LCD20_1 | G SD2_CMD |
+| 151 | G GPIOG25 | G ULPI3_D3 | G LCD21_1 | G SD2_CLK |
+| 152 | G GPIOG26 | G ULPI3_D4 | G LCD22_1 | G SPI3_CK |
+| 153 | G GPIOG27 | G ULPI3_D5 | G LCD23_1 | G SPI3_NSS |
+| 154 | G GPIOG28 | G ULPI3_D6 | G SD2_D0 | G SPI3_IO0 |
+| 155 | G GPIOG29 | G ULPI3_D7 | G SD2_D1 | G SPI3_IO1 |
+| 156 | G GPIOG30 | | G SD2_D2 | G SPI3_IO2 |
+| 157 | G GPIOG31 | | G SD2_D3 | G SPI3_IO3 |
+
+# Pinmap for Smartphone / Tablet
+
+## B1:LCD/22
+
+RGB/TTL LCD, 800x480 or use SN75LVDS83b for up to 1440x900
+
+* LCDCK_0 16 B0/1
+* LCDDE_0 17 B1/1
+* LCDHS_0 18 B2/1
+* LCDVS_0 19 B3/1
+* LCD0_0 20 B4/1
+* LCD1_0 21 B5/1
+* LCD2_0 22 B6/1
+* LCD3_0 23 B7/1
+* LCD4_0 24 B8/1
+* LCD5_0 25 B9/1
+* LCD6_0 26 B10/1
+* LCD7_0 27 B11/1
+* LCD8_0 28 B12/1
+* LCD9_0 29 B13/1
+* LCD10_0 30 B14/1
+* LCD11_0 31 B15/1
+* LCD12_0 32 B16/1
+* LCD13_0 33 B17/1
+* LCD14_0 34 B18/1
+* LCD15_0 35 B19/1
+* LCD16_0 36 B20/1
+* LCD17_0 37 B21/1
+
+## ULPI1/8
+
+USB-OTG, connect to ULPI OTG PHY (for charging)
+as well as USB Host or USB Device
+
+* ULPI1_CK 44 C0/1
+* ULPI1_DIR 45 C1/1
+* ULPI1_STP 46 C2/1
+* ULPI1_NXT 47 C3/1
+* ULPI1_D0 48 C4/1
+* ULPI1_D1 49 C5/1
+* ULPI1_D2 50 C6/1
+* ULPI1_D3 51 C7/1
+
+## ULPI2/8
+
+USB2 Host, connect to ULPI PHY w/and 4-port USB2 Hub
+for example GL850G or FE1.1. Connects to 2/3/4G/LTE Modem, 2x USB-Camera (VC0345)
+
+* ULPI2_CK 56 C12/1
+* ULPI2_DIR 57 C13/1
+* ULPI2_STP 58 C14/1
+* ULPI2_NXT 59 C15/1
+* ULPI2_D0 60 C16/1
+* ULPI2_D1 61 C17/1
+* ULPI2_D2 62 C18/1
+* ULPI2_D3 63 C19/1
+
+## MMC
+
+eMMC: main internal storage
+
+* MMCCMD 0 A0/1
+* MMCCLK 1 A1/1
+* MMCD0 2 A2/1
+* MMCD1 3 A3/1
+* MMCD2 4 A4/1
+* MMCD3 5 A5/1
+* MMCD4 6 A6/1
+* MMCD5 7 A7/1
+* MMCD6 8 A8/1
+* MMCD7 9 A9/1
+
+## SD1
+
+internal, multiplexed with JTAG1
+and UART2, for debug purposes
+
+* SD1_CMD 10 A10/2
+* SD1_CLK 11 A11/2
+* SD1_D0 12 A12/2
+* SD1_D1 13 A13/2
+* SD1_D2 14 A14/2
+* SD1_D3 15 A15/2
+
+## F1:IIS
+
+I2C Audio, connect to AC97 Audio IC
+
+* IISMCK 116 F0/1
+* IISBCK 117 F1/1
+* IISLRCK 118 F2/1
+* IISDI 119 F3/1
+* IISDO0 120 F4/1
+* IISDO1 121 F5/1
+* IISDO2 122 F6/1
+* IISDO3 123 F7/1
+
+## TWI2
+
+Connect to AC97 Audio IC
+
+* TWI2_SDA 70 D2/3
+* TWI2_SCL 71 D3/3
+
+## E2:UART1
+
+Connect to BT on AP6234/AP6335
+
+* UART1_TX 106 E14/2
+* UART1_RX 107 E15/2
+* UART1_CTS 108 E16/2
+* UART1_RTS 109 E17/2
+
+## E2:SD2
+
+Connect to WIFI on AP6234/AP6335
+
+* SD2_CMD 92 E0/2
+* SD2_CLK 93 E1/2
+* SD2_D0 94 E2/2
+* SD2_D1 95 E3/2
+* SD2_D2 96 E4/2
+* SD2_D3 97 E5/2
+
+## C3:UART0
+
+* UART0_TX 64 C20/3
+* UART0_RX 65 C21/3
+* UART0_CTS 66 C22/3
+* UART0_RTS 67 C23/3
+
+## D2:UART3
+
+Spare? UART (or 2 extra GPIO / EINT)
+
+* UART3_TX 89 D21/2
+* UART3_RX 90 D22/2
+
+## D2:UART4
+
+Spare? UART (or 2 extra GPIO)
+
+* UART4_TX 81 D13/2
+* UART4_RX 82 D14/2
+
+## D3:TWI1
+
+Connect to PMIC
+
+* TWI1_SDA 78 D10/3
+* TWI1_SCL 79 D11/3
+
+## D2:TWI3
+
+Connect to sensors (Trackpad? CTP GSENSOR TILT COMPASS)
+
+* TWI3_SDA 87 D19/2
+* TWI3_SCL 88 D20/2
+
+## SPI2
+
+Spare? SPI, connect to higher-speed sensor?
+
+* SPI2_CLK 52 C8/2
+* SPI2_NSS 53 C9/2
+* SPI2_MOSI 54 C10/2
+* SPI2_MISO 55 C11/2
+
+## SPI3
+
+Boot Storage (connection to companion / debug / boot MCU)
+Only actually needs MISO/MOSI, bootstrap loader v. small
+Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.
+
+* SPI3_CK 110 E18/2
+* SPI3_NSS 111 E19/2
+* SPI3_IO0 112 E20/2
+* SPI3_IO1 113 E21/2
+* SPI3_IO2 114 E22/2
+* SPI3_IO3 115 E23/2
+
+## EINT
+
+* EINT24 102 E10/3 : BT_HOST_WAKE
+* EINT25 103 E11/3 : WIFI_HOST_WAKE
+* EINT26 104 E12/3 : CTP_INT
+* EINT27 105 E13/3 : GSENSOR_INT
+* EINT8 84 D16/3 : GPS_INT
+* EINT7 83 D15/3 : TILT_SENSOR_INT
+* EINT22 100 E8/3 : COMPASS_INT
+* EINT23 101 E9/3 : MCU_INT
+* EINT16 98 E6/3 : PMIC_INT
+* EINT17 99 E7/3 : PWR_BUTTON_INT
+* EINT30 68 D0/3 : OTG_ID
+* EINT31 69 D1/3 : Spare?
+
+## PWM
+
+* PWM_0 124 F8/2 : LCD Backlight
+* PWM_1 125 F9/2 : Spare? PWM (or extra GPIO / EINT)
+* PWM_2 91 D23/1 : Spare? PWM (or extra GPIO / EINT)
+
+## Unused Pinouts (spare as GPIO) for 'Smartphone / Tablet'
+
+9 spare GPIO pins for miscellaneous functions:
+wake-up of BT, WIFI, LCD power, sensor power etc.
+4 GPIO may be needed for PWM Audio from Modem.
+LED lights for camera will be needed.
+Some phones may have clam-shell or lid switch.
+Some Modems have spare GPIO (over AT commandset).
+AXP209 PMIC has 4x GPIO, accessible over I2C.
+SPI2, UART3-4, PWM1-2 may also be spare (10 extra GPIO).
+If more needed, companion MCU may be used (48+ pin variant)
+which also includes ADC, DAC, more PWM etc.
+
+| Pin | Mux0 | Mux1 | Mux2 | Mux3 |
+| --- | ----------- | ----------- | ----------- | ----------- |
+| 38 | B GPIOB22 | B LCD18_0 | B SD1_CMD | B FB_AD26 |
+| 39 | B GPIOB23 | B LCD19_0 | B SD1_CLK | B FB_AD27 |
+| 40 | B GPIOB24 | B LCD20_0 | B SD1_D0 | B FB_AD28 |
+| 41 | B GPIOB25 | B LCD21_0 | B SD1_D1 | B FB_AD29 |
+| 42 | B GPIOB26 | B LCD22_0 | B SD1_D2 | B FB_AD30 |
+| 43 | B GPIOB27 | B LCD23_0 | B SD1_D3 | B FB_AD31 |
+| 72 | D GPIOD4 | D FB_AD4 | D SD2_CMD | |
+| 73 | D GPIOD5 | D FB_AD5 | D SD2_CLK | |
+| 74 | D GPIOD6 | D FB_AD6 | D SD2_D0 | |
+| 75 | D GPIOD7 | D FB_AD7 | D SD2_D1 | |
+| 76 | D GPIOD8 | D FB_CS0 | D SD2_D2 | |
+| 77 | D GPIOD9 | D FB_CS1 | D SD2_D3 | |
+| 80 | D GPIOD12 | D FB_RW | | |
+| 85 | D GPIOD17 | D FB_BWE2 | D TWI2_SDA | D FB_A0 |
+| 86 | D GPIOD18 | D FB_BWE3 | D TWI2_SCL | D FB_A1 |
+| 126 | G GPIOG0 | G RG_ERXD0 | G LCDCK_1 | G FB_AD8 |
+| 127 | G GPIOG1 | G RG_ERXD1 | G LCDDE_1 | G FB_AD9 |
+| 128 | G GPIOG2 | G RG_ERXD2 | G LCDHS_1 | G FB_AD10 |
+| 129 | G GPIOG3 | G RG_ETXD0 | G LCDVS_1 | G FB_AD11 |
+| 130 | G GPIOG4 | G RG_ETXD1 | G LCD0_1 | G FB_AD12 |
+| 131 | G GPIOG5 | G RG_ETXD2 | G LCD1_1 | G FB_AD13 |
+| 132 | G GPIOG6 | G RG_FB_CS0 | G LCD2_1 | G FB_AD14 |
+| 133 | G GPIOG7 | G RG_FB_CS1 | G LCD3_1 | G FB_AD15 |
+| 134 | G GPIOG8 | G RG_ERXCK | G LCD4_1 | G FB_AD16 |
+| 135 | G GPIOG9 | G RG_ERXERR | G LCD5_1 | G FB_AD17 |
+| 136 | G GPIOG10 | G RG_ERXDV | G LCD6_1 | G FB_AD18 |
+| 137 | G GPIOG11 | G RG_EMDC | G LCD7_1 | G FB_AD19 |
+| 138 | G GPIOG12 | G RG_EMDIO | G LCD8_1 | G FB_AD20 |
+| 139 | G GPIOG13 | G RG_ETXEN | G LCD9_1 | G FB_AD21 |
+| 140 | G GPIOG14 | G RG_ETXCK | G LCD10_1 | G FB_AD22 |
+| 141 | G GPIOG15 | G RG_ECRS | G LCD11_1 | G FB_AD23 |
+| 142 | G GPIOG16 | G RG_ECOL | G LCD12_1 | G FB_AD24 |
+| 143 | G GPIOG17 | G RG_ETXERR | G LCD13_1 | G FB_AD25 |
+| 144 | G GPIOG18 | G ULPI3_CK | G LCD14_1 | G FB_AD26 |
+| 145 | G GPIOG19 | G ULPI3_DIR | G LCD15_1 | G FB_AD27 |
+| 146 | G GPIOG20 | G ULPI3_STP | G LCD16_1 | G FB_AD28 |
+| 147 | G GPIOG21 | G ULPI3_NXT | G LCD17_1 | G FB_AD29 |
+| 148 | G GPIOG22 | G ULPI3_D0 | G LCD18_1 | G FB_AD30 |
+| 149 | G GPIOG23 | G ULPI3_D1 | G LCD19_1 | G FB_AD31 |
+| 150 | G GPIOG24 | G ULPI3_D2 | G LCD20_1 | G SD2_CMD |
+| 151 | G GPIOG25 | G ULPI3_D3 | G LCD21_1 | G SD2_CLK |
+| 152 | G GPIOG26 | G ULPI3_D4 | G LCD22_1 | G SPI3_CK |
+| 153 | G GPIOG27 | G ULPI3_D5 | G LCD23_1 | G SPI3_NSS |
+| 154 | G GPIOG28 | G ULPI3_D6 | G SD2_D0 | G SPI3_IO0 |
+| 155 | G GPIOG29 | G ULPI3_D7 | G SD2_D1 | G SPI3_IO1 |
+| 156 | G GPIOG30 | | G SD2_D2 | G SPI3_IO2 |
+| 157 | G GPIOG31 | | G SD2_D3 | G SPI3_IO3 |
+
+# Pinmap for Laptop / Netbook
+
+## D1:FB/17
+
+FlexBus. Connect to DM9000 or AX99896A MCU-style Bus
+10/100 Ethernet PHY.
+
+* FB_AD0 68 D0/1
+* FB_AD1 69 D1/1
+* FB_AD2 70 D2/1
+* FB_AD3 71 D3/1
+* FB_AD4 72 D4/1
+* FB_AD5 73 D5/1
+* FB_AD6 74 D6/1
+* FB_AD7 75 D7/1
+* FB_CS0 76 D8/1
+* FB_CS1 77 D9/1
+* FB_ALE 78 D10/1
+* FB_OE 79 D11/1
+* FB_RW 80 D12/1
+* FB_TA 81 D13/1
+* FB_CLK 82 D14/1
+* FB_BWE0 83 D15/1
+* FB_BWE1 84 D16/1
+
+## E1:FB/8
+
+FlexBus bus bits 8-15, needed to make a 16-bit bus width
+
+* FB_AD8 92 E0/1
+* FB_AD9 93 E1/1
+* FB_AD10 94 E2/1
+* FB_AD11 95 E3/1
+* FB_AD12 96 E4/1
+* FB_AD13 97 E5/1
+* FB_AD14 98 E6/1
+* FB_AD15 99 E7/1
+
+## B1:LCD/22
+
+RGB/TTL LCD, use SN75LVDS83b for LVDS or SSD2828 for MIPI,
+or a Chrontel CH7039, CH7038, CH7034 or CH7018 for dual
+display output (eDP/LVDS and HDMI/VGA) conversion.
+
+* LCDCK_0 16 B0/1
+* LCDDE_0 17 B1/1
+* LCDHS_0 18 B2/1
+* LCDVS_0 19 B3/1
+* LCD0_0 20 B4/1
+* LCD1_0 21 B5/1
+* LCD2_0 22 B6/1
+* LCD3_0 23 B7/1
+* LCD4_0 24 B8/1
+* LCD5_0 25 B9/1
+* LCD6_0 26 B10/1
+* LCD7_0 27 B11/1
+* LCD8_0 28 B12/1
+* LCD9_0 29 B13/1
+* LCD10_0 30 B14/1
+* LCD11_0 31 B15/1
+* LCD12_0 32 B16/1
+* LCD13_0 33 B17/1
+* LCD14_0 34 B18/1
+* LCD15_0 35 B19/1
+* LCD16_0 36 B20/1
+* LCD17_0 37 B21/1
+
+## ULPI1/8
+
+USB-OTG, connect to ULPI OTG PHY (for charging)
+as well as USB Host or USB Device
+
+* ULPI1_CK 44 C0/1
+* ULPI1_DIR 45 C1/1
+* ULPI1_STP 46 C2/1
+* ULPI1_NXT 47 C3/1
+* ULPI1_D0 48 C4/1
+* ULPI1_D1 49 C5/1
+* ULPI1_D2 50 C6/1
+* ULPI1_D3 51 C7/1
+
+## ULPI2/8
+
+USB2 Host, connect to ULPI PHY w/and 4-port USB2 Hub
+for example GL850G or FE1.1. Connects to USB-Camera (VC0345 and 3x external USB Ports)
+
+* ULPI2_CK 56 C12/1
+* ULPI2_DIR 57 C13/1
+* ULPI2_STP 58 C14/1
+* ULPI2_NXT 59 C15/1
+* ULPI2_D0 60 C16/1
+* ULPI2_D1 61 C17/1
+* ULPI2_D2 62 C18/1
+* ULPI2_D3 63 C19/1
+
+## MMC
+
+eMMC: main internal storage
+
+* MMCCMD 0 A0/1
+* MMCCLK 1 A1/1
+* MMCD0 2 A2/1
+* MMCD1 3 A3/1
+* MMCD2 4 A4/1
+* MMCD3 5 A5/1
+* MMCD4 6 A6/1
+* MMCD5 7 A7/1
+* MMCD6 8 A8/1
+* MMCD7 9 A9/1
+
+## SD1
+
+internal, multiplexed with JTAG1
+and UART2, for debug purposes
+
+* SD1_CMD 10 A10/2
+* SD1_CLK 11 A11/2
+* SD1_D0 12 A12/2
+* SD1_D1 13 A13/2
+* SD1_D2 14 A14/2
+* SD1_D3 15 A15/2
+
+## F1:IIS
+
+I2C Audio, connect to AC97 Audio IC
+
+* IISMCK 116 F0/1
+* IISBCK 117 F1/1
+* IISLRCK 118 F2/1
+* IISDI 119 F3/1
+* IISDO0 120 F4/1
+* IISDO1 121 F5/1
+* IISDO2 122 F6/1
+* IISDO3 123 F7/1
+
+## TWI2
+
+Connect to AC97 Audio IC
+
+* TWI2_SDA 85 D17/2
+* TWI2_SCL 86 D18/2
+
+## E2:UART1
+
+Connect to BT on AP6234/AP6335
+
+* UART1_TX 106 E14/2
+* UART1_RX 107 E15/2
+* UART1_CTS 108 E16/2
+* UART1_RTS 109 E17/2
+
+## E2:SD3
+
+Connect to WIFI on AP6234/AP6335
+
+* SD3_CMD 100 E8/2
+* SD3_CLK 101 E9/2
+* SD3_D0 102 E10/2
+* SD3_D1 103 E11/2
+* SD3_D2 104 E12/2
+* SD3_D3 105 E13/2
+
+## D2:TWI3
+
+Connect to PMIC
+
+* TWI3_SDA 87 D19/2
+* TWI3_SCL 88 D20/2
+
+## SPI3
+
+Boot Storage (connection to companion / debug / boot MCU)
+Only actually needs MISO/MOSI, bootstrap loader v. small
+Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.
+MCU implements keyboard-matrix for keyboard (also trackpad?)
+
+* SPI3_CK 110 E18/2
+* SPI3_NSS 111 E19/2
+* SPI3_IO0 112 E20/2
+* SPI3_IO1 113 E21/2
+* SPI3_IO2 114 E22/2
+* SPI3_IO3 115 E23/2
+
+## EINT
+
+* EINT20 89 D21/3 : BT_HOST_WAKE
+* EINT21 90 D22/3 : WIFI_HOST_WAKE
+* EINT9 91 D23/3 : MCU_INT
+* EINT31 125 F9/3 : PMIC_INT
+
+## PWM
+
+* PWM_0 124 F8/2 : LCD Backlight
+
+## Unused Pinouts (spare as GPIO) for 'Laptop / Netbook'
+
+Plenty of spare GPIO pins for miscellaneous functions
+MCU EINT-capable GPIO may be used to generate extra EINTs
+on the single MCU_INT line, if really needed
+
+| Pin | Mux0 | Mux1 | Mux2 | Mux3 |
+| --- | ----------- | ----------- | ----------- | ----------- |
+| 38 | B GPIOB22 | B LCD18_0 | B SD1_CMD | B FB_AD26 |
+| 39 | B GPIOB23 | B LCD19_0 | B SD1_CLK | B FB_AD27 |
+| 40 | B GPIOB24 | B LCD20_0 | B SD1_D0 | B FB_AD28 |
+| 41 | B GPIOB25 | B LCD21_0 | B SD1_D1 | B FB_AD29 |
+| 42 | B GPIOB26 | B LCD22_0 | B SD1_D2 | B FB_AD30 |
+| 43 | B GPIOB27 | B LCD23_0 | B SD1_D3 | B FB_AD31 |
+| 52 | C GPIOC8 | C ULPI1_D4 | C SPI2_CLK | C JTAG2_MS |
+| 53 | C GPIOC9 | C ULPI1_D5 | C SPI2_NSS | C JTAG2_DI |
+| 54 | C GPIOC10 | C ULPI1_D6 | C SPI2_MOSI | C JTAG2_DO |
+| 55 | C GPIOC11 | C ULPI1_D7 | C SPI2_MISO | C JTAG2_CK |
+| 64 | C GPIOC20 | C ULPI2_D4 | C IISDO3 | C UART0_TX |
+| 65 | C GPIOC21 | C ULPI2_D5 | C PWM_2 | C UART0_RX |
+| 66 | C GPIOC22 | C ULPI2_D6 | C UART2_TX | C UART0_CTS |
+| 67 | C GPIOC23 | C ULPI2_D7 | C UART2_RX | C UART0_RTS |
+| 126 | G GPIOG0 | G RG_ERXD0 | G LCDCK_1 | G FB_AD8 |
+| 127 | G GPIOG1 | G RG_ERXD1 | G LCDDE_1 | G FB_AD9 |
+| 128 | G GPIOG2 | G RG_ERXD2 | G LCDHS_1 | G FB_AD10 |
+| 129 | G GPIOG3 | G RG_ETXD0 | G LCDVS_1 | G FB_AD11 |
+| 130 | G GPIOG4 | G RG_ETXD1 | G LCD0_1 | G FB_AD12 |
+| 131 | G GPIOG5 | G RG_ETXD2 | G LCD1_1 | G FB_AD13 |
+| 132 | G GPIOG6 | G RG_FB_CS0 | G LCD2_1 | G FB_AD14 |
+| 133 | G GPIOG7 | G RG_FB_CS1 | G LCD3_1 | G FB_AD15 |
+| 134 | G GPIOG8 | G RG_ERXCK | G LCD4_1 | G FB_AD16 |
+| 135 | G GPIOG9 | G RG_ERXERR | G LCD5_1 | G FB_AD17 |
+| 136 | G GPIOG10 | G RG_ERXDV | G LCD6_1 | G FB_AD18 |
+| 137 | G GPIOG11 | G RG_EMDC | G LCD7_1 | G FB_AD19 |
+| 138 | G GPIOG12 | G RG_EMDIO | G LCD8_1 | G FB_AD20 |
+| 139 | G GPIOG13 | G RG_ETXEN | G LCD9_1 | G FB_AD21 |
+| 140 | G GPIOG14 | G RG_ETXCK | G LCD10_1 | G FB_AD22 |
+| 141 | G GPIOG15 | G RG_ECRS | G LCD11_1 | G FB_AD23 |
+| 142 | G GPIOG16 | G RG_ECOL | G LCD12_1 | G FB_AD24 |
+| 143 | G GPIOG17 | G RG_ETXERR | G LCD13_1 | G FB_AD25 |
+| 144 | G GPIOG18 | G ULPI3_CK | G LCD14_1 | G FB_AD26 |
+| 145 | G GPIOG19 | G ULPI3_DIR | G LCD15_1 | G FB_AD27 |
+| 146 | G GPIOG20 | G ULPI3_STP | G LCD16_1 | G FB_AD28 |
+| 147 | G GPIOG21 | G ULPI3_NXT | G LCD17_1 | G FB_AD29 |
+| 148 | G GPIOG22 | G ULPI3_D0 | G LCD18_1 | G FB_AD30 |
+| 149 | G GPIOG23 | G ULPI3_D1 | G LCD19_1 | G FB_AD31 |
+| 150 | G GPIOG24 | G ULPI3_D2 | G LCD20_1 | G SD2_CMD |
+| 151 | G GPIOG25 | G ULPI3_D3 | G LCD21_1 | G SD2_CLK |
+| 152 | G GPIOG26 | G ULPI3_D4 | G LCD22_1 | G SPI3_CK |
+| 153 | G GPIOG27 | G ULPI3_D5 | G LCD23_1 | G SPI3_NSS |
+| 154 | G GPIOG28 | G ULPI3_D6 | G SD2_D0 | G SPI3_IO0 |
+| 155 | G GPIOG29 | G ULPI3_D7 | G SD2_D1 | G SPI3_IO1 |
+| 156 | G GPIOG30 | | G SD2_D2 | G SPI3_IO2 |
+| 157 | G GPIOG31 | | G SD2_D3 | G SPI3_IO3 |
+
+# Pinmap for IoT
+
+## B1:LCD
+
+RGB/TTL LCD, use SN75LVDS83b for LVDS or SSD2828 for MIPI,
+or a Chrontel CH7039, CH7038, CH7034 or CH7018 for dual
+display output (eDP/LVDS and HDMI/VGA) conversion.
+
+* LCDCK_0 16 B0/1
+* LCDDE_0 17 B1/1
+* LCDHS_0 18 B2/1
+* LCDVS_0 19 B3/1
+* LCD0_0 20 B4/1
+* LCD1_0 21 B5/1
+* LCD2_0 22 B6/1
+* LCD3_0 23 B7/1
+* LCD4_0 24 B8/1
+* LCD5_0 25 B9/1
+* LCD6_0 26 B10/1
+* LCD7_0 27 B11/1
+* LCD8_0 28 B12/1
+* LCD9_0 29 B13/1
+* LCD10_0 30 B14/1
+* LCD11_0 31 B15/1
+* LCD12_0 32 B16/1
+* LCD13_0 33 B17/1
+* LCD14_0 34 B18/1
+* LCD15_0 35 B19/1
+* LCD16_0 36 B20/1
+* LCD17_0 37 B21/1
+* LCD18_0 38 B22/1
+* LCD19_0 39 B23/1
+* LCD20_0 40 B24/1
+* LCD21_0 41 B25/1
+* LCD22_0 42 B26/1
+* LCD23_0 43 B27/1
+
+## ULPI2/8
+
+USB-OTG, connect to ULPI OTG PHY (for charging)
+as well as USB Host or USB Device
+
+* ULPI2_CK 56 C12/1
+* ULPI2_DIR 57 C13/1
+* ULPI2_STP 58 C14/1
+* ULPI2_NXT 59 C15/1
+* ULPI2_D0 60 C16/1
+* ULPI2_D1 61 C17/1
+* ULPI2_D2 62 C18/1
+* ULPI2_D3 63 C19/1
+
+## ULPI1/8
+
+USB2 Host, connect to ULPI PHY
+
+* ULPI1_CK 44 C0/1
+* ULPI1_DIR 45 C1/1
+* ULPI1_STP 46 C2/1
+* ULPI1_NXT 47 C3/1
+* ULPI1_D0 48 C4/1
+* ULPI1_D1 49 C5/1
+* ULPI1_D2 50 C6/1
+* ULPI1_D3 51 C7/1
+
+## MMC
+
+eMMC: main internal storage
+
+* MMCCMD 0 A0/1
+* MMCCLK 1 A1/1
+* MMCD0 2 A2/1
+* MMCD1 3 A3/1
+* MMCD2 4 A4/1
+* MMCD3 5 A5/1
+* MMCD4 6 A6/1
+* MMCD5 7 A7/1
+* MMCD6 8 A8/1
+* MMCD7 9 A9/1
+
+## SD1
+
+internal, multiplexed with JTAG1
+and UART2, for debug purposes
+
+* SD1_CMD 10 A10/2
+* SD1_CLK 11 A11/2
+* SD1_D0 12 A12/2
+* SD1_D1 13 A13/2
+* SD1_D2 14 A14/2
+* SD1_D3 15 A15/2
+
+## F1:IIS
+
+I2C Audio, connect to AC97 Audio IC
+
+* IISMCK 116 F0/1
+* IISBCK 117 F1/1
+* IISLRCK 118 F2/1
+* IISDI 119 F3/1
+* IISDO0 120 F4/1
+* IISDO1 121 F5/1
+* IISDO2 122 F6/1
+* IISDO3 123 F7/1
+
+## C3:UART0
+
+Connect to HSPA UART
+
+* UART0_TX 64 C20/3
+* UART0_RX 65 C21/3
+* UART0_CTS 66 C22/3
+* UART0_RTS 67 C23/3
+
+## E2:UART1
+
+Connect to BT UART
+
+* UART1_TX 106 E14/2
+* UART1_RX 107 E15/2
+* UART1_CTS 108 E16/2
+* UART1_RTS 109 E17/2
+
+## C2:SPI2
+
+HSPA SPI
+
+* SPI2_CLK 52 C8/2
+* SPI2_NSS 53 C9/2
+* SPI2_MOSI 54 C10/2
+* SPI2_MISO 55 C11/2
+
+## E2:SD3
+
+Connect to WIFI
+
+* SD3_CMD 100 E8/2
+* SD3_CLK 101 E9/2
+* SD3_D0 102 E10/2
+* SD3_D1 103 E11/2
+* SD3_D2 104 E12/2
+* SD3_D3 105 E13/2
+
+## D3:TWI1
+
+Connect to sensors CTP
+
+* TWI1_SDA 78 D10/3
+* TWI1_SCL 79 D11/3
+
+## D2:TWI3
+
+Connect to PMIC
+
+* TWI3_SDA 87 D19/2
+* TWI3_SCL 88 D20/2
+
+## SPI3
+
+Boot Storage (connection to companion / debug / boot MCU)
+Only actually needs MISO/MOSI, bootstrap loader v. small
+Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.
+MCU implements keyboard-matrix for keyboard (also trackpad?)
+
+* SPI3_CK 110 E18/2
+* SPI3_NSS 111 E19/2
+* SPI3_IO0 112 E20/2
+* SPI3_IO1 113 E21/2
+* SPI3_IO2 114 E22/2
+* SPI3_IO3 115 E23/2
+
+## GPIO
+
+* GPIOD12 80 D12 : LCD_RDN
+* GPIOD17 85 D17 : LCD_WRN
+* GPIOD18 86 D18 : LCD_RS
+* GPIOD2 70 D2 : HSPA_SHUTDOWN
+* GPIOD21 89 D21 : LCD_CSN
+* GPIOD3 71 D3 : CTP_RST
+* GPIOD4 72 D4 : WL_WAKE_AP
+* GPIOD5 73 D5 : BT_WAKE_AP
+* GPIOD6 74 D6 : AP_WAKE_BT
+* GPIOD7 75 D7 : AP_CK32KO
+* GPIOD8 76 D8 : HSPA_PWRON
+* GPIOD9 77 D9 : BT_RST_N
+* GPIOE5 97 E5 : HSPA_ON_OFF
+
+## EINT
+
+* EINT5 81 D13/3 : HSPA_MST_RDY
+* EINT6 82 D14/3 : HSPA_SL_RDY
+* EINT7 83 D15/3 : HSPA_RING
+* EINT8 84 D16/3 : WL_PMU_EN
+* EINT9 91 D23/3 : HSPA_GPIO1
+* EINT10 92 E0/3 : IR_DT
+* EINT11 93 E1/3 : BT_PCM_CLK
+* EINT12 94 E2/3 : BT_PCM_DIN
+* EINT13 95 E3/3 : BT_PCM_SYNC
+* EINT14 96 E4/3 : BT_PCM_DOUT
+* EINT16 98 E6/3 : USB_DRVVBUS
+* EINT17 99 E7/3 : USB_VBUSDET
+* EINT21 90 D22/3 : USB_ID
+* EINT30 68 D0/3 : CTP_INT
+* EINT31 69 D1/3 : SD_DETN
+
+## PWM
+
+* PWM_0 124 F8/2 : LCD Backlight
+
+## Unused Pinouts (spare as GPIO) for 'IoT'
+
+Plenty of spare GPIO pins for miscellaneous functions
+MCU EINT-capable GPIO may be used to generate extra EINTs
+on the single MCU_INT line, if really needed
+
+| Pin | Mux0 | Mux1 | Mux2 | Mux3 |
+| --- | ----------- | ----------- | ----------- | ----------- |
+| 125 | F GPIOF9 | F UART4_RX | F PWM_1 | F EINT31 |
+| 126 | G GPIOG0 | G RG_ERXD0 | G LCDCK_1 | G FB_AD8 |
+| 127 | G GPIOG1 | G RG_ERXD1 | G LCDDE_1 | G FB_AD9 |
+| 128 | G GPIOG2 | G RG_ERXD2 | G LCDHS_1 | G FB_AD10 |
+| 129 | G GPIOG3 | G RG_ETXD0 | G LCDVS_1 | G FB_AD11 |
+| 130 | G GPIOG4 | G RG_ETXD1 | G LCD0_1 | G FB_AD12 |
+| 131 | G GPIOG5 | G RG_ETXD2 | G LCD1_1 | G FB_AD13 |
+| 132 | G GPIOG6 | G RG_FB_CS0 | G LCD2_1 | G FB_AD14 |
+| 133 | G GPIOG7 | G RG_FB_CS1 | G LCD3_1 | G FB_AD15 |
+| 134 | G GPIOG8 | G RG_ERXCK | G LCD4_1 | G FB_AD16 |
+| 135 | G GPIOG9 | G RG_ERXERR | G LCD5_1 | G FB_AD17 |
+| 136 | G GPIOG10 | G RG_ERXDV | G LCD6_1 | G FB_AD18 |
+| 137 | G GPIOG11 | G RG_EMDC | G LCD7_1 | G FB_AD19 |
+| 138 | G GPIOG12 | G RG_EMDIO | G LCD8_1 | G FB_AD20 |
+| 139 | G GPIOG13 | G RG_ETXEN | G LCD9_1 | G FB_AD21 |
+| 140 | G GPIOG14 | G RG_ETXCK | G LCD10_1 | G FB_AD22 |
+| 141 | G GPIOG15 | G RG_ECRS | G LCD11_1 | G FB_AD23 |
+| 142 | G GPIOG16 | G RG_ECOL | G LCD12_1 | G FB_AD24 |
+| 143 | G GPIOG17 | G RG_ETXERR | G LCD13_1 | G FB_AD25 |
+| 144 | G GPIOG18 | G ULPI3_CK | G LCD14_1 | G FB_AD26 |
+| 145 | G GPIOG19 | G ULPI3_DIR | G LCD15_1 | G FB_AD27 |
+| 146 | G GPIOG20 | G ULPI3_STP | G LCD16_1 | G FB_AD28 |
+| 147 | G GPIOG21 | G ULPI3_NXT | G LCD17_1 | G FB_AD29 |
+| 148 | G GPIOG22 | G ULPI3_D0 | G LCD18_1 | G FB_AD30 |
+| 149 | G GPIOG23 | G ULPI3_D1 | G LCD19_1 | G FB_AD31 |
+| 150 | G GPIOG24 | G ULPI3_D2 | G LCD20_1 | G SD2_CMD |
+| 151 | G GPIOG25 | G ULPI3_D3 | G LCD21_1 | G SD2_CLK |
+| 152 | G GPIOG26 | G ULPI3_D4 | G LCD22_1 | G SPI3_CK |
+| 153 | G GPIOG27 | G ULPI3_D5 | G LCD23_1 | G SPI3_NSS |
+| 154 | G GPIOG28 | G ULPI3_D6 | G SD2_D0 | G SPI3_IO0 |
+| 155 | G GPIOG29 | G ULPI3_D7 | G SD2_D1 | G SPI3_IO1 |
+| 156 | G GPIOG30 | | G SD2_D2 | G SPI3_IO2 |
+| 157 | G GPIOG31 | | G SD2_D3 | G SPI3_IO3 |
+
+# Reference Datasheets
+
+datasheets and pinout links
+
+* <http://datasheets.chipdb.org/AMD/8018x/80186/amd-80186.pdf>
+* <http://hands.com/~lkcl/eoma/shenzen/frida/FRD144A2701.pdf>
+* <http://pinouts.ru/Memory/sdcard_pinout.shtml>
+* p8 <http://www.onfi.org/~/media/onfi/specs/onfi_2_0_gold.pdf?la=en>
+* <https://www.heyrick.co.uk/blog/files/datasheets/dm9000aep.pdf>
+* <http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4393.pdf>
+* <https://www.nxp.com/docs/en/data-sheet/MCF54418.pdf>
+* ULPI OTG PHY, ST <http://www.st.com/en/interfaces-and-transceivers/stulpi01a.html>
+* ULPI OTG PHY, TI TUSB1210 <http://ti.com/product/TUSB1210/>
--- /dev/null
+#!/usr/bin/env python
+
+from copy import deepcopy
+
+def pins(pingroup, bankspec, suffix, offs, bank, mux, spec=None, limit=None):
+ res = {}
+ names = {}
+ idx = 0
+ for name in pingroup[:limit]:
+ if suffix:
+ name_ = "%s_%s" % (name, suffix)
+ else:
+ name_ = name
+ if spec and spec.has_key(name):
+ continue
+ pin = {mux: (name_, bank)}
+ offs_bank, offs_ = offs
+ idx_ = offs_ + idx
+ idx += 1
+ idx_ += bankspec[bank]
+ res[idx_] = pin
+ names[name] = idx_
+ for name in pingroup:
+ if suffix:
+ name_ = "%s_%s" % (name, suffix)
+ else:
+ name_ = name
+ if not spec:
+ continue
+ if not spec.has_key(name):
+ continue
+ idx_, mux_, bank_ = spec[name]
+ idx_ = names[idx_]
+ #idx_ += bankspec[bank_]
+ pin = {mux_: (name_, bank_)}
+ if res.has_key(idx_):
+ res[idx_].update(pin)
+ else:
+ res[idx_] = pin
+ return res
+
+def i2s(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
+ i2spins = ['IISMCK', 'IISBCK', 'IISLRCK', 'IISDI']
+ for i in range(4):
+ i2spins.append("IISDO%d" % i)
+ return pins(i2spins, bankspec, suffix, offs, bank, mux, spec, limit)
+
+def emmc(bankspec, suffix, offs, bank, mux=1, spec=None):
+ emmcpins = ['MMCCMD', 'MMCCLK']
+ for i in range(8):
+ emmcpins.append("MMCD%d" % i)
+ return pins(emmcpins, bankspec, suffix, offs, bank, mux, spec)
+
+def sdmmc(bankspec, suffix, offs, bank, mux=1, spec=None,
+ start=None, limit=None):
+ sdmmcpins = ['CMD', 'CLK']
+ for i in range(4):
+ sdmmcpins.append("D%d" % i)
+ print sdmmcpins, start, limit
+ sdmmcpins = sdmmcpins[start:limit]
+ sdmmcpins = namesuffix('SD', suffix, sdmmcpins)
+ return pins(sdmmcpins, bankspec, '', offs, bank, mux, spec)
+
+def spi(bankspec, suffix, offs, bank, mux=1, spec=None):
+ spipins = namesuffix('SPI', suffix,
+ ['CLK', 'NSS', 'MOSI', 'MISO', 'NSS'])
+ return pins(spipins, bankspec, '', offs, bank, mux, spec)
+
+def quadspi(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
+ spipins = namesuffix('SPI', suffix,
+ ['CK', 'NSS', 'IO0', 'IO1', 'IO2', 'IO3'])
+ return pins(spipins, bankspec, '', offs, bank, mux, spec, limit)
+
+def i2c(bankspec, suffix, offs, bank, mux=1, spec=None):
+ spipins = namesuffix('TWI', suffix,
+ ['SDA', 'SCL'])
+ return pins(spipins, bankspec, '', offs, bank, mux, spec)
+
+def jtag(bankspec, suffix, offs, bank, mux=1, spec=None):
+ uartpins = namesuffix('JTAG', suffix, ['MS', 'DI', 'DO', 'CK'])
+ return pins(uartpins, bankspec, '', offs, bank, mux, spec)
+
+def uart(bankspec, suffix, offs, bank, mux=1, spec=None):
+ uartpins = namesuffix('UART', suffix, ['TX', 'RX'])
+ return pins(uartpins, bankspec, '', offs, bank, mux, spec)
+
+def namesuffix(name, suffix, namelist):
+ names = []
+ for n in namelist:
+ names.append("%s%s_%s" % (name, suffix, n))
+ return names
+
+def ulpi(bankspec, suffix, offs, bank, mux=1, spec=None):
+ ulpipins = namesuffix('ULPI', suffix, ['CK', 'DIR', 'STP', 'NXT'])
+ for i in range(8):
+ ulpipins.append('ULPI%s_D%d' % (suffix, i))
+ return pins(ulpipins, bankspec, "", offs, bank, mux, spec)
+
+def uartfull(bankspec, suffix, offs, bank, mux=1, spec=None):
+ uartpins = namesuffix('UART', suffix, ['TX', 'RX', 'CTS', 'RTS'])
+ return pins(uartpins, bankspec, '', offs, bank, mux, spec)
+
+def rgbttl(bankspec, suffix, offs, bank, mux=1, spec=None):
+ ttlpins = ['LCDCK', 'LCDDE', 'LCDHS', 'LCDVS']
+ for i in range(24):
+ ttlpins.append("LCD%d" % i)
+ return pins(ttlpins, bankspec, suffix, offs, bank, mux, spec)
+
+def rgmii(bankspec, suffix, offs, bank, mux=1, spec=None):
+ buspins = []
+ for i in range(3):
+ buspins.append("RG_ERXD%d" % i)
+ for i in range(3):
+ buspins.append("RG_ETXD%d" % i)
+ for i in range(2):
+ buspins.append("RG_FB_CS%d" % i)
+ buspins += ['RG_ERXCK', 'RG_ERXERR', 'RG_ERXDV',
+ 'RG_EMDC', 'RG_EMDIO',
+ 'RG_ETXEN', 'RG_ETXCK', 'RG_ECRS',
+ 'RG_ECOL', 'RG_ETXERR']
+ return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
+
+def flexbus1(bankspec, suffix, offs, bank, mux=1, spec=None):
+ buspins = []
+ for i in range(8):
+ buspins.append("FB_AD%d" % i)
+ for i in range(2):
+ buspins.append("FB_CS%d" % i)
+ buspins += ['FB_ALE', 'FB_OE', 'FB_RW', 'FB_TA', 'FB_CLK',
+ 'FB_A0', 'FB_A1', 'FB_TS', 'FB_TBST',
+ 'FB_TSIZ0', 'FB_TSIZ1']
+ for i in range(4):
+ buspins.append("FB_BWE%d" % i)
+ for i in range(2,6):
+ buspins.append("FB_CS%d" % i)
+ return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
+
+def flexbus2(bankspec, suffix, offs, bank, mux=1, spec=None):
+ buspins = []
+ for i in range(8,32):
+ buspins.append("FB_AD%d" % i)
+ return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
+
+def mcu8080(bankspec, suffix, offs, bank, mux=1, spec=None):
+ buspins = []
+ for i in range(8):
+ buspins.append("MCUD%d" % i)
+ for i in range(8):
+ buspins.append("MCUAD%d" % (i+8))
+ for i in range(6):
+ buspins.append("MCUCS%d" % i)
+ for i in range(2):
+ buspins.append("MCUNRB%d" % i)
+ buspins += ['MCUCD', 'MCURD', 'MCUWR', 'MCUCLE', 'MCUALE',
+ 'MCURST']
+ return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
+
+def _pinbank(bankspec, prefix, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
+ gpiopins = []
+ for i in range(gpiooffs, gpiooffs+gpionum):
+ gpiopins.append("%s%s%d" % (prefix, bank, i))
+ return pins(gpiopins, bankspec, suffix, offs, bank, mux, spec)
+
+def eint(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
+ gpiopins = []
+ for i in range(gpiooffs, gpiooffs+gpionum):
+ gpiopins.append("EINT%d" % (i))
+ return pins(gpiopins, bankspec, suffix, offs, bank, mux, spec)
+
+def pwm(bankspec, suffix, offs, bank, mux=1, spec=None):
+ return pins(['PWM', ], bankspec, suffix, offs, bank, mux, spec)
+
+def gpio(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
+ return _pinbank(bankspec, "GPIO", suffix, offs, bank, gpiooffs,
+ gpionum, mux=0, spec=None)
+
+def display(pins):
+ print "| Pin | Mux0 | Mux1 | Mux2 | Mux3 |"
+ print "| --- | ----------- | ----------- | ----------- | ----------- |"
+ pinidx = pins.keys()
+ pinidx.sort()
+ for pin in pinidx:
+ pdata = pins[pin]
+ res = '| %3d |' % pin
+ for mux in range(4):
+ if not pdata.has_key(mux):
+ res += " |"
+ continue
+ name, bank = pdata[mux]
+ res += " %s %-9s |" % (bank, name)
+ print res
+
+def fnsplit(f):
+ a = ''
+ n = 0
+ if not f.startswith('FB_'):
+ f2 = f.split('_')
+ if len(f2) == 2:
+ if f2[1].isdigit():
+ return f2[0], int(f2[1])
+ return f2[0], f2[1]
+ #print f
+ while f and not f[0].isdigit():
+ a += f[0]
+ f = f[1:]
+ return a, int(f) if f else None
+
+def fnsort(f1, f2):
+ a1, n1 = fnsplit(f1)
+ a2, n2 = fnsplit(f2)
+ x = cmp(a1, a2)
+ if x != 0:
+ return x
+ return cmp(n1, n2)
+
+def find_fn(fname, names):
+ for n in names:
+ if fname.startswith(n):
+ return n
+
+def display_fns(bankspec, pins, function_names):
+ fn_names = function_names.keys()
+ fns = {}
+ for (pin, pdata) in pins.items():
+ for mux in range(1,4): # skip GPIO for now
+ if not pdata.has_key(mux):
+ continue
+ name, bank = pdata[mux]
+ if not fns.has_key(name):
+ fns[name] = []
+ fns[name].append((pin-bankspec[bank], mux, bank))
+
+ fnidx = fns.keys()
+ fnidx.sort(fnsort)
+ current_fn = None
+ for fname in fnidx:
+ fnbase = find_fn(fname, fn_names)
+ if fnbase != current_fn:
+ if current_fn is not None:
+ print
+ print "## %s" % fnbase
+ print
+ print function_names[fnbase]
+ print
+ current_fn = fnbase
+ print "* %-9s :" % fname,
+ for (pin, mux, bank) in fns[fname]:
+ print "%s%d/%d" % (bank, pin, mux),
+ print
+
+ return fns
+
+def check_functions(title, bankspec, fns, pins, required, eint, pwm,
+ descriptions=None):
+ fns = deepcopy(fns)
+ pins = deepcopy(pins)
+ if descriptions is None:
+ descriptions = {}
+
+ print "# Pinmap for %s" % title
+ print
+
+
+ for name in required:
+ print "## %s" % name
+ print
+ if descriptions and descriptions.has_key(name):
+ print descriptions[name]
+ print
+
+ name = name.split(':')
+ if len(name) == 2:
+ findbank = name[0][0]
+ findmux = int(name[0][1:])
+ name = name[1]
+ else:
+ name = name[0]
+ findbank = None
+ findmux = None
+ name = name.split('/')
+ if len(name) == 2:
+ count = int(name[1])
+ else:
+ count = 100000
+ name = name[0]
+ found = set()
+ fnidx = fns.keys()
+ #fnidx.sort(fnsort)
+ pinfound = {}
+ for fname in fnidx:
+ if not fname.startswith(name):
+ continue
+ for pin, mux, bank in fns[fname]:
+ if findbank is not None:
+ if findbank != bank:
+ continue
+ if findmux != mux:
+ continue
+ pin_ = pin + bankspec[bank]
+ if pins.has_key(pin_):
+ pinfound[pin_] = (fname, pin_, bank, pin, mux)
+
+ pinidx = pinfound.keys()
+ pinidx.sort()
+
+ for pin_ in pinidx:
+ fname, pin_, bank, pin, mux = pinfound[pin_]
+ if fname in found:
+ continue
+ found.add(fname)
+ if len(found) > count:
+ continue
+ del pins[pin_]
+ print "* %s %d %s%d/%d" % (fname, pin_, bank, pin, mux)
+
+ print
+
+ # gpios
+ gpios = []
+ for name in descriptions.keys():
+ if not name.startswith('GPIO'):
+ continue
+ if name == 'GPIO':
+ continue
+ gpios.append(name)
+ gpios.sort()
+
+ if gpios:
+ print "## GPIO"
+ print
+
+ for fname in gpios:
+ if fname in found:
+ continue
+ desc = ''
+ if descriptions and descriptions.has_key(fname):
+ desc = ': %s' % descriptions[fname]
+ bank = fname[4]
+ pin = int(fname[5:])
+ pin_ = pin + bankspec[bank]
+ if not pins.has_key(pin_):
+ continue
+ del pins[pin_]
+ found.add(fname)
+ print "* %-8s %d %s%-2d %s" % (fname, pin_, bank, pin, desc)
+ print
+
+ if eint:
+ display_group("EINT", eint, fns, pins, descriptions)
+ if pwm:
+ display_group("PWM", pwm, fns, pins, descriptions)
+
+ print "## Unused Pinouts (spare as GPIO) for '%s'" % title
+ print
+ if descriptions and descriptions.has_key('GPIO'):
+ print descriptions['GPIO']
+ print
+ display(pins)
+ print
+
+ return pins # unused
+
+def display_group(title, todisplay, fns, pins, descriptions):
+ print "## %s" % title
+ print
+
+ found = set()
+ for fname in todisplay:
+ desc = ''
+ if descriptions and descriptions.has_key(fname):
+ desc = ': %s' % descriptions[fname]
+ fname = fname.split(':')
+ if len(fname) == 2:
+ findbank = fname[0][0]
+ findmux = int(fname[0][1:])
+ fname = fname[1]
+ else:
+ fname = fname[0]
+ findbank = None
+ findmux = None
+ for (pin, mux, bank) in fns[fname]:
+ if findbank is not None:
+ if findbank != bank:
+ continue
+ if findmux != mux:
+ continue
+ if fname in found:
+ continue
+ pin_ = pin + bankspec[bank]
+ if not pins.has_key(pin_):
+ continue
+ del pins[pin_]
+ found.add(fname)
+ print "* %s %d %s%d/%d %s" % (fname, pin_, bank, pin, mux, desc)
+ print
+
+def pinmerge(pins, fn):
+ for (pinidx, v) in fn.items():
+ if not pins.has_key(pinidx):
+ pins[pinidx] = v
+ continue
+ pins[pinidx].update(v)
+
+def display_fixed(fixed, offs):
+
+ fkeys = fixed.keys()
+ fkeys.sort()
+ pin_ = offs
+ for pin, k in enumerate(fkeys):
+ print "## %s" % k
+ print
+ prevname = ''
+ linecount = 0
+ for name in fixed[k]:
+ if linecount == 4:
+ linecount = 0
+ print
+ if prevname[:2] == name[:2] and linecount != 0:
+ print name,
+ linecount += 1
+ else:
+ if linecount != 0:
+ print
+ print "* %d: %d %s" % (pin_, pin, name),
+ linecount = 1
+ prevname = name
+ pin_ += 1
+ if linecount != 0:
+ print
+ print
+
+if __name__ == '__main__':
+ pinouts = {}
+
+ pinbanks = {'A': 16,
+ 'B': 28,
+ 'C': 24,
+ 'D': 24,
+ 'E': 24,
+ 'F': 10,
+ 'G': 32,
+ }
+ bankspec = {}
+ pkeys = pinbanks.keys()
+ pkeys.sort()
+ offs = 0
+ for kn in pkeys:
+ bankspec[kn] = offs
+ offs += pinbanks[kn]
+
+ # Bank A, 0-15
+ pinmerge(pinouts, gpio(bankspec, "", ('A', 0), "A", 0, 16, 0))
+ pinmerge(pinouts, spi(bankspec, "1", ('A', 0), "A", 3))
+ pinmerge(pinouts, uartfull(bankspec, "1", ('A', 0), "A", 2))
+ pinmerge(pinouts, i2c(bankspec, "1", ('A', 4), "A", 2))
+ pinmerge(pinouts, emmc(bankspec, "", ('A', 0), "A", 1))
+ #pinmerge(pinouts, uart(bankspec, "2", ('A', 14), "A", 1))
+ pinmerge(pinouts, spi(bankspec, "2", ('A', 6), "A", 2))
+ pinmerge(pinouts, eint(bankspec, "", ('A', 10), "A", 0, 6))
+ pinmerge(pinouts, eint(bankspec, "", ('A', 4), "A", 0, 6, mux=3))
+ pinmerge(pinouts, sdmmc(bankspec, "1", ('A', 10), "A", 2))
+ pinmerge(pinouts, jtag(bankspec, "1", ('A', 10), "A", 3))
+ pinmerge(pinouts, uart(bankspec, "2", ('A', 14), "A", 3))
+
+ # Bank B, 16-47
+ pinmerge(pinouts, gpio(bankspec, "", ('B', 0), "B", 0, 28, 0))
+ pinmerge(pinouts, rgbttl(bankspec, "0", ('B', 0), "B", 1))
+ pinmerge(pinouts, spi(bankspec, "1", ('B', 12), "B", 2))
+ pinmerge(pinouts, quadspi(bankspec, "3", ('B', 4), "B", 2, limit=4))
+ pinmerge(pinouts, uart(bankspec, "3", ('B', 16), "B", 2))
+ pinmerge(pinouts, i2c(bankspec, "3", ('B', 18), "B", 2))
+ pinmerge(pinouts, pwm(bankspec, "0", ('B', 9), "B", mux=2))
+ pinmerge(pinouts, pwm(bankspec, "1", ('B', 20), "B", mux=2))
+ pinmerge(pinouts, pwm(bankspec, "2", ('B', 21), "B", mux=2))
+ pinmerge(pinouts, sdmmc(bankspec, "1", ('B', 22), "B", 2))
+ pinmerge(pinouts, eint(bankspec, "", ('B', 0), "B", 6, 4, mux=3))
+ pinmerge(pinouts, flexbus2(bankspec, "", ('B', 4), "B", 3))
+ pinmerge(pinouts, i2c(bankspec, "1", ('B', 0), "B", 2))
+ pinmerge(pinouts, uart(bankspec, "2", ('B', 2), "B", 2))
+ pinmerge(pinouts, uart(bankspec, "4", ('B', 10), "B", 2))
+
+ # Bank C, 48-71
+ pinmerge(pinouts, gpio(bankspec, "", ("C", 0), "C", 0, 24, 0))
+ pinmerge(pinouts, ulpi(bankspec, "1", ('C', 0), "C", 1))
+ pinmerge(pinouts, ulpi(bankspec, "2", ('C', 12), "C", 1))
+ pinmerge(pinouts, spi(bankspec, "2", ('C', 8), "C", 2))
+ #pinmerge(pinouts, spi(bankspec, "2", ('C', 28), "C", 2))
+ pinmerge(pinouts, uartfull(bankspec, "0", ('C', 20), "C", 3))
+ pinmerge(pinouts, eint(bankspec, "", ('C', 0), "C", 10, 8, mux=3))
+ pinmerge(pinouts, jtag(bankspec, "2", ('C', 8), "C", 3))
+ pinmerge(pinouts, eint(bankspec, "", ('C', 12), "C", 22, 8, mux=3))
+ pinmerge(pinouts, uart(bankspec, "2", ('C', 22), "C", 2))
+ pinmerge(pinouts, i2s(bankspec, "", ('C', 13), "C", 2))
+ pinmerge(pinouts, pwm(bankspec, "2", ('C', 21), "C", mux=2))
+
+ # Bank D, 72-96
+ flexspec = {
+ 'FB_TS': ('FB_ALE', 2, "D"),
+ 'FB_CS2': ('FB_BWE2', 2, "D"),
+ 'FB_A0': ('FB_BWE2', 3, "D"),
+ 'FB_CS3': ('FB_BWE3', 2, "D"),
+ 'FB_A1': ('FB_BWE3', 3, "D"),
+ 'FB_TBST': ('FB_OE', 2, "D"),
+ 'FB_TSIZ0': ('FB_BWE0', 2, "D"),
+ 'FB_TSIZ1': ('FB_BWE1', 2, "D"),
+ }
+ #pinmerge(pinouts, mcu8080("", 72, "D", 1))
+ pinmerge(pinouts, gpio(bankspec, "", ('D', 0), "D", 0, 24, 0))
+ pinmerge(pinouts, flexbus1(bankspec, "", ('D', 0), "D", 1, spec=flexspec))
+ pinmerge(pinouts, i2c(bankspec, "2", ('D', 17), "D", 2))
+ pinmerge(pinouts, pwm(bankspec, "0", ('D', 21), "D", mux=1))
+ pinmerge(pinouts, pwm(bankspec, "1", ('D', 22), "D", mux=1))
+ pinmerge(pinouts, pwm(bankspec, "2", ('D', 23), "D", mux=1))
+ pinmerge(pinouts, i2c(bankspec, "1", ('D', 10), "D", 3))
+ pinmerge(pinouts, i2c(bankspec, "3", ('D', 19), "D", 2))
+ pinmerge(pinouts, uartfull(bankspec, "0", ('D', 0), "D", 2))
+ pinmerge(pinouts, uart(bankspec, "3", ('D', 21), "D", 2))
+ pinmerge(pinouts, uart(bankspec, "4", ('D', 13), "D", 2))
+ pinmerge(pinouts, eint(bankspec, "", ('D', 19), "D", 18, 4, mux=3))
+ pinmerge(pinouts, eint(bankspec, "", ('D', 23), "D", 9, 1, mux=3))
+ pinmerge(pinouts, eint(bankspec, "", ('D', 13), "D", 5, 4, mux=3))
+ pinmerge(pinouts, eint(bankspec, "", ('D', 0), "D", 30, 2, mux=3))
+ pinmerge(pinouts, i2c(bankspec, "2", ('D', 2), "D", 3))
+ pinmerge(pinouts, sdmmc(bankspec, "2", ('D', 4), "D", 2))
+
+ # Bank E
+ pinmerge(pinouts, gpio(bankspec, "", ('E', 0), "E", 0, 24, 0))
+ pinmerge(pinouts, flexbus2(bankspec, "", ('E', 0), "E", 1))
+ pinmerge(pinouts, sdmmc(bankspec, "2", ('E', 0), "E", 2))
+ pinmerge(pinouts, sdmmc(bankspec, "3", ('E', 8), "E", 2))
+ pinmerge(pinouts, quadspi(bankspec, "3", ('E', 18), "E", 2))
+ pinmerge(pinouts, uartfull(bankspec, "1", ('E', 14), "E", 2))
+ pinmerge(pinouts, i2c(bankspec, "2", ('E', 6), "E", 2))
+ pinmerge(pinouts, eint(bankspec, "", ('E', 0), "E", 10, 8, mux=3))
+ pinmerge(pinouts, eint(bankspec, "", ('E', 8), "E", 22, 6, mux=3))
+ pinmerge(pinouts, emmc(bankspec, "", ('E', 14), "E", 3))
+
+ # Bank F
+ pinmerge(pinouts, gpio(bankspec, "", ('F', 0), "F", 0, 10, 0))
+ pinmerge(pinouts, i2s(bankspec, "", ('F', 0), "F", 1))
+ pinmerge(pinouts, i2c(bankspec, "1", ('F', 6), "F", 2))
+ pinmerge(pinouts, pwm(bankspec, "0", ('F', 8), "F", mux=2))
+ pinmerge(pinouts, pwm(bankspec, "1", ('F', 9), "F", mux=2))
+ pinmerge(pinouts, uart(bankspec, "4", ('F', 8), "F", 1))
+ pinmerge(pinouts, sdmmc(bankspec, "3", ('F', 0), "F", 2))
+ pinmerge(pinouts, eint(bankspec, "", ('F', 0), "F", 18, 4, mux=3))
+ pinmerge(pinouts, pwm(bankspec, "2", ('F', 4), "F", mux=3))
+ pinmerge(pinouts, eint(bankspec, "", ('F', 5), "F", 7, 1, mux=3))
+ pinmerge(pinouts, eint(bankspec, "", ('F', 6), "F", 28, 4, mux=3))
+
+ # Bank G
+ pinmerge(pinouts, gpio(bankspec, "", ('G', 0), "G", 0, 32, 0))
+ pinmerge(pinouts, rgmii(bankspec, "", ('G', 0), "G", 1))
+ pinmerge(pinouts, ulpi(bankspec, "3", ('G', 18), "G", 1))
+ pinmerge(pinouts, rgbttl(bankspec, "1", ('G', 0), "G", 2))
+ pinmerge(pinouts, quadspi(bankspec, "3", ('G', 26), "G", 3))
+ pinmerge(pinouts, flexbus2(bankspec, "", ('G', 0), "G", 3))
+ mmc2 = sdmmc(bankspec, "2", ('G', 24), "G", 3, limit=2)
+ pinmerge(pinouts, mmc2)
+ mmc2 = sdmmc(bankspec, "2", ('G', 28), "G", 2, start=2)
+ pinmerge(pinouts, mmc2)
+
+ print "# Pinouts (PinMux)"
+ print
+ print "auto-generated by [[pinouts.py]]"
+ print
+ print "[[!toc ]]"
+ print
+ display(pinouts)
+ print
+
+ print "# Pinouts (Fixed function)"
+ print
+
+ fixedpins = {
+ 'DDR3':
+ ['SDQ0', 'SDQ1', 'SDQ2', 'SDQ3', 'SDQ4', 'SDQ5', 'SDQ6', 'SDQ7',
+ 'SDQ8', 'SDQ9', 'SDQ10', 'SDQ11', 'SDQ12', 'SDQ13', 'SDQ14', 'SDQ15',
+ 'SDQ16', 'SDQ17', 'SDQ18', 'SDQ19', 'SDQ20', 'SDQ21', 'SDQ22', 'SDQ23',
+ 'SDQ24', 'SDQ25', 'SDQ26', 'SDQ27', 'SDQ28', 'SDQ29', 'SDQ30', 'SDQ31',
+ 'SVREF0', 'SVREF1', 'SVREF2', 'SVREF3',
+ 'SDQS0', 'SDQS0#', 'SDQS1', 'SDQS1#',
+ 'SDQS2', 'SDQS2#', 'SDQS3', 'SDQS3#',
+ 'SDQM0', 'SDQM1', 'SDQM2', 'SDQM3',
+ 'SCK#', 'SCK', 'SCKE0', 'SCKE1',
+ 'SA0', 'SA1', 'SA2', 'SA3', 'SA4', 'SA5', 'SA6', 'SA7',
+ 'SA8', 'SA9', 'SA10', 'SA11', 'SA12', 'SA13', 'SA14',
+ 'SBA0', 'SBA1', 'SBA2',
+ 'SWE', 'SCAS', 'SRAS',
+ 'SCS0', 'SCS1',
+ 'SZQ', 'SRST',
+ 'SDBG0', 'SDBG1', 'ADBG',
+ 'ODT0', 'ODT1'
+ ],
+
+ 'CTRL_SYS':
+ [
+ 'TEST', 'JTAG_SEL', 'UBOOT_SEL',
+ 'NMI#', 'RESET#',
+ 'CLK24M_IN', 'CLK24M_OUT',
+ 'PLLTEST', 'PLLREGIO', 'PLLVP25',
+ 'PLLDV', 'PLLVREG', 'PLLGND',
+ ],
+
+ 'POWER_DRAM':
+ ['VCC0_DRAM', 'VCC1_DRAM', 'VCC2_DRAM', 'VCC3_DRAM', 'VCC4_DRAM',
+ 'VCC5_DRAM', 'VCC6_DRAM', 'VCC7_DRAM', 'VCC8_DRAM', 'VCC9_DRAM',
+ 'GND0_DRAM', 'GND1_DRAM', 'GND2_DRAM', 'GND3_DRAM', 'GND4_DRAM',
+ 'GND5_DRAM', 'GND6_DRAM', 'GND7_DRAM', 'GND8_DRAM', 'GND9_DRAM',
+ ],
+
+ 'POWER_CPU':
+ ['VDD0_CPU', 'VDD1_CPU', 'VDD2_CPU', 'VDD3_CPU', 'VDD4_CPU', 'VDD5_CPU',
+ 'GND0_CPU', 'GND1_CPU', 'GND2_CPU', 'GND3_CPU', 'GND4_CPU', 'GND5_CPU',
+ ],
+
+ 'POWER_DLL':
+ ['VDD0_DLL', 'VDD1_DLL', 'VDD2_DLL',
+ 'GND0_DLL', 'GND1_DLL', 'GND2_DLL',
+ ],
+
+ 'POWER_INT':
+ ['VDD0_INT', 'VDD1_INT', 'VDD2_INT', 'VDD3_INT', 'VDD4_INT',
+ 'VDD5_INT', 'VDD6_INT', 'VDD7_INT', 'VDD8_INT', 'VDD9_INT',
+ 'GND0_INT', 'GND1_INT', 'GND2_INT', 'GND3_INT', 'GND4_INT',
+ 'GND5_INT', 'GND6_INT', 'GND7_INT', 'GND8_INT', 'GND9_INT',
+ ],
+
+ 'POWER_GPIO':
+ ['VDD_GPIOA', 'VDD_GPIOB', 'VDD_GPIOC',
+ 'VDD_GPIOD', 'VDD_GPIOE', 'VDD_GPIOF',
+ 'VDD_GPIOG',
+ 'GND_GPIOA', 'GND_GPIOB', 'GND_GPIOC',
+ 'GND_GPIOD', 'GND_GPIOE', 'GND_GPIOF',
+ 'GND_GPIOG',
+ ]
+
+ }
+
+ display_fixed(fixedpins, len(pinouts))
+
+ print "# Functions (PinMux)"
+ print
+ print "auto-generated by [[pinouts.py]]"
+ print
+
+ function_names = {'EINT': 'External Interrupt',
+ 'FB': 'MC68k FlexBus',
+ 'IIS': 'I2S Audio',
+ 'JTAG1': 'JTAG (same as JTAG2, JTAG_SEL=LOW)',
+ 'JTAG2': 'JTAG (same as JTAG1, JTAG_SEL=HIGH)',
+ 'LCD': '24-pin RGB/TTL LCD',
+ 'RG': 'RGMII Ethernet',
+ 'MMC': 'eMMC 1/2/4/8 pin',
+ 'PWM': 'PWM (pulse-width modulation)',
+ 'SD1': 'SD/MMC 1',
+ 'SD2': 'SD/MMC 2',
+ 'SD3': 'SD/MMC 3',
+ 'SPI1': 'SPI (Serial Peripheral Interface) 1',
+ 'SPI2': 'SPI (Serial Peripheral Interface) 2',
+ 'SPI3': 'Quad SPI (Serial Peripheral Interface) 3',
+ 'TWI1': 'I2C 1',
+ 'TWI2': 'I2C 2',
+ 'TWI3': 'I2C 3',
+ 'UART0': 'UART (TX/RX/CTS/RTS) 0',
+ 'UART1': 'UART (TX/RX/CTS/RTS) 1',
+ 'UART2': 'UART (TX/RX) 2',
+ 'UART3': 'UART (TX/RX) 3',
+ 'UART4': 'UART (TX/RX) 4',
+ 'ULPI1': 'ULPI (USB Low Pin-count) 1',
+ 'ULPI2': 'ULPI (USB Low Pin-count) 2',
+ 'ULPI3': 'ULPI (USB Low Pin-count) 3',
+ }
+
+ fns = display_fns(bankspec, pinouts, function_names)
+ print
+
+ # Scenarios below can be spec'd out as either "find first interface"
+ # by name/number e.g. SPI1, or as "find in bank/mux" which must be
+ # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
+ # EINT and PWM are grouped together, specially, but may still be spec'd
+ # using "BM:Name". Pins are removed in-order as listed from
+ # lists (interfaces, EINTs, PWMs) from available pins.
+
+ # EOMA68 scenario. not totally complete (some GPIO needed for PMIC)
+ # One interface to be connected to the MCU to give RTC and boot/dbg
+ # VBUS_EN, OTG_ID etc. are all not included below, there is plenty
+ # of spare GPIO.
+
+ eoma68 = ['B1:LCD/22', 'ULPI1/8', 'ULPI2', 'MMC', 'SD1', 'UART3',
+ 'TWI3', 'SPI2', 'E2:SD2',]
+ eoma68_eint = ['EINT16', 'EINT17', 'EINT18', 'EINT19']
+ eoma68_pwm = ['D1:PWM_2']
+ descriptions = {
+ 'MMC': 'internal (on Card)',
+ 'SD1': 'user-facing: internal (on Card), multiplexed with JTAG1\n'
+ 'and UART2, for debug purposes',
+ 'TWI3': 'EOMA68-compliance: must be entirely free of devices.\n'
+ 'Address 0x51 used (externally) for EOMA68 EEPROM Id',
+ 'E2:SD2': 'EOMA68-compliance',
+ 'SPI2': 'EOMA68-compliance',
+ 'UART3': 'EOMA68-compliance',
+ 'B1:LCD/22': 'EOMA68-compliance, 18-bit RGB/TTL LCD',
+ 'ULPI1/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
+ 'ULPI2': 'EOMA68-compliance: dual USB2 Host ULPI PHY'
+ }
+
+ unused_pins = check_functions("EOMA68", bankspec, fns, pinouts,
+ eoma68, eoma68_eint, eoma68_pwm,
+ descriptions)
+
+ # Industrial scenario. not totally complete (some GPIO needed for PMIC)
+ # One interface to be connected to the MCU to give RTC, boot/dbg,
+ # option of CAN Bus, ADC, DAC, OWB, more GPIO, more PWM etc. etc.
+ # Focus is on getting as many UARTs, SPIs and TWIs as possible.
+ # OTG_ID (if to be used) would require dropping some functions in order
+ # to free up GPIO. LCD could be reduced to 15-bit (freeing 3).
+ # MMC could be reduced to 4-bit-wide, used as SD/MMC (freeing 4).
+ # SPI3 could be used in 1-bit (MOSI/MISO) mode (freeing up 2 more).
+
+ industrial = ['D1:FB/17', 'E1:FB/8', 'B1:LCD/22', 'ULPI1/8', 'ULPI2/8',
+ 'MMC', 'B2:SD1',
+ 'JTAG1', 'A3:UART2', 'E2:UART1', 'C3:UART0',
+ 'F2:TWI1', 'D2:TWI2', 'D2:TWI3', 'SPI2', 'SPI3', 'F2:SD3']
+ industrial_pwm = ['F2:PWM_0', 'F2:PWM_1', 'D1:PWM_2']
+ industrial_eint = ['EINT24', 'EINT25', 'EINT26', 'EINT27',
+ 'EINT20', 'EINT21', 'EINT22', 'EINT23']
+
+ unused_pins = check_functions("Industrial", bankspec, fns, pinouts,
+ industrial, industrial_eint, industrial_pwm)
+
+ # Industrial scenario, using an SPI-based LCD instead of RGB/TTL
+ # not totally complete (some GPIO needed for PMIC)
+ # One interface to be connected to the MCU to give RTC, boot/dbg,
+ # option of CAN Bus, ADC, DAC, OWB, more GPIO, more PWM etc. etc.
+ # Focus is on getting as many UARTs, SPIs and TWIs as possible,
+ # leaving some GPIO spare from the RGB/TTL bank (SPI CS#)
+ # also possibility of freeing up FlexBus CS# with a little reorg.
+
+ industrial = ['D1:FB/17', 'E1:FB/8', 'B2:SPI1', 'ULPI1/8', 'ULPI2/8',
+ 'MMC', 'B2:SD1',
+ 'JTAG1',
+ 'A3:UART2', 'E2:UART1', 'C3:UART0', 'B2:UART4', 'B2:UART3',
+ 'F2:TWI1', 'D2:TWI2', 'D2:TWI3', 'SPI2', 'SPI3', 'F2:SD3']
+ industrial_pwm = ['F2:PWM_0', 'F2:PWM_1', 'D1:PWM_2']
+ industrial_eint = ['EINT24', 'EINT25', 'EINT26', 'EINT27',
+ 'EINT20', 'EINT21', 'EINT22', 'EINT23']
+ ind_descriptions = {
+ 'B2:SPI1': 'Used for 320x240 or 640x480 etc. SPI-based LCD.\n'
+ 'Frees up large numbers of GPIO from RGB/TTL bank'
+ }
+ unused_pins = check_functions("Industrial with SPI-LCD",
+ bankspec, fns, pinouts,
+ industrial, industrial_eint, industrial_pwm,
+ ind_descriptions)
+
+ # Smartphone / Tablet - basically the same thing
+
+ tablet = ['B1:LCD/22', 'ULPI1/8', 'ULPI2/8',
+ 'MMC', 'SD1',
+ 'F1:IIS', # I2C Audio
+ 'TWI2', # I2C Audio
+ 'E2:UART1', # WIFI/BT
+ 'E2:SD2', # WIFI
+ 'C3:UART0', # GPS
+ 'D2:UART3',
+ 'D2:UART4',
+ 'D3:TWI1', 'D2:TWI3', 'SPI2', 'SPI3']
+ tablet_pwm = ['F2:PWM_0', # LCD_BACKLIGHT
+ 'F2:PWM_1', 'D1:PWM_2']
+ tablet_eint = ['EINT24', # BT_HOST_WAKE
+ 'EINT25', # WIFI_HOST_WAKE
+ 'EINT26', # CTP_INT
+ 'EINT27', # GSENSOR_INT
+ 'EINT8', # GPS_INT
+ 'EINT7', # TILT_SENSOR_INT
+ 'EINT22', # COMPASS_INT
+ 'EINT23', # MCU_INT
+ 'EINT16', # PMIC_INT
+ 'EINT17', # PWR_BUTTON_INT
+ 'EINT30', # OTG_ID
+ 'EINT31',
+ ]
+ descriptions = {
+ 'B1:LCD/22':
+ 'RGB/TTL LCD, 800x480 or use SN75LVDS83b for up to 1440x900',
+ 'MMC': 'eMMC: main internal storage',
+ 'ULPI1/8': 'USB-OTG, connect to ULPI OTG PHY (for charging)\n'
+ 'as well as USB Host or USB Device',
+ 'ULPI2/8': 'USB2 Host, connect to ULPI PHY w/and 4-port USB2 Hub\n'
+ 'for example GL850G or FE1.1. '
+ 'Connects to 2/3/4G/LTE Modem, 2x USB-Camera (VC0345)',
+ 'SD1': 'internal, multiplexed with JTAG1\n'
+ 'and UART2, for debug purposes',
+ 'F1:IIS': 'I2C Audio, connect to AC97 Audio IC',
+ 'TWI2': 'Connect to AC97 Audio IC',
+ 'E2:UART1': 'Connect to BT on AP6234/AP6335',
+ 'E2:SD2': 'Connect to WIFI on AP6234/AP6335',
+ 'SPI3': 'Boot Storage (connection to companion / debug / boot MCU)\n'
+ 'Only actually needs MISO/MOSI, bootstrap loader v. small\n'
+ 'Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.',
+ 'SPI2': 'Spare? SPI, connect to higher-speed sensor?',
+ 'D2:UART3': 'Spare? UART (or 2 extra GPIO / EINT)',
+ 'D2:UART4': 'Spare? UART (or 2 extra GPIO)',
+ 'D3:TWI1': 'Connect to PMIC',
+ 'D2:TWI3': 'Connect to sensors (Trackpad? CTP GSENSOR TILT COMPASS)',
+ 'GPIO': '9 spare GPIO pins for miscellaneous functions:\n'
+ 'wake-up of BT, WIFI, LCD power, sensor power etc.\n'
+ '4 GPIO may be needed for PWM Audio from Modem.\n'
+ 'LED lights for camera will be needed.\n'
+ 'Some phones may have clam-shell or lid switch.\n'
+ 'Some Modems have spare GPIO (over AT commandset).\n'
+ 'AXP209 PMIC has 4x GPIO, accessible over I2C.\n'
+ 'SPI2, UART3-4, PWM1-2 may also be spare (10 extra GPIO).\n'
+ 'If more needed, companion MCU may be used (48+ pin variant)\n'
+ 'which also includes ADC, DAC, more PWM etc.',
+ 'F2:PWM_0': 'LCD Backlight',
+ 'F2:PWM_1': 'Spare? PWM (or extra GPIO / EINT)',
+ 'D1:PWM_2': 'Spare? PWM (or extra GPIO / EINT)',
+ 'EINT24': 'BT_HOST_WAKE',
+ 'EINT25': 'WIFI_HOST_WAKE',
+ 'EINT26': 'CTP_INT',
+ 'EINT27': 'GSENSOR_INT',
+ 'EINT8': 'GPS_INT',
+ 'EINT7': 'TILT_SENSOR_INT',
+ 'EINT22': 'COMPASS_INT',
+ 'EINT23': 'MCU_INT',
+ 'EINT16': 'PMIC_INT',
+ 'EINT17': 'PWR_BUTTON_INT',
+ 'EINT30': 'OTG_ID',
+ 'EINT31': 'Spare?',
+ }
+ unused_pins = check_functions("Smartphone / Tablet",
+ bankspec, fns, pinouts,
+ tablet, tablet_eint, tablet_pwm,
+ descriptions)
+
+ # Laptop
+
+ laptop = ['D1:FB/17', 'E1:FB/8', 'B1:LCD/22', 'ULPI1/8', 'ULPI2/8',
+ 'MMC', 'SD1',
+ 'F1:IIS', # I2C Audio
+ 'TWI2', # I2C Audio
+ 'E2:UART1', # WIFI/BT
+ 'E2:SD3', # WIFI
+ 'D2:TWI3', 'SPI3']
+ laptop_pwm = ['F2:PWM_0', # LCD_BACKLIGHT
+ ]
+ laptop_eint = ['EINT20', # BT_HOST_WAKE
+ 'EINT21', # WIFI_HOST_WAKE
+ 'EINT9', # MCU_INT
+ 'EINT31', # PMIC_INT
+ ]
+ descriptions = {
+ 'D1:FB/17': 'FlexBus. Connect to DM9000 or AX99896A MCU-style Bus\n'
+ '10/100 Ethernet PHY.',
+ 'E1:FB/8': 'FlexBus bus bits 8-15, needed to make a 16-bit bus width',
+ 'B1:LCD/22':
+ 'RGB/TTL LCD, use SN75LVDS83b for LVDS or SSD2828 for MIPI,\n'
+ 'or a Chrontel CH7039, CH7038, CH7034 or CH7018 for dual\n'
+ 'display output (eDP/LVDS and HDMI/VGA) '
+ 'conversion.',
+ 'MMC': 'eMMC: main internal storage',
+ 'ULPI1/8': 'USB-OTG, connect to ULPI OTG PHY (for charging)\n'
+ 'as well as USB Host or USB Device',
+ 'ULPI2/8': 'USB2 Host, connect to ULPI PHY w/and 4-port USB2 Hub\n'
+ 'for example GL850G or FE1.1. '
+ 'Connects to USB-Camera (VC0345 and 3x external USB Ports)',
+ 'SD1': 'internal, multiplexed with JTAG1\n'
+ 'and UART2, for debug purposes',
+ 'F1:IIS': 'I2C Audio, connect to AC97 Audio IC',
+ 'TWI2': 'Connect to AC97 Audio IC',
+ 'E2:UART1': 'Connect to BT on AP6234/AP6335',
+ 'E2:SD3': 'Connect to WIFI on AP6234/AP6335',
+ 'SPI3': 'Boot Storage (connection to companion / debug / boot MCU)\n'
+ 'Only actually needs MISO/MOSI, bootstrap loader v. small\n'
+ 'Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.\n'
+ 'MCU implements keyboard-matrix for keyboard (also trackpad?)',
+ 'D2:TWI3': 'Connect to PMIC',
+ 'GPIO': 'Plenty of spare GPIO pins for miscellaneous functions\n'
+ 'MCU EINT-capable GPIO may be used to generate extra EINTs\n'
+ 'on the single MCU_INT line, if really needed',
+ 'F2:PWM_0': 'LCD Backlight',
+ 'EINT20': 'BT_HOST_WAKE',
+ 'EINT21': 'WIFI_HOST_WAKE',
+ 'EINT9': 'MCU_INT',
+ 'EINT31': 'PMIC_INT',
+ }
+ unused_pins = check_functions("Laptop / Netbook",
+ bankspec, fns, pinouts,
+ laptop, laptop_eint, laptop_pwm,
+ descriptions)
+
+ # IoT
+
+ iot = ['B1:LCD', 'ULPI2/8', 'ULPI1/8',
+ 'MMC', 'SD1',
+ 'F1:IIS', # I2C Audio
+ #'TWI2', # I2C Audio
+ 'C3:UART0', # HSPA UART
+ 'E2:UART1', # BT UART
+ 'C2:SPI2', # HSPI SPI
+ 'E2:SD3', # WIFI
+ 'D3:TWI1', # sensors CTP,
+ 'D2:TWI3', 'SPI3']
+ iot_pwm = ['F2:PWM_0', # LCD_BACKLIGHT
+ ]
+ iot_eint = [ 'EINT5', # 'HSPA_MST_RDY',
+ 'EINT6', # 'HSPA_SL_RDY',
+ 'EINT7', # 'HSPA_RING',
+ 'EINT8', # 'WL_PMU_EN',
+ 'EINT9', # HSPA_GPIO1
+ 'EINT10', # IR_DT
+ 'EINT11', # 'BT_PCM_CLK',
+ 'EINT12', # 'BT_PCM_DIN',
+ 'EINT13', # 'BT_PCM_SYNC',
+ 'EINT14', # 'BT_PCM_DOUT',
+ 'EINT16', # 'USB_DRVVBUS',
+ 'EINT17', # 'USB_VBUSDET',
+ 'EINT21', # 'USB_ID',
+ 'EINT30', # 'CTP_INT',
+ 'EINT31', # 'SD_DET#',
+ ]
+ descriptions = {
+ 'B1:LCD':
+ 'RGB/TTL LCD, use SN75LVDS83b for LVDS or SSD2828 for MIPI,\n'
+ 'or a Chrontel CH7039, CH7038, CH7034 or CH7018 for dual\n'
+ 'display output (eDP/LVDS and HDMI/VGA) '
+ 'conversion.',
+ 'MMC': 'eMMC: main internal storage',
+ 'F1:IIS': 'I2C Audio, connect to AC97 Audio IC',
+ 'ULPI2/8': 'USB-OTG, connect to ULPI OTG PHY (for charging)\n'
+ 'as well as USB Host or USB Device',
+ 'ULPI1/8': 'USB2 Host, connect to ULPI PHY',
+ 'SD1': 'internal, multiplexed with JTAG1\n'
+ 'and UART2, for debug purposes',
+ 'C3:UART0': 'Connect to HSPA UART',
+ 'E2:UART1': 'Connect to BT UART',
+ 'E2:SD3': 'Connect to WIFI',
+ 'C2:SPI2': 'HSPA SPI',
+ 'SPI3': 'Boot Storage (connection to companion / debug / boot MCU)\n'
+ 'Only actually needs MISO/MOSI, bootstrap loader v. small\n'
+ 'Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.\n'
+ 'MCU implements keyboard-matrix for keyboard (also trackpad?)',
+ 'D2:TWI3': 'Connect to PMIC',
+ 'D3:TWI1': 'Connect to sensors CTP',
+ 'GPIO': 'Plenty of spare GPIO pins for miscellaneous functions\n'
+ 'MCU EINT-capable GPIO may be used to generate extra EINTs\n'
+ 'on the single MCU_INT line, if really needed',
+ 'F2:PWM_0': 'LCD Backlight',
+ 'GPIOD4': 'WL_WAKE_AP',
+ 'GPIOD5': 'BT_WAKE_AP',
+ 'GPIOD6': 'AP_WAKE_BT',
+ 'GPIOD7': 'AP_CK32KO',
+ 'GPIOD8': 'HSPA_PWRON',
+ 'GPIOD9': 'BT_RST_N',
+ 'GPIOE5': 'HSPA_ON_OFF',
+ 'GPIOD2': 'HSPA_SHUTDOWN',
+ 'GPIOD3': 'CTP_RST',
+ 'GPIOD12': 'LCD_RDN',
+ 'GPIOD17': 'LCD_WRN',
+ 'GPIOD18': 'LCD_RS',
+ 'GPIOD21': 'LCD_CSN',
+
+ 'EINT5': 'HSPA_MST_RDY',
+ 'EINT6': 'HSPA_SL_RDY',
+ 'EINT7': 'HSPA_RING',
+ 'EINT8': 'WL_PMU_EN',
+ 'EINT9': 'HSPA_GPIO1',
+ 'EINT10': 'IR_DT',
+ 'EINT11': 'BT_PCM_CLK',
+ 'EINT12': 'BT_PCM_DIN',
+ 'EINT13': 'BT_PCM_SYNC',
+ 'EINT14': 'BT_PCM_DOUT',
+
+ 'EINT16': 'USB_DRVVBUS',
+ 'EINT17': 'USB_VBUSDET',
+ 'EINT21': 'USB_ID',
+ 'EINT30': 'CTP_INT',
+ 'EINT31': 'SD_DETN',
+ }
+ unused_pins = check_functions("IoT",
+ bankspec, fns, pinouts,
+ iot, iot_eint, iot_pwm,
+ descriptions)
+
+ print "# Reference Datasheets"
+ print
+ print "datasheets and pinout links"
+ print
+ print "* <http://datasheets.chipdb.org/AMD/8018x/80186/amd-80186.pdf>"
+ print "* <http://hands.com/~lkcl/eoma/shenzen/frida/FRD144A2701.pdf>"
+ print "* <http://pinouts.ru/Memory/sdcard_pinout.shtml>"
+ print "* p8 <http://www.onfi.org/~/media/onfi/specs/onfi_2_0_gold.pdf?la=en>"
+ print "* <https://www.heyrick.co.uk/blog/files/datasheets/dm9000aep.pdf>"
+ print "* <http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4393.pdf>"
+ print "* <https://www.nxp.com/docs/en/data-sheet/MCF54418.pdf>"
+ print "* ULPI OTG PHY, ST <http://www.st.com/en/interfaces-and-transceivers/stulpi01a.html>"
+ print "* ULPI OTG PHY, TI TUSB1210 <http://ti.com/product/TUSB1210/>"
+
--- /dev/null
+# Analysis of Options for Memory Interfaces for a Mobile-class Libre SoC
+
+This document covers why, according to best risk-reducing and practical
+issues, DDR3/DDR3L/LPDDR3 is the best option for a mobile-class SoC
+*at the time of writing*.
+
+The requirements which minimise risk are:
+
+* Reasonable power consumption for the target SoC (well below 1.5 watts)
+ power budget for the RAM ICs.
+* Minimum or equivalent of 700mhz @ 32-bit transfers (so 350mhz clockrate
+ for a total 700mhz DDR @ 32-bit or 175mhz @ 64-bit or 700mhz @ 16-bit)
+* Mass-volume pricing
+* High availability
+* Multiple suppliers
+* No more than 15 cm^3 board area required for RAM plus routing to SoC
+ (just about covers 4x DDR3 78-pin FBGA ICs, or 4x DDR3 96-pin FBGA ICs).
+ Around 15 cm^3 is quite generous, and is practical for making a credit-card
+ sized SBC with all RAM ICs and the SoC on TOP side of the PCB.
+
+Each of these will be covered in turn, below. Then, there will be a
+separate section covering the various types of RAM offerings, including
+some innovative (research-style) ideas. These are:
+
+* Package-on-Package (POP)
+* RAM on-die (known as Multi-Chip Modules)
+* MCM standard and *non*-standard interfaces (custom-designed)
+* Standard off-the-shelf die vs custom-made DRAM or SRAM ASIC
+* DDR1, DDR2, DDR3, DDR4 ....
+
+# Requirements
+
+## Power Consumption
+
+Lowering the power consumption is simply a practical consideration to keep
+cost down and make component selection, manufacturing and design of the PCB
+easier. For example: if the AXP209 can be utilised as the PMIC for the
+entire product, that is a USD $0.5 part and the layout, amount of current
+it consumes, and general support including linux drivers makes it an easy
+choice. On the other hand, if more complex PMIC layouts are required that
+automatically pushes pricing up, introduces risk and NREs.
+
+Therefore if the total budget for the entire design can be kept below
+around 3.5 watts, which translates roughly to around 1.5 watts for the memory
+and around 1.5 to 2W for the SoC, a lower-cost PMIC can be deployed *and*
+there is a lot less to worry about when it comes to thermal dissipation.
+
+Note that from Micron's Technical Note TN-41-01, a single x16 1033mhz
+DDR3 (not DDR3L) DRAM can consume 436mW on its own. If two of those
+are deployed to give a 32-bit-wide memory interface @ 1033mhz, that's
+872mW which is just about acceptable. It would be much better to
+consider using DDR3L (1.35v instead of 1.5v) as this would lower power
+consumption roughly on a square law with voltage for an approximate
+20% drop.
+
+## Minimum 700mhz @ 32-bit transfer rates
+
+This is a practical consideration for delivering reasonable performance
+and being able to cover 720 / 1080p video playback without stalling.
+Once decoded from their compressed format, video framebuffers take up
+an enormous amount of memory bandwidth, which cannot be cached on-chip
+so has to be written out to RAM and then read back in again. Video
+(and 3D) therefore have a massive impact on the SoC's performance when
+using a lower-cost "shared memory bus" architecture.
+
+1.4 Gigabytes per second of raw reads/writes is therefore a reasonable
+compromise between development costs, overall system price, running too
+hot, and running so slow that users start complaining or cannot play
+certain videos or applications at all.
+If better than this absolute minimum can be achieved within the power
+budget that would be great.
+
+Other options to include are: going for a 64-bit wide total bus bandwidth,
+which can be achieved with either 4x 16-bit FBGA96 ICs, or 2x 32-bit
+FBGA168 LPDDR3 ICs. The issue is: that assumes that it's okay to
+correspondingly increase the number of pins of the SoC by an extra
+100 on its pincount, in order to cover dual 32-bit DRAM interfaces.
+Aside from the increased licensing costs and power consumption associated
+with twin DRAM interfaces, the current proposed SoC is only 290 pins, meaning
+that it can be done as a 0.8mm pitch BGA that is only around 15mm on
+a side. That makes it extremely low-cost and very easy to manufacture,
+even being possible to consider 4-layer PCBs and 10mil drill-holes
+(very cheap).
+
+If the pincount were increased to 400 it would be necessary to go to
+a 0.6mm pin pitch in order to keep the package size down. That then in
+turn increases manufacturing costs (6-7 mil BGA VIA drill-holes, requiring
+laser-drilling) and so on. Whilst it seems strange to consider the
+pin count and pin pitch of an SoC when considering something like the
+bandwidth of the memory bus, it goes some way to illustrate quite how
+interconnected everything really is.
+
+Bottom line: yes you *could* go to dual 32-bit-wide DDR RAM interfaces,
+but the *production* cost increases in doing so need to be taken into
+consideration. Some SoCs do actually take only a 16-bit wide DDR RAM
+interface: these tend not to be very popular (or are used in specialist
+markets such as smart watches) as the reduction in memory bandwidth tends
+to go hand-in-hand with ultra-low-power scenarios. Try putting them into
+the hands of mass-volume end users running general-purpose OSes such as
+Android and the users only complain and consider their purchase to have
+been a total waste of money. 32-bit-wide at around 1066mhz seems
+to be an acceptable compromise on all fronts.
+
+## Mass-volume Pricing, High availability, Multiple Suppliers
+
+These are all important inter-related considerations. Surprisingly,
+older ICs *and* newer ICs tend to be higher cost. It comes down to
+what is currently available and being mass-produced. Older ICs fall
+out of popularity and thus become harder to find, or move to "legacy"
+foundries that have a higher cost per unit production.
+
+Newer ICs tend to be higher speeds and higher capacities, meaning that
+the yields are lower, the demands higher. Costs can be sky high on a
+near-exponential curve based on capacity and speed compared to other
+offerings.
+
+Picking the right RAM interface (*and* picking the right speed grade range
+and bus bandwidth)
+that will ensure that the entire SoC
+has a useful lifetime is therefore really rather important! If the
+expected lifetime is to be for example 5 years, it would be foolish
+to pick a DDR RAM interface that, towards the end of those 5 years,
+the cost of the only available RAM ICs is ten times higher than it
+was when the SoC first came out.
+
+In short - jumping the gun somewhat on why this document has been
+written - this means that DDR3/DDR3L/LPDDR3 is the preferred interface
+*at the moment*, given especially that SoCs such as the iMX6 have a
+support profile (lifetime) of 19 years, another 15 of which are
+still to go before the iMX6 reaches EOL. Whilst DDR4/LPDDR4 would be
+"nice to have", it's still simply not reached the point yet where
+it's commonly available from multiple suppliers, and will not do
+so for many years yet. It will require at least two Chinese
+Memory Manufacturers (not just Hynix, Micron and Samsung basically)
+before it starts to become price-competitive. A quick search
+on taobao.com for Hynix P/N H9HCNNNBUUMLHR basically tells you
+what you need to know: very few suppliers, all with multiple
+"fake" listings, fluffing themselves up literally like a peacock
+to make them appear more attractive. Compare that to searching
+for P/N H5TC4G63CFR on taobao and the fact that there are 5 *pages*
+of results from wildly disparate sellers, all roughly around the
+same price of RMB 20 (around USD $3) and that tells you that it's
+mass-produced and commonly available.
+
+## Board area
+
+15 cm^2 is about the minimum in which either four x8 or x16 DDR3 RAM ICs
+can be accommodated, including their routing, on one side of the PCB.
+There are other arrangements however 15 cm^2 is still reasonable
+for the majority of products with the exception of mobile phones and
+smaller sized smartphones. 7in Tablets, SBCs, Netbooks, Media Centres:
+all these products can be designed with a 15 cm^2 budget for RAM, and
+meet a very reasonable target price due to not needing 8+ layers, blind
+vias, double-sided reflow involving epoxy resin to glue underside ICs,
+or other strategies that get really quite expensive if they are to be
+considered for small initial production runs.
+
+With massive production budgets to jump over many of the hurdles, there is
+nothing to be concerned about. However if considering a production and
+design budget below USD $50,000 and initial production runs using Shenzhen
+factories for pre-production and prototyping, "techniques" such as
+blind vias, 8+ layer PCBs and epoxy resin for gluing ICs onto the underside
+of PCBs become quickly cost-prohibitive, despite the costs averaging out
+by the time mass-production is reached.
+
+So there is a barrier to entry to overcome, and the simplest way to
+overcome that is to not get into the "small PCB budget" territory that
+requires these techniques in the first place.
+
+# RAM Design Options
+
+This section covers various options for board layout and IC selection,
+including custom-designing ICs.
+
+## Multi-Chip Modules
+
+This is basically where the SoC and the RAM bare die are on a common
+PCB *inside* the same IC packaging. Routing between the dies is carried
+out on the common PCB, which is usually multi-layer.
+
+With the down-side that it requires large up-front costs to produce, plus
+an overhead on production costs when compared to separate ICs, the space
+and pincount savings can be enormous: one IC taking up 1.5 cm^2 instead
+of up to 15 cm^2 for a larger SoC plus routing plus 4 DRAM ICs, plus a
+saving of around 75 pins for 32-bit-wide DDR RAM not being needed to be
+brought out.
+
+In addition, beyond a certain speed (and number of dies on-board), the
+amount of power consumption could potentially exceed the thermal capacity
+of smaller packages in the first place.
+
+The short version is: for smaller DRAM sizes (32mb up to 256mb), on-board
+RAM as a Multi-Chip Module has proven extremely successful, as evidenced
+by the Ingenic M200 and X1000 SoCs that are used in smart watches sold in
+China. Beyond that capacity (512mb and above) the cost of the resultant
+multi-die chip appear less attractive than a multi-chip solution, meaning
+that it is quite a risky investment proposition.
+
+## Package-on-Package RAM
+
+The simplest way to express how much PoP RAM is not a good idea is
+to reference the following, an analysis of a rather useful but
+very expensive lesson:
+<http://laforge.gnumonks.org/blog/20170306-gta04-omap3_pop_soldering/>
+
+Package-on-Package RAM basically saves a lot of space on a PCB by stacking
+ICs vertically. It's typically used in mobile phones where space is at
+a premium, yet the flexibility when compared to (fixed capacity) Multi-Chip
+Modules is desirable.
+
+The problem comes in assembly, as the GTA04 / GTA05 team found out to their
+cost. In the case of the TI SoC selected, it was discovered - *after* the
+design had been finalised and pre-production prototypes were being assembled -
+that the SoC actually *warped and buckled* under the heat of the reflow oven.
+"Fixing" this involves extremely careful analysis and much more costly
+equipment than is commonly available, plus trying tricks such as covering
+the SoC and the PoP RAM in U.V. sensitive epoxy resin prior to placing it
+into the reflow oven, as a way to make sure that the IC "stack" has a
+reduced chance of warpage.
+
+Normally, a PoP RAM supplier, knowing that these problems can occur, simply
+will not sell the RAM to a manufacturer unless they have proven expertise
+or deep pockets to solve these kinds of issues. Nokia for example was known
+to have tried, in one case, to have failed sufficient times such that they
+had around 10,000 to 50,000 production-grade PCBs that needed to be recovered
+before they managed to find a solution. Once they had succeeded they went
+back to those failed units, had the SoC and PoP RAM removed (and either
+re-balled or, if too badly warped, simply thrown out), and re-processed
+the PCBs with new PoP RAM and SoC on them rather than write them off entirely:
+still a costly proposition all on its own.
+
+In short: Package-on-Package RAM is only something that, realistically, a
+multi-billion-dollar company can consider, when the supply volumes are
+*guaranteed* to exceed tens of millions of units.
+
+## Multi-chip Module RAM Interfaces
+
+One possibility would be to consider either custom-designing
+a RAM IC vs using a standard (JEDEC) RAM interface, or even some kind
+of pre-existing Bus (ATI, Wishbone, AXI). When DDR (JEDEC) standard
+interfaces are utilised, the advantage is that off-the-shelf die pricing
+and supply can be negotiated with any of the DRAM vendors.
+
+However, in a fully libre IC, if that is indeed one of the goals,
+it becomes necessary to actually implement the DRAM interface (JEDEC
+standard DDRn). Several independent designers have considered this:
+there even exists two published DDR3 designs that are already available
+online, the only problem being: they are Controllers not including the
+PHY (actual pin pads).
+
+So to save on doing that, logically we might consider utilising a
+pre-existing bus for which the VHDL / Verilog source code already
+exists: ATI Bus, SRAM Bus, even ONFI, or better Wishbone or AXI.
+The only problem is: now that you are into non-standard territory,
+it becomes necessary to consider *designing and making your own DRAM*.
+This is covered in the following section.
+
+## Custom DRAM or SRAM vs off-the-shelf dies
+
+The distinct advantage of an off-the-shelf die that conforms to the JEDEC
+DDR1/2/3/4 standard is: it's a known quantity, mass-produced (all the
+advantages already described above). We might reasonably wish to consider
+utilising SRAM instead, but SRAM is a multi-gate solution per "bit" whereas
+a DRAM cell is basically a capacitor, taking up only one gate's worth of
+space per bit: absolutely tiny, in other words, which is why it's used.
+
+Not only that but considering creating your own custom DRAM, you in effect
+become your own "single supplier", with Research and Development overheads
+to have had to take into consideration as well.
+
+In short: it's a huge risk with no guaranteed payoff, and not only that
+but if the development of the alternative DRAM fails but the SoC was
+designed exclusively without a JEDEC-standard DRAM interface on the
+expectation that the alternative DRAM *would* succeed, the SoC is now
+up the creek without a paddle.
+
+In reverse-engineering terms: the rule of thumb is, you never make more
+than one change at a time, because then you cannot tell which change
+actually caused the error. An adaptation of this rule of thumb to apply
+heree: there are *three* changes being made: one to use a non-standard
+Memory interface, two to develop and eentirely new DRAM chip and three to
+use the same non-standard Memory interface *on* that DRAM IC. In short,
+it's too much to consider all at once.
+
+## DDR1..DDR4
+
+Overall it's pointing towards using one of the standard JEDEC DDR interfaces.
+DDR1 only runs at 133mhz and the power consumption is enormous: 1.8v and above
+is not uncommon. DDR2 again is too slow and too power-hungry. DDR3 hits
+the right spot in terms of "common mass production" whereas DDR4, despite
+its speed and power consumption advantages, is migrating towards being
+too challenging.
+
+In an earlier section the availability of LPDDR4 RAM ICs, which would be great
+to use if they were easily accessible, was shown to be far too low. Not only
+that but DDR4 runs at a minimum 2400mhz DDR clock rate: 1200mhz (1.2ghz!)
+signal paths. It's now necessary to take into consideration the length of
+the tracks *on the actual dies* - both in the SoC and inside the DRAM - when
+designing the tracks between the two. It's just far too risky to consider
+tackling.
+
+So overall this is reinforcing that DDR3/DDR3L/LPDDR3 is the right choice
+*at this time*.
+
+# Conclusion: DDR3/DDR3L/LPDDR3
+
+DDR3 basically meets the requirements.
+
+* 4x DDR3L 8-bit FBGA78 ICs @ 1066mhz meets the power budget
+* Likewise 2x DDR3L 16-bit FBGA96 @ 1066mhz
+* Likewise 1x LPDDR3 32-bit FBGA168 @ 1866mhz
+* Pricing and availability is good on 8x and 16x DDR3/DDR3L ICs
+ (not so much on LPDDR3)
+* There are multiple suppliers of DDR3 including some chinese companies
+* 4x DDR3 8/16-bit RAM ICs easily fits into around 15 cm^2.
+
+Risks are reduced, pricing is competitive, supply is guaranteed, future
+supply as speeds increase is also guaranteed, power consumption is reasonable.
+Overall everything points towards DDR3 *at the moment*. Despite the iMX6
+still having nearly 15 years until it is EOL, meaning that Freescale / NXP
+genuinely anticipate availability of the types (speed grades) of DDR3 RAM ICs
+with which the iMX6 is compatible, it is *always* sensible to monitor the
+situation continuously, and, critically, to bear in mind that, in the
+projected lifespan planning, an SoC takes at least 18 months before it
+hits production.
+
+So from the moment that the SoC is planned, whatever peripherals (including
+DRAM ICs) it is to be used with, the availability planning starts a
+full *eighteen months* into the future. For a libre SoC where many
+people working on it will not consider signing NDAs, it becomes even
+more critically important to ensure that whatever ICs it requires -
+DRAM especially - are cast-iron guaranteed to be available within the SoC's
+projected lifespan. DDR3 it can be said to meet that and all other
+requirements.
+