- Computers & electronics
- Software
- Computer utilities
- Development software
- ST
- Linux
- User manual
- 220 Pages
ST Linux User Manual
ST Linux is a Linux-based operating system for the STreamPlug ST2100, a highly integrated system-on-a-chip (SoC) device. ST Linux provides a comprehensive set of features and capabilities that make it ideal for a wide range of applications, including home automation, industrial control, and multimedia streaming. With its powerful ARM-based core, wide range of peripherals, and support for the HomePlug AV standard, ST Linux is a versatile and capable platform for a variety of embedded applications.
advertisement
Assistant Bot
Need help? Our chatbot has already read the manual and is ready to assist you. Feel free to ask any questions about the device, but providing details will make the conversation more productive.
UM1942
User manual
Linux software user manual for STreamPlug ST2100
Introduction
The STreamPlug ST2100 is a highly integrated SoC including an ARM
®
-based core, a wide set of peripherals and a PLC modem supporting the HomePlug™ AV standard. The full configuration of STreamPlug software is composed of three most important components as
Section 1: STreamPlug full software architecture on page 10
: the
STMicroelectronics
®
interface layer with the core scheduler, the system software and OK
Linux
®
, (i.e.: a Linux kernel over the hypervisor provided by Open Kernel Labs, Inc. (OK
Labs), now General Dynamics Broadband). The minimal configuration of the STreamPlug software includes the native Linux kernel running after the boot, without the core scheduler and hypervisor. This configuration is called also “native Linux” or “native” in following sections.
This document is not intended to be a tutorial on the Linux operating system or embedded software design/development. It only covers topics that are specific to use the STreamPlug
Linux.
November 2015 DocID028276 Rev 1 1/220
www.st.com
220
1
2
Contents
Contents
3
4
2/220
UM1942
STreamPlug full software architecture . . . . . . . . . . . . . . . . . . . . . . . . . 10
Linux OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Platform software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Platform kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . 14
Board compilation support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Pad software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Pad kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Clock framework software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Clock framework kernel source and configuration . . . . . . . . . . . . . . . . . 26
Clock framework internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Clock framework usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
RTC software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
RTC kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . 31
RTC platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Communication drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Gigabit media access controller (GMAC) - Ethernet . . . . . . . . . . . . . . . . 34
GMAC software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
GMAC kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 36
GMAC platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
DocID028276 Rev 1
UM1942 Contents
Universal serial bus (USB) host . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
USB host kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . 39
USB host platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Universal serial bus (USB) device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
USB device software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
USB device kernel source and configuration . . . . . . . . . . . . . . . . . . . . . 47
USB device platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
USB platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
C controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
C controller hardware overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
C controller software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
C controller kernel source and configuration . . . . . . . . . . . . . . . . . . . . 61
C controller platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
C controller usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Serial peripheral interface (SPI) controller . . . . . . . . . . . . . . . . . . . . . . . . 67
SPI software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
SPI kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
SPI platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Linux TTY framework software overview . . . . . . . . . . . . . . . . . . . . . . . . 74
kernel source . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Linux TTY framework usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Universal asynchronous receiver/transmitter (UART) . . . . . . . . . . . . . . . 76
UART software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
UART kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 78
UART platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Control area network (CAN) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
CAN software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
CAN kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . 80
CAN platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
DocID028276 Rev 1 3/220
220
Contents
5
UM1942
Fast infrared data association (FIrDA) . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
FIrDA software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
FIrDA kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 83
FIrDA platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Peripheral component interconnect express (PCIe) . . . . . . . . . . . . . . . . . 90
PCIe software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
PCIe kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . 97
PCIe platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Serial advanced technology attachment (SATA) . . . . . . . . . . . . . . . . . . 100
SATA software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
SATA kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 101
SATA platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Memory technology devices (MTD) . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
Linux MTD framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
Accessing to MTD devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Raw access from user space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Raw access from kernel space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Access through file system from user space . . . . . . . . . . . . . . . . . . . . 112
Flexible static memory controller (FSMC) . . . . . . . . . . . . . . . . . . . . . . . .112
NAND, FSMC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Parallel NOR, FSMC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Static RAM (SRAM), flexible static memory controller . . . . . . . . . . . . . 119
Serial memory interface (SMI) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
SMI hardware overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
SMI software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
SMI kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . 124
SMI platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
4/220 DocID028276 Rev 1
UM1942
6
7
8
Contents
Accelerators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
JPEG encoder/decoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
JPEG encoder/decoder software overview . . . . . . . . . . . . . . . . . . . . . 127
JPEG encoder/decoder kernel source and configuration . . . . . . . . . . 128
JPEG encoder/decoder platform configuration . . . . . . . . . . . . . . . . . . 128
JPEG encoder/decoder usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Direct memory access (DMA) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
DMA hardware overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
DMA software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
DMA kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 144
DMA platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Channel controller coprocessor (C3) . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
C3 software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
C3 kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
C3 platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Frame buffer drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Miscellaneous devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
General purpose input/output (GPIO) . . . . . . . . . . . . . . . . . . . . . . . . . . 158
GPIO software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
GPIO kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 159
GPIO platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
Application specific GPIO (AS GPIO) . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
AS GPIO software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
AS GPIO kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . 163
AS GPIO platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
DocID028276 Rev 1 5/220
220
Contents
9
10
11
UM1942
Watchdog timer (WDT) driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
WDT software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
WDT kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 169
Audio drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
SPORT controller kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . 177
Video drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Video for Linux Two framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
SoC-Camera framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Video transport stream (TS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
TS software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
TS kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
TS platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Virtualized devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
KSP software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
KSP kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . . 205
KSP platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Miscellaneous register access (Misc) . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Virtual log software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Virtual log kernel source and configuration . . . . . . . . . . . . . . . . . . . . . 208
Virtual log platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
6/220 DocID028276 Rev 1
UM1942 Contents
SMI/FSMC NAND memory shared access . . . . . . . . . . . . . . . . . . . . . . 209
SMI/FSMC NAND software overview . . . . . . . . . . . . . . . . . . . . . . . . . 209
SMI/FSMC NAND kernel source and configuration . . . . . . . . . . . . . . . 210
SMI/FSMC NAND platform configuration . . . . . . . . . . . . . . . . . . . . . . 210
HomePlug AV (HPAV) driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
HPAV software overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
HPAV kernel source and configuration . . . . . . . . . . . . . . . . . . . . . . . . 212
HPAV platform configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Image validate device driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Image validate device driver software overview . . . . . . . . . . . . . . . . . 214
Image validate device driver kernel source and configuration . . . . . . . 216
Image validate device driver platform configuration . . . . . . . . . . . . . . 216
Image validate device driver usage . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
Appendix A Acronyms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Revision history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
DocID028276 Rev 1 7/220
220
List of tables
List of tables
UM1942
C configurations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
S configurations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
8/220 DocID028276 Rev 1
UM1942
List of figures
List of figures
C framework architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
DocID028276 Rev 1 9/220
220
STreamPlug full software architecture
1 STreamPlug full software architecture
UM1942
The interface layer with the core scheduler provides the necessary APIs to support the system software layer and the hypervisor. The system software provides the core software which implements the HPAV/1901/GP MAC as well as the supporting modules. The OK
Linux consists of a collection of all the Linux (2.6.35.0) device drivers that control the specific hardware controllers embedded in the STreamPlug board and the virtualization technology provided by the OKL, (i.e.: the OKL4 Microvisor). Using the OKL technology to host a Linux guest OS confers the following benefits:
ï‚·
Linux applications can run on the same processor side by side with legacy applications and legacy OSes.
ï‚·
Concurrent support for two OS environments eliminates the need for either multiprocessor hardware or porting the legacy system to the Linux OS.
ï‚·
Using “Secure HyperCell
TM
Technology”, OKL4 native cells can complement the Linux virtual machine (VM) by providing an execution environment with better real-time properties and stronger security.
OKL4 cells are well suited to hosting real-time OSes, easing implementation of latencysensitive functions without sacrificing the rich ecosystem support available for the Linux.
Figure 1. STreamPlug full software architecture
Linux applications
OK Linux kernel
Hypervisor
System software
HPAV/1901/GP
MAC
Support modules:
· Boot
· Firmware upgrade
· Production test
Interface layer / core scheduler
AM039813
10/220 DocID028276 Rev 1
UM1942 Linux OS
The Linux supplied with the LSP, which is based on the kernel version 2.6.35.0, is licensed under the GPLv2 and distributed with the full source code.
Linux is an open source operating system running on all major processor architectures, including ARM processors. It is supported by a large group of engineers contributing back into the open source. This makes Linux a very dynamic and fast moving operating system.
Key benefits of Linux on ARM:
ï‚·
Complete scalable operating system providing a reliable multi-tasking environment
ï‚·
Based on an open source model (GPL)
ï‚·
Leverage a wide range of UNIX and open source applications
ï‚·
Early availability on ARM processor-based platforms
ï‚·
Used in many ARM technology-based designs including networking and wireless products
ï‚·
Broad support through open discussion forums.
Please refer to http://Kernel.org for references. Public forums are available to review patches and information related to Linux development on ARM.
Linux support package (LSP)
STreamPlug LSP supports the following features of Linux:
ï‚·
Based on Linux-2.6.35.0 version
ï‚·
Virtual layer provided by the OKL4 between the kernel and HW (not present in the native configuration)
ï‚·
All drivers integrated into standard Linux device model
ï‚·
Where ever possible the drivers available from the kernel.org repository mainline have been reused
DocID028276 Rev 1 11/220
220
Linux OS UM1942
The LSP incorporates the STreamPlug specific set of drivers shown in
Section
Audio support
Video support
Table 1. Linux support package
Platform section
Communication device drivers
Non-volatile memory device drivers
Accelerators
Human interface device (HID) drivers
Miscellaneous device drivers
Virtual devices support
(these driver are available only in paravirtualized configuration)
Module
Paravirtualized system clock
Paravirtualized vector interrupt controller (VIC)
Real-time clock (RTC) driver
GMAC Ethernet driver
USB host
USB device
I
2
C driver
SPI driver
UART driver
CAN driver
FIrDA
®
driver
PCIe driver (root complex and endpoint)
SATA driver
FSMC NAND driver
FSMC NOR driver
Serial NOR Flash driver (SMI interface)
USB mass storage support
I
2
C and SPI memory device support
JPEG driver
General purpose DMA (DMAC) drivers
C3 driver
CLCD, LCD panel support
General purpose I/O (GPIO) driver
AS GPIO (I/O and PWM) driver
Watchdog (WDT) driver
SPORT-I
2
S driver, sound card device support
TS driver, camera capture support
KSP interface
Misc regs access
Vlog
Flash memory shared access
HPAV driver
Image validate
12/220 DocID028276 Rev 1
UM1942
3 Platform
Platform
This section describes the basic STreamPlug platform code and driver distributed in the standard machine specific layout of the Linux ARM architecture.
The platform or the machine specific code is responsible for
ï‚·
Initializing Virtual Interrupt Controller (or vector interrupt controller in the native configuration)
ï‚·
Initializing the timer (clock source and clock event)
ï‚·
Initializing static memory mapping if required by the system
ï‚·
Defining the IO_ADDRESS and related macros so that the static memory can be used
ï‚·
Providing the platform specific code for
– Clock framework
– Padmux framework
– Initialization code for some specific controllers like FSMC and GPIO
– Defining virtual IRQs in case of shared IRQs on the platform
ï‚·
Providing system specific header files like those describing IRQ lines and base addresses of respective devices
ï‚·
Platform specific drivers
The machine specific code base is distributed among following directories:
ï‚·
“arch/arm/plat-streamplug”- indicates all the STreamPlug SoCs
ï‚·
“arch/arm/mach-streamplug - represents the STreamPlug family of boards
The platform is unique and when running in the full configuration it's paravirtualized by the presence of a hypervisor between FW and HW.
The “mach-streamplug” directory contains the following files:
ï‚·
“clock.c” (machines clock framework)
ï‚·
“dw_pcie.c” (PCIe functions for Synopsys DW controllers)
ï‚·
“fsmc-nor.c” (FSMC - flexible static memory controller - interface for NOR Flash)
ï‚·
“fsmc-sram.c” (FSMC - flexible static memory controller - interface for SRAM device)
ï‚·
“pswrst_ctrl.c” (STreamPlug machines IP's software reset control source file)
ï‚·
“miphy.c” (MiPHY™ routine source file)
ï‚·
“padmux.c” (STreamPlug machines IP's padmux handling source file)
ï‚·
“streamplug1x.c” (STreamPlug1x machines common source file)
ï‚·
“streamplug1x_pcie_rev_350.c” (supports STreamPlug1x PCIe rev_350)
ï‚·
“streamplug10.c” (STreasmPlug10 machine source file)
ï‚·
“streamplug_devel_board.c” (STreamPlug devel. board source file)
ï‚·
“streamplug_ksp_agent.c” (STreamPlug KSP interface controller)
DocID028276 Rev 1 13/220
220
Platform
3.1.2
UM1942
The “plat-streamplug” directory contains the following files:
ï‚·
“clcd.c” (CLCD configuration file)
ï‚·
“clock.c” (clock framework for STreamPlug platform)
ï‚·
“ipswrst_ctrl.c” (IP's software reset control for STreamPlug platform)
ï‚·
“jpeg.c” (JPEG platform specific information file)
ï‚·
“misc.c” (Misc platform routine source file)
ï‚·
“padmux.c” (STreamPlug platform specific IP's padmux handling source file)
ï‚·
“pll_clk.S” (PLL clock configuration for STreamPlug platform)
ï‚·
“time.c” (STreamPlug platform: timer configuration file)
ï‚·
“udc.c” (STreamPlug platform: USB device configuration file).
Platform kernel source and configuration
The Linux kernel running on the STreamPlug SoC was inherited from the open source basic software version 2.6.35. The STreamPlug chip is based on the ARM926 architecture.
lists the branches added or modified within the ARM Linux tree in order to include this release support of the STreamPlug machine (see
) and device drivers:
File or folder
/arch/arm/mach-STreamPlug
/arch/arm/plat-STreamPlug
/arch/arm/okl4-microvisor
/arch/arm/boot/Makefile
/arch/arm/configs
/arch/arm/Kconfig
/arch/arm/Makefile
Table 2. Linux branches
Status
New
New
New
Modified in order to support the build of an ELF image compressed
Modified in order to include machine configurations.
Paravirtualized kernel: okl4_hybrid_platform_streamplug_devel_board_defconfig
Native Linux configuration: streamplug_devel_board_defconfig
Modified in order to add the configuration for the STreamPlug platform
Modified in order to set the Linux entry offset to 0x00048000 and to add help comment for the ELF image
14/220 DocID028276 Rev 1
UM1942 Platform
The Linux kernel supports the following device drivers:
ï‚·
Virtual Interrupt Controller
ï‚·
Timers
ï‚·
RTC
ï‚·
Ethernet “Best Effort”
ï‚·
USB host
ï‚·
USB device (Ethernet, Zero and FS gadget) compiled as modules
ï‚·
I
2
C, with STreamPlug configured as master on I
2
C bus
ï‚·
SPI, with STreamPlug configured as master on SPI interface
ï‚·
UART
ï‚·
CAN
ï‚·
FIrDA
ï‚·
PCIe RC and EP
ï‚·
SATA
ï‚·
FSMC
ï‚·
SMI
ï‚·
JPEG (decoder and encoder)
ï‚·
DMA
ï‚·
C3
ï‚·
CLCD
ï‚·
GPIO
ï‚·
AS GPIO (I/O and PWM)
ï‚·
Watchdog
ï‚·
SPORT Audio out & in
ï‚·
TS
ï‚·
Virtualised devices (full configuration)
The STreamPlug provides numerous possible functions, some of which are multiplexed with each other. These configurations are very much application dependent. Each board designed around the STreamPlug follows the application need to develop a board which exploits a particular kind of applications. Accordingly, software needs to configure the SoC to suit the board layout and let the user to use the desired functionality. Besides multiplexed functionality there are other board dependent configurations like usage of GPIOs which again must be handled in software.
DocID028276 Rev 1 15/220
220
Platform UM1942
In ARM platforms each machine (board) is associated with a unique number called machine
ID (MACH_ID). In order to have a one-to-one association, a new MACH_ID should be registered in the table of the all Linux ARM machine, supported by Russell King. This machine ID can be registered from the arm website: www.arm.linux.org.uk/developer/ machines/?action=new.
lists the machine ID defined into arch/arm/tools/mach-types for STreamPlug boards.
# machine_is_xxx
STreamPlug
Table 3. STreamPlug machine ID
CONFIG_xxxx MACH_TYPE_xxx
MACH_STREAMPLUG STreamPlug
Number
4011
Note:
To compile the Linux, first setup these environment variables:
$ export CROSS_COMPILE=arm-none-linux-gnueabi--
$ export ARCH=arm
The generic commands to use for building the Linux kernel are the following ones:
$ make distclean -> to clean all obj files
$ make <configuration file>-> to configure Linux Kernel for the desired processor architecture
$ make <type of image> -> to build Linux Kernel elf Image
The makefile specific for the STreamPlug machine is below “<linux root>/arch/arm”.
Before building the Linux, install the toolchain provided by the CodeSourcery “arm-2009q1-
203-arm-none-linux-gnueabi-”: www.sources.buildroot.net/arm-2009q1-203-arm-nonelinux-gnueabi-i686-pc-linux-gnu.tar.bz2.
Using:
$ make ARCH=arm distclean will clean all *.objs and *.config files.
After cleaning the whole project, it's mandatory to build the configuration for the
STreamPlug, before building the Linux kernel image.
In order to build the Linux kernel binary image for the STreamPlug environment, the Linux
*.config file has to point to the configuration file specific for the STreamPlug chip; currently the configuration used are included into:
ï‚·
“okl4_hybrid_platform_streamplug_devel_board_defconfig” for the development SoC board
ï‚·
“streamplug_devel_board_defconfig” for the development SoC board (for native Linux) below the “arch/arm/configs” folder.
16/220 DocID028276 Rev 1
UM1942 Platform
The command line to setup the default configuration is:
$ make okl4_hybrid_platform_streamplug_devel_board_defconfig
Executing that command, the following traces will be displayed:
HOSTCC scripts/basic/fixdep
HOSTCC scripts/basic/docproc
HOSTCC scripts/basic/hash
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/kxgettext.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/lex.zconf.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
In case a new configuration is needed, the following commands are available:
$ make menuconfig or
$ make xconfig or
$ make gconfig using:
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- vmlinux will compile the Linux kernel project and build the kernel image below “<linux root>” for the full configuration or
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- elfImage will compile the Linux kernel project and build the uncompressed kernel image wrapper in the ELF container below “arch/arm/boot” for the native configuration.
Both configurations support Ext2, JFFS2 and UBI file systems.
DocID028276 Rev 1 17/220
220
Platform
3.3
UM1942
Pad multiplexing support
In order to decrease the number of pads, the STreamPlug design multiplexes some of the functionalities on the same I/O pins. So, which functionality has to be routed on a particular pad is board specific information that has to be activated at run-time according to the options that configure each peripheral, passed to the Linux at the startup via the command line.
Based upon the actual board layout and the functionality which it supports, the devices are listed into an array that is registered to the STreamPlug padmux framework.
From the STreamPlug machine architecture, below “arch/arm/mach-streamplug/padmux.c”: static struct pmx_dev *streamplug_pmx_dev_lookups[ ] =
{
&pmx_dev_arm_gpio1_info,
&pmx_dev_arm_gpio2_info,
&pmx_dev_pgc_info,
&pmx_dev_dai_info,
&pmx_dev_sport_info,
&pmx_dev_ts_info,
&pmx_dev_ark_gpio_info,
&pmx_dev_clcd_info,
&pmx_dev_uart1_info,
&pmx_dev_uart2_info,
&pmx_dev_sata_info,
&pmx_dev_pcie_info,
&pmx_dev_usb_info,
&pmx_dev_eth_info,
&pmx_dev_i2c_info,
&pmx_dev_ssp_info,
&pmx_dev_can_info,
&pmx_dev_fsmc_info,
&pmx_dev_firda_info
}
/* machine IP's padmux enabling */ void init streamplug1x_padmux(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(streamplug_pmx_dev_lookups); i++)
pmx_dev_enable(streamplug_pmx_dev_lookups[i]);
}
Padmux handling is enabled during the machine initialization phase.
18/220 DocID028276 Rev 1
UM1942 Platform
For development board support (“arch/arm/mach-streamplug/streamplug_devel_board.c”) use: static void init streamplug10_devel_board_init(void)
{
...
streamplug1x_padmux();
3.3.1
...
}
Pad software overview
The devices options passed via the command line to the Linux kernel are parsed by the padmux handler that is in the STreamPlug “arch/arm/mach-streamplug/padmux.c”. Its purpose is to translate the string format of peripheral devices configuration passed by the command line into platform data that will be needed to enable the activation and configuration of a peripheral device by its own driver.
Multiplexed devices on the STreamPlug are abstracted through a structure “pmx_dev” defined as:
/*
* struct pmx_dev: device definition structure
*
* name: device name
* platform: device to be register when pmx is actived
* modes: device configuration array for different modes supported
* mode_count: size of modes array
* is_active: is peripheral active/enabled
* selected: number of peripheral mode selected at bootime
*/ struct pmx_dev {
char *name;
struct pmx_dev_mode **modes;
u8 mode_count;
u8 selected;
void (*parse)(struct pmx_dev *pmx, char *options);
};
DocID028276 Rev 1 19/220
220
Platform UM1942
where “pmx_dev_mode” is essentially an array of the register’s set and value which must be written into it in order to enable the device
/*
* struct pmx_dev_mode: configuration structure every group of modes of a device
*
* name: mode name
* mux_regs: array of mux registers, masks and valuesto enable the device in
* this group of modes
* mux_reg_cnt: count of mux_regs elements
*/ struct pmx_dev_mode {
char *name;
struct pmx_mux_reg *mux_regs;
u8 mux_reg_cnt;
struct platform_device *platform_dev;
struct amba_device *amba_dev;
struct platform_device *platform_dev2;
struct amba_device *amba_dev2;
}; where “pmx_mux_reg” is a simple structure defining the address where one must write a particular value to enable the device.
/*
* struct pmx_mux_reg: configuration structure every group of modes of a device
*
* reg: register of multiplexing
* value: value to be written
*/ struct pmx_mux_reg {
struct pmx_reg *reg;
u32 value;
};
For example consider enumeration of the multiplexed SSP device: static struct pmx_reg conf_gpio_g21 = {
.address = (void *)( GetOffset (sMiscRegs, conf_gpio_g21)),
.mask = 0x7,
.offset = 0,
.size = 4,
};
static struct pmx_mux_reg ssp_mode_regs[] = {
{ .reg = &conf_gpio_g21, .value = 0x0 },
20/220 DocID028276 Rev 1
UM1942 Platform
}; static struct pmx_dev_mode ssp_mode = {
.name = "primary",
.mux_regs = ssp_mode_regs,
.mux_reg_cnt = ARRAY_SIZE(ssp_mode_regs),
.amba_dev = &streamplug1x_ssp_device,
}; static struct pmx_dev_mode *ssp_modes[] = {
&ssp_mode,
}; void parse_ssp_options(struct pmx_dev *dev, char *options)
{
cs_gpio_pin = simple_strtoul(options, NULL, 10);
printk(KERN_INFO "%s gpio_pin %d", func , cs_gpio_pin);
}
DECLARE_PMX_DEV(ssp, ssp_modes, 1, parse_ssp_options); where “DECLARE_PMX_DEV” is the macro purpose of which is generated the final device structure according to the optional parameters passed via the command line (in case of SSP options are the GPIO pin number for select CHIP-SELECT) that will be used to enable the correspondent device (i.e.: “pmx_dev_ssp_info” for SSP).
The STreamPlug platform padmux generic framework is implemented in “arch/arm/platstreamplug/padmux.c”.
DocID028276 Rev 1 21/220
220
Platform UM1942
lists all of the possible configurations to be passed to the ATAG command line in order to enable the desired set of peripherals.
Peripheral
Table 4. Command line options for padmux configuration
Values
CLCD
PCIe bridge
USB controller
I
2
Ethernet network controller
C controller
Synchronous serial port
UART port 1 clcd=on:24bpp, if the CLCD is enabled with 24 bpp clcd=on:18bpp, if the CLCD is enabled with 18 bpp clcd=off, if the CLCD is disabled
– pcie=on:rc:1, if the PCIe is configured as a root complex with the MiPHY clock generated by the pll2 input clock
– pcie=on:rc:2, if the PCIe is configured as a root complex with the MiPHY clock generated by the qfs4 input clock
– pcie=on:rc:3, if the PCIe is configured as a root complex with the MiPHY clock generated by the external clock
– pcie=on:ep:1, if the PCIe is configured as an endpoint with the MiPHY clock generated by the pll2 input clock
– pcie=on:ep:2, if the PCIe is configured as an endpoint with the MiPHY clock generated by the qfs4 input clock
– pcie=on:ep:3, if the PCIe is configured as an endpoint with the MiPHY clock generated by the external clock
– pcie=off, if the PCIe is disabled
– usb=on:device, if the USB is activated as a gadget
– usb=on:host, if the USB is activated as a host
– usb=off if the USB is not configured
– eth=<on,off,rtos>:<primary.secondary>:<1,. . . ,3>:<Mac Address>
Some examples:
– eth=on:primary:1:00:80:40:AE:20:98, if the device driver is configured on low GPIOs groups, with the pll2 input clock as a PHY clock root, and with a default MAC address
– eth=on:secondary: :00:80:40:AE:20:98, if the device driver is configured on high GPIOs groups, with the qfs4 input clock as a PHY clock root, and with a default MAC address
– eth=on:primary:3:00:80:40:AE:20:98, if the device driver is configured on low GPIOs groups, with the external clock as a PHY clock root, and with a default MAC address
– eth=off, if Ethernet is disabled
– eth=rtos:primary, if the device driver is configured on high GPIOs groups and assigned to system FW
– i2c=on, if the I
2
C interface is enabled and configured
– i2c=off, if the I
2
C interface is disabled
– ssp=on:<24,. . . ,39>, if the SPI interface is enabled and configured with a fixed CHIP-SELECT line
– ssp=off, if the SPI interface is disabled
The default value for number of GPIO used by the OK Linux to reserve the SPI CHIP-SELECT
Line is 39. For STreamPlug OK Linux GPIOs the numbers reserved start from 24 to 39.
– uart1=on:primary, the UART1 enabled on the GPIO primary group
– uart1=on:secondary, the UART1 enabled on the GPIO secondary group
– uart1=off, the UART1 switched off
– uart1=rtos:secondary, the UART1 enabled on the secondary group by system FW
22/220 DocID028276 Rev 1
UM1942 Platform
Peripheral
UART port 2
CAN network controller
FIrDA
FSMC
SATA
SPORT
TS
AS GPIO
Table 4. Command line options for padmux configuration (continued)
Values
– uart2=on:primary, the UART2 enabled on the GPIO primary group
– uart2=on:secondary, the UART2 enabled on the GPIO secondary group
– uart2=off, the UART2 switched off
– uart2=rtos:secondary, the UART2 enabled on the secondary group by system FW
– can=on:primary, if the device driver is configured on the low GPIOs group
– can=on:secondary, if the device driver is configured on the high GPIOs group
– can=off, if the device driver is disabled
– firda=on:1, if it supports only the SIR mode
– firda=on:2, if it supports only SIR and MIR modes
– firda=on:3, if it supports all SIR, MIR and FIR modes
– firda=off, if the device driver is disabled
– fsmc=on:<nand,sram,nor><0,1>:[initdone]
Some examples:
– fsmc=on:nand0:initdone, if the FSMC controller is enabled and configured for NAND Flash memory devices with 8-bit data width, while timing parameters are not changed (initialized by
RTOS)
– fsmc=on:nand1, if the FSMC controller is enabled and configured for NAND Flash memory devices with 16-bit data width
– fsmc=on:nor1, if the FSMC controller is enabled and configured for Parallel NOR Flash memory devices with 16-bit data width
– fsmc=off, if the FSMC is disabled
– sata=on:1, if the SATA is enabled and configured with the MiPHY clock generated by the pll2 input clock
– sata=on:2, if the SATA is enabled and with the MiPHY clock generated by the qfs4 input clock
– sata=on:3, if the SATA is enabled and with the MiPHY clock generated by the external clock
– sata=off, if the SATA is disabled
– sport=on, if the SPORT is enabled
– sport=off, if the SPORT is disabled
– ts=on, if the TS is enabled
– ts=off, if the TS is disabled
– ark_gpio=<on,off>:<nnnnnn,n=0,1,2>
Some examples:
– ark_gpio=on:110000, if the ARK_GPIO device driver is enabled with only the GPIOs group A and B enabled
– ark_gpio=on:011221, if the ARK_GPIO device driver is enabled with AS GPIOs groups:
– A disabled
– B enabled
– C enabled on the GPIO_GROUP 04
– D enabled on the GPIO_GROUP 10
– E enabled on the GPIO_GROUP 18
– F enabled on the GPIO_GROUP 13
– ark_gpio=off, if the AS GPIO is disabled
DocID028276 Rev 1 23/220
220
Platform UM1942
Peripheral
GP (ARM)
GPIO
LINUX
CONSOLE
SYSTEM
(RTOS)
CONSOLE
Table 4. Command line options for padmux configuration (continued)
Values
– arm_gpio1=on, if the GP gpio group 1 is enabled
– arm_gpio2=on, if the GP gpio group 2 is enabled
For the native Linux, they should be always on and they are set by default cmdline.
– console=none if the Linux console is suppressed
– console=<tty device>,<tty configuration>
– console= ttyAMA0,115200n8, if the Linux console on ttyAMA0 with configuration: baudrate
115200 bps, flow control “none”, data size 8 bits (default)
– console= ttyAMA1,115200n8, if the Linux console on ttyAMA1 (valid only if both UARTs to
Linux) with default configuration.
– rtosconsole=<uart port>,<uart configuration>
– rtosconsole=uart1,115200n81
– rtosconsole=uart2,115200n81 (default)
If not present no console is available on UARTs.
In this case, the stpconsole application example can be used to access the RTOS console from the Linux.
Note: Important: It is up to the user to ensure that no conflicting configurations are chosen.
Normally this is taken care of in the board design, because the board has to be designed with a particular configuration option in mind and any conflicts must be resolved at the board design level. In the LSP support, only the devices supported by the board have to be enumerated in the manner described above. However, if there are any conflicting options chosen, the padmux initialization for the device mentioned last in the array is retained and the other device multiplexed with this particular device may not work.
The clock framework defines programming interfaces to support software management of the system clock tree. This framework is widely used with system-on-chip (SOC) platforms to support various devices which may need custom clock rates. Note that these “clocks” don't relate to timekeeping or real-time clocks (RTC), each of which have separate frameworks.
24/220
Clock framework support in the LSP is implemented around the Linux abstraction layer for clocks defined in “include/linux/clk.h”.
This abstraction only tends to declare and not define the APIs with their standard interfaces that must be implemented by the required platform. The platform is also expected to define the clock abstraction through “struct clk”. The struct clk is abstracted in “arch/arm/platstreamplug/include/plat/clock.h”:
/**
* struct clk - clock structure
* @usage_count: num of users who enabled this clock
* @flags: flags for clock properties
* @rate: programmed clock rate in Hz
DocID028276 Rev 1
UM1942 Platform
* @en_reg: clk enable/disable reg
* @en_reg_bit: clk enable/disable bit
* @ops: clk enable/disable ops - generic_clkops selected if NULL
* @recalc: pointer to clock rate recalculate function
* @set_rate: pointer to clock set rate function
* @calc_rate: pointer to clock get rate function for index
* @rate_config: rate configuration information, used by set_rate
* @div_factor: division factor to parent clock.
* @pclk: current parent clk
* @pclk_sel: pointer to parent selection structure
* @pclk_sel_shift: register shift for selecting parent of this clock
* @children: list for childrens or this clock
* @sibling: node for list of clocks having same parents
* @private_data: clock specific private data
* @node: list to maintain clocks linearly
* @cl: clocklook up assoicated with this clock
* @dent: object for debugfs
*/ struct clk {
unsigned int usage_count; unsigned int flags; unsigned long rate; unsigned int *en_reg;
u8 en_reg_bit;
const struct clkops *ops;
int (*recalc) (struct clk *clk, unsigned long *rate,
unsigned long prate);
int (*set_rate) (struct clk *clk, unsigned long rate); unsigned long
(*calc_rate)(struct clk *, int index);
struct rate_config rate_config;
unsigned int div_factor;
struct clk *pclk;
struct pclk_sel *pclk_sel;
unsigned int pclk_sel_shift;
struct list_head children; struct list_head sibling; void *private_data;
#ifdef CONFIG_DEBUG_FS
struct list_head node; struct clk_lookup *cl; struct dentry *dent;
#endif
};
DocID028276 Rev 1 25/220
220
Platform UM1942
The following APIs are defined by the standard Linux CLK abstraction, which can be found in “include/linux/clk.h”:
ï‚·
“clk_get” lookup and obtain a reference to a clock producer
ï‚·
“clk_enable” inform the system when the clock source should be running
ï‚·
“clk_disable” inform the system when the clock source is no longer required
ï‚·
“clk_get_rate” obtain the current clock rate (in Hz) for a clock source. (This is only valid once the clock source has been enabled.)
ï‚·
“clk_put” “free” the clock source
ï‚·
“clk_round_rate” adjust a rate to the exact rate a clock can provide
ï‚·
“clk_set_rate” set the clock rate for a clock source
ï‚·
“clk_set_parent” set the parent clock source for this clock
ï‚·
“clk_get_parent” get the parent clock source for this clock
ï‚·
“clk_get_sys” get a clock based upon the device name
ï‚·
“clk_add_alias” add a new clock alias
Above mentioned APIs and “struct clk” are implemented in following files:
ï‚·
“arch/arm/plat-streamplug/include/plat/clock.h”
ï‚·
“arch/arm/plat/streamplug/clock.c” while the definitions and enumerations of each clock are defined in the following file:
“arch/arm/mach-streamplug/clock.c”.
This section defines and provides an overview about the internal implementation of the
STreamPlug clock framework. Users may not need to know all the details mentioned below.
However, referring to this section can be beneficial to extend the clock framework or the rate tables in order to adapt to specific needs.
All of the clocks which can be used in the system are defined in: “arch/arm/machstreamplug/clock.c”. For example the clk struct for the UART1 device is configured as follows:
/* uart1 clock */ static struct clk uart1_clk =
{
.flags = ENABLED_ONCE,
.en_reg = (u32* )( GetOffset (sMiscRegs, low_speed_sub_clk_enb_reg)),
.en_reg_bit = UART1_CLKENB_Pos,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLKSEL_Pos,
.recalc = &follow_parent,
};
26/220 DocID028276 Rev 1
UM1942 Platform
Note that this clock object has:
ï‚· an enable/disable bit
ï‚· a multiple parent clock possible, defined through “uart1_pclk_sel”
ï‚· and that it just follows parent's clock rate without applying any divisor
In general a parent clock can be selected by writing corresponding “pclk_val to pclk_sel_reg” with a mask of “pclk_sel_mask “shifted by “pclk_sel_shift”. The user would not bother with these internal details because they are implementation details, the user may just call the “clk_set_parent” API. The “uart_synth_clk “and “pll3_usb_48m_clk” which are possible parents of the UART clock, can have their own parents and so on, in order to build the complete hierarchy.
An example to show the possible parents of the UART 1 is:
/* uart parent select structure */ static struct pclk_sel uart_pclk_sel =
{
.pclk_info = uart_pclk_info,
.pclk_count = ARRAY_SIZE(uart_pclk_info),
.pclk_sel_reg = (u32* )( GetOffset (sMiscRegs, gen_clk_cfg_reg)),
.pclk_sel_mask = GEN_CLK_CFG_UART_CLKSEL_MASK,
}; static struct pclk_info uart_pclk_info[] =
{
{
.pclk = &uart_synth_clk,
.pclk_val = GEN_CLK_PLL1_VAL,
},
{
.pclk = &pll3_usb_48m_clk,
.pclk_val = GEN_CLK_PLL3_VAL,
},
};
These structures define possible parents of the UART1 and how to select them, for example:
ï‚·
“uart_synth_clk” can be selected by writing 1 onto the bit 4 “UART/UART2” of the
“gen_clk_cfg_reg” miscellaneous register
ï‚·
“pll3_usb_48m_clk” can be selected by writing 0 onto the bit 4 “UART/UART2” of the
“gen_clk_cfg_reg” miscellaneous register
As an example to show one of the parents, “uart_synth_clk”:
/* uart synth clock */ static struct clk uart_synth_clk =
{
.en_reg = (u32* )( GetOffset (sMiscRegs, uart_clk_synt_reg)),
.en_reg_bit = SYNT_CLK_ENB_Pos,
.pclk = &pll1_clk,
DocID028276 Rev 1 27/220
220
Platform UM1942
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
.private_data = &uart_synth_config,
};
Because this is a synthesizer which has divisors and multipliers, it can adapt to the required rate. For this, it defines its “calc_rate”, “recalc” and “set_rate” functions which can be used by the clock framework to set the desired clock rate. It also defines rate_config which actually points to a table (“aux_rtbl”) which contains entries of divisors values used to generate a given rate.
The “rate_config” is a simple structure defined as:
/**
* struct rate_config - clk rate configurations
* @tbls: array of device specific clk rate tables, in ascending order of rates
* @count: size of tbls array
* @default_index: default setting when originally disabled
*/ struct rate_config {
void *tbls;
u8 count;
u8 default_index;
};
The “rate_config” points to a rate table (see example below) and a default index. The default index is used by the clock framework to fall back to a particular rate (pointed by index) when an invalid rate attempts to be programmed.
/* aux rate configuration table, in ascending order of rates */ struct aux_rate_tbl aux_rtbl[] =
{
/* For PLL1 = 332 MHz */
{.xscale = 2, .yscale = 37, .eq = 0},/* 9 MHz */
{.xscale = 1, .yscale = 8, .eq = 0}, /* 20.075 MHz */
{.xscale = 1, .yscale = 4, .eq = 0}, /* 41.5 MHz */
{.xscale = 1, .yscale = 2, .eq = 0}, /* 83 MHz */
{.xscale = 1, .yscale = 1, .eq = 0}, /* 166 MHz */
};
Tables such as this may vary from the clock to clock for e.g.: the auxiliary synthesizer's table format is different from PLL to VCO and so on.
Using this rate table, the clock framework can program the synthesizer to generate desired frequency. The user can just simply call the “clk_set_rate” API.
In addition, please note that the entries in the above “aux_rtbl” should be sorted in ascending order according to the output clock rate generated assuming a constant parent clock rate.
28/220 DocID028276 Rev 1
UM1942 Platform
The LSP tries to define and enumerate all possible clocks in the STreamPlug SoC. The following clocks are defined in: “arch/arm/mach-streamplug/clocks.c”:
/* array of all streamplug 1x clock lookups */ static struct clk_lookup streamplug_clk_lookups[] = {
/* root clks */
{ .con_id = "dummy_clk",.clk = &dummy_clk},
{ .con_id = "osc_32k_clk", .clk = &osc_32k_clk},
{ .con_id = "osc_24m_clk", .clk = &osc_24m_clk},
/* clock derived from 32 KHz osc clk */
{ .dev_id = "rtc-streamplug", .con_id = "hclk",.clk = &rtc_clk},
/* clock derived from 24 MHz osc clk */
{ .con_id = "pll1_clk", .clk = &pll1_clk},
{ .con_id = "pll2_clk", .clk = &pll2_clk},
{ .con_id = "pll3_usb_48m_clk", .clk = &pll3_usb_48m_clk},
{ .dev_id = "wdt", .con_id = "hclk", .clk = &wdt_clk},
/* clock derived from pll1 clk */
{ .con_id = "cpu_clk",.clk = &cpu_clk},
{ .con_id = "ahb_clk",.clk = &ahb_clk},
{ .con_id = "uart_synth_clk", .clk = &uart_synth_clk},
{ .con_id = "firda_synth_clk", .clk = &firda_synth_clk},
{ .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk},
{ .con_id = "gpt1_synth_clk", .clk = &gpt1_synth_clk},
{ .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk},
{ .dev_id = "uart1", .con_id = "hclk",.clk = &uart1_clk},
{ .dev_id = "uart2", .con_id = "hclk",.clk = &uart2_clk},
{ .dev_id = "dice_fir", .con_id = "hclk", .clk = &firda_clk},
{ .dev_id = "dice_ir", .con_id = "hclk", .clk = &firda_clk},
{ .dev_id = "gpt0", .con_id = "hclk", .clk = &gpt0_clk},
{ .dev_id = "gpt1", .con_id = "hclk", .clk = &gpt1_clk},
{ .dev_id = "gpt2", .con_id = "hclk", .clk = &gpt2_clk},
/* clock derived from pll3 clk */
{ .dev_id = "designware_udc", .con_id = "hclk",.clk = &usbd_clk},
{ .con_id = "usbh_clk",.clk = &usbh_clk},
/* clock derived from ahb clk */
{ .con_id = "ahbmult2_clk", .clk = &ahbmult2_clk},
{ .con_id = "ddr_clk",.clk = &ddr_clk},
{ .con_id = "apb_lowsub_clk",.clk = &apb_lowsub_clk},
{ .con_id = "apb_bassub_clk",.clk = &apb_bassub_clk},
{ .con_id = "apb_appsub_clk",.clk = &apb_appsub_clk},
{ .con_id = "apb_armsub_clk",.clk = &apb_armsub_clk},
{ .dev_id = "i2c_designware.0", .con_id = "hclk",.clk =
&i2c_clk},
{ .dev_id = "dw_dmac", .con_id = "hclk",.clk = &dma_clk},
{ .dev_id = "jpeg-designware", .con_id = "hclk",.clk = &jpeg_clk},
DocID028276 Rev 1 29/220
220
Platform UM1942
{ .dev_id = "stmmaceth",.con_id = "ptp", .clk = &ptp_clk},
{ .dev_id = "stmmaceth", .con_id = "eth",.clk = &mii_clk},
{ .dev_id = "stmmaceth",.con_id = "eth_phy", .clk =
ð_phy_clk},
{ .dev_id = "stmmaceth", .con_id = "hclk",.clk = &gmac_clk},
{ .dev_id = "smi",.con_id = "hclk",.clk = &smi_clk},
{ .dev_id = "c3", .con_id = "hclk",.clk = &c3_clk},
{ .dev_id = "streamplug-sport", .con_id = "hclk",.clk =
&sport_clk},
{ .dev_id = "streamplug-ts.0", .con_id = "hclk",.clk = &ts_clk},
/* clock derived from apb clk */
{ .dev_id = "ssp-pl022.0", .con_id = "hclk",.clk = &ssp_clk},
{ .dev_id = "streamplug_ark_gpio", .con_id = "hclk",.clk =
&ark_gpio_clk},
{ .dev_id = "gpio1", .con_id = "hclk",.clk = &gpio1_clk},
{ .dev_id = "gpio2", .con_id = "hclk",.clk = &gpio2_clk},
{.con_id = "clcd_synth_clk",.clk = &clcd_synth_clk},
{ .dev_id = "clcd", .con_id = "clcdclk", .clk = &clcd_clk},
{ .dev_id = "clcd", .con_id = "hclk", .clk = &amba_clcd_clk},
{.con_id = "fsmc",.clk = &fsmc_clk},
{.dev_id = "fsmc-nor",.clk = &fsmc_nor_clk},
{.dev_id = "fsmc-sram",.clk = &fsmc_sram_clk},
{.dev_id = "fsmc-nand",.clk = &fsmc_nand_clk},
{ .dev_id = "c_can_platform.1", .clk = &can1_clk},
{ .dev_id = "c_can_platform.2", .clk = &can2_clk},
{.dev_id = "uport",.clk = &uport_clk},
{.con_id = "dw_pcie",.clk = &pcie_clk},
{.dev_id = "dw_pcie-rc", .con_id = "hclk", .clk = &pcie_rc_clk},
{.dev_id = "dw_pcie-ep", .con_id = "hclk", .clk = &pcie_ep_clk},
{.dev_id = "ahci",.clk = &sata_clk},
};
3.5 Real-time clocks (RTC)
The real-time clocks (RTC) is used to keep track of days, dates and time, including the century, year, month, hour, minutes and seconds.
30/220 DocID028276 Rev 1
UM1942
3.5.1
Platform
RTC software overview
RTC support in the kernel is provided in the RTC framework. This is illustrated in
Figure 2. RTC software stack
hwclock rtcwake
User space
RTC core
RTC driver
Kernel space
RTC H/W
Hardware
3.5.2
AM039709
RTC kernel source and configuration
The driver is implemented in “drivers/rtc/rtc-streamplug.c” and follows the Linux RTC class framework documented under: “linux-2.6/Documentation/rtc.txt”.
lists the “Kconfig” options available for the RTC.
Table 5. RTC configurations
Configuration
CONFIG_RTC_DRV_STREAMPLUG
Description
Enables the STreamPlug RTC support
DocID028276 Rev 1 31/220
220
Platform UM1942
There are no platform options available for this driver and the driver on its own functionally initializes the RTC hardware.
The RTC driver is enumerated in its respective CPU file “arch/arm/mach-streamplug/ streamplug1x.c” which can be included by a corresponding board file to avail the support.
/* rtc device registration */ static struct resource rtc_resources[] = {
{
.start = STREAMPLUG1X_ICM3_RTC_BASE,
.end = STREAMPLUG1X_ICM3_RTC_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
}, {
.start = STREAMPLUG1X_IRQ_BAS_SUBS_RTC,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device streamplug1x_rtc_device = {
.name = "rtc-streamplug",
.id = -1,
.num_resources = ARRAY_SIZE(rtc_resources),
.resource = rtc_resources,
};
32/220
The hwclock is a shell utility for accessing the RTC clock. It is used to display the current time, set the hardware clock to a specified time, set the hardware clock to the system time, and set the system time from the hardware clock. The hwclock utility can be run periodically to insert or remove time from the hardware clock in order to compensate for a systematic drift (where the clock consistently gains or loses time at a certain rate if left to run).
# hwclock -h hwclock: invalid option -- 'h'
BusyBox v1.18.4 (2015-01-27 15:55:04 CET) multi-call binary.
Usage: hwclock [-r|--show] [-s|--hctosys] [-w|--systohc] [-l|--localtime]
[-u|--utc] [-f FILE]
Query and set hardware clock (RTC)
Options:
-r Show hardware clock time
-s Set system time from hardware clock
-w Set hardware clock to system time
-u Hardware clock is in UTC
-l Hardware clock is in local time
DocID028276 Rev 1
UM1942
-f FILE Use specified device (e.g. /dev/rtc2)
# date 2015.02.02-03:34
Mon Feb 2 03:34:00 UTC 2015
# date 2015.02.02-15:34
Mon Feb 2 15:34:00 UTC 2015
# hwclock -r
Wed Dec 31 23:59:59 1969 0.000000 seconds
# hwclock -w
# hwclock -s
# reboot
...
# date
Mon Feb 2 15:36:26 UTC 2015
Platform
DocID028276 Rev 1 33/220
220
Communication drivers UM1942
4.1
4.1.1
The communication drivers provide the support to the STreamPlug interfaces like Ethernet,
USB, I
2
C and SPI.
Gigabit media access controller (GMAC) - Ethernet
Ethernet is a family of standard technologies widely used in local area networks (LAN). The
GMAC Ethernet controller is embedded into the STreamPlug architecture and it is hard configured to support only fast Ethernet. This section describes the STMMAC (GMAC)
Ethernet driver.
GMAC software overview
The STMMAC Ethernet device driver sits on the top of the GMAC controller and interfaces with the Linux TCP/IP stack through the standard Linux network interface as shown in
Figure 3. Ethernet framework
FTP HTTP SSH
User space
Socket interface
UDP - TCP/IP stack
NETIF interface
Ethernet device driver
Raw L2
Kernel space
Ethernet controller
Ethernet PHY
Hardware
AM039710
The software overview section is broadly divided into two parts. The first part is more related to the STMMAC device driver core; while the second part is more related to the Ethernet
PHY configurations that the user may need to handle through the driver.
34/220 DocID028276 Rev 1
UM1942 Communication drivers
STMMAC core
The following paragraphs cover the configurations that the user can do to the “stmmac” core at run-time, provide some more insights about transmission/reception data handling and give more information about key features of the driver.
Transmit process
The Xmit method is invoked when the kernel needs to transmit a packet. It sets the descriptors in the ring and informs the DMA engine that there is a packet ready to be transmitted. Once the controller has finished transmitting the packet, an interrupt is triggered so the driver will be able to release the socket buffers.
Receive process
When one or more packets are received, an interrupt is generated. The interrupts are not queued so the driver has to scan all the descriptors in the ring during the receive process.
This is based on NAPI so the interrupt handler signals only if there is work to be done, and the related callback is scheduled at some future point. The incoming packets are stored, by the internal DMA controller, in a list of pre-allocated socket buffers in order to avoid using the memcpy.
PHY interface
The following paragraphs capture few tips and tricks that developers can use when porting to a new Ethernet physical device.
PHY abstraction layer
The physical abstraction layer provides a unified interface to a number of different physical layer (PHY) engines. For more information please see “Documentation/networking/phy.txt” within the kernel source tree.
PHY device driver
With the PHY abstraction layer, adding support for new PHYs is quite easy. In some cases, no work is required at all because a generic PHY driver is already provided.
The generic driver, by default, works without any interrupts (polling mode). This means that a timer will be used to periodically communicate between the PHY and the STMMAC in order to check the link status.
PHY platform setup
The driver setup information comes from specific platform structures. For example,
“streamplug_devel_board.c”, as shown:
/* ethernet phy device */ static struct plat_stmmacphy_data phy_private_data = {
.bus_id = 0,
.phy_addr = -1,
.phy_mask = 0,
.interface = PHY_INTERFACE_MODE_MII,
}; static struct resource phy_resources = {
.name = "phyirq",
.start = -1,
DocID028276 Rev 1 35/220
220
Communication drivers
.end = -1,
.flags = IORESOURCE_IRQ,
}; struct platform_device streamplug10_phy_device = {
.name = "stmmacphy",
.id = -1,
.num_resources = 1,
.resource = &phy_resources,
.dev.platform_data = &phy_private_data,
};
UM1942
lists the “Kconfig” options available for Ethernet:
Table 6. STreamPlug STMMAC configurations
Configuration Description
CONFIG_NET
CONFIG_NETDEVICES
CONFIG_STMMAC_ETH
It enables networking support
It enables network device support
It enables STreamPlug Ethernet (Synopsys) support
The kernel sources related to Ethernet driver implementation are present in the
“drivers/net/stmmac/” folder, which is spread across following files:
ï‚·
“dwmac1000_core.c” carries GMAC core initializations
ï‚·
“dwmac1000_dma.c” carries GMAC DMA initializations
ï‚·
“dwmac100_core.c” carries MAC core initializations
ï‚·
“dwmac100_dma.c” carries MAC DMA initializations
ï‚·
“dwmac_lib.c” generic utility functions
ï‚·
“enh_desc.c” enhanced descriptors handlers
ï‚·
“norm_desc.c” normal descriptors handlers
ï‚·
“stmmac_ethtool.c” ethtool support implementation
ï‚·
“stmmac_main.c” main driver implementation
ï‚·
“stmmac_mdio.c” MDIO implementation to access the PHY interface
36/220 DocID028276 Rev 1
UM1942
4.1.3
Communication drivers
GMAC platform configuration
The Ethernet driver expects several pieces of information from the platform. Refer to the driver's header file in “include/linux directory”. The data structure below (included into
“arch/arm/mach-straemplug/streamplug1x.c”) provides the platform data passed to the
STMMAC driver.
/* Ethernet device registration */ struct plat_stmmacenet_data ether_platform_data = {
.bus_id = 0,
.has_revmii = ETH_REVMII_ADDRESS,
.has_gmac = 1,
.enh_desc = 1,
.pbl = 8,
.dev_addr = "00:80:e1:26:0a:5b",
}; while the data structure below, included into the files specific for each supported board, provides the details of the PHY specific data passed by the platform to the driver.
/* ethernet phy device */ static struct plat_stmmacphy_data phy_private_data = {
.bus_id = 0,
.phy_addr = -1,
.phy_mask = 0,
.interface = PHY_INTERFACE_MODE_MII,
};
The following Linux commands can be used to configure the Ethernet interface:
ifconfig
The “ifconfig” command allows the operating system to setup the network interfaces and the user to view information about the configured interfaces.
To configure the network IP address the following command should be used:
$ ifconfig eth0 192.168.1.1 netmask 255.255.255.0
The status of the configuration can be obtained with:
$ ifconfig eth0 eth0Link encap:EthernetHWaddr 08:00:27:bd:c6:6e inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICASTMTU:1500Metric:1
RX Packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:32
RX bytes:0 (0.0 B)TX bytes: 0 (0.0 B)
DocID028276 Rev 1 37/220
220
Communication drivers UM1942
This shuts down the interface and reactivates it:
$ ifconfig eth0 down
$ ifconfig eth0 up
To configure the MTU size:
$ ifconfig eth0 down
$ ifconfig eth0 mtu <size>
$ ifconfig eth0 up
ethtool
The “ethtool” utility is used to display or change the Ethernet card settings. To setup the auto negotiation use:
$ ethtool -s eth0 autoneg on
To check the existing network configurations:
$ ethtool eth0
To setup the forced speed 100, the full duplex mode (default):
$ ethtool -s eth0 autoneg off speed 100 duplex full
To setup the forced speed 100, the half duplex mode:
$ ethtool -s eth0 autoneg off speed 100 duplex half
To setup the forced speed 10, the full duplex mode:
$ ethtool -s eth0 autoneg off speed 10 duplex full
4.2 Universal serial bus (USB) host
The universal serial bus (USB) is an industry standard to connect computers and electronic devices.
Linux provides two host control drivers (Linux EHCI and Linux OHCI). The architecture driver plugs into the USB host stack and allocates the basic resources for the USB host controller. The host side drivers for USB devices talk to the “usbcore” APIs. There are standard details of the API available. The details of the USB host APIs could be found online at the following address: www.Kernel.org/doc/htmldocs/usb.html.
38/220 DocID028276 Rev 1
UM1942
4.2.1
Communication drivers
USB host kernel source and configuration
To ensure proper USB device support some of the options in the kernel need to be enabled.
lists the configuration options.
Examples in this document show configuration options for basic USB support as well as the commonly needed options, such as an USB mass storage device (most cameras and USB
Thumb
®
drives).
Configuration
Table 7. USB host configurations
Description
CONFIG_USB_SUPPORT
CONFIG_USB
CONFIG_USB_DEVICES
CONFIG_USB_EHCI_HCD
CONFIG_USB_OHCI_HCD
This option adds core support for the USB bus.
Enable this option if the system has the host side bus and will use USB devices. Also see the USB devices in “/proc/bus/usb”.
Enabling this option is recommended.
If this option is enabled, it will get a “file/proc/bus/usb/devices” which lists the devices currently connected to your USB bus or buses, and a file named “/proc/bus/usb/xxx/yyy” for every connected device, where xxx is the bus number and yyy the device number.
Enable this option to configure the host controller driver to support the USB2. EHCI is standard for USB 2.0 high speed host control hardware.
Enable this option to configure the USB host controller hardware for the OHCI specification. The OHCI is the standard for accessing USB 1.1 host controller hardware.
CONFIG_USB_STORAGE
CONFIG_SCSI
CONFIG_USB_ACM
CONFIG_NET
CONFIG_USB_USBNET
CONFIG_USB_NET_CDCETHER
CONFIG_HID_SUPPORT
CONFIG_HID
Enable this option to connect a USB mass storage device to the host USB port. The option depends on SCSI support being enabled.
Enable this option to use an SCSI hard disk, an SCSI tape drive, an SCSI CD-ROM or any other SCSI device under Linux. USB mass storage devices follow SCSI protocol, and hence this option should be enabled over USB mass storage devices.
This driver supports USB modems and ISDN adapters which support the communication device class abstract control model interface.
Required for enabling USB modem support
Multi-purpose USB networking framework
This option supports devices conforming to the communication device class (CDC) Ethernet control model.
Options for various computer human interface device drivers.
This option compiles into kernel the generic HID layer code
(parser, usages, etc.), which can then be used by transport- specific HID implementation (like USB or Bluetooth
®
).
DocID028276 Rev 1 39/220
220
Communication drivers
Using the following command it is possible to configure the Linux kernel: make menuconfig
UM1942
Device Drivers--->
SCSI device support--->
(Although SCSI will be enabled automatically when selecting USB Mass
Storage,we need to enable disk support.)
---SCSI support type (disk, tape, CD-ROM)
<*>SCSI disk support
(Then Move a Level Back and Go into USB Support)
USB support--->
(This is the root hub and is required for USB support. If you'd like to compile this as a module, it will be called usbcore.)
<*> Support for Host-side USB
(Enable this option if your system has the host side bus and wants to use USB devices and also to see your USB devices in /proc/bus/usb. This is recommended.)
[*]USB device filesystem
(Select at least one of the HCDs. If you are unsure, picking all is fine.)
--- USB Host Controller Drivers
<*> EHCI HCD (USB 2.0) support
<*> OHCI HCD support
(Moving a little further down, we come to CDC and mass storage.)
<*> USB Modem (CDC ACM) support
<> USB Printer support
<*> USB Mass Storage support
For use with a USB keyboard, mouse, joystick, or any other input device, enable HID support. Go back one level to “Device drivers” and enable HID support as shown:
Device Drivers --->
[*] HID Devices --->
<*>USB Human Interface Device (full HID) support
For use with a USB modem, enable the USB modem (CDC ACM) support as shown above along with the following supports:
Device Drivers ---->
[*] Network device support--->
USB Network Adapters--->
<*> Multi-Purpose USB Networking Framework
40/220 DocID028276 Rev 1
UM1942
4.2.2
Communication drivers
USB host platform configuration
The USB host device driver has the following platform configuration:
/* usb host device registration */ static struct resource ehci_resources[] = {
[0] = {
.start = STREAMPLUG1X_ICM4_USB_EHCI_BASE,
.end = STREAMPLUG1X_ICM4_USB_EHCI_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = STREAMPLUG1X_IRQ_HIGH_SPEED_SUBS_USB_EHCI,
.flags = IORESOURCE_IRQ,
},
}; static struct resource ohci_resources[] = {
[0] = {
.start = STREAMPLUG1X_ICM4_USB_OHCI_BASE,
.end = STREAMPLUG1X_ICM4_USB_OHCI_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = STREAMPLUG1X_IRQ_HIGH_SPEED_SUBS_USB_OHCI,
.flags = IORESOURCE_IRQ,
},
}; static u64 ehci_dmamask = ~0; static int usbh_id = -1; struct platform_device streamplug1x_ehci_device = {
.name = "streamplug-ehci"
.id = -1,
.dev = {
.coherent_dma_mask = ~0,
.dma_mask = &ehci_dmamask,
.platform_data = &usbh_id,
},
.num_resources = ARRAY_SIZE(ehci_resources),
.resource = ehci_resources,
}; static u64 ohci_dmamask = ~0;
DocID028276 Rev 1 41/220
220
Communication drivers
struct platform_device streamplug1x_ohci_device = {
.name = "streamplug-ohci",
.id = 0,
.dev = {
.coherent_dma_mask = ~0,
.dma_mask = &ohci_dmamask,
.platform_data = &usbh_id,
},
.num_resources = ARRAY_SIZE(ohci_resources),
.resource = ohci_resources,
};
UM1942
A USB device can either use a custom driver or use one already present in the system. This is based on the concept of a device class and means that if a device belongs to a certain class, then the other devices of the same class can make use of the same device driver.
Some of these classes are: the USB HID (human interface devices) class which includes input devices like keyboards and mice, the USB mass storage devices class which includes devices like pen drives, digital cameras, audio players, etc. and the USB CDC
(communication devices class) which essentially includes USB modems and similar devices.
To enable the USB host support at run-time it is necessary to configure the Linux kernel command line using the options mentioned in
.
USB mass storage class
The USB mass storage standard provides an interface to a variety of storage devices, like hard disk drives and Flash memories. Plug-in the Flash memory into the available USB port and then type the following commands:
# dmesg | less usb 1-1: new high speed USB device using streamplug-ehci and address 2 scsi0 : usb-storage 1-1:1.0
scsi 0:0:0:0: Direct-Access USB DISK 2.0 PMAP PQ: 0 ANSI: 4 sd 0:0:0:0: Attached scsi generic sg0 type 0 sd 0:0:0:0: [sda] 15124992 512-byte logical blocks: (7.74 GB/7.21 GiB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Mode Sense: 23 00 00 00 sd 0:0:0:0: [sda] Assuming drive cache: write through sd 0:0:0:0: [sda] Assuming drive cache: write through
sda: sda1 sd 0:0:0:0: [sda] Assuming drive cache: write through sd 0:0:0:0: [sda] Attached SCSI removable disk
# mount /dev/sda1 /mnt/
# df -h
42/220 DocID028276 Rev 1
UM1942 Communication drivers
Filesystem Size Used Available Use% Mounted on ubi0_0 7.8M 3.5M 4.3M 45% / tmpfs 51.0M 32.0K 50.9M 0% /tmp
/dev/sda1 7.2G 5.8G 1.4G 80% /mnt
/* Digital cameras can be accessed the same way as memory sticks. */
The device is picked up as a USB 1.1 device and allocates an address. It also indicated which HCD is used.
USB communication device class (CDC)
The USB CDC class supports a lot of communication devices, including Ethernet. Compile and then boot-up the kernel with the options relevant to the USB Ethernet adapters enabled.
The options are covered in the following configuration sections. Plug-in the USB Ethernet adapter, and console messages that are similar to the following will be displayed.
$hub 1-0:1.0: over-current change on prot 1 usb 1-1:new high speed USB device using streamplug-ehci and address 2 usb-1.1: configuration #1 chosen from 1 choice eth0:register 'asix' at usb-STreamPlug EHCI-1, ASIX AX88772 USB2.0
Ethernet,00;89:c8:3a:4c:0b
/* Type in the following command and check if the device has been recognized */
$ cat /proc/bus/usb/devices
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=ff(vendor)Sub=ff Prot=00 MxPS= 64 #Cfgs= 1
P: Vendor=2001 ProdID=3c05 Rev= 0.01
S: Manufacturer= D-Link Corporation
S: Product=DUB-E100
S: Serial Number=000001
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=250mA
I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vendor specific) Sub=ff Prot=00
Driver=asix
E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=128ms E: Ad=81(I) Atr=02(Bulk)
MxPS= 512 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
/* The functionality could be checked by assigning the IP and then test a simple ping operation. */
$ ifconfig eth0 192.168.1.11
eth0: link up, 100Mbps, full duplex, lpa 0xcde1 th0: linkup, 100Mbps, full-duplex, lpa 0xcde1
USB human interface device (HID) class
The USB HID class describes human interface devices such as keyboards and mice.
DocID028276 Rev 1 43/220
220
Communication drivers UM1942
USB mouse
Compile and then boot-up the kernel with the options relevant to the USB mouse enabled.
The options are shown in the configuration following paragraphs. Plug-in the USB mouse.
Print output messages that are similar to the following will be displayed:
$ hub 1-0:1.0: over-current change on prot 1 usb 3-1:new low speed USB device using streamplug-ohci and address 3 usb-3.1: configuration #1 chosen from 1 choice input: USB Optical Mouse as /class/input/input2 input: USB HID v1.11 Mouse[USB Optical Mouse] on usb-streamplug-ohci.0-
1
The following command can be used to check if the device has been recognized:
$ cat /proc/bus/usb/devices
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0461 ProdID=4d15 Rev= 2.00
S: Product=USB Optical Mouse
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS=4 Ivl=10ms
USB keyboard
Compile and then boot-up the kernel with the options relevant to the USB keyboard enabled. The options are included in the following configuration paragraphs. Plug-in the
USB keyboard. Print output messages that are similar to the following will be displayed.
$ hub 1-0:1.0: over-current change on prot 1 usb 3-1:new full speed USB device using streamplug-ohci and address 4 usb-3.1: configuration #1 chosen from 1 choice input: Dell Dell Smart Card Reader Keyboard as /class/input/input3 input: USB HID v1.11 Keyboard [Dell Dell Smart Card Reader Keyoard] on usb- streamplug-ohci.0-1
$cat /proc/bus/usb/devices
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=413c ProdID=2101 Rev= 1.00
S: Manufacturer=Dell
S: Product=Dell Smart Card Reader Keyboard
C:* #Ifs= 2 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=01 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS=8 Ivl=24ms
I:* If#= 1 Alt= 0 #EPs= 3 Cls=0b(scard) Sub=00 Prot=00
Driver=(none)
E: Ad=02(O) Atr=02(Bulk) MxPS=64 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS=64 Ivl=0ms
E: Ad=83(I) Atr=03(Int.) MxPS=8 Ivl=24ms
44/220 DocID028276 Rev 1
UM1942 Communication drivers
A simple method to verify if the STreamPlug chip is working as a USB host is to plug a USB mass storage device that has been formatted as FAT32, into the USB socket and verify from the kernel debug shell that USB signals are exchanged between the host and external device.
A portion of the Linux kernel log generated after the USB host device driver recognized the
USB device is shown below.
usb 1-1: new high speed USB device using streamplug-ehci and address 2 scsi0 : usb-storage 1-1:1.0
scsi 0:0:0:0: Direct-AccessVBTMStore 'n' Go5.00 PQ: 0 ANSI: 0 CCS sd 0:0:0:0: Attached scsi generic sg0 type 0 sd 0:0:0:0: [sda] 4028416 512-byte logical blocks: (2.06 GB/1.92 GiB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Assuming drive cache: write through sd 0:0:0:0: [sda]
Assuming drive cache: write through
sda: sd 0:0:0:0: [sda] Assuming drive cache: write through sd 0:0:0:0: [sda]
Attached SCSI removable disk
After the USB device is recognized, the user may use the command mount to mount the filesystem (/dev/sd##) in the “folder /mnt”.
$ mount /dev/sda1 /mnt
Going into “/mnt” will show the filesystem which is on “/dev/sda1”:
$ ls /mnt
4.3 Universal serial bus (USB) device
The STreamPlug USB chip controller may run either as a USB host (master) or as a USB device (slave) and the mutually exclusive selection is done during the startup of the board.
There is a wide variety of USB devices (USBD) available in the market. Examples of these devices are USB Ethernet adapters, USB audio devices, USB mass storage devices, USB printers, and so on. In the Linux USB world, these functions are called “gadgets”. The
STreamPlug USBD can be used to build any of these functions. A device with multiple functions can also be built. Multifunctional printers, USB Ethernet plus mass storage are examples. These devices are generally known as “composite” devices.
DocID028276 Rev 1 45/220
220
Communication drivers
4.3.1 USB device software overview
UM1942
The USB device controller driver in the STreamPlug LSP supports the Linux USB gadget framework. This framework provides a flexible and easy interface for adding different USB slave devices. It also offers the facility to easily add multifunction USB composite devices.
shows the USB gadget framework most important components.
Figure 4. USBD software architecture
ipconfig mount Ip
User space
Ethernet
(usb0)
File storage Printer
Kernel space
Composite device
USB gadget framework
USBD driver
USBD controller
Hardware
AM039711
As shown in
, the gadget drivers can access the USB device driver either directly
through the gadget framework or through the composite layer. The composite layer provides an interface where multifunctional devices (like audio and video) can be easily supported. It is preferable that USB gadget drivers which do not have composite features also interact through the composite layer. Please note that only one gadget driver at a time can exist in this framework using the gadget framework. Also remember that the composite layer is in an
itself gadget drive. Therefore according to
, the printer and the composite layer cannot exist at the same time. One possibility is to build the printer gadget over the composite layer.
The remaining part of this document describes the composite layer interface. For detailed documentation on the gadget framework please refer to: www.linux-usb.org/gadget/.
46/220 DocID028276 Rev 1
UM1942
4.3.2
4.3.3
Communication drivers
USB device kernel source and configuration
The following files contain some of the source code part of the STreamPlug device driver for the USB gadget controller: arch/arm/mach-streamplug/ipswrst_ctrl.c arch/arm/mach-streamplug/include/mach/generic.h arch/arm/mach-streamplug/include/mach/streamplug10.h arch/arm/mach-streamplug/clock.c
arch/arm/mach-streamplug/padmux.c arch/arm/mach-streamplug/streamplug1x.c drivers/usb/gadget/designware_udc.h drivers/usb/gadget/designware_udc.c drivers/usb/gadget/inode.c drivers/usb/gadget/zero.c.
The USB gadgets device driver is built into the following modules: g_zero.ko g_ether.ko gadgetfs.ko
USB device platform configuration
A partial list of Linux kernel configuration options useful to configure the USB controller is present in
.
Table 8. USB gadget Linux kernel configuration
Configuration Description
CONFIG_USB
CONFIG_USB_SUPPORT
CONFIG_USB_DEVICE_CLASS
CONFIG_USB_GADGET
-
-
-
This enables USB gadget support in Linux kernel
CONFIG_USB_GADGETFS
CONFIG_USB_ZERO
CONFIG_USB_ETH
-
This enables a test gadget driver (“zero”)
-
CONFIG_USB_GADGET_DESIGNWARE This enables STreamPlug USB device controller support
CONFIG_USB_DESIGNWARE -
CONFIG_USB_TEST
CONFIG_USB_GADGET_DUALSPEED
This enables the USB test module for testing the zero gadget on the host side.
This enables dual (FULL and HIGH) speed support.
DocID028276 Rev 1 47/220
220
Communication drivers UM1942
Other may be necessary and/or more fine-grained configurations may be needed by directly changing the source code. One of these cases is related to the FIFO configurations. The
RxFIFO on the STreamPlug USBD can be configured for each endpoint. Keep in mind that total combined RxFIFO usage for all out endpoints should not exceed 2 KB. Similarly, total combined TxFIFO usage for all IN endpoints should be limited to 2 KB. To change this FIFO configuration, it is possible to edit the corresponding macro in the source code file.
An example is the configuration of the buffer length. The gadget drivers allocate a USB request and then submit it to the framework for transfer. The length of such transfer requests will determine the performance of the driver. Allocating a large buffer and hence a bigger buffer length will make CPU more free. The USB DMA would try to complete the transfer for the asked length and then interrupt CPU notifying the completion of the transfer.
The maximum buffer length is limited to 65535 bytes for an STreamPlug USB device.
USBD driver interface with Linux gadget layer
As mentioned above, the USB device controller driver supports the Linux gadget framework.
For this, it exports certain device, endpoint specific routines and two functions for registering and unregistering to the framework.
/* device specific operations exported by usbd driver */ static const struct usb_gadget_ops dw_udc_dev_ops = {
.get_frame = dw_dev_get_frame,
.wakeup = dw_dev_wakeup,
.set_selfpowered = dw_set_selfpowered,
.ioctl = dw_ioctl,
};
/* endpoint specific operations exported by usbd driver */ static struct usb_ep_ops dw_udc_ep_ops = {
.enable = dw_ep_enable,
.disable = dw_ep_disable,
.alloc_request = dw_ep_alloc_request,
.free_request = dw_ep_free_request,
.queue = dw_ep_queue,
.dequeue = dw_ep_dequeue,
.set_halt = dw_ep_set_halt,
.fifo_status = dw_ep_fifo_status,
.fifo_flush = dw_ep_fifo_flush,
};
/* routine exported by usbd driver for gadgets to register */ int usb_gadget_register_driver(struct usb_gadget_driver *driver);
/* routine exported by usbd driver for gadgets to un-register */ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
The composite device layer registers to the gadget framework by calling the above APIs and exposes an interface which can be used by different functions (gadgets) to represent a composite device.
48/220 DocID028276 Rev 1
UM1942
4.3.4
Communication drivers
USB device usage
The composite device is designed in a such way that, the driver should first register to the composite layer. During registration, it passes some of the device related details
(e.g.: device, string descriptor) to the composite layer. After registering, the composite device needs to add a configuration (multiple configurations are also possible) and then individual functions can add their interfaces.
shows a simple gadget driver (“zero
gadget”) available with the STreamPlug LSP.
Figure 5. Zero gadget device
Zero gadget device
Source/sink config.
Loop back config.
Function 1
Interface 0
Function 1
Interface 0
Out endpoint
In endpoint
Out endpoint
In endpoint
AM039712
The illustrated gadget driver is built over a composite layer (although it is not a composite device) and is mainly used for testing the USB device controller. It provides two configurations: the first one has a source/sink function for generating/consuming USB packets, and the second one has a loop back feature. This example gadget driver is referred to the explanations given throughout this part of the document.
This driver can be found in the file: linux/drivers/usb/gadget/zero.c.
DocID028276 Rev 1 49/220
220
Communication drivers UM1942
Registering to the composite device
The un/registration to the composite device can be done with the following calls:
/* usb composite gadget need to fill following structure */ static struct usb_composite_driver zero_driver = {
.name = "zero";
.dev = &device_desc;
.strings = dev_strings;
.bind = zero_bind; /* callback called on successful registration */
.unbind= zero_unbind,
.suspend= zero_suspend,
.resume= zero_resume,
};
/* Following are the APIs for register/un-register */ usb_composite_register(&zero_driver); usb_composite_unregister(&zero_driver);
Adding configuration
Any composite device can have multiple configurations with multiple interfaces, each interface (or a group of interfaces) representing a unique function. The following API can be used to add a configuration: static struct usb_configuration sourcesink_driver = {
.label = "source/sink",
.strings = sourcesink_strings,
.bind= sourcesink_bind_config, /* callback called during registration to finish other configurations */
.setup = sourcesink_setup, /* callback to handle control requests */
.bConfigurationValue = 3,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
/* following function registered earlier, is called during registration */ static int init zero_bind(struct usb_composite_dev *cdev)
{
...
usb_add_config(cdev, &sourcesink_driver);
...
}
50/220 DocID028276 Rev 1
UM1942 Communication drivers
Adding function
After adding configurations, the functions supported in each configuration need to be defined. Several functions as per the composite device design, can be added. The following mechanism can be used to add functions to configurations:
/* Following function registered earlier is called during registration */ static int sourcesink_bind_config(struct usb_configuration *c)
{
struct f_sourcesink*ss;
intstatus;
ss = kzalloc(sizeof *ss, GFP_KERNEL);
if (!ss)
return -ENOMEM;
ss->function.name = "source/sink";
ss->function.descriptors = fs_source_sink_descs;
ss->function.bind = sourcesink_bind;
ss->function.unbind = sourcesink_unbind;
ss->function.set_alt = sourcesink_set_alt;
ss->function.disable = sourcesink_disable;
status = usb_add_function(c, &ss->function);
if (status)
kfree(ss);
return status;
}
Initializing USB descriptors
There are some fields in standard USB descriptors that require inputs from the composite layer for initialization. In almost all descriptors some of these fields are indexed to string tables and to an interface number for the interface descriptors. Some helper routines are described below: static int zero_bind(struct usb_composite_dev *cdev)
{
/* get next available string index */
id = usb_string_id(cdev);
if (id < 0)
return id;
strings_dev[STRING_MANUFACTURER_IDX].id = id;
device_desc.iManufacturer = id;
...
} static int sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
{
...
DocID028276 Rev 1 51/220
220
Communication drivers UM1942
/* allocate interface ID(s) */
id = usb_interface_id(c, f);
if (id < 0)
return id;
source_sink_intf.bInterfaceNumber = id;
...
}
Data and control transfer
After completing the registering process, the gadget driver can handle setup requests through setup callbacks. In this way, other required endpoints can be configured and a transfer (of control or data) through the Linux gadget framework APIs can be initiated.
More details on these APIs can be found in the references.
and their purpose.
Table 9. Linux gadget framework API
Function Description
struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,struct usb_endpoint descriptor *) int usb_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
Allocates a suitable free endpoint described by struct usb_endpoint_descriptor.
Enables the endpoint ep, in order to be used for data transfer. The endpoint ep is described in struct usb_endpoint_descriptor.
struct usb_request *usb_ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) void usb_ep_free_request(struct usb_ep *ep, struct usb_request *req) int usb_ep_disable(struct usb_ep *ep) int usb_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags) int usb_ep_set_halt(struct usb_ep *ep)
Allocates a request for USB transfer.
Frees the allocated request.
Disables the endpoint ep, so that it is not usable.
Submits a transfer request on this endpoint (ep).
Halts a particular endpoint (ep).
52/220 DocID028276 Rev 1
UM1942 Communication drivers
USBD control
may be used to configure and program the USB device.
Function
Table 10. USB device control APIs
Description int usb_gadget_frame_number
(struct usb_gadget *gadget)
Returns the current start of the frame number int usb_gadget_wakeup (struct usb_gadget enables the remote wakeup feature of USB *gadget) device.
int usb_gadget_set_selfpowered
(struct usb_gadget *gadget) int usb_gadget_clear_selfpowered
(struct usb_gadget *gadget)
The USB device is self-powered.
The USB device is not self-powered but bus powered.
int usb_gadget_ioctl
(struct usb_gadget *,unsigned code, unsigned long param)
Configures the USB device on configuration change. This API is STreamPlug specific and is mandatory to call on SET CONFIGURATION as it programs the controller accordingly “param” points to the function descriptors.
The STreamPlug USB gadget device driver manages the resources shown in the following code:
/* usb device registration */ static struct resource udc_resources[] = {
[0] = {
.start = STREAMPLUG1X_ICM4_USBD_CSR_BASE,
.end = STREAMPLUG1X_ICM4_USBD_CSR_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = STREAMPLUG1X_ICM4_USB_PLDT_BASE,
.end = STREAMPLUG1X_ICM4_USB_PLDT_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[3] = {
.start = STREAMPLUG1X_IRQ_HIGH_SPEED_SUBS_USB_DEV,
.end = STREAMPLUG1X_IRQ_HIGH_SPEED_SUBS_USB_DEV,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device streamplug1x_udc_device = {
.name = "designware_udc",
.id = -1,
.dev = {
DocID028276 Rev 1 53/220
220
Communication drivers
.coherent_dma_mask = 0xffffffff,
},
.num_resources = ARRAY_SIZE(udc_resources),
.resource = udc_resources,
};
UM1942
54/220
As shown above, there can be various user defined functions over the Linux gadget framework. Each of the functions (gadgets) exposes its own interface. For example, the
USB Ethernet function exposes a netdev interface; the USB serial gadget exposes a tty interface and so on. This makes the usage of the USB gadgets very easy. Standard tools can be used for standard interfaces provided by these gadgets. The following files present in the Linux kernel documentation folder provide some usage examples:
* gadget_printer.txt for usb printer device
* gadget_serial.txt for usb serial device
The STreamPlug LSP provides a test gadget driver, “zero gadget”, to test the USB device controller. This gadget does not have any user interface. It just provides two configurations,
“source and sink” and “loop back”, to support several test cases which can be executed from the USB host side. On the USB host corresponding to the zero gadget the “usbtest” driver supports several test cases to validate the
USB through IOCTLs. A standard application “testusb” is available on the host side to execute desired test cases.
Please refer to the following link for details on this test setup: http://www.linuxusb.org/usbtest/, includes the binary image and the source code of an application to test the
USB device gadget file system.
To enable the USB gadget device driver it is necessary to use the following Linux kernel parameter: usb=on:device in the XML configuration file for the OK Linux.
USB device Ethernet gadget
A simple application that can be performed in order to verify the functionality of the
STreamPlug chip working as a USB device with the Ethernet gadget enabled is to try to establish a network communication with a remote machine such as it happens with the
Ethernet “Best Effort” device driver. The application used is “iperf” which is provided as a Buildroot package.
In order to run the test, perform the following steps:
1.
On the STreamPlug side, load the Ethernet gadget module:
$ modprobe g_ether.ko
g_ether gadget: using random self ethernet address g_ether gadget: using random host ethernet address usb0: MAC 4e:23:fc:67:21:49 usb0: HOST MAC 16:a6:02:7c:6c:53 g_ether gadget: Designware USB Device Controller driver, version:
Memorial Day 2008 g_ether gadget: g_ether ready registered gadget driver 'g_ether'
2. Assign an IP address to the usb0 interface. For example:
$ ifconfig usb0 192.168.3.1 up
DocID028276 Rev 1
UM1942 Communication drivers
ADDRCONF(NETDEV_UP): usb0: link is not ready
On the host PC side:
1.
Connect a USB cable.
[on STreamPlug console]: g_ether gadget: high speed config #1: CDC Ethernet (EEM)
ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
2. Verify that the usb0 device is detected.
[on Host PC terminal]:
$ ifconfig usb0 usb0 Link encap:Ethernet HWaddr 96:f1:78:09:8e:53 inet6 addr: fe80::94f1:78ff:fe09:8e53/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1494 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:26 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000
RX bytes:384 (384.0 B) TX bytes:5713 (5.7 KB)
3. Assign an IP address to the usb0 interface. For example:
$ sudo ifconfig usb0 192.168.3.10 up
4. Check if the connection is up and running using the ping command on both sides.
On the STreamPlug side:
$ ping -c4 192.168.3.10
PING 192.168.3.10 (192.168.3.10): 56 data bytes
64 bytes from 192.168.3.10: seq=0 ttl=64 time=14.405 ms
64 bytes from 192.168.3.10: seq=1 ttl=64 time=4.534 ms
64 bytes from 192.168.3.10: seq=2 ttl=64 time=12.234 ms
64 bytes from 192.168.3.10: seq=3 ttl=64 time=20.256 ms
--- 192.168.3.10 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss round-trip min/avg/max = 4.534/12.857/20.256 ms
On the host PC side:
$ping -c4 192.168.3.1
PING 192.168.3.1 (192.168.3.1) 56(84) bytes of data.
64 bytes from 192.168.3.1: icmp_req=1 ttl=64 time=15.0 ms
64 bytes from 192.168.3.1: icmp_req=2 ttl=64 time=31.2 ms
64 bytes from 192.168.3.1: icmp_req=3 ttl=64 time=6.29 ms
64 bytes from 192.168.3.1: icmp_req=4 ttl=64 time=21.4 ms
--- 192.168.3.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms rtt min/avg/max/mdev = 6.290/18.482/31.220/9.106 ms
Finally, the “iperf” application may be used to evaluate the link bandwidth.
On the host PC side:
$iperf -s
DocID028276 Rev 1 55/220
220
Communication drivers UM1942
On the STreamPlug side:
$iperf -c 192.168.3.10
The STreamPlug console will display:
------------------------------------------------------------
Client connecting to 192.168.3.10, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.3.1 port 54883 connected with 192.168.3.10 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.1 sec 14.0 MBytes 11.6 Mbits/sec
The output logs on the host PC side will show:
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 192.168.3.10 port 5001 connected with 192.168.3.1 port 54883
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.2 sec 14.0 MBytes 11.5 Mbits/sec
The following is an example of console output while doing a gadget Ethernet test:
STreamPlug login: root
# modprobe g_ether g_ether gadget: using random self ethernet address g_ether gadget: using random host ethernet address usb0: MAC 9a:98:08:e8:69:91 usb0: HOST MAC 4a:61:f9:f4:cf:ed g_ether gadget: Designware USB Device Controller driver, version:
Memorial Day 2008 g_ether gadget: g_ether ready registered gadget driver 'g_ether'
# ifconfig
# ifconfig usb0 192.168.3.1 up
# ifconfig usb0 Link encap:Ethernet HWaddr 9A:98:08:E8:69:91 inet addr:192.168.3.1 Bcast:192.168.3.255 Mask:255.255.255.0 inet6 addr: fe80::9898:8ff:fee8:6991/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:68 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000
RX bytes:11947 (11.6 KiB) TX bytes:504 (504.0 B)
# ping 192.168.3.2
PING 192.168.3.2 (192.168.3.2): 56 data bytes
64 bytes from 192.168.3.2: seq=0 ttl=64 time=3.520 ms
56/220 DocID028276 Rev 1
UM1942
Note:
Communication drivers
64 bytes from 192.168.3.2: seq=1 ttl=64 time=0.654 ms
64 bytes from 192.168.3.2: seq=2 ttl=64 time=0.660 ms
64 bytes from 192.168.3.2: seq=3 ttl=64 time=0.656 ms
64 bytes from 192.168.3.2: seq=4 ttl=64 time=0.660 ms
64 bytes from 192.168.3.2: seq=5 ttl=64 time=0.645 ms
64 bytes from 192.168.3.2: seq=6 ttl=64 time=0.664 ms
64 bytes from 192.168.3.2: seq=7 ttl=64 time=0.628 ms
64 bytes from 192.168.3.2: seq=8 ttl=64 time=0.645 ms
--- 192.168.3.2 ping statistics ---
9 packets transmitted, 9 packets received, 0% packet loss round-trip min/avg/max = 0.628/0.970/3.520 ms
# iperf -c 192.168.3.2
------------------------------------------------------------ Client connecting to 192.168.3.2, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.3.1 port 34838 connected with 192.168.3.2 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 34.6 MBytes 29.0 Mbits/sec
# rmmod g_ether
USB gadget FS
In order to test the USB device FS gadget, Run, on the STreamPlug, the application
“gadgetfs” which may be found at the root level of the root FS “below/examples” folder.
The host PC must have a Linux OS running, with a VM the test will not run.
1.
Load the gadget FS module.
$ modprobe gadgetfs.ko
2. Verify the subfolder /gadget is present below the “/dev” folder, otherwise create it.
3. Mount the gadget FS module. Note that the message shows the driver is not associated anymore because the cable is not connected.
$ mount -t gadgetfs none /dev/gadget/ bind to driver nop --> error -120
4. Verify if the “designware_udc” device driver is correctly mounted and it is created below
/dev/gadget.
5. Verify the USB cable is plugged on an appropriate connector only at the STreamPlug side.
6. Go into the “/example/gadgetfs” folder and run the application in background.
$ ./gadgetfs -v &
7. Verify it will display the following string:
$ /dev/gadget/designware_udc ep0 configured
$ serial="bvxryq1ex7ue0nw2yod9m9t5y2sib8939wzx4lo4y8g4h3m27peuxq1qi1z4p82"
DocID028276 Rev 1 57/220
220
Communication drivers UM1942
Below the “/dev/gadget”, are the endpoints created ep1in, ep2out, ep3in:
8. Connect the cable to the
PC USB connector.
9. On the host side, execute the command lsusb both as the normal user and superuser.
Note that the host has correctly detected the USB device.
$ lsusb
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 002: ID 0525:a4a4 Netchip Technology, Inc. OKLinux-USB user-mode bulk?' source/sink
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
$ sudo lsusb -v -s1:2
Bus 001 Device 002: ID 0525:a4a4 Netchip Technology, Inc. Linux-USB user-mode bulk? source/sink
Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB2.00
bDeviceClass255 Vendor Specific Class bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor0x0525 Netchip Technology, Inc.
idProduct0xa4a4 Linux-USB user-mode bulk source/sink bcdDevice1.08
iManufacturer1 Analog Devices, Inc. iProduct2 EZKIT-BF548 iSerial3 bNumConfigurations 1
Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 39 bNumInterfaces 1 bConfigurationValue 3 iConfiguration4
GadgetFS Configuration bmAttributes0xc0
Self Powered
MaxPower 2mA
Device Qualifier (for other device speed): bLength 10 bDescriptorType 6 bcdUSB2.00
bDeviceClass255 Vendor Specific Class
58/220 DocID028276 Rev 1
UM1942 Communication drivers
bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 1
Device Status: 0x0000 (Bus Powered)
10. On STreamPlug side, check that it will be displayed something like the following:
SUSPEND
CONNECT high speed
DISCONNECT
CONNECT high speed
SETUP 80.06 v0300 i0000 255
SETUP 80.06 v0302 i0409 255
SETUP 80.06 v0301 i0409 255
SETUP 80.06 v0303 i0409 255
SETUP 80.06 v0303 i0409 2
SETUP 80.06 v0303 i0409 128
4.4 I
2
C controller
The I
2
C is a multimaster serial single-ended 2-wire computer bus invented by Philips. It is used to attach low speed peripherals to a motherboard, embedded system, cellphone, or an other electronic device. It is a master-slave protocol, where communication takes a place between a host adapter (or a host controller) and client devices (or slaves).
4.4.1 I
2
C controller hardware overview
The I
2
C uses only two bidirectional lines, the serial data (SDA) and serial clock (SCL), pulled up with resistors. Typical voltages used are +5 V or +3.3 V, but systems with higher or lower voltages are also permitted. The I
APB bus and the serial I
2
2
C controller serves as an interface between the
C bus. It provides master functions and controls all the I
2
C bus specific sequencing, protocol, arbitration and timing.
Features supported by I
2
C are:
ï‚·
Two-wire I
2
C serial interface
ï‚·
Two speeds:
– Standard mode (100 Kbits/s)
– Fast mode (400 Kbits/s)
ï‚·
Master or slave I
2
C operation (LSP supports only the master mode)
ï‚·
7-bit or 10-bit addressing
ï‚·
Slave bulk transfer mode
ï‚·
Interrupt or polled-mode operation (LSP supports only the interrupt mode)
DocID028276 Rev 1 59/220
220
Communication drivers UM1942
4.4.2 I
2
C controller software overview
Because the I
2
C works on the master/slave protocol, the communication takes a place between the host adapter (master) and client devices (slave).
The following terms are used for the I
2
C:
Bus
ï‚·
Algorithm driver
ï‚·
Adapter driver
Device
ï‚·
Client driver
An algorithm driver contains the general code that can be used for the whole class of I
2
C adapters. Each specific adapter driver either depends on one algorithm driver, or includes its own implementation.
A client driver contains the general code to access some type of a device. Each detected device gets its own data in the client structure.
For a given configuration, it will need:
ï‚·
A driver for the I
2
C bus,
ï‚·
Drivers for I
2
C devices (usually one driver for each device), like the EEPROM, image sensor, etc.
2
C subsystem.
Figure 6. I
2
C framework architecture
User application
User space
I2C client driver
I2C core layer
I2C dev
I2C controller driver
I2C controller H/W
Kernel space
Hardware
AM039713
60/220 DocID028276 Rev 1
UM1942 Communication drivers
4.4.3 I
2
C controller kernel source and configuration
The I
2
C kernel code is broken up into a number of logical blocks: the I
2
C core, I
2
C bus drivers and I
2
C client drivers.
I
2
C core
The I
2
C core is a code base consisting of routines and data structures available to host adapter drivers and client drivers. The core also provides a level of indirection that renders client drivers independent of the host adapter, allowing them to work even if the client device is used on a board that has a different I
2
C host adapter.
Busses
Busses are used for reading/writing to the slave device. The I
2
C busses drivers are provided in the following path: “drivers/i2c/busses/i2c-designware.c”.
I
2
C-dev
The I
2
C-dev allows communication with the user space. The I
2
C-dev code is provided in the following path: “drivers/i2c/i2c-dev.c”.
lists the details corresponding to the layout of kernel configuration:
Table 11. I
2
C configurations
Configuration
CONFIG_I2C
CONFIG_I2C_CHARDEV
CONFIG_I2C_DESIGNWARE
CONFIG_I2C_HELPER_AUTO
Description
It enables I
2
C support
It provides a character device for each I
2
C device present in the system, allowing the user to read and write directly from the I
2
C bus by ioctl() function.
It enables the Synopsys designware I
2
C adapter (I
2
C hardware bus support).
Only the master mode is supported.
It enables the “I
2
C algorithm” modules. These are basically software only abstractions of generic I
2
C interfaces.
4.4.4 I
2
C controller platform configuration
The optional platform data passed from machines for the I
2
C is as follows:
/* i2c device registration */ static struct resource i2c_resources[] = {
{
.start = STREAMPLUG1X_ICM1_I2C_BASE,
.end = STREAMPLUG1X_ICM1_I2C_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
}, {
.start = STREAMPLUG1X_IRQ_LOW_SPEED_SUBS_I2C,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device streamplug1x_i2c_device = {
.name = "i2c_designware",
DocID028276 Rev 1 61/220
220
Communication drivers UM1942
.id = 0,
.dev = {
.coherent_dma_mask = ~0,
},
.num_resources = ARRAY_SIZE(i2c_resources),
.resource = i2c_resources,
};
4.4.5 I
2
C controller usage
To enable the I
2
C support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
.
Access from user space
Usually, I
2
C devices are controlled by a kernel driver. But all devices on an adapter can be accessed from the user space, through the “/dev” interface, by loading the module “i2c-dev”.
Each registered I
2
C adapter gets an integer number, counting from zero (0). One can examine “/sys/class/i2c-dev/” to see what number corresponds to which adapter. The I
2
C device files are character device files with a major device number 89 and a minor device number corresponding to the number assigned as explained above. They should be called
“i2c-%d” (i2c-0, i2c-1, . . . , i2c-10, . . . ).
All 256 minor device numbers are reserved for “i2c”.
To access an I
2
C adapter from a C program, for example: “#include <linux/i2c-dev.h>”.
Note that there are two files named “i2c-dev.h” . One is distributed with the Linux kernel and is meant to be included from the kernel driver code, the other one is distributed with “i2ctools” and is meant to be included from user space programs.
After deciding which adapter to access, inspect “/sys/class/i2c-dev/”. Adapter numbers are assigned somewhat dynamically, few assumptions about them can be made. They can even change from one boot to the next.
Next thing, open the device file, as follows:
#define DEVICE_FILE_NAME_I2C "/dev/i2c-0" int fd; fd = open( DEVICE_FILE_NAME_I2C, O_RDWR ); if (fd < 0) {
fprintf(stderr, "FAILED OPEN Device i2c-0. Ret=%d\n", fd);
close(fd);
exit(-1);
}
After the device is opened, specify the device address with which to communicate:
/* The I2C address */
#define I2C_SLAVE0x41
#define REGISTER_ADDR0x11
62/220 DocID028276 Rev 1
UM1942 Communication drivers
res = ioctl(fd, I2C_SLAVE, REGISTER_ADDR); if (res < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong
*/
fprintf(stderr, "FAILED I2C Set Address. Ret=%d\n", res);
close(fd);
exit(-1);
}
This completes the setup. The SMBus commands or the plain I
2
C can now be used to communicate with a device. SMBus commands are preferred if the device supports them.
Both are illustrated below.
Note that only a subset of the I
2
C and SMBus protocols can be achieved by the means of read() and write() calls. In particular, so called combined transactions (mixing read and write messages in the same transaction) aren't supported. For this reason, this interface is almost never used by user space programs.
I
2
C dev. interface
The following IOCTLs are defined for user space access:
“ioctl(file, I2C_SLAVE, long addr)”
Change the slave address. The address is passed in the 7 lower bits of the argument
(except for 10-bit addresses, passed in the 10 lower bits in this case).
“ioctl(file, I2C_TENBIT, long select)”
Selects 10-bit addresses if selection not equals 0, selects normal 7-bit addresses if selection equals 0. Default 0. This request is only valid if the adapter has “I2C_FUNC_10BIT_ADDR”.
“ioctl(file, I2C_FUNCS, unsigned long *funcs)”
Gets the adapter functionality and puts it in *funcs.
“ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)”
Do combine read/write transaction without stop in between. Only valid if the adapter has
“I2C_FUNC_I2C”. The argument is a pointer to the following “struct”: struct i2c_rdwr_ioctl_data {
struct i2c_msg *msgs;/* ptr to array of simple messages */
int nmsgs;/* number of messages to exchange */
}
The “msgs” pointer contains further pointers to data buffers. The function will write or read data to or from that buffers depending on whether the “I2C_M_RD” flag is set in a particular message or not. The slave address and whether to use the 10-bit address mode has to be set in each message, overriding the values set with the above ioctl's.
“ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)”
These are not meant to be called directly. Instead, use the access functions below. Plain I
2
C transactions can be done by using read(2) and write(2) calls. The address byte does not need to be passed. Instead, set it through the ioctl “I2C_SLAVE” before accessing the device.
DocID028276 Rev 1 63/220
220
Communication drivers
Note:
UM1942
SMBus level transactions (see <linux src>/Documentation/i2c/smbus-protocol for details) are done through the following functions:
s32 i2c_smbus_write_quick(int file, u8 value) , _s32 i2c_smbus_read_byte(int file)
All these transactions return -1 on failure; errno can be read to see what happened.
The write transactions return “0” on success; the read transactions return the read value, except for the “read_block”, which returns the number of values read. The block buffers need not be longer than 32 bytes. The above functions are all inline functions that resolve to calls to the “i2c_smbus_access” function that on its turn calls a specific ioctl with the data in a specific format. Read the source code to know what happens behind the screens.
Access in kernel space, through client driver
Usually, a single driver structure will be implemented and all clients instantiate from it.
A driver structure contains general access routines, and should be zero initialized except for fields with data provided by the user. A client structure holds device specific information like the driver model device node, and its I
2
C address.
Following example is taken from “drivers/misc/eeprom/eeprom.c”, an I
2
C client driver to access EEPROMs.
Device creation
If it is known that an I
2
C device is connected to a given I
2
C bus, the device can be instantiated by simply filling an i2c_board_info structure with the device address and driver name and calling “i2c_new_device()”. This will create the device, the driver core will take care of finding the right driver and will call its “probe()” method. If a driver supports different device types, the type can be specified using the type field. IRQ and platform data can also be specified if needed.
For example, in “arch/arm/mach-streamplug/streamplug_devel_board.c”: static struct i2c_board_info initdata i2c_board_info[] = {
{
.type = "eeprom",
.addr = 0x50,
}
}; static void init i2c_init(void)
{
i2c_register_board_info(0, i2c_board_info,
ARRAY_SIZE(i2c_board_info));
}
Device detection
Sometimes is not known in advance which I
2
C devices are connected to a given I
2
C bus .
This is for example the case of hardware monitoring devices on a PC's SMBus. In that case, the driver may be used to detect supported devices automatically. This is how the legacy model was working, and is now available as an extension to the standard driver model.
Simply define a detect callback which will attempt to identify supported devices (returning 0 for supported devices and “-ENODEV” for unsupported devices), a list of addresses to probe, and a device type (or class) so that only I
2
C buses which may have that type of the
64/220 DocID028276 Rev 1
UM1942 Communication drivers
device connected (and not otherwise enumerated) will be probed. For example, a driver for a hardware monitoring chip for which auto-detection is needed would set its class to
“I2C_CLASS_HWMON”, and only I
2
C adapters with a class including
“I2C_CLASS_HWMON” would be probed by this driver. Note that the absence of matching classes does not prevent the use of a device of that type on the given I
2
C adapter. All it prevents is auto-detection; explicit instantiation of devices is still possible.
This device detection mechanism is purely optional and not suitable for all devices.
A reliable way to identify the supported devices (typically using device specific, dedicated identification registers) is needed, otherwise misdetections are likely to occur and errors will occur.
Keep in mind that the I
2
C protocol doesn't include any standard way to detect the presence of a chip at a given address, let alone a standard way to identify devices. Even worse is the lack of semantics associated to bus transfers, which means that the same transfer can be seen as a read operation by a chip and as a write operation by another chip. For these reasons, explicit device instantiation should always be preferred to auto-detection where possible.
Device driver initialization
When the kernel is booted, or when an I
2
C driver module is inserted, some initializing has to be done. Fortunately, just registering the driver module is usually enough. The following example specifies the initialization procedure for an EEPROM device.
In the struct “i2c_driver”, below, the name field is the driver name, and must not contain spaces. It should match the module name (if the driver can be compiled as a module), although the “MODULE_ALIAS” can be used to add another name for the module. If the driver name doesn't match the module name, the module won't be automatically loaded
(“HotPlug/ColdPlug”).
static const struct i2c_device_id eeprom_id[] = {
{ "eeprom", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, eeprom_id); static struct i2c_driver eeprom_driver = {
.driver = {
.name= "eeprom",
},
.probe= eeprom_probe,
.remove= eeprom_remove,
.id_table= eeprom_id,
.class= I2C_CLASS_DDC | I2C_CLASS_SPD,
.detect= eeprom_detect,
.address_list= normal_i2c,
}; static int init eeprom_init(void)
{
DocID028276 Rev 1 65/220
220
Communication drivers UM1942
return i2c_add_driver(&eeprom_driver);
} static void exit eeprom_exit(void)
{
i2c_del_driver(&eeprom_driver);
}
All other fields are for callback functions.
Extra client data
Each client structure has a special data field that can point to any structure at all. This may be used to keep device specific data:
/* store the value */ void i2c_set_clientdata(struct i2c_client *client, void *data);
/* retrieve the value */ void *i2c_get_clientdata(const struct i2c_client *client);
I
2
C communication in kernel space
There are several functions that may be used to communicate with a device. They can be found in “include/linux/i2c.h”.
“int i2c_master_send(struct i2c_client *client, const char *buf, int count)”
These routines read and write some bytes from/to a client. The client contains the I
2
C address, it does not have to be included. The second parameter contains the bytes to read/write, the third contains the number of bytes to read/write (must be less than the length of the buffer, also should be less than 64 Kbytes because “msg.len” is u16). The actual number of bytes read or written is returned.
“int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)”
This routine sends a series of messages. Each message can be a read or write, and they can be mixed in any way. When the transactions are combined, no stop bit is sent between transactions. The “i2c_msg” structure contains for each message the client address, the number of bytes of the message and the message data itself.
SMBus communication in kernel space
Following defines SMBus APIs to access I
2
C devices from kernel space.
“s32 i2c_smbus_read_byte(struct i2c_client *client)”, “s32 i2c_smbus_write_byte(struct i2c_client *client)”
All these transactions return a negative errno value on failure. The write transactions return
0 on success; the read transactions return the read value, except for block transactions, which return the number of values read. The block buffers need not be longer than 32 bytes.
s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data);
Read the file “linux-2.6/Documentation/i2c/smbus-protocol” for more information about the actual SMBus protocol.
66/220 DocID028276 Rev 1
UM1942 Communication drivers
All functions in the above subsection are implemented in using the following “s32 i2c_smbus_xfer( )” function which must not be used directly.
4.5 Serial peripheral interface (SPI) controller
The serial peripheral interface (SPI) bus is a synchronous serial data link standard named by Motorola that operates in the full duplex mode. Devices communicate in the master/slave mode where the master device initiates the data frame. Individual slave select (CHIP-
SELECT) lines allow to multiple slave devices as shown in
connect microcontrollers to the sensors, memory and peripherals.
Figure 7. SPI master/slave connectivity
SPI
Master
SCLK
MOSI
MISO ss1 ss2 ss3
SCLK
MOSI
MISO ss
SPI
Slave
SCLK
MOSI
MISO ss
SPI
Slave
The SPI bus specifies four logic signals.
ï‚·
SCLK - serial clock (output from master)
ï‚·
MOSI - master output, slave input (output from master)
ï‚·
MISO - master input, slave output (output from slave)
ï‚·
SS - slave select (active low; output from master).
SCLK
MOSI
MISO ss
SPI
Slave
AM039714
DocID028276 Rev 1 67/220
220
Communication drivers UM1942
The SPI framework present in Linux supports only the master side of the Motorola SPI interface. User applications can use the interface provided by the protocol drivers present in
Linux. Protocol drivers use the standard calls provided by the SPI framework present in
Linux. The SPI controller driver provides the interface to the SPI framework for accessing the SPI controller. The SPI controller transfers data to the SPI slave devices/memories connected to it according to the configuration provided by the SPI controller driver.
presents the SPI software system architecture.
Figure 8. SPI framework architecture
User application
User space
EPROM protocol driver
SPIDev interface
Linux SPI framework
SPI controller driver
Kernel space
SPI controller SPI slave devices
Hardware
AM039715
The Linux SPI framework defines two types of SPI drivers in Linux:
ï‚·
Control drivers
ï‚·
Protocol/slave drivers
Controller drivers configure SPI controllers. Their interface can be used for configuring the controller and transfer data over the SPI bus. They may or may not use DMA for data transfer with the slave device. The Linux SPI framework uses controller drivers for all its SPI related operations. The ARM PL022 controller driver can be found at “drivers/spi/ambapl022.c”.
Protocol/slave drivers pass messages through the controller driver to communicate with a slave device on the other side of an SPI link. They are present above the SPI kernel framework and they provide the interface to the user applications present in the user space.
68/220 DocID028276 Rev 1
UM1942 Communication drivers
Currently two sample protocol drivers are present in the “drivers/spi” folder.
ï‚·
FLASH protocol driver (“m25p80”, supported but not configured)
ï‚·
General character interface driver, spidev (spidev is supported and configured by default).
The FLASH driver uses the SPI framework to communicate with a range of serial NOR chips. This driver presents a standard MTD interface to user applications. The MTD node for the SPI can be found by looking at the “/proc/mtd” file after booting Linux. This driver can be enabled through the CONFIG_MTD_M25P80 Kconfig option and is present in
“drivers/mtd/devices/”.
The general character interface driver provides a character special device to the SPI controller. To access it, use the following calls: “open()”, “read()”, “write()” and “ioctl()”.
For a new interface, write a new protocol driver. For information on using the SPI framework, see the “spidev.c” files in the “drivers/spi” folder.
The SPI shows up in “sysfs” at several locations:
ï‚·
/sys/devices/. . . /CTLR . . . physical node for a given SPI controller
ï‚·
/sys/devices/. . . /CTLR/spiB.C . . . spi_device on bus “B”, CHIP-SELECT C, accessed through CTLR.
ï‚·
/sys/bus/spi/devices/spiB.C . . . symlink to that physical . . . /CTLR/spiB.C device
ï‚·
/sys/devices/. . . /CTLR/spiB.C/modalias . . . identifies the driver that should be used with this device (for hot plug/cold plug)
ï‚·
/sys/bus/spi/drivers/D . . . a driver for one or more spi*.* devices.
ï‚·
/sys/class/spi_master/spiB . . . symlink (or actual device node) to a logical node which could hold the class related state for the controller managing the bus “B”. All spiB.* devices share one physical SPI bus segment, with SCLK, MOSI, and MISO.
The Linux SPI framework provides APIs for registering and unregistering SPI slave drivers and transferring data over the SPI bus. These functions will be explained one by one with examples from the FLASH driver.
“int spi_register_driver(struct spi_driver *sdrv)”
The SPI slave driver must register itself with the SPI framework by calling this API, preferably from its “module_init()” routine. In this routine, the “struct slave_driver” is a structure which contains information about the SPI slave driver.
struct spi_driver {
const struct spi_device_id *id_table;
int(*probe)(struct spi_device *spi);
int(*remove)(struct spi_device *spi);
void (*shutdown)(struct spi_device *spi);
int(*suspend)(struct spi_device *spi, pm_message_t mesg);
int(*resume)(struct spi_device *spi);
struct device_driverdriver;
};
Implementation of all these functions may not be required.
DocID028276 Rev 1 69/220
220
Communication drivers UM1942
The following “spi_setup” API used to configure SPI controller slave drivers can change the previously saved struct “spi_device” with the new SPI configuration, like “bits_per_word”,
“max_speed_hz”, mode, etc., and then call this API.
int spi_setup(struct spi_device *spi)
The following API writes len (length) bytes of data present at the “buf” (buffer) address to the
SPI slave device attached to the SPI controller.
int spi_write(struct spi_device *spi, const u8 *buf, size_t len)
The following API reads “len” bytes of data from the SPI slave device attached to the SPI controller and saves data to the buf address.
int spi_read(struct spi_device *spi, u8 *buf, size_t len)
The following API is used for using the full duplex mode of the SPI controller. It writes data to the slave device from the “txbuf” address and reads data to the “rxbuf” address from the slave device. The length of transfer is “len” for both Tx and Rx.
int spi_write_and_read(struct spi_device *spi, const u8 *txbuf, u8
*rxbuf, size_t len)
The following spi_unregister API is used to unregister a slave driver from the SPI framework. Preferably done from “module_exit()” routine of the slave driver.
void spi_unregister_device(struct spi_device *spi)
Adding a new slave driver
This section will explain how a slave device driver should register itself with the SPI framework, using the “m25p80.c” driver as a basis for the example.
Registering slave driver
The SPI slave driver must be registered with the SPI framework. This is accomplished by calling: spi_register_driver(&m25p_driver);
Unregistering the driver
The SPI slave driver must unregister itself when its module is removed. This is done by calling: spi_unregister_driver(&m25p_driver).
70/220 DocID028276 Rev 1
UM1942 Communication drivers
Following is a registration part of the “drivers/mtd/devices/m25p80.c” driver: static const struct spi_device_id m25p_ids[] = {
{ "at25fs010", INFO(0x1f6601, 0, 32 * 1024,4, SECT_4K) },
{ "at25fs040", INFO(0x1f6604, 0, 64 * 1024,8, SECT_4K) },
......
/* ST Microelectronics -- newer production may have feature updates?'
*/
{ "m25p05", INFO(0x202010, 0, 32 * 1024,2, 0)},
{ "m25p10", INFO(0x202011, 0, 32 * 1024,4, 0)},
{ "m25p20", INFO(0x202012, 0, 64 * 1024,4, 0)},
{ "m25p40", INFO(0x202013, 0, 64 * 1024,8, 0)},
{ "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) },
......
{ },
};
MODULE_DEVICE_TABLE(spi, m25p_ids); static struct spi_driver m25p_driver = {
.driver = {
.name = "m25p80",
.owner = THIS_MODULE,
},
.id_table = m25p_ids,
.probe= m25p_probe,
.remove= devexit_p(m25p_remove),
}; static int init m25p80_init(void)
{
return spi_register_driver(&m25p_driver);
} module_init(m25p80_init); static void exit m25p80_exit(void)
{
spi_unregister_driver(&m25p_driver);
} module_exit(m25p80_exit);
DocID028276 Rev 1 71/220
220
Communication drivers
4.5.2
UM1942
The kind of the interface provided to the user applications is slave driver dependent (sysfs, proc, dev, etc.). The struct spi_device is passed to the slave driver when the probe function of the slave is called from the SPI framework after the device registration. The structure in the slave driver must be saved and used for any communication with the SPI framework.
SPI kernel source and configuration
Following is the detail corresponding to the layout of the driver and kernel configuration:
The SPI controllers driver is present in “drivers/spi/amba-pl022.c”.
The SPI slave controller drivers are present in:
ï‚·
“m25p80” slave driver: “drivers/mtd/devices/m25p80.c”
ï‚·
“spidev” slave driver: “drivers/spi/spidev.c”
lists the kernel configuration options associated with the SPI:
Table 12. SPI configurations
Configuration
CONFIG_SPI
CONFIG_SPI_MASTER
CONFIG_SPI_PL022
CONFIG_SPI_SPIDEV
Description
It enables SPI framework layer support
It enables SPI_MASTER support
It enables AMBA™ PL022 controller support
It enables SPIDEV slave support
72/220
Once the slave/protocol driver is up, we must add/register a slave device with the SPI bus.
The SPI controller driver and slave driver need some board specific data to work correctly.
This data is present in the all SoC's board files, (i.e.: “streamplug_devel_board.c”). There are two types of platform information:
ï‚·
“platform_data” which initializes “spi_device.platform_data”, the particular data stored there is slave driver specific.
ï‚·
“controller_data” which is required by the SPI controller driver. This structure is controller driver specific and for adding a new slave device, it must be supplied.
DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control);
/* This will define CHIP_INFO structure for a specific spi slave */
#define DECLARE_SPI_CHIP_INFO(id, type, chip_select_control)\ static struct pl022_config_chip spi##id##_##type##_chip_info = {\
.lbm = LOOPBACK_DISABLED,\
.iface = SSP_INTERFACE_MOTOROLA_SPI,\
.hierarchy = SSP_MASTER,\
.slave_tx_disable = 0,\
.endian_tx = 0,\
.endian_rx = 0,\
.ctrl_len = SSP_BITS_8,\
.data_size = SSP_DATA_BITS_8,\
.com_mode = INTERRUPT_TRANSFER,\
DocID028276 Rev 1
UM1942 Communication drivers
.rx_lev_trig = 0,\
.tx_lev_trig = 0,\
.clk_phase = SSP_CLK_FIRST_EDGE,\
.clk_pol = SSP_CLK_POL_IDLE_LOW,\
.cs_control = chip_select_control,\
}; static struct spi_board_info initdata spi_board_info[] = {
/* register m25p80 driver */
{
.modalias = "m25p80",
.controller_data = &spi0_flash_chip_info,
.platform_data = &spi_flash_info,
.max_speed_hz = 800000,
.bus_num = 0,
.chip_select = 0,
.mode = 0,
}
};
/* Define chip select routine using GPIO_15 (gpio line 39) as default, otherwise is provided by command line option */
DECLARE_SPI_CS_CONTROL(0, flash, cs_gpio_pin);
/* This will define cs_control function for a specific spi slave */
#define DECLARE_SPI_CS_CONTROL(id, type, gpio)\
static void spi##id##_##type##_cs_control(u32 control)\
{\
static int count, ret;\
\
if (unlikely(!count)) {\
count++; \ ret = spi_cs_gpio_request(gpio);\
} \
\
if (!ret) \
gpio_set_value(gpio, control); \
}
/* Definition of spi_cs_gpio_request() is present in <plat/spi.h> */ static inline int spi_cs_gpio_request(u32 gpio_pin)
{
int ret;
ret = gpio_request(gpio_pin, "SPI_CS");
if (ret < 0) {
DocID028276 Rev 1 73/220
220
Communication drivers
printk(KERN_ERR "SPI: gpio:%d request fail\n", gpio_pin);
return ret;
}
else {
ret = gpio_direction_output(gpio_pin, 1);
if (ret) {
printk(KERN_ERR "SPI: gpio:%d direction set fail\n",
gpio_pin);
return ret;
}
}
return 0;
}
UM1942
The user space and kernel space usage through the framework or directly (if the framework is not present).
4.6 Linux TTY framework
The TTY framework of the Linux kernel, serves as an intermediary layer between hardware device drivers and user applications to provide line buffering and management of input and output. The layer is purely software oriented and makes no direct communication with physical hardware. Instead, the TTY driver relies on an underlying device driver to communicate directly with the hardware.
4.6.1 Linux TTY framework software overview
The basic function of the TTY layer is to interface with the lower level device driver and insulate the higher level from the complexity of the hardware level. There are different types of TTY drivers: the console and serial port. The console driver is used at two different places in Linux. Firstly, at boot time it is used before the initialization of the serial TTY framework as it takes some time for the serial TTY framework to initialize during Linux boot-up. Secondly, after Linux boot-up, the console device sits in the lowest levels of Linux in order to bring critical information out of the system as soon as possible. It is not involved in all the complexity of TTY management.
4.6.2 Linux framework kernel source
The tty source code in Linux is present in “drivers/char/tty_*” files.
4.6.3 Linux TTY framework usage
The following paragraphs briefly describe system calls which can be used to access and use serial devices in the TTY framework. The non-blocking mode is supported. When running in the blocking mode it may need to wait for the carrier.
74/220 DocID028276 Rev 1
UM1942 Communication drivers
System calls
TTY side interfaces:
open()
Called when the line discipline is attached to the terminal. No other call into the line discipline for this TTY will occur until it completes successfully. Returning an error will prevent the ldisc from being attached. If the “O_NONBLOCK” flag is specified and the open() call would result in the process being blocked for some reason it returns immediately.
The first time the process attempts to perform I/O on the open descriptor it will block.
close()
This is called on a terminal when the line discipline is being unplugged. At the point of execution no further users will enter the ldisc code for this TTY.
hangup()
Called when the tty line is hung up. The line discipline should cease I/O to the TTY. No further calls into the ldisc code will occur. The return value is ignored.
write()
A process is writing data through the line discipline. Multiple write calls are serialized by the tty layer for the “ldisc”.
flush_buffer()
(Optional). May be called at any point between open and close, and instructs the line discipline to empty its input buffer.
chars_in_buffer()
(Optional). Reports the number of bytes in the input buffer.
set_termios()
(Optional). Called on “termios” structure changes. The caller passes the old termios data and the current data is in the TTY. It is called under the termios semaphore so it is allowed to sleep. Serialized only against itself.
read()
Moves data from the line discipline to the user. Multiple read calls may occur in parallel and the ldisc must deal with serialization issues.
poll()
Checks the status for the poll/select calls. Multiple poll calls may occur in parallel.
ioctl()
Called when an ioctl is handed to the TTY layer that might be for the ldisc. Multiple ioctl calls may occur in parallel.
compat_ioctl()
Called when a 32-bit ioctl is handed to the TTY layer that might be for the ldisc. Multiple ioctl calls may occur in parallel.
DocID028276 Rev 1 75/220
220
Communication drivers UM1942
Example commands
The following paragraphs are example commands:
Getty
Getty opens a TTY port, prompts for a login name and invokes the “/bin/login” command.
The getty command sets and manages terminals by setting up the speed, the terminal flags, and the line discipline.
Example:
/sbin/getty 9600 ttyAMA1
Stty
Stty is used to change and print the terminal line settings.
+/* List the attribute settings for a terminal that has a user logged+
+ * on it already.+
+ */+ stty -a -F /dev/ttyAMA0
+/* Disable modem control signals. */+ stty clocal -F /dev/ttyAMA0
+/* Enable RTS/CTS handshaking */+ stty crtscts -F /dev/ttyAMA0
/* Set the baud rate of current terminal to 9600 baud. */ stty
The UART is a universal asynchronous receiver/transmitter that supports much of the industry standard 16C550 UART. Two UART ports are available on the STreamPlug. This section describes the integration of the STreamPlug UART device driver into the Linux kernel.
76/220 DocID028276 Rev 1
UM1942
4.7.1
Communication drivers
UART software overview
UART drivers support the TTY kernel layer. The I/O system calls start above top level line disciplines and finally ripple down to UART drivers through the TTY layer as shown in
. The data flow between the user space and the serial device driver, therefore, is
mediated by the TTY layer, that implements functionalities that are common to all TTY-type devices.
Figure 9. UART software system architecture
Application
User space
Console driver
Linux TTY layer
Kernel space
UART driver
UART hardware ARM PL011
Hardware
AM039716
There are different types of TTY drivers: the console and serial port. The console driver is used at two different places in Linux. First, at boot time it is used before the initialization of the serial TTY framework as it takes some time for the serial TTY framework to initialize during Linux boot-up. Secondly, after Linux boot-up, the console device sits in the lowest levels of Linux in order to bring critical information out of the system as soon as possible.
It is not involved in all the complexity of TTY management. The serial ports are named ttyAMA0, ttyAMA1, etc. For each such serial port, there is a special file in the /dev (device) directory. The major number 204 is associated to the ttyAMA driver. For the UART layer the major number is 204 and the minor number ranges between 64 - 255.
DocID028276 Rev 1 77/220
220
Communication drivers
4.7.2 UART kernel source and configuration
UM1942
The following section contains details corresponding to the layout of the driver and kernel configuration.
The UART AMBA PL011 controller driver is present in “drivers/serial/amba-pl011.c”.
The serial core controller is present in “drivers/serial/serial-core.c”.
The platform data defining UART1 and UART2 controller configurations is present in
“arch/arm/mach-streamplug/streamplug1x.c” as listed:
ï‚·
“CONFIG_SERIAL_CORE” enables the UART TTY framework.
ï‚·
“CONFIG_SERIAL_CORE_CONSOLE” enables the UART console framework.
ï‚·
“CONFIG_SERIAL_AMBA_PL011” enables STreamPlug AMBA PrimeCell PL011
UART driver support for the TTY framework.
ï‚·
“CONFIG_SERIAL_AMBA_PL011_CONSOLE” enables the STreamPlug UART driver support for the console framework.
78/220
This section lists the driver's platform interface and its possible configuration.
Driver configuration
Default device registration of the UART1/2 controller depends on the platform data passed from the boards (“arch/arm/mach-streamplug/streamplug1x.c”).
/* uart1 device registration */ struct amba_device streamplug1x_uart1_device = {
.dev = {
.init_name = "uart1",
},
.res = {
.start = STREAMPLUG1X_ICM1_UART1_BASE,
.end = STREAMPLUG1X_ICM1_UART1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {STREAMPLUG1X_IRQ_LOW_SPEED_SUBS_UART1, NO_IRQ},
}; struct amba_device streamplug1x_uart2_device = {
.dev = {
.init_name = "uart2",
},
.res = {
.start = STREAMPLUG1X_ICM1_UART2_BASE,
.end = STREAMPLUG1X_ICM1_UART2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {STREAMPLUG1X_IRQ_LOW_SPEED_SUBS_UART2, NO_IRQ},
};
DocID028276 Rev 1
UM1942 Communication drivers
4.8
4.8.1
For usage please refer to the chapter on the Linux TTY framework.
Control area network (CAN)
The controller area network (CAN) bus is a bus designed to allow microcontrollers and devices to communicate with each other without a host computer. The STreamPlug CAN device driver is derived from the CAN bus driver for the “C_CAN” controller which is compliant to the CAN protocol version 2.0.
CAN software overview
The CAN device driver belongs to the Linux network stack and it is accessible through network interfaces. The entire stack can be summarized in the following layers and features:
ï‚·
Application layer
ï‚·
Object layer
– Message filtering
– Message and status handling
ï‚·
Transfer layer
– Fault confinement
– Error detection and signaling
– Message validation
– Acknowledgment
– Arbitration
– Message framing
– Transfer rate and timing
ï‚·
Physical layer
– Signal level and bit representation
– Transmission medium
DocID028276 Rev 1 79/220
220
Communication drivers
4.8.2 CAN kernel source and configuration
UM1942
lists the STreamPlug Linux kernel configuration which
must be used to support the
STreamPlug CAN bus.
Table 13. CAN Linux kernel configuration
Configuration Description
Enable CAN support CONFIG_CAN=y
CONFIG_CAN_RAW=y
CONFIG_CAN_BCM=y
CONFIG_CAN_DEV=y
CONFIG_CAN_CALC_BITTIMING=y
CONFIG_CAN_C_CAN=y
CONFIG_CAN_C_CAN_PLATFORM=y
Enable C_CAN support
Enable C_CAN platform
The key source code about the STreamPlug CAN device driver can be found in the following files: drivers/net/can/c_can drivers/net/can/c_can/c_can.h drivers/net/can/c_can/c_can.c drivers/net/can/c_can/c_can_platform.c arch/arm/mach-streamplug/ipswrst_ctrl.c arch/arm/mach-streamplug/include/mach/generic.h
arch/arm/mach-streamplug/include/mach/streamplug10.h arch/arm/mach-streamplug/clock.c
arch/arm/mach-streamplug/padmux.c arch/arm/mach-streamplug/streamplug1x.c
An other related source code can be found also in the following folders: include/linux/can include/linux/can/platform net/can
The hardware filtering mechanism is not enabled there, so all messages are considered good.
80/220 DocID028276 Rev 1
UM1942 Communication drivers
The STreamPlug CAN device driver manages two resources: CAN1 and CAN2. The platform code for the driver is shown in the following paragraphs:
/* CAN1 device registration */ static struct resource can1_resources[] = {
{
.start = STREAMPLUG1X_ICM1_CAN1_BASE,
.end = STREAMPLUG1X_ICM1_CAN1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
}, {
.start = STREAMPLUG1X_IRQ_LOW_SPEED_SUBS_CAN1,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device streamplug1x_can1_device = {
.name = "c_can_platform",
.id = 1,
.num_resources = ARRAY_SIZE(can1_resources),
.resource = can1_resources,
};
/* CAN2 device registration */ static struct resource can2_resources[] = {
{
.start = STREAMPLUG1X_ICM1_CAN2_BASE,
.end = STREAMPLUG1X_ICM1_CAN2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
}, {
.start = STREAMPLUG1X_IRQ_LOW_SPEED_SUBS_FIRDA_CAN2,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device streamplug1x_can2_device = {
.name = "c_can_platform",
.id = 2,
.num_resources = ARRAY_SIZE(can2_resources),
.resource = can2_resources,
};
DocID028276 Rev 1 81/220
220
Communication drivers UM1942
To enable the CAN support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
.
The CAN device driver can be tested connecting the board to a remote PC by a CAN to the
USB bridge.
Two CAN interfaces are available for STreamPlug user application: CAN0 and CAN1. The file can_readme.txt available in the folder “/examples/can” describes a set of user space commands to test the CAN interfaces. In particular, it focuses on the following commands:
/sbin/ip link set <device> type can bitrate <value> ifconfig <device> up cansend <device> <can_frame> candump <device> > <outputfile>
The following is an example of a Linux session where the previous commands are used to setup the CAN bus and to receive and send simple messages.
STreamPlug login: root
#
# cd /examples/can
# /sbin/ip link set can0 type can bitrate 125000
# /sbin/ip -details -statistics link show can0
2: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN qlen 10 link/can can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0 bitrate 125000 sample-point 0.875
tq 1000 prop-seg 3 phase-seg1 3 phase-seg2 1 sjw 1 c_can: tseg1 2..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp-inc 1 clock 83000000 re-started bus-errors arbit-lost error-warn error-pass bus-off
0 0 0 0 0 0
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
# ifconfig can0 up c_can_platform c_can_platform.1: can0: setting BTR=0512 BRPE=0001
# cansend can0 5A1#11.22.33.44.55.66.77.88
# candump can0 can0 888 [8] 01 02 03 04 05 06 07 08 can0 888 [8] 01 02 03 04 05 06 07 08 can0 888 [8] 01 02 03 04 05 06 07 08 can0 888 [8] 01 02 03 04 05 06 07 08
Other tests can be performed with the can utils utilities provided with the auxiliary filesystem.
82/220 DocID028276 Rev 1
UM1942
4.9
4.9.1
4.9.2
Communication drivers
Fast infrared data association (FIrDA)
The FIrDA IP is a Fast infrared controller that provides an interface to infrared wireless devices. It supports three IrDA
™
modes, SIR, MIR and FIR. The transfer speed ranges from
2400 bps (SIR) to 4 Mbps (FIR). The standard mode, SIR, accesses the infrared port through a serial interface. The faster modes, MIR and FIR, require special support handling in Linux. In general, as reported by “irattach” manual page, Linux FIR support is not as stable and mature as SIR or MIR.
FIrDA software overview
The FIrDA Linux device driver belongs to the Linux network subsystem. The device may enable and be configured from the command line into the OK Linux XML cell configuration file. The FIrDA Linux device driver is initialized using platform data provided by the command line. In particular the QOS (Quality Of Service) parameters are set at driver initialization. The QoS parameters are used by IrLAP protocol during the negotiation phase with IrDA peers.
FIrDA kernel source and configuration
The most important source files for this device driver are: drivers/net/irda/dice_fir.c include/linux/dice_fir.h
However, other aspects of it are defined in the following files: arch/arm/mach-streamplug/ipswrst_ctrl.c arch/arm/mach-streamplug/include/mach/generic.h
arch/arm/mach-streamplug/include/mach/streamplug10.h arch/arm/mach-streamplug/clock.c
arch/arm/mach-streamplug/padmux.c
arch/arm/mach-streamplug/streamplug_devel_board.c arch/arm/mach-streamplug/streamplug1x.c
In order to support the FIrDA device driver it is necessary to enable the following options in
within the STreamPlug Linux kernel configuration file.
Table 14. FIrDA Linux kernel configuration
Configuration
Description
CONFIG_IRDA=y
CONFIG_IRLAN=y
CONFIG_IRCOMM=y
CONFIG_DICE_FIR=y
CONFIG_IRDA_DEBUG_DEVICE=y
Add support for the IrDA™ protocols.
Add support for IrLAN protocol.
Add support for the IrCOMM protocol.
Add support for FIR
Activate debugging of IrDA device drivers
DocID028276 Rev 1 83/220
220
Communication drivers UM1942
The FIrDA device driver is characterized by the following STreamPLug FIrDA platform C structures:
/* Fast Irda Controller registration */ static struct resource irda_resources[] = {
{
.start = STREAMPLUG1X_ICM1_FIRDA_BASE,
.end = STREAMPLUG1X_ICM1_FIRDA_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
}, {
.start = STREAMPLUG1X_IRQ_LOW_SPEED_SUBS_FIRDA_CAN2,
.flags = IORESOURCE_IRQ,
},
};
#if defined (CONFIG_DICE_FIR) static struct dice_fir_platform_data irda_platform_data;
#endif struct platform_device streamplug1x_irda_device = {
#if defined (CONFIG_DICE_FIR)
.name = "dice_fir",
#elif defined (CONFIG_DICE_IR)
.name = "dice_ir",
#endif
.id = -1,
.num_resources = ARRAY_SIZE(irda_resources),
.resource = irda_resources,
#if defined (CONFIG_DICE_FIR)
.dev.platform_data = &irda_platform_data,
#endif
};
To enable the FIrDA support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
.
A user space application, “irda_xfer” is provided in the STreamPlug filesystem
(/examples/irda). It shall be used to test IrDA functionalities using two STreamPlug boards wire connected via the FIrDA I/Os. Since the IrDA is a network interface, the first step is the activation of the network IrDA interface using the ifconfig command.
$ ifconfig irda0 up
Finally, a file transfer can be established by using run “irda_xfer”. It starts a discover procedure to determine whether there are any IrDA peers and upon the discovery it transfers the files indicated in the command argument between them.
84/220 DocID028276 Rev 1
UM1942 Communication drivers
To put side “A” in the listening mode, use:
$ ./irda_xfer -r
To send the file from the side B to side A, use :
$ ./irda_xfer -s</path/irdaInputFile>
An example of a session that sends a file through the IrDA interface is shown below.
# uname -a
Linux STreamPlug 2.6.35-vcpu-okl_streamplug+ #76 Mon Aug 27 14:48:15
CEST 2012 vcpuv5-el GNU/Linux
# pwd
/examples/irda
# cat hello_world.txt hello world
# ifconfig irda0 Link encap:UNSPEC HWaddr C0-70-0B-A0-1D-00-00-00-00-00-00-00-00-00-
00-00
UP RUNNING NOARP MTU:2048 Metric:1
RX packets:81 errors:0 dropped:0 overruns:0 frame:0
TX packets:107 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:8
RX bytes:366 (366.0 B) TX bytes:866 (866.0 B) Interrupt:25
# ./irda_xfer -shello_world.txt
804: Using default DeviceIrDA: irda0
807: open socket
133: Waiting for discovery to finish.
122: getsockopt IRLMP_ENUMDEVICES ok, len=40
Discovered: daddr: 81a3310a saddr: a00b70c0 name: Linux
Connected to 81a3310a mtu = 2039 date: 497 date: 62168263697000000 sent: FILE 12 32 14474676 3656803904 hello_world.txt
Received (5) ACK Y
Sent hello_world.txt, 12 bytes in 1 sec. 0.012 KBytes/sec last read:
Transport endpoint is not connected
#
While the following is the dump of a session to receive a file through the same interface.
# ifconfig
# ifconfig irda0 up
# ifconfig irda0 Link encap:UNSPEC HWaddr
56-0A-1D-F4-1D-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:2048 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:8
DocID028276 Rev 1 85/220
220
Communication drivers UM1942
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:25
# ./irda_xfer -r
804: Using default DeviceIrDA: irda0
807: open socket mtu=2039
FILE 12 32 14474676 3656803904 hello_world.txt filename: hello_world.txt
filesize: 12
Filemode: 32, Modified fdate1: 14474676 = 0xdcddb4 fdate2: 3656803904 = 0xd9f66640 filedate: 62168263697000000 filedate: 497 = Thu Jan 1 00:08:17 1970
Received hello_world.txt, 12 bytes in 1 sec. 0.012 KBytes/sec
# ls -altr
-rwxrwxrwx 1 1000 1000 625971 Jan 1 1970 irda_xfer
-rw-r--r-- 1 1000 1000 1344 Jan 1 1970 irda_readme.txt
-rw-r--r-- 1 1000 1000 1341 Jan 1 1970 irdaInputFile.txt drwxr-xr-x
10 1000 1000 0 Jan 1 1970 ..
-rw-r--r-- 1 root root12 Jan 1 1970 hello_world.txt drwxr-xr-x 2
1000 1000 0 Mar 3 21:43 .
# cat hello_world.txt hello world
#
# dmesg bootconsole [early0] enabled
Linux version 2.6.35-vcpu (xxxx@VirtualBox) (gcc version 4.3.3
(Sourcery G++ Lite 2009q1-203) ) #9 Tue Aug 28 09:36:05 CEST 2012
CPU: vCPUv5 [14069260] revision 0 (ARMv5TEJ) CPU: VIVT data cache, VIVT instruction cache Machine: ST-STREAMPLUG-DEBUG
ATag virq 4, "timer_tick"
ATag microvisor_timer 2d, 4, "timer_microvisor_timer"
ATag vclient 2e, 20, 6, "vserial_vtty0_vclient"
On node 0 totalpages: 8192 free_area_init_node: node 0, pgdat 843e4eb8, node_mem_map 847a4000
Normal zone: 64 pages used for memmap
Normal zone: 0 pages reserved
Normal zone: 8128 pages, LIFO batch:0
OKL4: vcpu_helper_page at 847e5000/01fff000
VMMU:paging_init: VMMU: Cache management handing is possibly not correct
(SDK-1545).
Built 1 zonelists in Zone order, mobility grouping on. Total pages:
8128
86/220 DocID028276 Rev 1
UM1942 Communication drivers
Kernel command line: console=vcon0,115200n8 clcd=off sata=off pcie=off usb=on:host eth=off i2c=off ssp=off uart1=on:primary uart2=on:primary can=off firda=on:3 fsmc=off sport=off ts=off
PID hash table entries: 128 (order: -3, 512 bytes)
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes) Inodecache hash table entries: 2048 (order: 1, 8192 bytes) Memory: 32MB =
32MB total
Memory: 24652k/24652k available, 8116k reserved, 0K highmem
Virtual Kernel memory layout: vector : 0x01fff000 - 0x02000000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xfb800000 - 0xfc000000 ( 8 MB) vmalloc : 0x86800000 - 0xf0000000 (1688 MB) lowmem : 0x84000000 - 0x86000000 ( 32 MB) modules : 0x83000000 - 0x84000000 ( 16 MB)
.init : 0x84000000 - 0x8401d000 ( 116 kB)
.text : 0x8401d000 - 0x8439d000 (3584 kB)
.data : 0x843b4000 - 0x843e54c0 ( 198 kB)
Hierarchical RCU implementation.
Verbose stalled-CPUs detection is disabled. NR_IRQS:512
Console: colour dummy device 80x30
Calibrating delay loop... 164.24 BogoMIPS (lpj=821248) pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
VCPU support v1.0
NET: Registered protocol family 16 padmux: dev name usb padmux: dev name uart1 padmux: dev name uart2 padmux: dev name firda
Serial: AMBA PL011 UART driver uart1: ttyAMA0 at MMIO 0xd0000000 (irq = 26) is a AMBA/PL011 uart2: ttyAMA1 at MMIO 0xd0080000 (irq = 27) is a AMBA/PL011 bio: create slab <bio-0> at 0 vServices Framework 1.0 registering driver 0
SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb
NET: Registered protocol family 23
Switching to clocksource microvisor timer
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
DocID028276 Rev 1 87/220
220
Communication drivers UM1942
TCP: Hash tables configured (established 1024 bind 1024) TCP reno registered
NET: Registered protocol family 1
Trying to unpack rootfs image as initramfs... Freeing initrd memory:
3724K
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
msgmni has been set to 55 alg: No test for stdrng (krng) io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) vServices Microvisor Transport v1.0 registering driver 0
OKL4 virtual console init console [vcon0] enabled, bootconsole disabled brd: module loaded registering driver 0 st: Version 20081215, fixed bufsize 32768, s/g segs 256 smi smi: mtd
.name=w25q64_bank0 .size=800000(8M) smi smi: .erasesize = 0x10000(64K)
Creating 1 MTD partitions on "w25q64_bank0":
0x000000000000-0x000000800000 : "Reserved" smi smi: mtd .name=w25q64_bank1 .size=800000(8M) smi smi: .erasesize = 0x10000(64K)
Creating 1 MTD partitions on "w25q64_bank1":
0x000000000000-0x000000800000 : "Auxiliary Root File System" smi smi: mtd .name=w25q64_bank2 .size=800000(8M) smi smi: .erasesize = 0x10000(64K)
Creating 1 MTD partitions on "w25q64_bank2":
0x000000000000-0x000000800000 : "Root File System"
CAN device driver interface vs_ethernet_server_init - registering registering driver 0 usbcore: registered new interface driver asix usbcore: registered new interface driver cdc_ether usbcore: registered new interface driver cdc_eem usbcore: registered new interface driver net1080 dice_fir dice_fir: DICE Fast IrDA probed successfully ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver streamplug-ehci streamplug-ehci: STREAMPLUG EHCI streamplug-ehci streamplug-ehci: new USB bus registered, assigned bus number 1 streamplug-ehci streamplug-ehci: irq 5, io mem 0xe1800000 streamplug-ehci streamplug-ehci: USB 0.0 started, EHCI 1.00 hub 1-0:1.0: USB hub found
88/220 DocID028276 Rev 1
UM1942 Communication drivers
hub 1-0:1.0: 1 port detected ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver streamplug-ohci streamplug-ohci.0: STREAMPLUG OHCI streamplug-ohci streamplug-ohci.0: new USB bus registered, assigned bus number 2 streamplug-ohci streamplug-ohci.0: irq 5, io mem 0xe1900000 hub 2-0:1.0: USB hub found hub 2-0:1.0: 1 port detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
Loading designware_udc: rtc-streamplug rtc-streamplug: rtc core: registered rtc-streamplug as rtc0 i2c /dev entries driver sp805-wdt wdt: registration successful dw_dmac: DesignWare DMA Controller, 8 channels
TCP cubic registered
NET: Registered protocol family 10
IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17 can: controller area network core (rev 20090105 abi 8)
NET: Registered protocol family 29 can: raw protocol (rev 20090105) can: broadcast manager protocol (rev 20090105 t)
IrCOMM protocol (Dag Brattli)
802.1Q VLAN Support v1.8 Ben Greear <[email protected]>
All bugs added by David S. Miller <[email protected]> registering driver
0 rtc-streamplug rtc-streamplug: setting system clock to 1990-03-03
21:35:15 UTC (636500115)
Freeing init memory: 116K net irda0: dice_fir_set_baudrate IrDA mode FIR -> SIR mode net irda0: dice_fir_set_baudrate IrDA mode SIR -> FIR mode
Further IrDA utilities (provided by the buildroot for the auxiliary filesystem) or IrTTY device driver functionalities (SIR only) can be used for IrDA test purposes.
DocID028276 Rev 1 89/220
220
Communication drivers UM1942
The PCIe is an important serial bus protocol which is commonly used for peripheral expansion. Gen1 operates at 2.5 Gbits/s. It is very similar to legacy PCI from the user's perspective.The upper software layer is the same as that of PCI. The lower layer has some
PCIe-specific read/write configuration. When software boots, it determines which devices are connected downstream and at what speed (Gen1). Then it creates a map for the entire downstream device, which is further used by a device specific driver.
The STreamPlug PCIe controller is a dual mode controller, which can work as:
ï‚·
Root complex (RC, host)
ï‚·
Endpoint (EP, device)
4.10.1 PCIe software overview
Both the PCIe host and device controllers require initial PCIe modules configured.
The IP initialization (“arch/arm/mach-streamplug/streamplu1x.c”) code is shown below.
static int pcie_init(struct device *dev, void iomem *mmio)
{
int ret; set_pcie_reset_disable();
set_pcie_clock_enable();
set_ltssm_disable();
set_uport_reset_disable();
set_uport_clock_enable();
set_pcie_core_reset_n_release();
set_uport_reset_enable();
set_uport_clock_disable();
set_pcie_core_reset_n_setup();
set_uport_reset_disable();
set_uport_clock_enable();
set_pcie_core_reset_n_release();
ret = miphy_pipew_completion();
if (ret) {
dev_err(dev, "failed miphy init pipew completion\n");
goto err;
}
90/220 DocID028276 Rev 1
UM1942 Communication drivers
miphy_write(MIPHY_TX_DETECT_POLL_REG, 0x08);
ret = miphy_pll_idll_ready();
if (ret) {
dev_err(dev, "failed pll/idll not ready\n");
goto err;
}
return 0;
err:
return ret;
}
The initialization happens in the following order: set_pcie_reset_disable()
The “arch/arm/plat-streamplug/misc.c” routine removes the PCIe controller from the reset state as shown below.
void set_pcie_reset_disable(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, expi_sub_swrst_reg))
);
val &= ~EXPI_SUB_PCIE_SWRST_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, expi_sub_swrst_reg))
);
}
set_pcie_clock_enable()
The “arch/arm/plat-streamplug/misc.c” routine configures the clock for the PCIe controller as shown below: void set_pcie_clock_enable(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, expi_sub_clk_enb_reg))
);
val |= EXPI_SUB_PCIE_CLKENB_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, expi_sub_clk_enb_reg))
);
}
DocID028276 Rev 1 91/220
220
Communication drivers
set_ltssm_disable()
The “arch/arm/plat-streamplug/misc.c” routine disables ltssm as shown below.
void set_ltssm_disable(void)
{
u32 val;
UM1942
val = misc_readl((u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
val &= ~PCIE_CTR_LTSSM_ENB_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
}
set_uport_reset_disable()
The “arch/arm/plat-streamplug/misc.c” routine removes the PCIe UPort
TM
from the reset state as shown below.
void set_uport_reset_disable(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, expi_sub_swrst_reg))
);
val &= ~EXPI_SUB_UPORT_SWRST_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, expi_sub_swrst_reg))
);
}
set_uport_clock_enable()
The “arch/arm/plat-streamplug/misc.c” routine configures the clock for the UPort controller as shown below.
void set_uport_clock_enable(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, expi_sub_clk_enb_reg))
);
val |= EXPI_SUB_UPORT_CLKENB_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, expi_sub_clk_enb_reg))
);
}
92/220 DocID028276 Rev 1
UM1942 Communication drivers
set_pcie_core_reset_n_release()
The “arch/arm/plat-streamplug/misc.c” removes the PCIe core from the reset state as shown below.
void set_pcie_core_reset_n_release(void)
{
set_pcie_pcie_core_reset_n_release();
set_pcie_pipew_core_reset_n_release();
} wherein,
set_pcie_pcie_core_reset_n_release()
The “arch/arm/plat-streamplug/misc.c” removes the core from the reset state as shown below.
void set_pcie_pcie_core_reset_n_release(void)
{
u32 val; val = misc_readl((u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
val |= PCIE_CTR_CORE_RST_N_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
} and
set_pcie_pipew_core_reset_n_release()
the “arch/arm/plat-streamplug/misc.c” removes the pipe wrapper from the reset state as shown below.
void set_pcie_pipew_core_reset_n_release(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
val |= PCIE_CTR_PIPEW_RTS_N_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
}
DocID028276 Rev 1 93/220
220
Communication drivers UM1942
set_uport_reset_enable()
The “arch/arm/plat-streamplug/misc.c” puts the UPort controller into the reset state, as shown below.
void set_uport_reset_enable(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, expi_sub_swrst_reg))
);
val |= EXPI_SUB_UPORT_SWRST_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, expi_sub_swrst_reg))
);
}
set_uport_clock_disable()
The “arch/arm/plat-streamplug/misc.c”, switch off the UPort controller clock is shown below.
void set_uport_clock_disable(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, expi_sub_clk_enb_reg))
);
val &= ~EXPI_SUB_UPORT_CLKENB_MASK;
misc_writel(val, (u32* )( GetOffset(sMiscRegs, expi_sub_clk_enb_reg))
);
}
set_pcie_core_reset_n_setup()
This code puts the PCIe core into the reset state, as shown below.
void set_pcie_core_reset_n_setup(void)
{
u32 val;
val = misc_readl((u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
val &= ~(PCIE_CTR_CORE_RST_N_MASK | PCIE_CTR_PIPEW_RTS_N_MASK);
misc_writel(val, (u32* )( GetOffset(sMiscRegs, pcie_ctr)) );
}
94/220 DocID028276 Rev 1
UM1942 Communication drivers
miphy_pipew_completion()
The “arch/arm/mach-streamplug/miphy.c” waits for the MIPHY Pipe Wrapper Configuration completed as shown below.
int miphy_pipew_completion(void)
{
unsigned char val;
unsigned int ucount=0;
do {
val = miphy_read(MIPHY_RX_BUFFER_REG);
if (val == MIPHY_PIPEW_COMPL) {
return 0;
}
udelay(1);
ucount++;
} while (ucount <= (MIPHY_PIPEW_COMPL_TIMEOUT*100*1000));
return 1;
}
After enabling the “TX_POLL bit from MIPHY” regs. space, it checks the MiPHY Pll/iDll.
int miphy_pll_idll_ready(void)
{
unsigned char val;
unsigned int ucount=0;
do {
val = miphy_read(MIPHY_STATUS_REG);
if ((val & MIPHY_PLL_IDLL_MASK) == MIPHY_PLL_IDLL_MASK) {
return 0;
} udelay(1); ucount++;
} while (ucount <= (MIPHY_PLL_IDLL_RDY_TIMEOUT*100*1000));
return 1;
}
DocID028276 Rev 1 95/220
220
Communication drivers UM1942
PCIe root complex
The PCIe root complex device driver performs the following steps in order to complete the
PCIe interface initialization:
ï‚·
PCIe header type 0 configuration.
ï‚·
Enabled the inbound transactions, for which two memory windows ranges have been opened within local DDR memory space:
– From 0x00000000 to 0x00047FFF
– From 0x10000000 to 0x7FFFFFFFF
ï‚·
Enabled the entire PCIe AHB space for outbound transactions:
– From 0x40000000 to 0x4000FFFF; this memory window provides accesses in configuration space. According to the STreamPlug design architecture, the PCIe
RC device driver supports connections until eight single function endpoints are connected by a PCIe switch. The current PCIe RC device driver will interface with only one single endpoint due to the absence of a switch. In that way the configuration space of the single endpoint will be found within the range
[0x40000000-0x40000FFF].
ï‚·
From 0x40010000 to 0x5FFFFFFF; this memory window provides 32-bit accesses in memory space (with or without prefetchable option) of the target endpoint.
ï‚·
From 0x60000000 to 0xBFFFFFFF; the local base addresses of the low memory spaces defined for the root complex, have been set as:
– BAR0 = 0x60000000 with size 512 Mbyte
– BAR1 = 0x80000000 with size 1 Gbyte
ï‚·
Enable the LTSSM machine state in order to negotiate the Link-up.
ï‚·
INTA: HW interrupt RX handling is initialized; the PCIe INTA interrupt routine is attached to the VIC line 3.
ï‚·
MSI: SW interrupt RX handling is initialized; the PCIe RC will retrieve the information about MSI from the target endpoint and set the MSI capabilities.
ï‚·
Bus enumeration, in order to find the target endpoint in case the link is up.
PCIe target scanning, during that phase the endpoint will be configured according to its capabilities in order to perform memory transactions in both directions.
Note that:
ï‚·
Only one endpoint will be supported when the STreamPlug is configured as a root complex
ï‚·
“PCIE_LINK_REQ_RST_NOT_ITS” interrupt is left masked. Otherwise, it can cause the link disconnection.
96/220 DocID028276 Rev 1
UM1942 Communication drivers
PCIe endpoint
The PCIe endpoint device driver performs the following steps in order to complete the PCIe interface initialization:
ï‚·
PCI header type 0 configuration
– Enable bus master
– Enable memory space access
– Base addresses mask, to define the size of the three inbound windows:
ï‚·
BAR0 mask, 32-bit memory access size 128 Mbyte
ï‚·
BAR1 mask, 32-bit memory access size 2 Mbyte
ï‚·
BAR2 mask, 32-bit memory access size 2 Mbyte
ï‚·
Enabled the address translation:
– The inbound transactions, for each BAR the following inbound window range has been defined
ï‚·
Local DDR memory, from 0x00000000 to 0x08000000
ï‚·
Lower peripheral interface, from 0xD0000000 to 0xD01FFFFF
ï‚·
CLCD peripheral controller, from 0xFC200000 to 0xFC21FFFF
– The outbound transactions; two memory windows ranges are defined to perform outbound transactions towards the root complex:
ï‚·
From 0x40000000 to 0x47FFFFFF, it will be translated into target RC memory space starting from 0x00000000
ï‚·
From 0x50000000 to 0x57FFFFFF, it will be translated into target RC memory space starting from 0x01000000
4.10.2 PCIe kernel source and configuration
The following details correspond to the layout of the driver and kernel configuration.
The PCI driver stack is in “drivers/pci”. This is common for all PCI and PCIe controllers.
illustrates the kernel Kconfig option required to be enabled for the PCIe.
Table 15. PCIe configurations
Configuration
CONFIG_PCI
CONFIG_PCIEPORTBUS
Description
Enable the PCI bus system.
Enable PCI express port bus support.
These are required to enable kernel PCIe generic support, while the detailed options for the two possible configuration (the root complex and endpoint) are listed below.
PCIe root complex
The driver of the root complex is in “arch/arm/mach-streamplug”:
ï‚·
“dw_pcie.c”
ï‚·
“streamplug1x_pcie_rev_350”, for IP revision 3.50
DocID028276 Rev 1 97/220
220
Communication drivers UM1942
illustrates the kernel Kconfig options required to be enabled for the root complex.
Table 16. PCIe root complex configurations
Configuration Description
CONFIG_DW_PCIE
CONFIG_STREAMPLUG_PCIE_REV350
CONFIG_PCI_MSI
Enable the support of the Synopsys designware
PCIe dual mode controller.
Enable the ST STreamPlug PCIe Rev 3.50.
Enable the drivers to enable MSI (message signaled interrupts).
PCIe endpoint
The driver of the endpoint is in “drivers/misc streamplug1x_pcie_gadget.c”.
illustrates the kernel Kconfig options required to be enabled for the endpoint.
Table 17. PCIe endpoint configurations
Configuration Description
CONFIG_STREAMPLUG1X_PCIE_GADGET Enable ST STreamPlug PCIe device support.
Due to mutual exclusive PCIe controllers, the root complex or endpoint platform configuration is set by padmuxing. The files containing the platform configurations for both types of supported PCIe controllers are in “arch/arm/mach-streamplug”:
ï‚·
“streamplug1x.c”, where are defined the platform device structures
ï‚·
“padmux.c”, where are defined the padmux option for configuring the PCIe controller as a host or a device.
static struct pmx_dev_mode *pcie_modes[] = {
&pcie_rc_mode,
&pcie_ep_mode,
}; void parse_pcie_options(struct pmx_dev *dev, char *options)
{
pcie_clk_opt = simple_strtoul(options, NULL, 10);
printk(KERN_INFO "[M10]: %s pcie_clk_opt = %d", func , pcie_clk_opt);
}
DECLARE_PMX_DEV(pcie, pcie_modes, PMX_DEV_DISABLE, parse_pcie_options);
98/220 DocID028276 Rev 1
UM1942 Communication drivers
PCIe root complex
The PCIe platform device configuration is shown below.
struct platform_device streamplug1x_pcie_host_device = {
.name = "dw_pcie-rc",
.id = 0,
.dev = {
.coherent_dma_mask = ~0,
.dma_mask = &pcie_host_dmamask,
.platform_data = &pcie_host_info,
},
.num_resources = ARRAY_SIZE(pcie_resources),
.resource = pcie_resources,
}; and the “padmux” option to set the PCIe controller as a root complex is: static struct pmx_mux_reg pcie_rc_regs[] = {
{ .reg = &pci_sata_sel, .value = 0x0 },
{ .reg = &pci_device_type_sel, .value = 0x1 },
}; static struct pmx_dev_mode pcie_rc_mode = {
.name = "rc",
.mux_regs = pcie_rc_regs,
.mux_reg_cnt = ARRAY_SIZE(pcie_rc_regs),
.platform_dev = &streamplug1x_pcie_host_device,
};
PCIe endpoint
The PCIe platform device configuration is shown below.
struct platform_device streamplug1x_pcie_gadget_device = {
.name = "dw_pcie-ep",
.id = 0,
.dev = {
.coherent_dma_mask = ~0,
.dma_mask = &pcie_gadget_dmamask,
.platform_data = &pcie_gadget_info, //pcie_gadget0_id,
},
.num_resources = ARRAY_SIZE(pcie_resources),
.resource = pcie_resources,
}; and the “padmux” option to set the PCIe controller as an endpoint is: static struct pmx_mux_reg pcie_ep_regs[] = {
{ .reg = &pci_sata_sel, .value = 0x0 },
{ .reg = &pci_device_type_sel, .value = 0x0 },
};
DocID028276 Rev 1 99/220
220
Communication drivers
static struct pmx_dev_mode pcie_ep_mode = {
.name = "ep",
.mux_regs = pcie_ep_regs,
.mux_reg_cnt = ARRAY_SIZE(pcie_ep_regs),
.platform_dev = &streamplug1x_pcie_gadget_device,
};
UM1942
To enable the PCIe RC/EP support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
. Then PCIe devices/registers can be managed/monitored using any of the following utilities or commands:
ï‚·
“lspci” is a utility for displaying information about all PCI buses in the system and all devices connected to them. Its details can be seen with man lspci.
ï‚·
“setpci” is a utility for querying and configuring PCI devices. Its details can also be seen with man setpci.
ï‚·
The PCI sysfs can be managed using the following commands: “cat/hexdump/echo”.
It's possible to access to PCI sysfs of the both PCIe host and device, below
“/sys/bus/pci/devices/0000\:0X\00.0/”, where X stays for a primary bus number at which the root complex and endpoint are connected.
4.11 Serial advanced technology attachment (SATA)
This chapter describes the functional behavior and software interface of the STreamPlug device driver for the serial advanced technology attachment (SATA) bus controller. The
SATA, also called Serial ATA, is the evolution of the Parallel ATA (PATA), a computer bus interface to connect a host PC to physical storage devices such as hard disk drivers and optical drivers.
The STreamPlug SATA controller uses the advanced host controller interface (AHCI), which is a hardware mechanism (PCI class device) that allows software to communicate with
Serial ATA devices. In other words AHCI acts as a data movement engine between the system memory and Serial ATA devices.
4.11.1 SATA software overview
The STreamPlug device driver has been inherited from the official Linux kernel AHCI platform controller which uses the libATA library. The libATA provides an ATA driver API, class transports for ATA and ATAPI devices, and SCSI/ATA translation for ATA devices according to the T10 SAT specification. Features include power management, S.M.A.R.T.,
PATA/SATA, ATAPI, port multiplier, hot swapping and NCQ. For any more details have a look to the following Wikipedia page: https://en.wikipedia.org/wiki/LibATA.
Furthermore, some Linux specific information about libATA can be found in the following text document released together with the Linux kernel.
Documentation/DocBook/libata.tmpl
100/220 DocID028276 Rev 1
UM1942 Communication drivers
lists source code files which have been modified to support the SATA on the
STreamPlug boards:
File
./drivers/ata/libahci.c
./drivers/ata/ahci.h
Table 18. SATA source code files
Description
Set OOB timing according the RXOOB_CLK_FREQ to be used.
Add two vendor specific registers for the DWC SATA.
To enable the device driver it is necessary to enable the following Linux kernel configuration options as shown in
Table 19. Linux kernel configuration for SATA support
Configuration Description
CONFIG_ATA
CONFIG_ATA_VERBOSE_ERROR
CONFIG_SATA_AHCI_PLATFORM
Activate serial and parallel ATA support
Activate SATA verbose error reporting
Activate the AHCI SATA platform
Configuration of the device/driver through platform data or inherently in the driver itself.
To enable the SATA support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
.
The following shows the log of the Linux kernel startup which detects an attached SATA device.
Linux version 2.6.35-vcpu-okl_streamplug (restellil@restellil-laptop) (gcc version 4.3.3 ?' (Sourcery G++ Lite 2009q1-203) ) #32 Fri Feb 8 08:46:23
CET 2013
CPU: vCPUv5 [14069260] revision 0 (ARMv5TEJ) CPU: VIVT data cache, VIVT instruction cache Machine: ST-STREAMPLUG
ATag virq 8, "timer_tick"
ATag microvisor_timer 39, 8, "timer_microvisor_timer"
ATag virq 9, "ksp_signal"
ATag ksp_agent 3a, 9, "ksp_ksp_agent"
ATag ksp_shared_mem fd100000, 6c00000, a00000, "shm_KSP_SHARED_MEMORY"
ATag vclient 3b, 20, a, "vserial_vtty0_vclient"
OKL4: vcpu_helper_page at 84c18000/01fff000
VMMU:paging_init: VMMU: Cache management handing is possibly not correct (SDK-1545). Built 1 zonelists in Zone order, mobility grouping on.Total pages: 21082
Kernel command line: console=vcon0,115200n8 root=/dev/mtdblock2 rootfstype=ext2,jffs2 ?' clcd=off sata=on:2 pcie=off usb=on:host eth=off i2c=on ssp=on uart1=off uart2=off ?'
DocID028276 Rev 1 101/220
220
Communication drivers UM1942
can=off firda=off fsmc=off sport=off ts=off
[M10]: parse_sata_options sata_clk_opt = 2
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) Inodecache hash table entries: 8192 (order: 3, 32768 bytes) Memory: 83MB
= 83MB total
Memory: 72868k/72868k available, 12124k reserved, 0K highmem
Virtual Kernel memory layout: vector : 0x01fff000 - 0x02000000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xef800000 - 0xf0000000 ( 8 MB)
Vmalloc : 0x89800000 - 0xe4000000 (1448 MB) lowmem : 0x84000000 - 0x89300000 ( 83 MB) modules : 0x83000000 - 0x84000000 ( 16 MB)
.init : 0x84000000 - 0x84022000 ( 136 kB)
.text : 0x84022000 - 0x8443b000 (4196 kB)
.data : 0x84454000 - 0x84487f80 ( 208 kB)
Hierarchical RCU implementation.
Verbose stalled-CPUs detection is disabled. NR_IRQS:512
Console: colour dummy device 80x30
Calibrating delay loop... 164.24 BogoMIPS (lpj=821248) pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
VCPU support v1.0
NET: Registered protocol family 16 padmux: dev name sata padmux: dev name usb padmux: dev name i2c padmux: dev name ssp
[STreamPlugDBG]: miphy input clock for sata is qfs4
ENTER set_reference_clock
MiPHY Input clock provided by QFS EXIT set_reference_clock
Serial: AMBA PL011 UART driver bio: create slab <bio-0> at 0 vServices Framework 1.0
SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb
Advanced Linux Sound Architecture Driver Version 1.0.23.
NET: Registered protocol family 23
Switching to clocksource microvisor timer
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
102/220 DocID028276 Rev 1
UM1942 Communication drivers
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
NET: Registered protocol family 1
Trying to unpack rootfs image as initramfs... Freeing initrd memory:
6584K
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
fuse init (API version 7.14) msgmni has been set to 155 alg: No test for stdrng (krng) io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) vServices Microvisor Transport v1.0
OKL4 virtual console init console [vcon0] enabled brd: module loaded st: Version 20081215, fixed bufsize 32768, s/g segs 256
PIPEW COMPLETION!!!!!
MIPHY PLL LOCKED!!!!! reset ff reset 0 ahci ahci: forcing PORTS_IMPL to 0x1
HBA Capabilities - 0x6726ff80
HBA Capabilities after write 0 - 0x6726ff80
HBA Init after write 0x1 to PI register
PI register read - 0x1
Initializing HBA ... Done
TESTR register read - 0x0
OOB register read - 0x5080f19
Wrote OOBR register value=8204080c for 30 MHz
P0SCTL register read - 0x0
DocID028276 Rev 1 103/220
220
Communication drivers UM1942
TESTR register read - 0x0
OOB register read - 0x204080c
Wrote OOBR register value=8204080c for 30 MHz ahci ahci: AHCI 0001.0300 32 slots 1 ports 3 Gbps 0x1 impl platform mode ahci ahci: flags: ncq sntf pm led clo only pmp pio slum part ccc apst scsi0 : ahci ata1: SATA max UDMA/133 irq_stat 0x00400040, connection status changed irq 3 smi smi: mtd .name=w25q64_bank0 .size=800000(8M) smi smi: .erasesize = 0x10000(64K)
Creating 1 MTD partitions on "w25q64_bank0":
0x000000000000-0x000000800000 : "Reserved" smi smi: mtd .name=w25q64_bank1 .size=800000(8M) smi smi: .erasesize = 0x10000(64K)
Creating 1 MTD partitions on "w25q64_bank1":
0x000000000000-0x000000800000 : "Auxiliary Root File System" smi smi: mtd .name=w25q64_bank2 .size=800000(8M) smi smi: .erasesize = 0x10000(64K)
Creating 1 MTD partitions on "w25q64_bank2":
0x000000000000-0x000000800000 : "Root File System" ssp-pl022 ssp-pl022.0: ARM PL022 driver, device ID: 0x00241022 pl022: mapped registers from 0xd0100000 to 8987c000 m25p80 spi0.0: non-JEDEC variant of m25p80 m25p80 spi0.0: m25p80 (1024 Kbytes)
Creating 1 MTD partitions on "w25x40":
0x000000000000-0x000000080000 : "External SPI Flash"
CAN device driver interface usbcore: registered new interface driver asix
usbcore: registered new interface driver cdc_ether usbcore: registered new interface driver cdc_eem usbcore: registered new interface driver net1080 ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver streamplug_ehci_hcd_drv_probe 0x89880000 streamplug-ehci streamplug-ehci: STREAMPLUG EHCI streamplug-ehci streamplug-ehci: new USB bus registered, assigned bus number 1 streamplug-ehci streamplug-ehci: irq 5, io mem 0xe1800000 streamplug-ehci streamplug-ehci: USB 0.0 started, EHCI 1.00 hub 1-0:1.0: USB hub found hub 1-0:1.0: 1 port detected ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver streamplug-ohci streamplug-ohci.0: STREAMPLUG OHCI
104/220 DocID028276 Rev 1
UM1942 Communication drivers
streamplug-ohci streamplug-ohci.0: new USB bus registered, assigned bus number 2 streamplug-ohci streamplug-ohci.0: irq 5, io mem 0xe1900000 hub 2-0:1.0: USB hub found hub 2-0:1.0: 1 port detected Initializing
USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered. Loading designware_udc: rtc-streamplug rtc-streamplug: rtc core: registered rtc-streamplug as rtc0 i2c /dev entries driver sp805-wdt wdt: registration successful dw_dmac: DesignWare DMA Controller, 8 channels
No device for DAI AKCODEC set_qfs2_clock - qfs_id = 5
ALSA device list:
No soundcards found. TCP cubic registered
NET: Registered protocol family 10
IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17 can: controller area network core (rev 20090105 abi 8) NET: Registered protocol family 29 can: raw protocol (rev 20090105) can: broadcast manager protocol (rev 20090105 t) IrCOMM protocol (Dag
Brattli)
802.1Q VLAN Support v1.8 Ben Greear <[email protected]> All bugs added by David S. Miller <[email protected]> rtc-streamplug rtc-streamplug: hctosys: invalid date/time ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300) ata1.00: ATA-8: KINGSTON
SS100S28G, 110512, max UDMA/100 ata1.00: 15649200 sectors, multi 16:
LBA48 NCQ (depth 31/32) ata1.00: configured for UDMA/100 scsi 0:0:0:0: Direct-AccessATAKINGSTON SS100S2 1105 PQ: 0 ANSI: 5 sd
0:0:0:0: Attached scsi generic sg0 type 0 sd 0:0:0:0: [sda] 15649200 512-byte logical blocks: (8.01 GB/7.46 GiB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA sda: sda1 sd 0:0:0:0: [sda] Attached SCSI disk
Freeing init memory: 136K
STreamPlug login: root
Please note that the device is enumerated by kernel as the SCSI device, “/dev/sda1” (“sda: sda1”). The user can print the partition table of the SATA driver using the sfdisk command as shown below.
$ sfdisk -ls
/dev/sda: 7824600
Disk /dev/sda: 974 cylinders, 255 heads, 63 sectors/track
Warning: The partition table looks like it was made
DocID028276 Rev 1 105/220
220
Communication drivers UM1942
for C/H/S=*/246/40 (instead of 974/255/63).
For this listing I'll assume that geometry.
Units = cylinders of 5038080 bytes, blocks of 1024 bytes, counting from 0
Device Boot Start End #cyls #blocks Id System
/dev/sda10+ 1590- 1590- 7822336 7 NTFS start: (c,h,s) expected (0,51,9) found (0,32,33) end: (c,h,s) expected (1023,245,40) found (973,245,40)
/dev/sda20 -0 0 0 Empty
/dev/sda30 -0 0 0 Empty
/dev/sda40 -0 0 0 Empty total: 7824600 blocks
Then, at the user space level, commands are provided to mount the external SATA device and to access the corresponding filesystem. Therefore, the user may mount a FAT32 filesystem on the SATA device (“/dev/sda1”) into the folder “/mnt” just using one of the following command:
$ mount /dev/sda1 /mnt
If the SATA drive is formatted as NTFS filesystem, use:
$ ntfs-3g /dev/sda1 /mnt
The folder examples/sata, delivered with the LSP package, includes a “readme” file that explains a procedure to test the SATA bus interface.
106/220 DocID028276 Rev 1
UM1942
5
Memory technology devices (MTD)
Memory technology devices (MTD)
Memory technology devices (MTD) is a generic subsystem for handling memory technology devices under Linux. MTD provides an abstraction layer for raw Flash devices. It makes it possible to use the same API when working with different Flash types and technologies, e.g.: NAND, OneNAND, NOR, AND, ECC'd NOR, etc.
5.1 Linux MTD framework
MTD provides a generic interface between the device drivers and the upper layers of the system.
Device drivers do not need to know about the storage formats used, such as FTL, FFS2, etc. They only need to provide simple routines for read, write and erase. The presentation of the device's contents to the user in an appropriate form will be handled by the upper layers of the system.
The MTD system is divided into two types of the module: “users” and “drivers”. Drivers are the modules which provide raw read/write/erase access to physical memory devices. Users are like YAFFS or JFFS, they are the modules which use MTD drivers and provide a higher level interface to the user space. JFFS is a file system which runs directly on the Flash, and
MTDBLOCK performs no translation.
The user space application can access the Flash device content using the mtdblock nodes
(“/dev/mtdblockN”) and the mtdchar nodes (“/dev/mtdN”), either in the raw mode, for example using the MTD utils command, or in the logical mode, by mounting a file system
(usually JFFS2) and accessing its files through open/read/write system calls.
MTD kernel configuration
is the detail corresponding to the layout of the kernel configuration.
Configuration
CONFIG_MTD
CONFIG_MTD_CHAR
Table 20. MTD configurations
Description
Enable memory technology devices.
Provide a character device for each MTD device present in the system, allowing the user to read and write directly to the memory chips, and also use ioctl() to obtain information about the device, or to erase parts of it.
DocID028276 Rev 1 107/220
220
Memory technology devices (MTD)
5.2
5.2.1
Accessing to MTD devices
UM1942
Raw access from user space
MTD utils can be used to access on Flash devices via the MTD layer. A set of MTD utilities are available in the STreamPlug filesystem.
The MTD project provides a number of helpful tools for handling Flash such as:
ï‚·
“mtd_debug”: gets info, read and write data or erase the specified MTD device.
ï‚·
“flash_erase”: erases an erase block of Flash
ï‚·
“flashcp”: copies data into MTD Flash
ï‚·
“flash_info”: displays information about Flash devices
ï‚·
“flash_lock”: lock Flash pages to prevent writing
ï‚·
“flash_unlock”: unlock Flash pages to allow writing
Information about all MTD devices may be get using the “mtdinfo -a” command:
# mtdinfo -a
Count of MTD devices: 1
Present MTD devices: mtd0
Sysfs interface supported: yes
5.2.2
mtd0
Name: rootfs
Type: nor
Eraseblock size: 65536 bytes, 64.0 KiB
Amount of eraseblocks: 160 (10485760 bytes, 10.0 MiB)
Minimum input/output unit size: 1 byte
Sub-page size: 1 byte
Character device major/minor: 90:0
Bad blocks are allowed: false
Device is writable: true
At the startup three devices are detected by Linux. They are the NOR Flash memories, through the SMI interface.
Raw access from kernel space
MTD devices can be directly accessed through MTD calls such as “mtd_read”, “mtd_erase” and “mtd_write” can be used to read, erase and write to MTD devices.
In this particular Linux distribution provides support for NAND, NOR Flashes and SRAM chips. MTD calls are mapped on specific functions for each different drivers (one for every device). Refer to
Section 5.3: Flexible static memory controller (FSMC) on page 112
The first MTD information is the mtd_info structure. It is retrieved by iterating through all registered MTD devices. This structure is defined in “include/linux/mtd/mtd.h”. This structure contains all necessary informations for the device configuration (the size of the whole device, the minimum size can be erased, etc.), without neglecting its main feature which consists in interfacing between the kernel space and user space.
The following code snippet shows a portion of the “mtd_info” structure.
108/220 DocID028276 Rev 1
UM1942 Memory technology devices (MTD)
/* following is defined in 'include/linux/mtd/mtd.h' */ struct mtd_info {
u_char type;
uint32_t flags;
uint64_t size;// Total size of the MTD
/* "Major" erase size for the device.
*/
uint32_t erasesize;
/* Minimal writable flash unit size.
* Any driver registering a struct mtd_info must ensure a writesize of
* 1 or larger.
*/
uint32_t writesize;
uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
uint32_t oobavail; // Available OOB bytes per block
/*
* If erasesize is a power of 2 then the shift is stored in
* erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.
*/
unsigned int erasesize_shift;
unsigned int writesize_shift;
/* Masks based on erasesize_shift and writesize_shift */
unsigned int erasesize_mask;
unsigned int writesize_mask;
// Kernel-only stuff starts here.
const char *name;
int index;
/* ecc layout structure pointer - read only ! */
struct nand_ecclayout *ecclayout;
/* Data for variable erase regions. If numeraseregions is zero,
* it means that the whole device has erasesize as given above.
*/
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
/*
* Erase is an asynchronous operation.Device drivers are supposed
* to call instr->callback() whenever the operation completes, even
* if it completes with a failure.
DocID028276 Rev 1 109/220
220
Memory technology devices (MTD) UM1942
* Callers are supposed to pass a callback function and wait for it
* to be called before writing to the block.
*/
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
/* This stuff for eXecute-In-Place */
/* phys is optional and may be set to NULL */
int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, resource_size_t *phys);
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
/* Allow NOMMU mmap() to directly map the device (if not NULL)
* - return the address to which the offset maps
* - return -ENOSYS to indicate refusal to do the mapping
*/
unsigned long (*get_unmapped_area) (struct mtd_info *mtd,
unsigned long len,
unsigned long offset,
unsigned long flags);
/* Backing device capabilities for this device
* - provides mmap capabilities
*/
struct backing_dev_info *backing_dev_info;
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t
*retlen, u_char *buf);
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t
*retlen, const u_char *buf);
int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t
*retlen, const u_char *buf);
int (*read_oob) (struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops);
int (*write_oob) (struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops);
/*
* Methods to access the protection register area, present in some
* flash devices. The user data is one time programmable but the
* factory data is read only.
*/
int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
110/220 DocID028276 Rev 1
UM1942 Memory technology devices (MTD)
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
/* kvec-based read/write methods.
NB: The 'count' parameter is the number of _vectors_, each of
which contains an (ofs, len) tuple.
*/
int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
/* Sync */
void (*sync) (struct mtd_info *mtd);
/* Chip-supported device locking */
int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
/* Power Management functions */
int (*suspend) (struct mtd_info *mtd);
void (*resume) (struct mtd_info *mtd);
/* Bad block management functions */
int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
struct notifier_block reboot_notifier; /* default mode before reboot */
/* ECC status information */
struct mtd_ecc_stats ecc_stats;
/* Subpage shift (NAND) */
int subpage_sft;
void *priv;
struct module *owner;
struct device dev;
int usecount;
/* If the driver is something smart, like UBI, it may need to maintain
DocID028276 Rev 1 111/220
220
Memory technology devices (MTD) UM1942
* its own reference counting. The below functions are only for driver.
* The driver may register its callbacks. These callbacks are not
* supposed to be called by MTD users */
int (*get_device) (struct mtd_info *mtd);
void (*put_device) (struct mtd_info *mtd);
};
After retrieving the “mtd_info” structure for the specific MTD device, reading (or writing) is relatively simple.
5.3
The MTD partition can be mounted using a file system and then can be used. The NOR
Flash partition is only supported by JFFS2. Therefore, make sure that a valid JFFS2 image is already present in the partition to avoid getting a lot of JFFS2 error messages.
$ mount -t jffs2 /dev/mtdblock3 /mnt
$ cp /tmp/file_name/mnt/
$ ls /mnt file_name
Flexible static memory controller (FSMC)
The FSMC can access a wide variety of memory. NAND and NOR Flashes and four SRAM chips are supported in this Linux distribution and their relative device drivers can be built as a module.
The following device driver modules are loadable using the modprobe command:
ï‚·
“fsmc_nand.ko” for NAND Flash (located below
“/lib/modules/2.6.35/Kernel/drivers/mtd/nand/)”
ï‚·
“physmap.ko” for NOR Flash (located below
“/lib/modules/2.6.35/Kernel/drivers/mtd/maps)”.
112/220 DocID028276 Rev 1
UM1942 Memory technology devices (MTD)
A NAND Flash example is:
# modprobe fsmc_nand.ko
As a result, a new MTD device is created. (i.e.: “mtd3”).
ï‚· # mtdinfo -m3 mtd3
ï‚· Name:
ï‚· Type:
External NAND Flash
NAND
ï‚· Erase block size:
ï‚· Subpage size:
16384 bytes, 16.0 KiB
ï‚· Amount of erase blocks: 4096 (67108864 bytes, 64.0 MiB) minimum input/output unit size: 512 bytes
512 bytes OOB size:16 bytes character device major/minor:
90:6
ï‚· Bad blocks are allowed: true
ï‚· Device is writable: true
In order to access to the memory device, it is necessary to get the device major and minor numbers. These numbers are used to create a special character file with the command
“mknod”.
# mknod /dev/mtd_nand c 90 6
Finally, FSMC functionalities may be tested using the provided MTD utilities.
The NAND Flash is a non-volatile memory with a data access width of 8 or 16 bits. The read and write operations are done in pages (typically 512 or 2048 bytes) while the erase operation is done in erase blocks (the block size is typically of 16 Kbits or 64 Kbits). The
NAND Flash is I/O mapped and requires a relatively complicated driver for any operation.
Nowadays, the NAND technology allows bigger size parts at a lower cost, but also with a lower reliability. The main issues with NAND technology are bit flipping and bad blocks. To correct bit flipping, the NAND controller and the driver use the error detection/correction code (EDC/ECC). The second issue requires the use of bad block management techniques.
The higher density, lower cost, faster write/erase times, and a longer rewrite life expectancy make the NAND Flash especially well suited for consumer media applications.
DocID028276 Rev 1 113/220
220
Memory technology devices (MTD) UM1942
NAND, FSMC software overview
The NAND device driver layer sits between the FSMC HW controller and the Linux MTD interface of the SW stack. The NAND device driver provides all the necessary functions for a file system via the standard Linux MTD interface at the top layer and controls the
functionality of the lower layer by using the available API as shown in
Figure 10. NAND FSMC software stack
mount mtd-utils
User space
114/220
JFFS2
Linux MTD interface
FSMC NAND driver
Kernel space
FSMC controller H/W
Hardware
AM039717
Users can erase, read and write to the NAND devices through the standard MTD interface.
NAND, FSMC source and configuration
lists the details corresponding to layout of the kernel configuration:
Configuration
Table 21. FSMC NAND configurations
Description
CONFIG_MTD
CONFIG_MTD_NAND
CONFIG_MTD_NAND_FSMC
Provide the generic support for MTD drivers to register themselves with the kernel.
Enable support for accessing all types of NAND Flash devices.
Enable support for NAND Flash chips on the STMicroelectronics flexible static memory controller (FSMC).
DocID028276 Rev 1
UM1942 Memory technology devices (MTD)
NAND, FSMC platform configuration
This section lists the driver's platform interface and its possible configuration. The default configuration of the FSMC controller depends on the platform data passed in the board definition under the machine folder. The platform configuration is implemented in the following routine:
/* set nand device's plat data */
/* following is defined in 'arch/arm/machstreamplug/streamplug_devel_board.c' */
/* set nand device's plat data */ fsmc_nand_set_plat_data(&streamplug1x_fsmc_nand_device,
NAND_SKIP_BBTSCAN,
FSMC_DEVICE_WIDTH8);
/* following is defined in 'arch/arm/plat-streamplug/include/plat/fsmc.h'
*/
/* This function is used to set platform data field of pdev->dev */ static inline void fsmc_nand_set_plat_data(struct platform_device *pdev,
struct mtd_partition *partitions, unsigned int nr_partitions,
unsigned int options, unsigned int width, unsigned int init_to_do)
{
struct fsmc_nand_platform_data *plat_data;
plat_data = dev_get_platdata(&pdev->dev);
if (partitions) {
plat_data->partitions = partitions;
plat_data->nr_partitions = nr_partitions;
}
plat_data->ale_off = PLAT_NAND_ALE;
plat_data->cle_off = PLAT_NAND_CLE;
plat_data->options = options;
plat_data->width = width;
}
NAND, FSMC usage
To enable the FSMC NAND support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
.
The following utilities are specific for using the NAND Flash through the MTD interface: nandtest - Perform Integrity Data test on the specified Nand mtd device.
nandwrite - Writes an input file to the specified Nand mtd device.
nanddump - Dumps the contents of a Nand mtd partition.
DocID028276 Rev 1 115/220
220
Memory technology devices (MTD)
5.3.2 Parallel NOR, FSMC
UM1942
Reading from the NOR Flash is similar to reading from a random access memory, the provided address and data bus are mapped correctly. Because of this, most microprocessors can use the NOR Flash memory as an execute in place (XIP) memory, meaning that programs stored in the NOR Flash can be executed directly from the NOR
Flash without needing to be copied into the RAM first. The NOR Flash may be programmed in a random access manner similar to reading. Programming changes bits from a logical one to a zero. Bits that are already zero are left unchanged. Erasure must happen a block at a time, and resets all the bits in the erased block back to logical one. Typical block sizes are
64, 128, or 256 Kbytes.
Bad block management is a relatively new feature in NOR chips. In older NOR devices not supporting bad block management, the software or the device driver controlling the memory chip must correct for blocks that wear out, or the device will cease to work reliably.
The specific commands used to lock, unlock, program, or erase NOR memories differ for each manufacturer. To avoid needing unique driver software for every device made, special common Flash memory interface (CFI) commands allow the device to identify itself and its critical operating parameters.
Besides using the NOR memory as a random access ROM, it can also be used as a storage device by taking advantage of random access programming. Some devices offer readwhile-write functionality so that the code continues to execute even while a program or erase operation is occurring in the background. For sequential data writes, NOR Flash chips typically have slow write speeds, compared with the NAND Flash.
116/220 DocID028276 Rev 1
UM1942 Memory technology devices (MTD)
Parallel NOR, FSMC software overview
The NOR device driver sits on the top of the FSMC HW controller and provides all the necessary functions for a file system via the standard Linux MTD interface. The NOR device driver controls the functionality of the FSMC by using the API of the FSMC driver.
The user can access, read and write to the NOR devices through the standard MTD interface as illustrated in
Figure 11. NOR FSMC stack
mount mtd-utils
User space
JFFS2
Linux MTD interface
FSMC NOR driver
Kernel space
FSMC controller H/W
Hardware
AM039718
Parallel NOR, FSMC source and configuration
The NOR Flash device driver provides a mapping driver which allows the NOR Flash and
ROM driver code to communicate with chips which are mapped physically into the CPU's memory. The physical address and size and bus width of the Flash chips being used will need to be configured either statically with config options or at run-time.
DocID028276 Rev 1 117/220
220
Memory technology devices (MTD) UM1942
lists the details corresponding to the layout of the driver and kernel configuration.
Configuration
CONFIG_MTD
Table 22. FSMC NOR configurations
Description
CONFIG_MTD_PHYSMAP
CONFIG_STREAMPLUG_FSMC
Provide the generic support for MTD drivers to register themselves with the kernel.
Allow mapping of the NOR Flash in the physical memory.
Enable the AHB master interface to FSMC memories.
The FSMC physmap driver is present in “drivers/mtd/maps/physmap.c”.
Parallel NOR, FSMC platform configuration
This section lists the driver's platform interface and its possible configuration. Default configuration of the FSMC controller depends on the platform data passed.
/* set default physmap's plat data */
/* following is defined in 'arch/arm/machstreamplug/streamplug_devel_board.c' */
/* fsmc NOR partition info */ static struct mtd_partition fsmc_nor_partition_info[] = {
PARTITION("External NOR Flash", 0x00000000, SZ_64M),
};
/* NOR 16 */
/* initialize fsmc related data in fsmc plat data */ fsmc_init_nor_board_info(&streamplug1x_fsmc_nor_device,
fsmc_nor_partition_info,
ARRAY_SIZE(fsmc_nor_partition_info),
FSMC_DEVICE_WIDTH16);
/* following is defined in 'arch/arm/mach-streamplug/fsmc-nor.c' */ void init fsmc_init_nor_board_info(struct platform_device *pdev,
struct mtd_partition *partitions,
unsigned int nr_partitions, unsigned int width)
{
fsmc_nor_set_plat_data(pdev, partitions, nr_partitions, width);
}
/* following is defined in 'arch/arm/plat-streamplug/include/plat/fsmc.h'
*/ static inline void fsmc_nor_set_plat_data(struct platform_device *pdev,
struct mtd_partition *partitions,
118/220 DocID028276 Rev 1
UM1942
5.3.3
Memory technology devices (MTD)
unsigned int nr_partitions, unsigned int width)
{
struct physmap_flash_data *plat_data;
plat_data = dev_get_platdata(&pdev->dev);
if (partitions) {
plat_data->parts = partitions;
plat_data->nr_parts = nr_partitions;
}
plat_data->width = width;
}
Parallel NOR, FSMC usage
Section 5.1: Linux MTD framework on page 107
for details on using the NOR Flash
through the MTD interface both from the kernel and user space.
Static RAM (SRAM), flexible static memory controller
The SRAM (Static RAM) is a type of the RAM that stores data in transistor circuits. The static RAM is faster than the dynamic RAM and does not need to be continuously refreshed.
The family of the SRAM memory can be divided into:
ï‚·
Asynchronous - independent of clock frequency, data in and data out are controlled by an address transistor.
ï‚·
Synchronous - all timing are initiated by the clock edge. The address, data and control signal are associates with the clock signals.
The FSMC device driver flexibility allows supporting the asynchronous static SRAM.
Asynchronous SRAMs are available from 4 kbytes to 64 Mbytes. The fast access time of the
SRAM makes the asynchronous SRAM appropriate as a main memory for small cache less embedded processors used in everything from industrial electronics and measurement systems to hard disks and networking equipment, among many other applications. They are used in various applications like switches and routers, IP phones, to automotive electronics.
DocID028276 Rev 1 119/220
220
Memory technology devices (MTD) UM1942
SRAM software overview
The SRAM device driver sits on the top of the FSMC HW controller and provides all the necessary functions for a file system via the standard Linux MTD interface as shown in
.
Figure 12. SRAM software stack
mount mtd-utils
User space
JFFS2
Linux MTD interface
FSMC SRAM driver
Kernel space
FSMC controller H/W
Hardware
AM039719
The FSMC device driver support is limited to asynchronous devices, but the controller also supports synchronous devices.
120/220 DocID028276 Rev 1
UM1942 Memory technology devices (MTD)
SRAM kernel source and configuration
lists the details corresponding to the layout of the driver and kernel configuration:
Configuration
Table 23. FSMC SCRAM configurations
Description
CONFIG_MTD
CONFIG_MTD_PLATRAM
CONFIG_STREAMPLUG_FSMC
Provide the generic support for MTD drivers to register themselves with the kernel.
Map SRAM Flash for RAM areas described via the platform device system (MTD-RAM).
Enable the AHB master interface to FSMC memories.
SRAM platform configuration
This section lists the driver's platform interface and its possible configuration. Default configuration of the FSMC controller depends on the platform data passed.
/* following is defined in 'arch/arm/machstreamplug/streamplug_devel_board.c' */
/* fsmc SRAM partition info */ static struct mtd_partition fsmc_sram_partition_info[] = {
PARTITION("External SRAM Bank0", 0x00000000, SZ_1M),
PARTITION("External SRAM Bank1", 0x01000000, SZ_1M),
PARTITION("External SRAM Bank2", 0x02000000, SZ_1M),
PARTITION("External SRAM Bank3", 0x03000000, SZ_1M),
};
/* SRAM 16*/
/* initialize fsmc related data in fsmc plat data */ fsmc_init_sram_board_info(&streamplug1x_fsmc_sram_device,
fsmc_sram_partition_info,
ARRAY_SIZE(fsmc_sram_partition_info),FSMC_DEVICE_WIDTH16);
/* following is defined in 'arch/arm/mach-streamplug/fsmc-sram.c' */ void init fsmc_init_sram_board_info(struct platform_device *pdev,
struct mtd_partition *partitions, unsigned int nr_partitions,
unsigned int width)
{
fsmc_sram_set_plat_data(pdev, partitions, nr_partitions, width);
}
/* following is defined in 'arch/arm/plat-streamplug/include/plat/fsmc.h'
*/ static inline void fsmc_sram_set_plat_data(struct platform_device *pdev,
struct mtd_partition *partitions, unsigned int nr_partitions,
unsigned int width)
DocID028276 Rev 1 121/220
220
Memory technology devices (MTD) UM1942
{
static struct platdata_mtd_ram *plat_data;
plat_data = dev_get_platdata(&pdev->dev);
if (partitions) {
plat_data->partitions = partitions;
plat_data->nr_partitions = nr_partitions;
}
plat_data->bankwidth = width;
}
SRAM usage
To enable the FSMC-SRAM support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
.
Section 5.1: Linux MTD framework on page 107
SRAM Flash through the MTD interface from both - the kernel and user space.
5.4 Serial memory interface (SMI)
The serial NOR Flash is one of the primary method for booting the system. This section describes the SMI controller driver used to access serial NOR devices.
The NOR Flash is a non-volatile memory which is memory mapped and has a standard serial (SPI) memory interface. The NOR Flash is well suited to be used as code storage because of its reliability, fast read operations, and random access capabilities.
Because the code can be directly executed in the place, the NOR Flash is ideal for storing the firmware, boot code, operating systems, and other data that changes infrequently. The
NOR Flash memory has traditionally been used to store relatively small amounts of the executable code for embedded computing devices such as PDAs and cell phones.
The serial NOR Flash on the STreamPlug platform is driven by an SMI (serial memory interface) controller. The serial memory interface (SMI), acting as an AHB slave interface
(32-, 16- or 8-bit), manages the clock, data access and status of the NOR Flash memory.
The main features of SMI are:
ï‚·
Supports a group of the SPI-compatible Flash and EEPROM devices.
ï‚·
The SMI clock signal (SMI_CLK) is generated by the SMI using the clock provided by the AHB bus.
122/220 DocID028276 Rev 1
UM1942
5.4.2
Memory technology devices (MTD)
SMI software overview
The SMI serial NOR device driver sits on the top of the SMI controller and provides all necessary functions for a file system via the standard Linux MTD interface.
The user can erase, read and write to the serial NOR devices through the standard MTD interface, as illustrated in
.
Figure 13. SMI software stack
mount mtd-utils
User space
JFFS2
Linux MTD interface
FSMC SMI driver
SMI controller H/W
Kernel space
Hardware
AM039720
DocID028276 Rev 1 123/220
220
Memory technology devices (MTD)
5.4.3 SMI kernel source and configuration
UM1942
lists the details corresponding to
the layout of the driver and kernel configuration:
The SMI controller driver is present in “drivers/mtd/devices/streamplug_smi.c”.
The platform data defining NOR partitioning and controller configuration is present in
“arch/arm/mach-streamplug/streamplug_devel_board.c”.
Table 24. SMI configurations
Configuration
CONFIG_MTD_STREAMPLUG_SMI
Description
CONFIG_MTD_CMDLINE_PARTS
Enable SMI controller drivers
Enable dynamic partitioning based upon kernel command line arguments
124/220
This section lists the driver's platform interface and its possible configuration.
SMI driver configuration
The default configuration of the SMI controller depends on the platform data passed from the boards (“arch/arm/mach-streamplug/streamplug_devel_board.c”).
/* serial nor flash specific board data */ static struct streamplug_smi_flash_info nor_flash_info[] =
{
{
.name = "smi0",
.fast_mode = 1,
.mem_base = FLASH_MEM_BASE_BANK0,
.size = 16 * 1024 * 1024,
},
{
.name = "smi1",
.fast_mode = 1,
.mem_base = FLASH_MEM_BASE_BANK1,
.size = 16 * 1024 * 1024,
},
{
.name = "smi2",
.fast_mode = 1,
.mem_base = FLASH_MEM_BASE_BANK2,
.size = 16 * 1024 * 1024,
},
};
/* smi specific board data */
DocID028276 Rev 1
UM1942 Memory technology devices (MTD)
static struct streamplug_smi_plat_data smi_plat_data =
{
.clk_rate = 40000000,/* used only in native configuration */
.num_flashes = ARRAY_SIZE(nor_flash_info),
.board_flash_info = nor_flash_info,
}; void init smi_init_board_info(struct platform_device *pdev)
{
smi_set_plat_data(pdev, &smi_plat_data);
}
The above snippet asks the
SMI controller driver to configure its clock to 25 MHz to access the serial NOR Flash with partition info embedded in the cmdline.
The timing values apply to Linux native configuration only because in the full configuration the timing setup will be performed by RTOS.
A new NOR device can be added by replacing or extending the “board_flash_info” array supported by the corresponding “num_flashes”.
NOR Flash support
Serial NOR Flash devices accept a different set of commands over the serial interface for read, write and erase. This is enumerated through a structure in
“drivers/mtd/devices/streamplug_smi.c”:
#define FLASH_ID(n, es, id, psize, ssize, size)\
{ \
.name = n,\
.erase_cmd = es,\
.device_id = id,\
.pagesize = psize,\
.sectorsize = ssize, \
.size_in_bytes = size\
} static struct flash_device flash_devices[] = {
/* name - erase cmd - capacity.memorytype.manufacter - psize - ssize - size
*/
FLASH_ID("winbond w25q128", 0xd8, 0x001840EF, 0x100, 0x10000,
0x1000000),
FLASH_ID("winbond w25q64", 0xd8, 0x001740EF, 0x100, 0x10000,
0x800000),
FLASH_ID("st m25p16", 0xd8, 0x00152020, 0x100, 0x10000, 0x200000),
FLASH_ID("st m25p32", 0xd8, 0x00162020, 0x100, 0x10000, 0x400000),
FLASH_ID("st m25p64", 0xd8, 0x00172020, 0x100, 0x10000, 0x800000),
FLASH_ID("st m25p128", 0xd8, 0x00182020, 0x100, 0x40000,
0x1000000),
FLASH_ID("st m25p05", 0xd8, 0x00102020, 0x80 , 0x8000 , 0x10000),
FLASH_ID("st m25p10", 0xd8, 0x00112020, 0x80 , 0x8000 , 0x20000),
DocID028276 Rev 1 125/220
220
Memory technology devices (MTD) UM1942
FLASH_ID("st m25p20", 0xd8, 0x00122020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m25p40", 0xd8, 0x00132020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m25p80", 0xd8, 0x00142020, 0x100, 0x10000, 0x100000),
FLASH_ID("st m45pe10", 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
FLASH_ID("st m45pe20", 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m45pe40", 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m45pe80", 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl004", 0xd8, 0x00120201, 0x100, 0x10000, 0x80000),
FLASH_ID("sp s25fl008", 0xd8, 0x00130201, 0x100, 0x10000,
0x100000),
FLASH_ID("sp s25fl016", 0xd8, 0x00140201, 0x100, 0x10000,
0x200000),
FLASH_ID("sp s25fl032", 0xd8, 0x00150201, 0x100, 0x10000,
0x400000),
FLASH_ID("sp s25fl064", 0xd8, 0x00160201, 0x100, 0x10000,
0x800000),
FLASH_ID("atmel 25f512", 0x52, 0x0065001F, 0x80 , 0x8000 ,
0x10000),
FLASH_ID("atmel 25f1024" , 0x52, 0x0060001F, 0x100, 0x8000 ,
0x20000),
FLASH_ID("atmel 25f2048" , 0x52, 0x0063001F, 0x100, 0x10000,
0x40000),
FLASH_ID("atmel 25f4096" , 0x52, 0x0064001F, 0x100, 0x10000,
0x80000),
FLASH_ID("atmel 25fs040" , 0xd7, 0x0004661F, 0x100, 0x10000,
0x80000),
FLASH_ID("mac 25l512", 0xd8, 0x001020C2, 0x010, 0x10000, 0x10000),
FLASH_ID("mac 25l1005", 0xd8, 0x001120C2, 0x010, 0x10000, 0x20000),
FLASH_ID("mac 25l2005", 0xd8, 0x001220C2, 0x010, 0x10000, 0x40000),
FLASH_ID("mac 25l4005", 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000),
FLASH_ID("mac 25l4005a", 0xd8, 0x001320C2, 0x010, 0x10000,
0x80000),
FLASH_ID("mac 25l8005", 0xd8, 0x001420C2, 0x010, 0x10000,
0x100000),
FLASH_ID("mac 25l1605", 0xd8, 0x001520C2, 0x100, 0x10000,
0x200000),
FLASH_ID("mac 25l1605a", 0xd8, 0x001520C2, 0x010, 0x10000,
0x200000),
FLASH_ID("mac 25l3205", 0xd8, 0x001620C2, 0x100, 0x10000,
0x400000),
FLASH_ID("mac 25l3205a", 0xd8, 0x001620C2, 0x100, 0x10000,
0x400000),
FLASH_ID("mac 25l6405", 0xd8, 0x001720C2, 0x100, 0x10000,
0x800000),
};
126/220 DocID028276 Rev 1
UM1942
6 Accelerators
Accelerators
The STreamPlug includes some hardware accelerators to speedup the complex algorithm elaboration and data management. In particular there are:
ï‚·
JPEG encoder/decoder
ï‚·
DMA engine
ï‚·
Cryptographic coprocessor (C3).
6.1.1
This section describes the JPEG encoder/decoder driver.
JPEG encoder/decoder software overview
The JPEG controller driver supports both JPEG encoding and decoding with/without header processing enabled. It acts as an interface between user level applications and the JPEG codec. The JPEG driver provides a char device interface to the user application and can be used from the user level only. The JPEG driver accepts (for encoding) and gives (for decoding) data in the MCU format. The overall JPEG codec software system architecture is
.
Figure 14. JPEG software architecture
User application
User space
DMAC driver
Linux Char device framework
JPEG controller driver
Kernel space
JPEG controller
Hardware
DMAC driver
JPEG codec
AM039721
The JPEG driver exposes two device nodes to the user application: “jpegread” and
“jpegwrite”. Input data may be written to the “jpegwrite” node and output data may be read from the “jpegread” node. Data may be written/read to or from the JPEG chunk by chunk.
This means that input and output data buffers do not need to be very large. Small buffers
DocID028276 Rev 1 127/220
220
Accelerators
6.1.2
UM1942
can be used again and again to write/read data to or from the JPEG. The following sections describe usage of the
JPEG driver in detail. Note that the sections are in the sequence in which the
JPEG driver is required to be programmed.
JPEG encoder/decoder kernel source and configuration
lists the Linux kernel options related to the JPEG device driver.
Table 25. JPEG driver configuration options
Configuration option Comment
CONFIG_DESIGNWARE_JPEG
CONFIG_DW_DMAC
This option enables the STreamPlug JPEG driver.
This option must be selected for JPEG operations. This will enable the DMA driver.
The STreamPlug JPEG device driver is composed by the following source code files:
ï‚·
“drivers/char/designware_jpeg.c”
ï‚·
“drivers/char/designware_jpeg.h”
ï‚·
“arch/arm/plat-streamplug/jpeg.c”
6.1.4
Configuration of the device/driver through platform data or inherently in the driver itself.
JPEG encoder/decoder usage
JPEG encoder/decoder kernel space
To access the JPEG driver specific data types in user applications, include
“<linux/spr_jpeg_syn_usr.h>”. The JPEG device is allocated the major number dynamically.
To obtain the major number of the JPEG device, run the following command after board boot-up:
$ cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
9 st
10 misc
13 input
21 sg
29 fb
81 video4linux
128/220 DocID028276 Rev 1
UM1942
Block devices:
1 ramdisk
259 blkext
8 sd
11 sr
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
254 vblock
89 i2c
90 mtd
116 alsa
128 ptm
136 pts
153 spi
161 ircomm
162 raw
180 usb
189 usb_device
204 ttyAMA
247 ubi0
248 bufV
249 ttyVS
250 ttyV
251 imageval
252 vlog
253 jpeg-designware
254 rtc
DocID028276 Rev 1
Accelerators
129/220
220
Accelerators UM1942
After obtaining the major number of the JPEG device, create JPEG nodes using the following commands:
$ mknod /dev/jpegread c major 0
$ mknod /dev/jpegwrite c major 1
In this example, the “major” is the major number allocated to the JPEG.
These user level nodes are used for any further interaction with the JPEG driver. The following steps illustrate how to do encoding/decoding with the JPEG.
Open JPEG nodes
After creating JPEG read and write nodes, the application should open them. Use the following system call to open JPEG nodes: rfd = open("/dev/jpegread", O_RDWR | O_SYNC); wfd = open("/dev/jpegwrite", O_RDWR | O_SYNC); where:
ï‚·
“O_RDWR” access permission is used to get read/write permissions.
ï‚·
“O_SYNC” access permission is used for synchronous I/O. Any writes on the resulting file descriptor will block the calling process until the data has been physically written to the underlying hardware. mmap function used later will give uncached memory if this flag is used, otherwise data consistency issues will occur.
ï‚·
“rfd” and “wfd” are read and write file descriptors used to further communicate with
JPEG nodes.
JPEG nodes can be opened by only one application at a time, thus they cannot be shared.
On success, positive file descriptors are returned, otherwise on error, -1 is returned and errno is set appropriately. These file descriptors can be used for any further communication with the JPEG device.
Set source image size
The JPEG driver must be told in advance the size of the input data (required by hardware).
Use the following system call to set the input data size: ioctl(wfd, JPEGIOC_SET_SRC_IMG_SIZE, size); where:
ï‚·
“wfd” is the file descriptor of the jpegwrite node
ï‚·
“JPEGIOC_SET_SRC_IMG_SIZE” is the ioctl command for setting input data size
ï‚·
“size” is the size of the source image in bytes
Upon success, zero is returned, otherwise on error, -1 is returned and errno is set appropriately. After completion of processing, if the user needs to encode/decode another image, the user doesn't have to close JPEG nodes, de-allocate the buffer memory and open the nodes again. The user can simply call this function again with the size of new input data.
This resets the complete JPEG system (software and hardware).
130/220 DocID028276 Rev 1
UM1942 Accelerators
Set JPEG information
The JPEG can perform four types of operations. They are:
ï‚·
Encoding with header processing (EWH): the output JPEG image will have a header as a part of the image.
ï‚·
Encoding without header processing (EWOH): the output JPEG image will not have a header as a part of the image.
ï‚·
Decoding with header processing (DWH): the input JPEG image will have a header as a part of the image.
ï‚·
Decoding without header processing (DWOH): the input JPEG image will not have a header as a part of the image.
The JPEG header and compression table information is passed to the
JPEG driver in all above cases, except DWH. In the DWH the JPEG codec extracts a header and table information from the input JPEG image. Before proceeding with encoding/decoding, provide header and table information to the
JPEG driver (not required for DWH). Use the following system call to set JPEG info for the EWH and EWOH: ioctl(wfd, JPEGIOC_SET_ENC_INFO, &enc_info); where:
ï‚·
“wfd” is the file descriptor of the jpegwrite node.
ï‚·
“JPEGIOC_SET_ENC_INFO” is the ioctl command for setting JPEG encoding information.
ï‚·
“enc_info” is the structure containing jpeg encoding information.
The “enc_info” structure is described below.
struct jpeg_enc_info {
struct jpeg_hdr hdr;/* jpeg image header */
int hdr_enable; /* header processing enable/disable */
char qnt_mem[QNT_MEM_SIZE]; /* quantization memory */
char dht_mem[DHT_MEM_SIZE]; /* DHT memory */
char henc_mem[HENC_MEM_SIZE]; /* Huff enc memory */
};
The “jpeg_hdr” structure is described below.
struct jpeg_hdr {
u32 num_clr_cmp; /* number of color components minus 1. */
u32 clr_spc_type; /* number of quantization tables in the output stream. */
u32 num_cmp_for_scan_hdr; /* number of components for scan header marker segment
minus 1.*/
u32 rst_mark_en;/* restart marker enable/disable */
u32 xsize; /* number of pixels per line */
u32 ysize; /* number of lines. */
u32 mcu_num; /* this value defines the number of minimum coded units to be coded,
minus 1 */
u32 mcu_num_in_rst; /* number of mcu's between two restart markers minus 1.*/
DocID028276 Rev 1 131/220
220
Accelerators UM1942
struct mcu_composition mcu_comp[MAX_MCU_COMP]; /* represents MCU composition */
};
The “mcu_composition” structure is described below.
struct mcu_composition {
u32 hdc; / *hdc bit selects the Huffman table for the encoding of the DC
* coefficient in the data units belonging to the color component */
u32 hac; /* hac bit selects the Huffman table for the encoding of the AC
* coefficients in the data units belonging to the color component */
u32 qt; /* QT indicates the quantization table to be used for the color
*component */
u32 nblock; /* nblock value is the number of data units (8 x 8 blocks of data) of
* the color component contained in the MCU */
u32 h; /* Horizontal Sampling factor for component */
u32 v; /* Vertical Sampling factor for component */
};
Use the following system call to set JPEG info for DWOH: ioctl(wfd, JPEGIOC_SET_DEC_INFO, &dec_info); where:
ï‚·
“wfd” is the file descriptor of the jpegwrite node.
ï‚·
“JPEGIOC_SET_DEC_INFO” is the ioctl command for setting JPEG decoding information.
ï‚·
“dec_info” is the structure containing jpeg decoding information.
The “dec_info” structure is described below.
struct jpeg_dec_info {
struct jpeg_hdr hdr; /* jpeg image header */
int hdr_enable;/* header processing enable/disable */
char qnt_mem[QNT_MEM_SIZE];/* quantization memory */
char hmin_mem[HMIN_MEM_SIZE];/* Huff min memory */
char hbase_mem[HBASE_MEM_SIZE]; /* Huff base memory */
char hsymb_mem[HSYMB_MEM_SIZE]; /* Huff symb memory */
};
Upon success, a zero is returned, otherwise on error, -1 is returned and errno is set appropriately. If this ioctl is not called before writing/reading data to/from the JPEG, then
DWH (decoding with header processing) is performed by default.
132/220 DocID028276 Rev 1
UM1942 Accelerators
Mapping memory for read and write
The JPEG driver needs to allocate buffers for storing the input and output data. To speed up the encoding/decoding process, the driver uses the “mmap()” Linux system call. This system call allocates physically contiguous memory for the
JPEG driver and returns the virtual address of this memory to the user application. The user can then read and write to the virtual addresses and the same data is reflected in the driver buffers. This saves unnecessary data copy time between the kernel and user level. In order to further increase the performance of the encoding/decoding process, two buffers are used both for read and write operations. By having two buffers for read and write, we are actually parallelizing
JPEG processing. By the time JPEG hardware reads/writes data from/to read/write buffer software has written/read data to/from an other buffer. Use the following system call to the map physical memory in virtual space: void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); where:
ï‚·
“fd” is the file descriptor of the jpeg read/jpeg write node.
ï‚·
“length” is the total size of buffers (write or read) to allocate. The size should be multiple of the page size, i.e.: 4096 bytes. The maximum size that can be allocated or mapped at once is 4 Mbytes, this makes the size of each buffer (write or read) 2 Mbytes. A single call to “mmap” for the “jpegread/jpegwrite” node will allocate “length” amount of the memory and will return its base address. The user application should use this memory as two buffers of the same size.
Upon success, “mmap” returns a pointer to the mapped area. On error, the value
“MAP_FAILED” [that is, (void *)], -1 is returned, and errno is set appropriately. The “mmap” function asks to map length bytes starting at offset “offset” from the file specified by the file descriptor “fd” into the memory, preferably at the address “start”. This “start” address is a hint only, and is usually specified as 0. The following parameters can be used to call this function for “rfd” and “wfd”.
mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, file_desc, 0)
After one codec operation (encoding/decoding) has been completed, additional encode/decode operations may be performed without closing nodes of jpegread/jpegwrite or having to allocate/map the memory again. However, if the user needs to map the memory again for a different size, any previously mapped memory must first be unmapped.
Write source JPEG data
After mapping the memory for the write buffer, input data may be written to it (data length less than equal to the size of one write buffer). This can be done by writing or copying data directly to the mapped virtual memory addresses of write buffers.
DocID028276 Rev 1 133/220
220
Accelerators UM1942
Start encoding or decoding
Once input data is written to the write buffer, encoding/decoding can be started/resumed.
Use the following system call to start and resume JPEG encoding/decoding with new input data: ioctl(wfd, JPEGIOC_START, size); where:
ï‚·
“wfd” is the file descriptor of the jpegwrite node
ï‚·
“JPEGIOC_START” is the command to start/resume jpeg encoding/decoding
ï‚·
“size” is the amount of data written on the jpegwrite node, the memory mapped for each jpeg write buffer.
This is a blocking system call which unblocks or returns only when encoding/decoding with data supplied from the current write buffer is started or an error has occurred. On success, zero is returned otherwise, -1 is returned on error and errno is set appropriately. For example, if the total size of the input data is 15 Kbytes, and the size of each write buffer is
4 Kbytes, then the following steps are used to pass data to the JPEG:
1.
Set the current write buffer to “write_buffer0”
2. Write 4 Kbytes of data into the current write buffer
3. Call “JPEGIOC_START ioctl” with the size equal to 4 Kbytes
4. If the current write buffer is buffer 0, toggle the write buffer to be buffer1. If it's set it to the buffer1, toggle it to the buffer0.
and
two more times with a size of 4 Kbytes and one time with a size of 3 Kbytes.
Get encoded/decoded data
Once encoding/decoding is started, the output data must be copied from the read buffer.
Use the following system call used to get the output data: ioctl(rfd, JPEGIOC_GET_OUT_DATA_SIZE, &size); where:
ï‚·
“rfd” is the read node file descriptor.
ï‚·
“JPEGIOC_GET_OUT_DATA_SIZE” is the command to get output data.
ï‚·
“size” is the variable which will store the size of output data in bytes. This must always be equal to the size of the individual read buffer. If it is less than the size of the individual read buffer, end of encoding/decoding is indicated.
134/220 DocID028276 Rev 1
UM1942 Accelerators
This is a blocking system call which unblocks or returns only when the output data size less than equal to the size of the individual read buffer is written to the current read buffer after encoding/decoding. On success, zero is returned otherwise, -1 is returned on error and errno is set appropriately. For example: the total size of output data is 15 Kbytes, the size of each write buffer is 4 Kbytes, then the user needs to do following steps to read data from the
JPEG:
1.
Set the current read buffer to the “read_buffer0”
3. Check the value of the parameter size if it is less than 4 kBytes
/
Kbits, wait until the end encoding/decoding is indicated
4. Read data from the current read buffer
5. If the current read buffer is the buffer0, toggle it the buffer1. If the read buffer is the buffer1, toggle it to the buffer0.
steps ,
,
, and
until the time step
doesn't indicate the end of encoding/decoding.
Writing input data to the write buffer and reading output data from the read buffer have to be done simultaneously. It is recommended to use different threads/processes for reading and writing. This will speed up the encoding/decoding process.
Get JPEG information
Once encoding/decoding is finished the user can read JPEG information (JPEG header information and compression tables). Use the following system call to get JPEG information: ioctl(rfd, JPEGIOC_GET_INFO, &jpeg_info); where:
ï‚·
“rfd” is the read node file descriptor
ï‚·
“JPEGIOC_GET_INFO” is the command to get jpeg information
ï‚·
“jepg_info” is the instance of struct jpeg_info. After successful completion of this system call, it will contain information of the JPEG header and compression tables.
On success, zero is returned otherwise, -1 is returned on error and errno is set appropriately. Struct. “jpeg_hdr_info” is defined below: struct jpeg_info {
struct jpeg_hdr hdr;/* jpeg image header */
char qnt_mem[QNT_MEM_SIZE]; /* quantization memory */
char hmin_mem[HMIN_MEM_SIZE]; /* Huff min memory */
char hbase_mem[HBASE_MEM_SIZE]; /* Huff base memory */
char hsymb_mem[HSYMB_MEM_SIZE]; /* Huff symb memory */
char dht_mem[DHT_MEM_SIZE]; /* DHT memory */
char henc_mem[HENC_MEM_SIZE]; /* Huff enc memory */
};
The struct “jpeg_hdr” is already defined earlier in
Section : Set JPEG information on page 131
.
This ioctl is mainly useful for DWH (decoding with header processing enabled).
DocID028276 Rev 1 135/220
220
Accelerators UM1942 munmap
Once the application is finished with JPEG processing, it should unmap the memory that has been mapped for read and write buffers. Use the following system call to unmap memory: munmap(adrs, size); where:
ï‚·
“adrs” is the address of the mapped memory
ï‚·
“size” is the size of the mapped memory
On success, a zero is returned otherwise, -1 is returned on error and errno is set appropriately.
Close
After unmapping the memory, JPEG nodes must be closed. Use the following system call to do this: close(fd);
Close returns zero on success, or -1 if error occurred, errno is set appropriately. This function must be called both for read and write nodes.
JPEG codec usage
JPEG read and write are not synchronized enough, for example, one chunk of input data may produce output data varying in size. Due to this, write and read should be simultaneously made to the
JPEG driver, otherwise the JPEG codec may be wasting time sitting idle. It is recommended to use two processes or threads to read and write data simultaneously from the JPEG driver. This will increase speed of JPEG processing. The following example is for encoding/decoding a JPEG image.
Below, input data is read by application from a file and is passed to the
JPEG driver. After that, it is processed by the JPEG codec based no processing type (encoding/decoding), and output data is read by application again.
#include <sys/mman.h>
#include "include/linux/spr_jpeg_syn_usr.h" struct jpeg_info jpeg_info; volatile unsigned char *wbuf[2] = {NULL, NULL},
*rbuf[2] = {NULL, NULL}; unsigned int wsize = 4*4096, rsize = 4*4096; unsigned int ssize = XXX;/* set size of input data here */ int rfd, wfd, cur_rbuf = 1, cur_wbuf = 1; pid_t pid; void jpegread()
{
int size = 0, status;
/* while encoding/decoding is not over */
do
{
shuffle_buf(cur_rbuf);
136/220 DocID028276 Rev 1
UM1942 Accelerators
if((status = ioctl(rfd, JPEGIOC_GET_OUT_DATA_SIZE, &size)) != 0)
return -1;
/* Add code here for manipulating decoded data present in rbuf[cur_rbuf] */
}while(size == rsize);
/* get jpeg info after encoding/decoding is over */
ioctl(rfd, JPEGIOC_GET_INFO, &jpeg_info);
/* unmap buf */
munmap((char *)rbuf[0], 2*rsize);
close(rfd);
} void jpegwrite()
{
uint size = 0, count=0;
int wfd, status;
/* open jpeg nodes */
wfd = open("/dev/jpegwrite", O_RDWR|O_SYNC);
if (wfd == -1)
return -1;
/* set src image size */
ioctl(wfd, JPEGIOC_SET_SRC_IMG_SIZE, ssize);
/* set jpeg info for DWOH */
/*
struct jpeg_dec_info dec_info;
ioctl(wfd, JPEGIOC_SET_DEC_INFO, dec_info);
*/
/* set jpeg info for EWH, EWOH */
/*
struct jpeg_enc_info enc_info;
ioctl(wfd, JPEGIOC_SET_ENC_INFO, enc_info);
*/
wbuf[0] = (unsigned char *)mmap(0, 2*wsize, PROT_READ | PROT_WRITE,
MAP_SHARED, wfd, 0);
wbuf[1] = wbuf[0] + wsize;
while(count < ssize)
DocID028276 Rev 1 137/220
220
Accelerators UM1942
{
size = (ssize-count) < wsize?(ssize-count):wsize;
count += size;
shuffle_buf(cur_wbuf);
/* Add code here to copy size amount of data on wbuf[cur_wbuf]
*/
if((status = ioctl(wfd, JPEGIOC_START, rd)) != 0)
return -1;
}
munmap((char *)wbuf[0], 2*wsize);
close(wfd);
} int main(void)
{
/* open jpeg nodes */
rfd = open("/dev/jpegread",O_RDWR|O_SYNC);
if (rfd == -1)
return -1;
rbuf[0] = (unsigned char *)mmap(0, 2*rsize, PROT_READ | PROT_WRITE,
MAP_SHARED, rfd, 0);
if (rbuf[0] == NULL)
return -1;
rbuf[1] = rbuf[0] + rsize;
pid = fork();
if (pid == 0)// child
{
jpegwrite();
exit(0);
}
else if (pid > 0)// parent
{
jpegread();
wait(0);
}
else// failed to fork
{
printf("Can't create child\n");
exit(1);
}
}
138/220 DocID028276 Rev 1
UM1942 Accelerators
JPEG encoder/decoder user space
Both encoding and decoding can be tested with ready-to-use demonstration applications provided under the folder “/examples/jpeg”. Proof of the usage of the JPEG device driver can be obtained printing the number of raised IRQs with the following command:
$ cat /proc/interrupts
CPU0
5: 1 vIRQ ehci_hcd:usb1, ohci_hcd:usb2
16: 0 vIRQ dw_dmac
17: 12367 vIRQ smi
18: 0 vIRQ rtc-streamplug
24: 0 vIRQ jpeg-designware
26: 57 vIRQ uart-pl011
105: 4906 vIRQ microvisor timer
106: 0 vIRQ okl4-ksp-agent
Err: 0
Decoder
In order to test the JPEG decoder device driver, an application is provided below the
“/examples/jpeg” folder for decoding. Go into the “/example/jpeg” folder and run the following application in the background:
$ ./decode <file in> <file out>
An input file example (“lena.jpg”) is on the same folder. The *.mcu output file has to be passed as an input parameter to the Synopsys JDEM utility in order to generate the decoded image.
Encoder
In order to test the JPEG encoder device driver, an application is provided below the
“/examples/jpeg” subfolder for encoding. Go into the “/example/jpeg” folder and run the application such as:
$ ./encode <Q table> <Huffman table> <DHT table> <X size> <Y size>
<MCU format>
<restar marker distance> <file in> <file out>
For example:
$ ./encode qetable.dat htable.dat dhttable.dat 128 128 1 1 lena.mcu out.jpeg
All STreamPlug MPUs are equipped with a general purpose DMA controllers which provide several DMA channels that can be used to off load the CPU from some of the memory copying tasks. This section describes the details of the DMAC driver.
DocID028276 Rev 1 139/220
220
Accelerators
6.2.1
UM1942
DMA hardware overview
Direct memory access (DMA) allows certain subsystems within the STreamPlug MPU to access the system memory for reading and/or writing independently of the CPU and to transfer data avoiding, in this way, an heavy CPU overhead.
The STreamPlug MPU uses the Synopsys designware DMA controller. It is connected to the
AHB bus. Synopsys designware DMAC's main features are:
ï‚·
AMBA 2.0-compliant
ï‚·
DMA transfers
– Peripheral-to-peripheral
– Memory-to-peripheral
– Peripheral-to-memory
– Memory-to-memory
ï‚·
Channels
– Up to eight channels, one per source and destination pair
– Unidirectional channels - data transfers in one direction only
ï‚·
Interrupt generation on DMA transfer (multiblock) completion, block transfer completion, single and burst transaction completion.
The Linux DMA support has been organized in two different layers in order to provide abstraction to the user which can hide the internal implementation of DMA controller drivers.
The Linux DMA engine framework defines clear APIs and channel abstraction for the user to access underlying DMA hardware and it expects the underlying DMA controller driver to provide necessary callbacks to support this.
The overall DMA software system architecture is represented in
140/220 DocID028276 Rev 1
UM1942 Accelerators
Figure 15. DMA framework architecture
Device driver
Linux DMA engine framework
DMA controller driver
Kernel space
DMA controller
DMA-capable peripheral devices
Hardware
AM039722
The DMA framework present in Linux provides a simple interface to client drivers who wish to use the DMA. Clients just request DMA channels, transfer data on allocated DMA channels and finally free allocated DMA channels.
To increase the performance of the DMA driver, cache/memory consistency related issues are handled by client drivers for non-slave transfer, i.e.: transfers involving peripherals. They can synchronize data between the cache and DDR if the source or destination memory is cached. If memories are uncached there is no need for synchronization.
DocID028276 Rev 1 141/220
220
Accelerators UM1942
DMA engine API
The entire DMA engine abstraction is built around the concept of DMA channels which is abstracted as:
/**
* struct dma_chan - devices supply DMA channels, clients use them
* @device: ptr to the dma device who supplies this channel, always !%NULL
* @cookie: last cookie value returned to client
* @chan_id: channel ID for sysfs
* @dev: class device for sysfs
* @device_node: used to add this to the device chan list
* @local: per-cpu pointer to a struct dma_chan_percpu
* @client-count: how many clients are using this channel
* @table_count: number of appearances in the mem-to-mem allocation table
* @private: private data for certain client-channel associations
*/ struct dma_chan {
struct dma_device *device;
dma_cookie_t cookie;
/* sysfs */
int chan_id;
struct dma_chan_dev *dev;
struct list_head device_node;
struct dma_chan_percpu percpu *local;
int client_count;
int table_count;
void *private;
};
The following example tries to list some of the common and the most used DMA engine framework APIs: struct dma_chan *dma_request_channel(dma_cap_mask_t mask, dma_filter_fn filter_fn, void *filter)
In order to do DMA transfers, the user must request a DMA channel. To request a channel
“dma_request_channel()”, the API is used. A channel allocated via this interface is reserved to the caller, until the “dma_release_channel()” is called.
The “dma_filter_fn” parameter is defined as “typedef” bool (*dma_filter_fn)(struct dma_chan
*chan, void *filter_param).
The “filter_fn” parameter is optional, but highly recommended for slave and cyclic channels as they typically need to obtain a specific DMA channel. When the optional “filter_fn” parameter is NULL, the “dma_request_channel()” simply returns the first channel that satisfies the capability mask. Otherwise, the “filter_fn” routine will be called once for each free channel which has a capability in the mask and return true when the desired DMA channel is found.
142/220 DocID028276 Rev 1
UM1942 Accelerators
The following is only required for slave (involving peripherals) transfers.
int dmaengine_slave_config(struct dma_chan *chan, struct dma_slave_config *config)
Most of the generic information which a slave DMA can use is in “struct dma_slave_config”.
This allows the clients to specify the DMA direction, DMA addresses, bus widths, DMA burst lengths, etc. for the peripheral. If some DMA controllers have more parameters to be sent then they should try to include “struct dma_slave_config” in their controller specific structure.
That gives flexibility to the client to pass more parameters, if required. “dma_slave_config” is defined as: struct dma_slave_config {
enum dma_data_direction direction;
dma_addr_t src_addr;
dma_addr_t dst_addr;
enum dma_slave_buswidth src_addr_width;
enum dma_slave_buswidth dst_addr_width;
u32 src_maxburst;
u32 dst_maxburst;
bool device_fc;
};
The “dma_async_tx_descriptor” API can be used for DMA from the source to the destination memory and is used for non-slave usage.
struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
size_t len, unsigned long flags);
Similarly the “dma_async_tx_descriptor” API sets destination memory with a specific value.
struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
struct dma_chan *chan, dma_addr_t dest, int value, size_t len,
unsigned long flags) struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_data_direction direction,
unsigned long flags);
For “slave_sg” usage one can prepare the DMA descriptor for a transfer through this API.
The DMA on calling of this API prepares a list of scatter gather buffers for transfer from/to a peripheral.
DocID028276 Rev 1 143/220
220
Accelerators
6.2.3
UM1942
DMA kernel source and configuration
The DMA controller device driver is composed by the Synopsys DMAC files:
“drivers/dma/dw_dmac.c”, “drivers/dma/dw_dmac_regs.h” and “include/linux/dw_dmac.h”.
lists the kernel configuration options related to STreamPlug DMA support.
Configuration
CONFIG_DMADEVICES
CONFIG_DW_DMAC
Table 26. DMA configurations
Description
Enable DMA ENGINE devices support
Enable SYNOPSYS designware DMA controller driver
6.2.4 DMA platform configuration
The optional platform data passed from machines for DMAC is as follows:
/* dmac device registration */ static struct dw_dma_platform_data dmac_platform_data = {
.nr_channels = 8,
}; static struct resource dmac_resources[] = {
{
.start = STREAMPLUG1X_ICM3_DMA_BASE,
.end = STREAMPLUG1X_ICM3_DMA_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
}, {
.start = STREAMPLUG1X_IRQ_BAS_SUBS_DMAC,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device streamplug1x_dmac_device = {
.name = "dw_dmac",
.id = -1,
.dev = {
.coherent_dma_mask = ~0,
.platform_data = &dmac_platform_data,
},
.num_resources = ARRAY_SIZE(dmac_resources),
.resource = dmac_resources,
};
144/220 DocID028276 Rev 1
UM1942 Accelerators
Below is a guide to device driver developers on how to use the DMA API of the DMA engine.
The DMA usage consists of following steps:
1.
Allocate a DMA slave channel
2. Set slave and controller specific parameters
3. Get a descriptor for transaction
5. Issue pending requests and wait for callback notification
Following are examples usage of the DMA engine for “memcpy”.
Common callback routine: static void dmatest_callback(void *arg) {
int *done = arg;
*done = 1;
printk(KERN_INFO "DMA xfer is complete");
}
Memcpy
void dma_memcpy() {
dma_cap_mask_t mask;
dma_cookie_t cookie;
struct dma_chan *chan;
struct dma_device *dmadev;
struct dma_async_tx_descriptor *tx = NULL;
u8 *sbuf = 0xc0000000, *dbuf = 0xc8000000;
dma_addr_t dma_srcs, dma_dsts;
int len = 0x1000, done = 0;
enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT |
DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY, mask); chan = dma_request_channel(mask,
NULL, NULL);
dmadev = chan->device;
dma_srcs = dma_map_single(dmadev->dev, sbuf, len, DMA_TO_DEVICE);
dma_dsts = dma_map_single(dmadev->dev, dbuf, len, DMA_BIDIRECTIONAL);
tx = dmaengine_prep_memcpy(chan, dma_dsts, dma_srcs, len, flags);
if (!tx) {
dma_unmap_single(dmadev->dev, dma_srcs, len, DMA_TO_DEVICE);
dma_unmap_single(dmadev->dev, dma_dsts, len, DMA_BIDIRECTIONAL);
}
DocID028276 Rev 1 145/220
220
Accelerators UM1942
tx->callback = dmatest_callback;
tx->callback_param = &done;
cookie = tx->tx_submit(tx);
if (dma_submit_error(cookie)) {
printk(KERN_INFO "Error in dma tx_submit\n");
return;
}
dma_async_issue_pending(chan);
while (!done)
msleep(10);
dma_unmap_single(dmadev->dev, dma_dsts, len, DMA_BIDIRECTIONAL);
}
For the Synopsys DMA controller, this must be an instance of “struct dw_dma_slave”.
/**
* struct dw_dma_slave - Controller-specific information about a slave
*
* @dma_dev: required DMA controller device
* @tx_reg: physical address of data register used for
* memory-to-peripheral transfers
* @rx_reg: physical address of data register used for
* peripheral-to-memory transfers
* @reg_width: peripheral register width
* @cfg_hi: Platform-specific initializer for the CFG_HI register
* @cfg_lo: Platform-specific initializer for the CFG_LO register
* @src_master: src master for transfers on allocated channel.
* @dst_master: dest master for transfers on allocated channel.
* @src_msize: src burst size.
* @dst_msize: dest burst size.
* @fc: flow controller for DMA transfer
*/
146/220 DocID028276 Rev 1
UM1942
6.3
Accelerators
Struct dw_dma_slave {
structdevice*dma_dev;
dma_addr_ttx_reg;
dma_addr_trx_reg;
enum dw_dma_slave_widthreg_width;
u32 cfg_hi;
u32 cfg_lo;
u8 src_master;
u8 dst_master;
u8src_msize;
u8dst_msize;
u8fc;
};
Channel controller coprocessor (C3)
The channel controller coprocessor (C3) is an hardware cryptographic coprocessor used to accelerate data intensive applications where computationally expensive algorithms must operate on medium to large memory buffers. Such applications can be found in the fields of security (data encryption, integrity check, etc.) and networking.
The most important features of the C3 are:
ï‚·
Supported many cryptographic algorithms (AES, DES, TripleDES, SHA-1, SHA-256,
MD5, etc.)
ï‚·
Instruction driven by the DMA based programmable engine.
The C3 is a highly programmable DMA based hardware coprocessor that executes some instructions flows (programs) written in the memory by the host processor. These programs specify which operations must be performed and where to locate data buffers (input, output, parameters) in the memory. After being setup the C3 is completely autonomous and can perform an unlimited number of operations, until it hits an end of program instruction in which case it can signal the end of processing by the means of an interrupt request (if programmed to do so).
DocID028276 Rev 1 147/220
220
Accelerators
6.3.1
6.3.2
UM1942
C3 software overview
The C3 device driver is composed by an API which allows to setup programs that the C3 processor can execute. The API is exposed through a set of Linux kernel symbols listed hereafter:
EXPORT_SYMBOL(count_sg_total); EXPORT_SYMBOL(count_sg);
EXPORT_SYMBOL(c3_unmap_sg_chain); EXPORT_SYMBOL(c3_unmap_sg);
EXPORT_SYMBOL(c3_map_sg); EXPORT_SYMBOL(c3_AES_CBC_encrypt);
EXPORT_SYMBOL(c3_AES_CBC_decrypt); EXPORT_SYMBOL(c3_AES_CBC_encrypt_sg);
EXPORT_SYMBOL(c3_AES_CBC_decrypt_sg);
EXPORT_SYMBOL(c3_AES_CTR_encrypt); EXPORT_SYMBOL(c3_AES_CTR_decrypt);
EXPORT_SYMBOL(c3_AES_CTR_encrypt_sg); EXPORT_SYMBOL(c3_AES_CTR_decrypt_sg);
EXPORT_SYMBOL(c3_SHA1_init); EXPORT_SYMBOL(c3_SHA1_append);
EXPORT_SYMBOL(c3_SHA1_append_sg); EXPORT_SYMBOL(c3_SHA1_end);
EXPORT_SYMBOL(c3_SHA1); EXPORT_SYMBOL(c3_SHA1_sg);
EXPORT_SYMBOL(c3_SHA1_HMAC_init); EXPORT_SYMBOL(c3_SHA1_HMAC_append);
EXPORT_SYMBOL(c3_SHA1_HMAC_append_sg); EXPORT_SYMBOL(c3_SHA1_HMAC_end);
EXPORT_SYMBOL(c3_SHA1_HMAC); EXPORT_SYMBOL(c3_SHA1_HMAC_sg);
C3 kernel source and configuration
The C3 device driver is composed by the following source code files: drivers/char/c3/c3_driver_interface.c drivers/char/c3/c3_driver_core.c drivers/char/c3/c3_cryptoapi.c drivers/char/c3/c3_autotest.c drivers/char/c3/c3_mpcm.c drivers/char/c3/c3_char_dev_driver_instructions.c drivers/char/c3/c3_streamplug.c drivers/char/c3/c3_char_dev_driver.c drivers/char/c3/c3_registers.c drivers/char/c3/c3_driver.mod.c drivers/char/c3/c3_cryptoapi.mod.c drivers/char/c3/c3_irq.c
arch/arm/mach-streamplug/ipswrst_ctrl.c
arch/arm/mach-streamplug/include/mach/streamplug10.h arch/arm/mach-streamplug/clock.c
which are compiled into the following Linux kernel modules: drivers/char/c3/c3_cryptoapi.ko drivers/char/c3/c3_driver.ko
148/220 DocID028276 Rev 1
UM1942 Accelerators
If the configuration listed in
is adopted:
Configuration
Table 27. C3 Linux kernel configuration
Description
CONFIG_C3_DRIVER=m
CONFIG_C3_DRIVER_STREAMPLUG1x=y
CONFIG_AUTO_TEST=y
CONFIG_C3_CRYPTOAPI_INTEGRATION=m
C3 is a crypto accelerator.
C3 on STreamPlug1x.
This setting enables default kernel level testing for different crypto algorithms.
Module for integration with Linux CryptoAPI (kernel version
2.6.37). Support for offloading asynchronous AES (CTR, CBC),
SHA-1, HMAC (SHA-1) operations to the C3 hardware.
This option provides the core Cryptographic API.
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
This option provides the API for cryptographic algorithms.
N/A
N/A
N/A
N/A
N/A
N/A
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_AUTHENC=m
CONFIG_CRYPTO_SEQIV=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=m
CONFIG_CRYPTO_HMAC=m
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_MD5=y
N/A
N/A
N/A
N/A
Create default cryptographic template instantiations such as CBC
(AES).
N/A
N/A
Authenc: a combined mode wrapper for IPSec. This is required for
IPSec.
This IV generator generates an IV based on a sequence number by XORing it with a salt. This algorithm is mainly useful for CTR.
CBC: a Cipher-Block Chaining mode. This block cipher algorithm is required for IPSec.
CTR: a counter mode. This block cipher algorithm is required for
IPSec.
HMAC: Keyed-Hashing for Message Authentication (RFC2104).
This is required for IPSec.
Castagnoli, et al.: cyclic redundancy check algorithm. Used by iSCSI for header and data digests and by others. See
Castagnoli93. The module will be crc32c.
MD5 message digest algorithm (RFC1321).
DocID028276 Rev 1 149/220
220
Accelerators UM1942
Table 27. C3 Linux kernel configuration (continued)
Configuration Description
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_CAST5=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_ANSI_CPRNG=y
AES cipher algorithms (FIPS 197). AES uses the Rijndael algorithm. The Rijndael appears to consistently be a very good performer in both hardware and software across a wide range of computing environments regardless of its use in feedback or nonfeedback modes. Its key setup time is excellent, and its key agility is good. Rijndael's very low memory requirements make it very well suited for restricted space environments, in which it also demonstrates an excellent performance. Rijndael's operations are among the easiest to defend against power and timing attacks.
The AES specifies three key sizes: 128, 192 and 256 bits. For more information, see http://csrc.nist.gov/groups/ST/toolkit/index.html
The CAST5 encryption algorithm (synonymous with CAST-128) is described in RFC2144.
DES cipher algorithm (FIPS 46-2), and triple DES EDE
(FIPS 46-3).
This option enables the generic pseudo random number generator for cryptographic modules. Uses the algorithm specified in ANSI
X9.31 A.2.4. Note that this option must be enabled if
CRYPTO_FIPS is selected.
The C3 device driver defines the following platform configuration: static struct device dev = {
.init_name = "c3",
.release = c3_release,
};
150/220
The C3 device driver module is tested only in kernel space using the following procedure.
The autotest loads up automatically when the “c3_driver.ko” module is loaded.
$ modprobe c3_driver
The test can be stopped by removing the module using the “rmmod” command.
$ rmmod c3_driver
The C3 autotest log captured from the UART kernel console is shown below.
[C3 INFO] - Crypto Channel Controller (c) ST Microelectronics
[C3 INFO] - Driver version = 2.0
[C3 INFO] - Built on Feb 29 2012 at 11:44:22 [C3 INFO] - C3 device found (HID: ffff9000)
[C3 INFO] - SHA1 test [buffer size: 64] throughput : 2976 KBps [C3
INFO] - SHA1 test [buffer size: 128] throughput : 5898 KBps [C3 INFO]
- SHA1 test [buffer size: 256] throughput : 11583 KBps [C3 INFO] -
SHA1 test [buffer size: 512] throughput : 20897 KBps [C3 INFO] - SHA1 test [buffer size: 1024] throughput : 33573 KBps [C3 INFO] - SHA1 test
DocID028276 Rev 1
UM1942 Accelerators
[buffer size: 2048] throughput : 48188 KBps [C3 INFO] - SHA1 test
[buffer size: 4096] throughput : 61686 KBps [C3 INFO] - SHA1 test
[buffer size: 8192] throughput : 71608 KBps
[C3 INFO] - SHA1_HMAC test [buffer size: 64] throughput : 2782 KBps
[C3 INFO] - SHA1_HMAC test [buffer size: 128] throughput : 5541 KBps
[C3 INFO] - SHA1_HMAC test [buffer size: 256] throughput : 10240 KBps
[C3 INFO] - SHA1_HMAC test [buffer size: 512] throughput : 18285 KBps
[C3 INFO] - SHA1_HMAC test [buffer size: 1024] throughput : 30029
KBps [C3 INFO] - SHA1_HMAC test [buffer size: 2048] throughput : 44618
KBps [C3 INFO] - SHA1_HMAC test [buffer size: 4096] throughput : 58514
KBps [C3 INFO] - SHA1_HMAC test [buffer size: 8192] throughput : 69482
KBps [C3 INFO] - SHA512 test [buffer size: 64] throughput : 6037 KBps
[C3 INFO] - SHA512 test [buffer size: 128] throughput : 11962 KBps [C3
INFO] - SHA512 test [buffer size: 256] throughput : 23486 KBps [C3
INFO] - SHA512 test [buffer size: 512] throughput : 45309 KBps [C3
INFO] - SHA512 test [buffer size: 1024] throughput : 84628 KBps [C3
INFO] - SHA512 test [buffer size: 2048] throughput : 150588 KBps
[C3 INFO] - SHA512 test [buffer size: 4096] throughput : 245269 KBps
[C3 INFO] - SHA512 test [buffer size: 8192] throughput : 357729 KBps
[C3 INFO] - SHA512HMAC test [buffer size: 64] throughput : 5423 KBps
[C3 INFO] - SHA512HMAC test [buffer size: 128] throughput : 10756
KBps [C3 INFO] - SHA512HMAC test [buffer size: 256] throughput : 21157
KBps [C3 INFO] - SHA512HMAC test [buffersize: 512] throughput : 40634
KBps
[C3 INFO] - SHA512HMAC test [buffer size: 1024] throughput : 76992
KBps [C3 INFO] - SHA512HMAC test [buffer size: 2048] throughput :
138378 KBps [C3 INFO] - SHA512HMAC test [buffer size: 4096] throughput
: 228826 KBps [C3 INFO] - SHA512HMAC test [buffer size: 8192] throughput : 339917 KBps [C3 INFO] - DES_CBC test [buffer size: 64] throughput : 3422 KBps
[C3 INFO] - DES_CBC test [buffer size: 128] throughput : 5378 KBps
[C3 INFO] - DES_CBC test [buffer size: 256] throughput : 10622 KBps
[C3 INFO] - DES_CBC test [buffer size: 512] throughput : 20078 KBps
[C3 INFO] - DES_CBC test [buffer size: 1024] throughput : 33032 KBps
[C3 INFO] - DES_CBC test [buffer size: 2048] throughput : 48530 KBps
[C3 INFO] - DES_CBC test [buffer size: 4096] throughput : 63209 KBps
[C3 INFO] - DES_CBC test [buffer size: 8192] throughput : 74540 KBps
[C3 INFO] - 3DES_CBC test [buffer size: 64] throughput : 2844 KBps [C3
INFO] - 3DES_CBC test [buffer size: 128] throughput : 5663 KBps [C3
INFO] - 3DES_CBC test [buffer size: 256] throughput : 10000 KBps [C3
INFO] - 3DES_CBC test [buffer size: 512] throughput : 16357 KBps
[C3 INFO] - 3DES_CBC test [buffer size: 1024] throughput : 24150 KBps
[C3 INFO] - 3DES_CBC test [buffer size: 2048] throughput : 31556 KBps
[C3 INFO] - 3DES_CBC test [buffer size: 4096] throughput : 37372 KBps
[C3 INFO] - 3DES_CBC test [buffer size: 8192] throughput : 41145 KBps
[C3 INFO] - AES128_CBC test [buffer size: 64] throughput : 3595 KBps
[C3 INFO] - AES128_CBC test [buffer size: 128] throughput : 6124 KBps
[C3 INFO] - AES128_CBC test [buffer size: 256] throughput : 10406 KBps
[C3 INFO] - AES128_CBC test [buffer size: 512] throughput : 20398 KBps
[C3 INFO] - AES128_CBC test [buffer size: 1024] throughput : 34362
KBps [C3 INFO] - AES128_CBC test [buffer size: 2048] throughput : 51979
KBps [C3 INFO] - AES128_CBC test [buffer size: 4096] throughput : 70378
KBps [C3 INFO] - AES128_CBC test [buffer size: 8192] throughput : 85244
KBps [C3 INFO] - AES256_CBC test [buffer size: 64] throughput : 3422
KBps
DocID028276 Rev 1 151/220
220
Accelerators UM1942
[C3 INFO] - AES256_CBC test [buffer size: 128] throughput : 5400 KBps
[C3 INFO] - AES256_CBC test [buffer size: 256] throughput : 10534 KBps
[C3 INFO] - AES256_CBC test [buffer size: 512] throughput : 20480 KBps
[C3 INFO] - AES256_CBC test [buffer size: 1024] throughput : 34711
KBps [C3 INFO] - AES256_CBC test [buffer size: 2048] throughput : 53194
KBps [C3 INFO] - AES256_CBC test [buffer size: 4096] throughput : 72882
KBps [C3 INFO] - AES256_CBC test [buffer size: 8192] throughput : 89237
KBps [C3 INFO] - [CDD] Unregistering character device driver
The autotest allows to check the performance of the following algorithms:
ï‚·
DES/3DES (CBC)
ï‚·
AES (CBC, CTR)
ï‚·
Hash (SHA1/SHA512 w/HMAC).
152/220 DocID028276 Rev 1
UM1942
7 Frame buffer drivers
Frame buffer drivers
The Linux frame buffer (“fbdev”) is a graphic hardware independent abstraction layer to show graphics on a computer monitor. The word frame buffer means a part of the video memory containing a current video frame, and the Linux frame buffer means “access method to the frame buffer under the Linux kernel”, without relying on system specific libraries such as “SVGALib” or another user space software.
Color liquid crystal display (CLCD)
The CLCD controller provides all the necessary control signals to interface directly to a variety of LCD panels. This section describes the driver for the CLCD controller available on the STreamPlug.
CLCD software overview
The CLCD device driver sits on the top of the CLCD controller and provides all necessary functions for a graphic application via the standard Linux frame buffer interface.
CLCD kernel source and configuration
Following is the detail corresponding to the layout of the driver and kernel configuration:
ï‚·
The digital blocks CLCD driver is present in “drivers/video/amba-clcd.c”
ï‚·
The platform data configuration is present in “arch/arm/plat-streamplug/clcd.c”.
The kernel configuration is listed in
Table 28. CLCD configurations
Configuration
CONFIG_FB_ARMCLCD
CONFIG_FB_ARMCLCD_SHARP_LQ043T1DG01
Description
Enable the ARM
®
PrimeCell
®
PL110 color LCD controller
Enable the LCD device controller for the
SHARP LQ043T1DG01 model. This is implementation of the “Sharp LQ043T1DG01, a 4.2" color TFT panel. The native resolution is
480 x 272.
DocID028276 Rev 1 153/220
220
Frame buffer drivers UM1942
CLCD clock source configuration
There are two clock domains in the LCD controller core:
ï‚·
Bus clock (BCLK) domain:
– Master and slave interfaces
– Control and status registers
– DMA controller
– Write side of the palette two-port RAM
– Write side of the input FIFO
– Interrupt controller
ï‚·
Pixel clock (PCLK) domain:
– Read side of the Input FIFO
– Read side of the palette two-port RAM
– Pixel unpack
– Timing and control unit
– Output formatter
Within the pixel clock domain, there are two versions of PCLK:
ï‚·
The internal pixel clock (PCLK), which serves as the on-chip clock for the DB9000 pixel pipeline logic
ï‚·
The external pixel clock (LCD_PCLK), which serves as the off-chip clock to the LCD panel pixel clock input.
The controller's clock generator can derive PCLK and LCD_PCLK from 2 possible sources:
ï‚·
The input bus clock (BCLK)
ï‚·
The input pixel clock (PCLK_IN)
The “PCLK_IN” can be selected from different sources. The CLCD synthesizer is being one of them.
In the controller, the clock generator outputs are determined by the pixel clock timing register (PCTR) programming parameters.
In the STreamPlug, “BCLK” is the AHB clock (166 MHz) and “PCLK_IN” can be configured further from several sources in the SoC but outside the controller. The clock selection criteria in the driver is based on following strategy:
First determine if the required pixel CLK for panel can be generated by “BCLK”:
LCD_PCLK = BCLK /(2 + PCD)
If the PCD is not configurable, then select “PCLK_IN” as the source and call “clk_set_rate” to set the desired pixel clock for the panel.
154/220 DocID028276 Rev 1
UM1942 Frame buffer drivers
CLCD allocate frame buffer memory
For a max. resolution of 800 x 400 pixels, the panel resolution requires 1.5 Mbytes of the contiguous memory for a frame buffer. During the setup, the routine
“dma_alloc_writecombine” is used to allocate the memory for the frame buffer as shown below.
static int clcd_setup(struct clcd_fb *fb)
{
dma_addr_t dma;
struct clk *clk;
int ret = 0;
clk = clk_get(&fb->dev->dev, "hclk");
if (IS_ERR(clk)) {
dev_err(&fb->dev->dev, "failed to get clcd clock\n");
ret = PTR_ERR(clk);
goto out;
}
clk_enable(clk);
/* Detect which LCD panel is connected */
#ifdef CONFIG_FB_ARMCLCD_SHARP_LQ043T1DG01
fb->panel = &sharp_LQ043T1DG01_in;
#endif
#ifdef CONFIG_FB_ARMCLCD_SAMSUNG_LMS700
fb->panel = &samsung_LMS700_in;
#endif
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, FRAMESIZE,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
return -ENOMEM;
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = FRAMESIZE;
out:
return ret;
}
DocID028276 Rev 1 155/220
220
Frame buffer drivers UM1942
CLCD platform data
Default configuration of the digital blocks CLCD controller depends on the platform data passed from the boards through functions defined in “arch/arm/plat-streamplug/clcd.c”. The
CLCD main structure is shown below.
static struct clcd_panel sharp_LQ043T1DG01_in = {
.mode = {
.name = "Sharp LQ043T1DG01",
.refresh = 0,
.xres = 480,
.yres = 272,
.pixclock = KHZ2PICOS(9000),
.left_margin = 2,
.right_margin = 2,
.upper_margin = 2,
.lower_margin = 2,
.hsync_len = 41,
.vsync_len = 11,
.sync = 0, //FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IOE | TIM2_CLKSEL | TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_BGR,
.bpp = 32,
.power_sleep = 0,
};
CLCD usage
In order to test the CLCD display the following utilities are available:
ï‚·
“fbv” - a frame buffer image viewer (provided as a buildroot package) that supports multiple image formats
ï‚·
“clcd”, found in the folder “/example/jpeg”, that displays the result of hardware JPEG decoding on the
CLCD.
ï‚·
“gpm” - a tool to support mouse interactivity in Linux. GPM utilities are provided within mountable auxiliary FS.
To enable the CLCD support at run-time it is necessary to configure the Linux kernel command line using the options listed in
. To run “fbv” use the following command line:
$ fbv -k -f "image to display"
The two options adapt the image to the screen size (-k) and frame buffer color depth (-f), only in case LCD bpp is less than the image bpp.
To run the CLCD use the following command line:
$ ./clcd "image to display"
156/220 DocID028276 Rev 1
UM1942 Frame buffer drivers
The program decodes the JPEG directly to the LCD frame buffer.
Some frame buffer options can be configured directly from the shell by accessing controls export through “sysfs”. Some useful options are:
ï‚·
Control blinking cursor:
$ echo 0 > /sys/class/graphics/fbcon/cursor_blink # to disable
$ echo 1 > /sys/class/graphics/fbcon/cursor_blink # to enable
ï‚· clcd sleep mode:
$ echo 1 > /sys/class/graphics/fb0/blank # to enter
$ echo 0 > /sys/class/graphics/fb0/blank # to leave
To test the CLCD with the “gpm” utility it is necessary to connect a keyboard and a mouse through a USB hub to the board. Then the USB host and CLCD device driver have to be enabled in the Linux command line using the options listed in
. If a CLCD is connected and enabled, a shell login is automatically redirected on the CLCD panel.
By running the following command
$ gpm -m /dev/input/mouse0 -t imps2
GPM will stay in background as a daemon and the cursor on the CLCD screen will follow the movements done with the mouse. To stop it, apply the following command:
$ gpm -k
DocID028276 Rev 1 157/220
220
Miscellaneous devices UM1942
This section contains information on drivers which are not part of the other sections.
8.1.1
The general purpose input/output (GPIO) is a flexible software controlled digital signal. Each
GPIO represents a bit connected to a particular pin, or “ball” on ball grid array (BGA) packages. Board schematics show which external device connects to which GPIOs. Drivers can be written generically, so that the board setup code passes such pin configuration data to drivers.
GPIO software overview
Each GPIO input/output can be controlled in the software mode through an APB interface.
The APB interface generates read and write decodes for accesses to control, interrupt, and data registers. A read-only decode is provided to access the ID codes. The APB interface implements the storage elements for the data, data direction, mode control, interrupt interface, and identification registers. The GPIO can be accessed from two levels in Linux:
ï‚·
From the user space using the “sysfs” interface
ï‚·
From other kernel modules
The GPIO software system architecture is shown in
158/220 DocID028276 Rev 1
UM1942
Figure 16. GPIO software stack
echo/cat sysfs interface
Linux drivers
Linux GPIO framework
(GPIOLIB)
GPIO controller driver
Miscellaneous devices
User space
Kernel space
GPIO controller
Hardware
AM039723
The GPIO device driver is implemented by the following source files:
ï‚·
The core features are implemented in “drivers/gpio/pl061.c”
ï‚·
Common functions are in “drivers/gpio/gpiolib.c”
lists the kernel configuration options related to GPIO support.
Configuration
Table 29. GPIO configurations
Description
CONFIG_GPIO_PL061
CONFIG_ARCH_REQUIRE_GPIOLIB
CONFIG_GPIOLIB
CONFIG_GPIO_SYSFS
This enables support for the prime cell pl061 GPIO device.
Selecting this from the architecture code will cause the
“gpiolib” code to always get built in.
This enables GPIO support through the generic GPIO library.
This enables the “sysfs” interface for GPIOs.
DocID028276 Rev 1 159/220
220
Miscellaneous devices UM1942
The
GPIO driver, both for pl061 and plgpios are implemented in the GPIO framework. Both these drivers must be informed about the platform details in order to work properly. All this information is purely SoC dependent and has already been provided from the corresponding
SoC file to the driver while initialization and the user has not bother about them. The user can directly look into the source for more information on this aspect.
The following GPIO user mode operations are allowed from the user space: the request, free, set and get direction, set and get value.
Request:
The user space may ask the kernel to export control of a GPIO pin to the user space by writing its number to this file “/sys/class/gpio/export”.
Example: export a node
The following line creates a “gpio24 node” for GPIO #24, if it is not requested by the kernel code:
# echo 24 > /sys/class/gpio/export
Free:
The user space may ask the kernel to take back control of a GPIO pin from the user space by writing its number to this file “/sys/class/gpio/unexport”.
Example: unexport a node
The following line removes the “gpio24” node exported using the “export” file:
# echo 24 > /sys/class/gpio/unexport
Set and get direction:
Once a GPIO pin is exported, the files “direction” and “value” appear under the
“/sys/class/gpio/gpiopin/” folder. The direction of the GPIO can be set to OUT or IN by writing “out” or “in” on the “direction” file.
Example: setting direction in the OUT mode
It is possible to set the direction of the pin 32 to out by using the following command:
# echo "out" > /sys/class/gpio/gpio32/direction
General purpose GPIOs are enumerated from 24 to 39.
The GPIO pin is a file created after exporting a GPIO pin (for example, gpio30, gpio32).
Set and get value:
The value of the GPIO can be configured, if the GPIO is configured in the OUT mode and its value can be read if the GPIO is configured in the IN mode. The value can be set by writing
1 or 0 in the “/sys/class/gpio/gpionr/value” file.
Example: setting GPIO pin 32
The pin 32 value can be set once the following command is used:
# echo 1 > /sys/class/gpio/gpio32/value
160/220 DocID028276 Rev 1
UM1942 Miscellaneous devices
GPIO kernel mode
The following GPIO operations are allowed from kernel space: the request, set and get direction and value, and configure the GPIO for interrupt.
Request:
A GPIO pin can be requested by calling following function:
/*
* gpio: is gpio pin number to be requested.
* label: is a string passed by user as a unique identification of user.
*/ int gpio_request(unsigned gpio, const char *label);
The function “gpio_request()” will fail if an invalid GPIO pin number is used or the requesting
GPIOs has already been claimed with the same function call. The return value is 0 if everything worked correctly otherwise a standard linux error is returned.
Free:
After using a previously requested GPIO pin, it must be set free. This can be done by using the following function:
/* Gpio: is gpio pin number already requested */ void gpio_free(unsigned gpio);
Passing an invalid GPIO number to “gpio_free()” will fail.
Set direction
After requesting a GPIO pin, its direction must be set. This can be done using following function:
/*
* gpio: is gpio pin number.
* value: is value to be set, 0 or 1.
*/ int gpio_direction_output(unsigned gpio, int value);
The return value is zero for success, otherwise a negative number is returned. The return value must be checked because the get/set calls do not return errors and it is possible to have a wrong configuration. Setting the direction can fail if the GPIO number is invalid, or when that particular GPIO cannot be used in that mode.
For the value parameter, it is preferable to include and use the GPIO macros defined in the corresponding CPU's “gpio.h” file.
DocID028276 Rev 1 161/220
220
Miscellaneous devices UM1942
Set and get value
After the direction of the GPIO is set, its value can be read or written. A value can be written to a GPIO that is in the OUT mode and can read a value from a GPIO that is in the IN mode.
This can be done using following functions:
/*
* gpio: is gpio pin number.
* value: is value to be set, 0 or 1.
*/ void gpio_set_value(unsigned gpio, int value);
/* gpio: is gpio pin number. */ int gpio_get_value(unsigned gpio);
The values are zero to mean “low” and nonzero to mean “high”.
To enable the GPIO support at run-time it is necessary to configure the Linux kernel command line using the options listed in
.
8.2.1
The application specific GPIO is a flexible software controlled digital signal. Each GPIO represents a bit connected to a particular pin, or “ball” on ball grid array (BGA) packages.
Board schematics show which external hardware connects to which GPIOs. Each AS GPIO works as a general purpose I/O GPIO. However, a subset of AS GPIOs are configurable as a pulse width modulator (PWM).
AS GPIO software overview
The operations of the GPIO pins are controlled by the registers, which can be, written/read by software through the APB interface. The pins can be used as dual function pins. The dual function may be either the PWM output, timer I/O and control, or the UART I/O and control.
The dual use selection will be defined at a higher level except for the PWM function. The status of the pins can be captured into a register when commanded to do so by the software or by an external signal. The source of the capture signal is set in a register by the software.
The GPIO pin can be used to generate interrupts when the pin is configured as an input.
The interrupt generation is programmable. Interrupt can be generated when there is a change in polarity, on the rising/falling edge, or on both the edges of the input signal.
The GPIO module also contains pulse width modulators (PWM). The PWM is capable of operating as a continuous repetitive pulse generator, or a single pulse generator. The duration of high and low time for a repetitive pulse and the duration for a single pulse are programmable. The PWM can be enabled/disabled by writing to the PWM enable register.
The polarity for a single pulse generator is also programmable. On reset the PWM output is set to low. The PWM operates on the APB clock (PCLK).
162/220 DocID028276 Rev 1
UM1942
8.2.2
Miscellaneous devices
AS GPIO kernel source and configuration
The GPIO device driver is implemented by the following source files:
ï‚·
The core features are implemented in “drivers/gpio/ark_gpio.c”
ï‚·
Common functions are in “drivers/gpio/gpiolib.c”
lists the kernel configuration options related to AS GPIO support.
Configuration
CONFIG_GPIO_ARK
Table 30. AS GPIO configurations
Description
CONFIG_ARCH_REQUIRE_GPIOLIB
CONFIG_GPIOLIB
CONFIG_GPIO_SYSFS
This option enables support for AS GPIO.
Selecting this from the architecture code will cause the
“gpiolib” code to always get built in.
This enables GPIO support through the generic GPIO library.
This enables the “sysfs” interface for GPIOs.
8.2.3 AS GPIO platform configuration
The optional platform data passed from the machine for AS GPIOs is as follows:
/* gpio device registration */ struct ark_gpio_platform_data ark_gpio_plat_data = {
.gpio_base= (unsigned)-1,
.irq_base= STREAMPLUG1X_IRQ_ARK_GPIO_BASE,
.enable_mask = ark_gpio_mask,
.groups = STREAMPLUG_ARK_GPIO_GROUPS,
.set_groups = STREAMPLUG_ARK_GPIO_SET_GROUP,
};
/* ark_gpio device registration */ struct resource ark_gpio_resources[] = {
{
.name = "ark_gpio",
.start = STREAMPLUG1X_ICM2_ARK_GPIO_BASE,
.end = STREAMPLUG1X_ICM2_ARK_GPIO_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
}, {
.name = "ark_gpio_irq",
.start = STREAMPLUG1X_IRQ_APP_SUBS_ARK_GPIO,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device streamplug10_ark_gpio_device = {
.name = "streamplug_ark_gpio",
.id = -1,
DocID028276 Rev 1 163/220
220
Miscellaneous devices
8.2.4
UM1942
.num_resources = ARRAY_SIZE(ark_gpio_resources),
.resource = ark_gpio_resources,
.dev = {
.platform_data = &ark_gpio_plat_data,
},
};
AS GPIO usage
AS GPIOs are enumerated from 0 to 23. Only a subset of AS GPIOs is configurable in the
PWM mode (GPIO [0:7]), the other ones works in I/O modality. Within the two subgroups of
4 GPIOs of GPIO [0:7], the first one handles dual PWMs, while the second one handles single PWMs.
I/O
The following GPIO operations are allowed from the user space: the request, free, set and get direction, set and get value, configure PWMs.
Request:
The user space may ask the kernel to export control of a GPIO pin to the user space by writing its number to this file “/sys/class/gpio/export”.
Example: export a pin
The following line creates a “gpio8 node” for GPIO #8, if it is not requested by the kernel code:
# echo 8 > /sys/class/gpio/export
Free:
The user space may ask the kernel to take back control of a GPIO pin from the user space by writing its number to this file “/sys/class/gpio/unexport”.
Example: unexport a pin
The following line removes the “gpio8” node exported using the “export” file.
# echo 8 > /sys/class/gpio/unexport
Set and get direction:
Once a GPIO pin is requested, the files “direction” and “value” can be found under the
“/sys/class/gpio/gpio<pin number>/” folder. The direction of the GPIO can be set to OUT or
IN by writing “out” or “in” in the “direction” file.
Example: setting direction in the OUT mode
The pin 16 can be set in the OUT mode with the following command:
# echo "out" > /sys/class/gpio/gpio16/direction
Set and get value:
The value of the GPIO can be configured, if the GPIO is configured in the OUT mode and its value can be read if the GPIO is configured in the IN mode. The value can be set by writing
1 or 0 in the “/sys/class/gpio/gpio<pinnumber>/value” file.
164/220 DocID028276 Rev 1
UM1942 Miscellaneous devices
Example: setting GPIO pin 16
The pin 16 value can be configured with the following command:
# echo 1 > /sys/class/gpio/gpio16/value
PWM configuration
When exporting a PWM GPIO the following files are created:
“pwm_mode”: to select to the output type, where 0 means a simple value mode, 1 is the
PWM mode.
A set of parameters for the PWM configuration:
“pwm_enable”: to enable the PWM output, 1 means enable and 0 means disable.
“pwm_type”: to select between “continuous wave” and “one pulse one”: 0 -> means continuous, while 1 one pulse only.
“pwm_high”: to define the duration of the high phase in clock units, applicable only when the pwm_type is equal to 0.
“pwm_low”: to define the duration of the low phase in clock units, applicable only when the pwm_type is equal to 0.
“pwm_width”: to define the duration of the pulse width in clock units, applicable only when the pwm_type is equal to 1.
“pwm_polarity”: to define the polarity of the pulse, applicable only when the pwm_type is equal to 1.
“pwm_prescaler”: as the width of the pulses is configured in clock units a prescaler can be applied to the system one. The prescaler range is from 0 to 14, with the meaning listed in
DocID028276 Rev 1 165/220
220
Miscellaneous devices UM1942
Table 31. AS GPIO PWM prescaler configurations
Value Divider
11
12
13
14
8
9
10
6
7
4
5
2
3
0
1
2048
4096
8192
16384
32768
65536
131072
128
256
512
1024
8
16
32
64
If exporting a dual PWM GPIO (0 - 3) two sets of PWM parameters are available, because the GPIO output is the combination of two PWMs.
Example: dual PWM configuration, pulse combined with continuous
# echo 0 > /sys/class/gpio/export
# echo out > /sys/class/gpio/gpio0/direction
# echo 1 > /sys/class/gpio/gpio0/pwm_mode
# echo 1 > /sys/class/gpio/gpio0/pwm_type
# echo 0 > /sys/class/gpio/gpio0/pwm2_type
# echo 1 > /sys/class/gpio/gpio0/pwm_polarity
# echo 10000 > /sys/class/gpio/gpio0/pwm_width
# echo 1000 > /sys/class/gpio/gpio0/pwm2_high
# echo 1000 > /sys/class/gpio/gpio0/pwm2_low
# echo 1 > /sys/class/gpio/gpio0/pwm2_enable ; echo 1 >
/sys/class/gpio/gpio0/pwm2_enable
166/220 DocID028276 Rev 1
UM1942
The resulting pin output is captured in
.
Figure 17. Dual PWM GPIO example
Miscellaneous devices
PAD MUX configuration
To enable the AS GPIO support at run-time it is necessary to configure the Linux kernel command line using the options listed in
.
In particular, the value passed on the cmdline is “ark_gpio=on:nnnnnn” where “nnnnnn” is the muxing definition.
Each digit represents a group of 4 GPIOs, while the groups are identified by letters from
a to f.
Some of them can be muxed onto different MFIOs, for example:
ï‚·
Group a => MFIOs 32 - 35 (muxed selection option 1)
ï‚·
Group b => MFIOs 28 - 31 (muxed selection option 1)
ï‚·
Group c => MFIOs 16 - 19 (muxed selection option 1) or MFIOs 36 - 39 (muxed selection option 2)
ï‚·
Group d => MFIOs 20 - 23 (muxed selection option 1) or MFIOs 40 - 43 (muxed selection option 2)
ï‚·
Group e => MFIOs 48 - 51 (muxed selection option 1) or MFIOs 72 - 75 (muxed selection option 2)
ï‚·
Group f => MFIOs 52 - 55 (muxed selection option 1) or MFIOs 76 - 79 (muxed selection option 2) where 0 means the GPIOs are not exposed on pins.
DocID028276 Rev 1 167/220
220
Miscellaneous devices
For instance the following ATAG “ark_gpio=on:010011” means:
ï‚·
AS GPIOs 0 - 3 (group a) off
ï‚·
AS GPIOs 4 - 7 (group b) in MFIOs 28 - 31
ï‚·
AS GPIOs 8 -1 1 (group c) off
ï‚·
AS GPIOs 12 - 15 (group d) off
ï‚·
AS GPIOs 16 - 19 (group e) in MFIOs 48 - 51
ï‚·
AS GPIOs 20 - 23 (group f) in MFIOs 52 - 55
8.3
UM1942
Watchdog timer (WDT) driver
A watchdog timer is a hardware device that triggers a system reset if its regularly generated interrupts are not acknowledged. The idea behind it is to have a reliable way to bring the system back from the hung state into the normal operation.
The watchdog driver for the STreamPlug in the Linux support package is a part of the standard Linux watchdog framework. Watchdog drivers in Linux are based on the character device using the Misc device layer and provide a standard set of IOCTLs to the user.
Through this interface the watchdog time can be configured, programed and refreshed. The standard Linux watchdog daemon can be used to configure and periodically pat (refresh) the driver in order to avoid system reset. A software crash or hang would thus prevent this pat from a happening and hence cause a system reset after timeout.
illustrates the watchdog framework.
168/220 DocID028276 Rev 1
UM1942
Figure 18. WDT software stack
Watchdog daemon
Miscellaneous devices
User space
/dev/watchdog
Misc. dev layer
Watchdog driver
Kernel space
8.3.2
Hardware
Watchdog timer
AM039724
WDT kernel source and configuration
In the Linux source tree, the watchdog driver is present in the file:
“drivers/watchdog/sp805_wdt.c”.
lists the kernel configuration options affect the watchdog timer. These
configurations can be selected through the “make menuconfig” interface in Linux.
Table 32. WDT Linux kernel configurations
Configuration Description
CONFIG_WATCHDOG
CONFIG_WATCHDOG_NOWAYOUT
CONFIG_ARM_SP805_WATCHDOG
This enables the watchdog support in the Linux kernel.
Enabling this option means that even on closing watchdog the timer would remain active and would eventually reset.
The default watchdog behavior is to stop the timer if the process managing it closes the file “/dev/watchdog”. If Y is used here, the watchdog cannot be stopped once it has been started.
This enables STreamPlug watchdog support.
DocID028276 Rev 1 169/220
220
Miscellaneous devices UM1942
Watchdog device driver interface with “Misc” device layer
As mentioned, the watchdog driver behaves as a character device, so normal file operations
(open, close, ioctl, write) can be used to access its features. For this, the driver uses the
“Misc” device layer and registers.
static const struct file_operations streamplug_wdt_fops = {
.owner = THIS_MODULE,
.write = streamplug_wdt_write,
.unlocked_ioctl = streamplug_wdt_ioctl,
.open = streamplug_wdt_open,
.release = streamplug_wdt_release,
};
/* minor no. is standard, defined in miscdevice.h */ streamplug_wdt_miscdev.minor = WATCHDOG_MINOR; streamplug_wdt_miscdev.name = "watchdog"; streamplug_wdt_miscdev.fops = &streamplug_wdt_fops;
/* register watchdog driver */ ret = misc_register(&streamplug_wdt_miscdev);
Watchdog driver usage
The watchdog device driver provides a char device interface (“/dev/watchdog”) to the user.
The standard file operations can be used to open and configure the watchdog device. The following sections explain how the watchdog device can be used.
Opening WDT
The watchdog timer is enabled as soon as it is opened by the user. The usual open call can be used to open the watchdog device.
--- char wdt_dev[] = "/dev/watchdog" int fd; fd = open(wdt_dev, O_RDWR); if (fd < 0) {
printf("Error in opening device\n");
}
---
Configuring WDT
IOCTL calls can be used to program and configure the watchdog timer. The following code snippet demonstrates the use of these IOCTLs.
int ret = 0; int timeleft=0; struct watchdog_info ident; int timeout = 45; /* in seconds */
/* to find out supported options in watchdog */
170/220 DocID028276 Rev 1
UM1942 Miscellaneous devices
ret = ioctl(fd, WDIOC_GETSUPPORT, &ident);
/* to set time out */ ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
/* to find out how much time is left before reset */ ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeleft);
/* Refresh watchdog timer at every 10 secs to prevent reset */ while (1) {
ioctl(fd, WDIOC,KEEPALIVE, 0);
sleep(10);
}
lists the standard “ioctl” calls supported by the STreamPlug watchdog driver.
IOCTLs
Table 33. Watchdog IOCTLs
Purpose
WDIOC_GETSUPPORT
The fields returned in the “ident” structure are: identity: A string identifying the watchdog driver “firmware_version”: the firmware version of the card if available. Options: A flags describing what the device supports.
WDIOC_KEEPALIVE
This “ioctl” does exactly the same thing as write to the watchdog device and hence refreshes the timer.
WDIOC_SETTIMEOUT
WDIOC_GETTIMEOUT
Set time out in seconds, after which reset would be generated (if WDT is not refreshed).
Query the current timeout.
For more information about Linux kernel support to the watchdog see the file: linux-2.6.35/Documentation/watchdog.txt
A simple watchdog demonstration application is provided in the “/examples/watchdog/” folder to perform some operations on the watchdog peripheral.
The application uses the watchdog device file “/dev/watchdog.” If a such file is not present, the user may create it using the “mknod” command:
$ mknod /dev/watchdog c 10 130
The “watchdog-demo” using IOCTL provided by the
ARM sp805 driver may be used to set and get the watchdog timeout, to check the last boot cause and to kick the watchdog.
Set the watchdog timeout.
DocID028276 Rev 1 171/220
220
Miscellaneous devices UM1942
The test procedure is:
1.
Open both UART terminals on the PC host and plug cables on RS232 connectors on the board.
2. Run the “watchdog-demo” and verify at power-on that reset was made by “power-on reset” procedure: a) With the option “-i <interval time in sec>” the interval time may be changed
(passing a decimal integer value) for the next watchdog.
b) Without the option “-i <interval time in sec>” the interval time set to 60 s is considered the default.
With the “watchdog-demo” running, the user can keep the watchdog alive by selecting the option “w” or restarting the interval time with “i'”. In this way the user will simulate the kernel behavior.
The user may perform two different tests with the “watchdog-demo”:
TEST 1: The user allows the watchdog to time out:
1.
The user waits for a time equal to initial interval time.
2. The user will not close the “watchdog-demo” application and watch for OK Linux restarting.
3. At next login, the user will start the “watchdog-demo” and will verify the cause of the reset.
The following is an example of such a test:
Welcome to OKL STreamPlug
STreamPlug login: root
#
#
# mount /dev/sda /mnt/
# cd /mnt/examples/watchdog/
# ./watchdog-demo -i5
Set watchdog interval to 5
Current watchdog interval is 5
Last boot is caused by : Power-On-Reset
Use:
<w> to kick through writing over device file
<i> to kick through IOCTL
<x> to exit the program
VMMU: segment too big (80000000) for index 0
Linux version 2.6.35-vcpu-okl_streamplug+ ([email protected]) (gcc version 4.3.3 ( ?'
Sourcery G++ Lite 2009q1-203) ) #13 Thu Jul 25 14:35:57 CEST 2013
CPU: vCPUv5 [14069260] revision 0 (ARMv5TEJ)
CPU: VIVT data cache, VIV ST-ATag virq 6a, "timer_tick"
ATag microvisor_timer c2, 6a, "timer_microvisor_timer"
ATag virq 6b, "oklinux_signal"
ATag ksp_agent c3, 6b, "oklinux_ksp_agent"
ATag ksp_shared_mem fd100000, 4800000, 1e00000, "shm_KSP_SHARED_MEMORY"
172/220 DocID028276 Rev 1
UM1942 Miscellaneous devices
ATag Shared Buffer 40000000, 80000000, "pci_express"
ATag vclient c4, 20, 6c, "vserial_vtty0_vclient"
OKL4: vcpu_helper_page at 84579000/01fff000
VMMU:paging_init: VMMU: Cache management handing is possibly not correct (SDK-1545). Built 1 zonelists in Zone order, mobility grouping on.Total pages: 11938
Kernel command line: console=vcon0,115200n8 root=/dev/mtdblock2 rootfstype=ext2,jffs2 clcd ?'
=off pcie=off sata=off usb=on:host eth=on:primary: i2c=off ssp=off uart1=off uart2=off?' can=off firda=off fsmc=off sport=off ts=off ark_gpio=off
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) Inodecache hash table entries: 4096 (order: 2, 16384 bytes) Memory: 47MB
= 47MB total
Memory: 42468k/42468k available, 5660k reserved, 0K highmem
Virtual Kernel memory layout: vector : 0x01fff000 - 0x02000000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xef600000 - 0xf0000000 ( 10 MB) vmalloc : 0x87000000 - 0xe9e00000 (1582 MB) lowmem : 0x84000000 - 0x86f00000 ( 47 MB) modules : 0x83000000 - 0x84000000 ( 16 MB)
.init : 0x84000000 - 0x84026000 ( 152 kB)
.text : 0x84026000 - 0x844ad000 (4636 kB)
.data : 0x844c8000 - 0x844fbbe0 ( 207 kB)
Hierarchical RCU implementation.
Verbose stalled-CPUs detection is disabled. NR_IRQS:121
Console: colour dummy device 80x30
Calibrating delay loop... 164.65 BogoMIPS (lpj=823296)
....
....
rtc-streamplug rtc-streamplug: rtc core: registered rtc-streamplug as rtc0 i2c /dev entries driver
Linux video capture interface: v2.00
HM1355 driver loaded sp805-wdt wdt: registration successful dw_dmac: DesignWare DMA Controller, 8 channels usbcore: registered new interface driver usbhid usbhid: USB HID core driver
No device for DAI AKCODEC
....
....
Welcome to OKL STreamPlug
STreamPlug login: root
#
DocID028276 Rev 1 173/220
220
Miscellaneous devices UM1942
#
# mount /dev/sda /mnt/
# cd /mnt/examples/watchdog/
# ./watchdog-demo
Current watchdog interval is 60
Last boot is caused by : Watchdog
Use:
<w> to kick through writing over device file
<i> to kick through IOCTL
<x> to exit the program
TEST 2: the user will continue to refresh the watchdog:
1.
The user may refresh before interval time expiring with one of the following options: a) “w” b) “i”
2. Run 'w' at least on time in order to refresh interval time to the value passed with 'i' or to default one
3. Do not close watchdog-demo and wait for OK Linux restart
The option “x” closes the “watchdog-demo”, leaving the watchdog control back to OK Linux kernel.
Interacting with watchdog via device file
The watchdog is automatically started. To stop the watchdog: write character “V” into
“/dev/watchdog” to prevent stopping the watchdog accidentally and close the
“/dev/watchdog” file.
To “kick” or to “feed” the watchdog any character can be written into the “/dev/watchdog” file.
Watchdog daemon
The watchdog is a daemon. It opens “/dev/watchdog” and keeps writing to it often enough to keep the kernel from resetting, at least once per minute. Each write delays the reboot time another minute. After a minute the watchdog hardware generates a reset. The watchdog can be stopped without causing a reboot if the device “/dev/watchdog” is closed correctly, unless the kernel is compiled with the “CONFIG_WATCHDOG_NOWAYOUT” option enabled.
The default timeout period can be programmed by passing an argument to the watchdog daemon in following manner:
$ watchdog -T 60
A “V” character writing causes a watchdog to stop. (See the “starting- stopping watchdog” point above).
174/220 DocID028276 Rev 1
UM1942 Audio drivers
This section describes the drivers that can be used for audio.
SPORT controller
The DSP's serial port (SPORT) can be utilized for a direct connection to a DSP or an other device with a high speed serial interface. The SPORT controller is integrated interchip sound (I
2
S) compliant that is an electrical serial bus interface standard used for connecting digital audio devices together. The controller provides a simple I
2
S interface to industry standard audio components. It supports the standard I
2
S frame format for transmitting and receiving audio data.
It features:
ï‚·
Synchronous serial data transfer
ï‚·
Dedicated transmit and receive data lines
ï‚·
Supports full duplex devices for simultaneous data transfer in both directions
ï‚·
Independent transmit and receive clocks. It provides an internally generated serial clock and frame sync signals in a wide range of frequencies, or accepts the clock and frame sync input from an external source.
ï‚·
Perform interrupt driven, single word transfers to and from the on-chip memory, controlled by the processor.
ï‚·
Execute DMA transfers to and from the on-chip memory where the SPORT interface can automatically receive or transmit an entire block of data.
ï‚·
Three 32-bit word length, programmable frame “sync” for every transmitted or received word
ï‚·
Can be configured to use early frame “sync”.
DocID028276 Rev 1 175/220
220
Audio drivers UM1942
SPORT controller software overview
The I
2
S driver is implemented within the “Advanced Linux Sound Architecture” (ALSA)
. The ALSA provides suitable layers and APIs to support
complex sound systems where it provides proper abstraction, so that each layer can be independent of others. As a consequence the applications dealing with audio remain immune to hardware and at the same time plugging new hardware is relatively easy.
Figure 19. ALSA framework
gstreamer ALSA aplay/arecord
User space
ALSA framework
ASoC layer
Platform
I2S controller driver
Machine
Audio support
SPORT controller
(I2S)
DMA
I2S
DAC/ADC
(I2C)
Kernel space
Hardware
AM039725
176/220 DocID028276 Rev 1
UM1942 Audio drivers
There is another layer of abstraction under the ALSA framework for embedded audio environment. The abstraction is known as the ALSA system-on-chip (ASoC) layer. The overall project goal of the ASoC layer is to provide better ALSA support for embedded system-on-chip processors and portable audio codecs.
The ASoC layer is designed to address these issues and provide the following features:
ï‚·
Codec independence. It allows reuse of codec drivers on other platforms and machines.
ï‚·
Easy I
2
S/PCM audio interface setup between the codec and SoC. Each SoC interface and codec registers its audio interface. Capabilities with the core and codec are subsequently matched and configured when the application hardware parameters are known.
To achieve all this, the ASoC basically splits an embedded audio system into three components:
Codec driver
The codec driver is platform independent and contains audio controls, audio interface capabilities, the codec DAPM definition and codec I/O functions.
Platform driver
The platform driver contains the audio DMA engine and audio interface drivers.
Machine driver
The machine driver handles any machine specific controls and audio events. Complete
STreamPlug audio support is within the ASoC framework. It has both the play and record feature.
SPORT controller kernel source and configuration
STreamPlug audio support is available below “sound/soc/streamplug/folder”.
ï‚·
The I
2
S controller driver is present in “sound/soc/streamplug/streamplug_i2s.c”.
ï‚·
The platform data defining the I
2
S PCM data format and PCM rate are present in
“sound/soc/streamplug/streamplug-i2s.h”.
ï‚·
The
STreamPlug ASoC platform driver is present in
“sound/soc/streamplug/streamplug_pcm.c”.
ï‚·
STreamPlug ASoC machine implementation can be found in
“sound/soc/streamplug/streamplug-sport.c”.
DocID028276 Rev 1 177/220
220
Audio drivers UM1942
lists the “Kconfig” options needed to enable the audio support over I
2
S for the
STreamPlug architecture.
Table 34. SPORT- I
2
S configurations
Configuration Description
CONFIG_SOUND
CONFIG_SND
CONFIG_SND_PCM
CONFIG_SND_STREAMPLUG_SOC
CONFIG_SND_STREAMPLUG_SOC_I2S
CONFIG_SND_STREAMPLUG_SOC_SPORT
CONFIG_SND_STREAMPLUG_SOC_VB
CONFIG_SND_SOC_AKCODEC
It enables ALSA sound system support
It enables ALSA for SoC audio support
It enables PCM for SoC audio support
It enables the ALSA SoC for the STreamPlug
It enables I
2
S support
It enables machine support it enables audio support
It enables the codec
SPORT controller platform configuration
In audio some essential parameters are required to play or record a song. These are the sample rate, sample format, number of channel, etc. These parameters are passed from the platform code. Platform data is used to pass the I
2
S capability like the maximum channel, formats, rates, etc. This depends on the HW capability of the I
2
S controller and the manner in which the platform intends to use it.
The following structure, “sport_platform_data”, is used to pass these capabilities which is defined in “include/linux/streamplug_sport_reg.h”.
struct sport_platform_data {
#define PLAY(1 << 0)
#define RECORD(1 << 1)
unsigned int cap;
int channel;
u8 swidth;
};
In above structure, the fields are:
cap
It is used to configure the PCM capability and can be equal to:
ï‚·
PLAY, or
ï‚·
RECORD
channel
The maximum number of channels supported by the controller.
snd_fmts
Sound formats like ”SNDRV_PCM_FMTBIT_S16_LE”, etc. supported by the controller.
Available formats are defined in “include/sound/pcm.h”.
178/220 DocID028276 Rev 1
UM1942 Audio drivers snd_rates
Sampling rates like “SNDRV_PCM_RATE_48000”, etc. supported. These are defined in
“include/sound/pcm.h/”.
play_dma_data
Configure the DMA channel for playing. This is DMA specific structure which can vary from the platform to platform. It will configure the TX line, transfer burst size, etc. Please refer to the DMA slave configuration section in
Section 6.2: Direct memory access (DMA) on page 139
.
capture_dma_data
Similar to “play_dma_data”, but for the capture interface.
bool (*filter)(struct dma_chan *chan, void *slave)
This is also DMA specific data which is called on the requesting DMA channel to validate the
channel selection. Please refer DMA slave configuration section in
. for details.
int (*i2s_clk_cfg)(struct i2s_clk_config_data *config)
The function is used for run-time audio clock configuration which is responsible to generate the correct reference, bit and word clock. These clocks depend on the sample rate, sample bit and number of the channel.
struct i2s_clk_config_data
This defines the clock related configuration data according to which the “i2s_clk_cfg” programs the required I
2
S clocks.
The platform data passed to the “
SPORT” controller driver is set below “arch/arm/machstreamplug/streamplug1x.c”: static struct sport_platform_data sport_data = {
.cap = PLAY | RECORD,
.channel = 1,
.swidth = 4,
};
Registration is set according to: static struct resource sport_resources[] = {
{
.name= "sport",
.start= STREAMPLUG1X_ICM2_SPORT_BASE,
.end = STREAMPLUG1X_ICM2_SPORT_BASE + SZ_4K - 1,
.flags= IORESOURCE_MEM,
},
{
.name= "sport_irq",
.start= STREAMPLUG1X_IRQ_APP_SUBS_TS_SPORT,
.flags= IORESOURCE_IRQ,
}
};
DocID028276 Rev 1 179/220
220
Audio drivers UM1942
struct platform_device streamplug1x_sport_device = {
.name = "streamplug-sport",
.id = -1,
.dev = {
.coherent_dma_mask = ~0,
.platform_data = &sport_data,
},
.num_resources = ARRAY_SIZE(sport_resources),
.resource = sport_resources,
}; struct platform_device streamplug_pcm_device = {
.name = "streamplug-pcm",
.id = -1,
};
SPORT controller usage
There are standard utilities available in the Linux kernel for play, capture and control interfaces:
ï‚·
“aplay”, “alsaplay” and “play” to play audio files
ï‚·
“arecord” to record audio into a file
ï‚·
“alsacntl” to control interfaces features like the master volume control, L/R volume control and ADC gain
Another user space application that performs both audio OUT/IN is the GStreamer that is based also on the ALSA framework. Basic command for play an audio file is:
$ aplay *.wav
while to record audio it is possible to use the following command:
$ arecord -r 48000 -f S16_LE foo.wav
where: “-r” is for the rate and “-f “is for the format.
ALSA has its own “proc filesystem” tree (“/proc/asound”) where many useful information can be found. The most useful are:
ï‚·
“/proc/asound/card0”, card0 directory exists for the sound card the system knows about the PCM devices area available on the card, there will be directories such as “pcm0p” or “pcm0c” (the latest char is for “p = playback”, “c = capture”). They hold the PCM information for each PCM stream.
ï‚·
“/proc/asound/cards” lists the card specific files
ï‚·
“/proc/asound/pcm” lists the allocated pcm streams.
ï‚·
“/proc/asound/version” lists the version and date the ALSA subsystem module (or kernel) was built.
180/220 DocID028276 Rev 1
UM1942 Video drivers
This section describes the drivers that can be used for a video.
10.1 Video for Linux Two framework
The “Video For Linux Two” is the second version of the “Video For Linux API”, a kernel interface for the analog radio, video capture and video output drivers. This section talks only about the V4L2 interface for video capture devices. (For the details of the V4L2 interface with other devices like analog radio, please refer to www.linuxtv.org/downloads/v4l-dvbapis/).
illustrates the V4L2 subsystem.
Figure 20. V4L2 software overview
V4L2
videobuf
videobuf
-core videobufsg-dma
V4l2dev
V4l2ioclt
videodev
V4l2-device
V4l2-intdevice
(old)
V4l2subdev
(new)
Camera interface
V4L2 driver
Command interface
Resolution handling
Data format handling
(YUV/RAW/JPEG..)
Buffer handling
Exposure control
Lens control
Camera sensor module
V4L2 driver
White balance control
Effect control
Face detect
Zoom control
Strobe control
.
.
.
AM039729
Details of the V4L2 framework can be found as well in the standard Linux documentation
“Documentation/video4linux/”.
DocID028276 Rev 1 181/220
220
Video drivers UM1942
Programming a V4L2 device
Programming a V4L2 device consists of these steps:
1.
Opening the device
2. Changing device properties, selecting a video input, video standard, picture brightness, etc.
3. Negotiating a data format
4. Negotiating an input/output method
5. The actual input/output loop
6. Closing the device
In practice, most steps are optional and can be executed out of order (depending on the
V4L2 device type). To open and close V4L2 devices applications use the “open()” and
“close()” functions, respectively. Devices are programmed using the “ioctl()” function as explained in the following sections. This section provides the details of only those IOCTLs which are required to capture streaming data from a simple video capture device. An example of such standard V4L2 capture application can be seen at http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html.
For a detailed discussion of all V4L2 IOCTLs please refer to http://www.linuxtv.org/downloads/v4l-dvb-apis/.
Opening and closing the driver
A video capture device can be opened using an “open()” call from the application with the device name and mode of operation as parameters. The application can open the driver in either blocking mode or non-blocking mode as shown in the code snippet below:
/* open a video capture device in blocking mode */ fd_blocking = open("/dev/video0", O_RDWR);
/* open a video capture device in non-blocking mode */ fd_nonblocking = open ("/dev/video0", O_RDWR | O_NONBLOCK);
The application can call the “close()” function with the respective file handle to close a specific device as shown in the code snippet below:
/* closing a video capture device as per the mode */ close (fd_blocking); close (fd_nonblocking);
182/220 DocID028276 Rev 1
UM1942 Video drivers
Video buffer management
A V4L2 driver allows two different types of memory allocation modes for allocating video buffers:
ï‚·
Driver-buffer mode (“MMAP I/O” method), for the MMAP I/O method, the application requests memory from the driver by calling “VIDIOC_REQBUFS ioctl”. In this method, the maximum number of buffers is limited to “VIDEO_MAX_FRAME” (which is usually set to 32).
ï‚·
User-buffer mode (user pointer I/O method), for the user pointer method, the application needs to allocate physically contiguous memory using some other mechanism in the user space and then provide a pointer to this memory to the video capture driver.
This section only presents the MMAP I/O method (for details of user pointer I/O method please refer to standard Linux documentation “Documentation/video4linux/videobuf”).
Below are the major steps the application needs to perform for the buffer allocation using the MMAP I/O method.
Allocating video buffers using MMAP I/O method:
The “ioctl” used by the user space application to allocate video buffers is
“VIDIOC_REQBUFS”. This “ioctl” takes the following arguments:
ï‚·
Pointer to the instance of “v4l2_requestbuffers” structure
ï‚·
Buffer type (set to” V4L2_BUF_TYPE_VIDEO_CAPTURE” for capture devices)
ï‚·
Number of buffers desired, and
ï‚·
Memory type (set to “V4L2_MEMORY_MMAP”).
The following code snippet depicts how to use the “VIDIOC_REQBUFS ioctl”: struct v4l2_requestbuffers reqbuf; /* buffer request parameters */
Note:
reqbuf.count = numbuffers; reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_MMAP; ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf); if(ret) {
printf("cannot allocate memory\n");
close(fd);
return -1;
}
It is important to know that this “ioctl” can be called only once from the application.
“Numbuffers” must have a value equal or greater than 2.
DocID028276 Rev 1 183/220
220
Video drivers UM1942
Mapping the kernel space video buffer address to user space:
Mapping the kernel space video buffer to the user space can be done via “mmap”. The buffer size and physical address of the buffer can be used to get the user space address.
The following code snippet depicts how to use the “mmap”:
/* allocate buffer by VIDIOC_REQBUFS */
...
/* query the buffer using VIDIOC_QUERYBUF */
...
/* addr holds the user space address of the video buffer */ int addr; addr = mmap (NULL /* start anywhere */, buf.length,
PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */,
fd, buf.m.offset);
/* buffer.m.offset is same as that returned by VIDIOC_QUERYBUF */
Not all video capture devices use the same kind of buffers. In fact, there are (at least) three common variations:
1.
Buffers which are scattered in both the physical and (kernel) virtual address spaces.
(Almost) all user space buffers are like this, but it makes great sense to allocate kernel space buffers this way as well when it is possible. Unfortunately, it is not always possible; working with this kind of the buffer normally requires hardware which can do scatter/gather DMA operations.
2. Buffers which are physically scattered, but which are virtually contiguous; buffers allocated with “vmalloc()”, in other words. These buffers are just as hard to use for DMA operations, but they can be useful in situations where DMA is not available but virtuallycontiguous buffers are convenient.
3. Buffers which are physically contiguous. Allocation of this kind of the buffer can be unreliable on fragmented systems, but simpler DMA controllers cannot deal with anything else.
“Videobuf” can work with all three types of buffers, but the driver author must pick one at the outset and design the driver around that decision. Depending on which type of buffers is being used, the driver should include one of the following files: media/videobuf-dma-sg.h /* Physically scattered */ media/videobuf-vmalloc.h media/videobuf-dma-contig.h
/* vmalloc() buffers */
/* Physically contiguous */
184/220 DocID028276 Rev 1
UM1942 Video drivers
The driver's data structure describing a V4L2 device should include a “struct videobuf_queue” instance for the management of the buffer queue, along with a “list_head” for the queue of available buffers. There will also need to be an interrupt safe spin lock which is used to protect (at least) the queue. The following “videobuf_queue_ops” are simple callbacks to help the “videobuf” deal with the management of buffers: struct videobuf_queue_ops {
int (*buf_setup)(struct videobuf_queue *q, unsigned int *count, unsigned int *size);
int (*buf_prepare)(struct videobuf_queue *q, struct videobuf_buffer
*vb,
enum v4l2_field field);
void (*buf_queue)(struct videobuf_queue *q, struct videobuf_buffer
*vb);
void (*buf_release)(struct videobuf_queue *q, struct videobuf_buffer
*vb);
};
These callbacks must be implemented by the video capture driver (for details please refer to
“Documentation/video4linux/videobuf”).
V4L2 IOCTL handling
This “ioctl” is used to identify video capture devices compatibility with the V4L2 specification and to obtain information about individual hardware capabilities.
Query capabilities (VIDIOC_QUERYCAP)
Capabilities of a video capture device, for example, can be
“V4L2_CAP_VIDEO_CAPTURE” and “V4L2_CAP_STREAMING”. The details of this “ioctl” and the mechanisms to use are depicted in the snippet below: struct v4l2_capability capability; ret = ioctl(fd, VIDIOC_QUERYCAP, &capability); if(ret) {
printf("Cannot do QUERYCAP\n");
return -1;
} if(capability.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
printf("Capture capability is supported\n");
} if(capability.capabilities & V4L2_CAP_STREAMING) {
printf("Streaming is supported\n");
} where “VIDIOC_QUERYCAP” is the “ioctl” name.
DocID028276 Rev 1 185/220
220
Video drivers UM1942
Format enumeration (VIDIOC_ENUM_FMT)
This “ioctl” is used to enumerate the information of the format (horizontal pitch/pixel length, pixel format, etc.) that are supported by underlying the video capture device. The details of this “ioctl” and the mechanisms to use are depicted in the snippet below: struct v4l2_fmtdesc fmt; int i = 0; while(1) {
fmt.index = i;
ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt); /* ioctl name:
VIDIOC_ENUM_FMT */
if(ret) {
break;
}
printf("description = %s\n",fmt.description);
if(fmt.type == V4L2_CAP_VIDEO_CAPTURE)
printf("Video Capture type\n");
if(fmt.pixelformat == V4L2_PIX_FMT_UYVY)
printf("V4L2_PIX_FMT_UYVY\n");
i++;
}
Set format (VIDIOC_S_FMT)
This “ioctl” is used to set the format for the underlying video capture device. The driver validates the parameters sent as arguments to this ioctl call. It returns an error if parameters are not valid; otherwise, it configures these parameters. The driver calculates the bytes per line and the image size based on the hardware capabilities and the application can retrieve the same using the “VIDIOC_G_FMT” [Get format (VIDIOC_G_FMT)] ioctl. The details of this ioctl and the mechanisms to use are depicted in the snippet below: struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; fmt.fmt.pix.height = height; fmt.fmt.pix.width = width; fmt.fmt.pix.field = V4L2_FIELD_NONE; ret = ioctl(fd, VIDIOC_S_FMT, &fmt); if(ret) {
perror("VIDIOC_S_FMT\n");
close(fd);
return -1;
}
186/220 DocID028276 Rev 1
UM1942 Video drivers
Get format (VIDIOC_G_FMT)
This “ioctl” is used to get the current format from the underlying video capture device. The driver provides format parameters in the structure pointer passed as an argument. The details of this ioctl and the mechanisms to use are depicted in the snippet below: struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl(fd, VIDIOC_G_FMT, &fmt); if(ret) {
perror("VIDIOC_G_FMT\n");
close(fd);
return -1;
}
Try format (VIDIOC_TRY_FMT)
This “ioctl” is used to validate a specific format for the underlying video capture device. The capture driver does know hardware changes for this ioctl. It just checks if it can support the requested format. The driver returns an error if parameters are not valid. The details of this ioctl and the mechanisms to use are depicted in the snippet below: struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; fmt.fmt.pix.height = height; fmt.fmt.pix.width = width; fmt.fmt.pix.field = V4L2_FIELD_NONE; ret = ioctl(fd, VIDIOC_TRY_FMT, &fmt); if(ret) {
perror("VIDIOC_TRY_FMT\n");
close(fd);
return -1;
}
Query crop capabilities (VIDIOC_CROPCAP)
This “ioctl” is used to query the crop capabilities of the underlying capture device.
Applications use this to query the cropping limits, the pixel aspect of the image, and to calculate the scale factor. Details of this ioctl and mechanism to use the same are depicted in the snippet below: struct v4l2_cropcap cropcap; memset(&cropcap,0,sizeof (cropcap)); ret = ioctl(fd, VIDIOC_CROPCAP, &cropcap); if(ret) {
perror("VIDIOC_CROPCAP\n");
close(fd);
return -1;
}
DocID028276 Rev 1 187/220
220
Video drivers UM1942
Set crop (VIDIOC_S_CROP)
To change the cropping rectangle applications initialize the type and “struct v4l2_rect” substructure named “c” of a “v4l2_crop structure” and call the “VIDIOC_S_CROP” ioctl with a pointer to this structure. The driver first adjusts the requested dimensions against hardware limits, i.e.: the bounds given by the capture/output window and it rounds to the closest possible values of the horizontal and vertical offset, width and height. Secondly, the driver adjusts the image size (the opposite rectangle of the scaling process, source or target depending on the data direction) to the closest size possible while maintaining the current horizontal and vertical scaling factor. Finally the driver programs the hardware with the actual cropping and image parameters. “VIDIOC_S_CROP” is a write-only ioctl, it does not return the actual parameters. To query them applications must call “VIDIOC_G_CROP” and
“VIDIOC_G_FMT”. Details of this ioctl and mechanism to use the same are depicted in the snippet below:
/* display half of the image area starting at 0,0 */ struct v4l2_crop crop; crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c.height = image_height/2; crop.c.width = image_width/2; crop.c.top = 0; crop.c.left = 0; ret = ioctl(fd, VIDIOC_S_CROP, &crop); if(ret) { perror("VIDIOC_S_CROP\n");
close(fd);
return -1;
}
Get crop (VIDIOC_G_CROP)
This “ioctl” is used by the user space application to get the current crop rectangle bounds.
Details of this ioctl and mechanism to use the same are depicted in the snippet below: struct v4l2_crop crop; crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl(fd, VIDIOC_G_CROP, &crop); if(ret) {
perror("VIDIOC_G_CROP\n");
close(fd);
return -1;
} printf ("top = %d\n",crop.c.top); printf("left = %d\n",crop.c.left); printf ("height = %d\n",crop.c.height); printf("width = %d\n",crop.c.width);
188/220 DocID028276 Rev 1
UM1942 Video drivers
Queue a video buffer (VIDIOC_QBUF)
This “ioctl” is used by the user space application to place a video buffer in the video buffer queue. The application has to specify the buffer type (“V4L2_BUF_TYPE_VIDEO_
CAPTURE”), buffer index, and memory type (“V4L2_MEMOR”) at the time of queuing. The driver adds the buffer at the tail of the video buffer queue. Details of this ioctl and mechanism to use the same are depicted in the snippet below: struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.type = V4L2_MEMORY_MMAP; buf.index = 0; ret = ioctl(fd, VIDIOC_QBUF, &buf); if(ret) {
perror("VIDIOC_QBUF\n");
close(fd);
return -1;
}
DeQueue a video buffer (VIDIOC_DQBUF)
This “ioctl” is used by the user space application to dequeue a video buffer from the video buffer queue. The application has to specify the buffer type
(“V4L2_BUF_TYPE_VIDEO_CAPTURE”), and memory type (“V4L2_MEMORY_MMAP”) at the time of dequeuing. The driver provides the latest video buffer processed at its end.
Details of this ioctl and mechanism to use the same are depicted in the snippet below: struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.type = V4L2_MEMORY_MMAP; buf.index = 0; ret = ioctl(fd, VIDIOC_DQBUF, &buf); if(ret) {
perror("VIDIOC_DQBUF\n");
close(fd);
return -1;
}
DocID028276 Rev 1 189/220
220
Video drivers UM1942
Stream on (VIDIOC_STREAMON)
This “ioctl” is used by the user space application to start video capture functionality. If streaming is already started, this ioctl call returns an error. Details of this ioctl and mechanism to use the same are depicted in the snippet below: int ret; ret = ioctl(fd, VIDIOC_STREAMON, NULL); if(ret) {
perror("VIDIOC_STREAMON \n");
close(fd);
return -1;
}
Stream off (VIDIOC_STREAMOFF)
This “ioctl” is used by the user space application to stop video capture functionality. If streaming is not yet started, this ioctl call returns an error. Details of this ioctl and mechanism to use the same are depicted in the snippet below: int ret; ret = ioctl(fd, VIDIOC_STREAMOFF, NULL); if(ret) {
perror("VIDIOC_STREAMOFF \n");
close(fd);
return -1;
}
190/220 DocID028276 Rev 1
UM1942 Video drivers
Usually the external on-board sensor is connected to the SoC via I
2
C bus which acts as the control path whereas an 8-bit parallel interface between the sensor and SoC is used as the data transfer path. There are also some additional signals like a pixel clock, HSYNC and
VSYNC which are used to signify valid data on the data bus.
a connection.
Figure 21. SoC-Camera interface
MASTER CLK
PIX CLK
VSYNCH
HSYNCH
SoC
Sensor module
Camera interface
DATA [7:0]
I2C control interface
AM039726
For a camera connection like the one described above, Linux provides a framework called
“Video for Linux 2” (V4L2) which supports a wide variety of video capture devices. Using the
V4L2 framework a user space application can access and configure a video capture device.
However, due to the broadness of the V4L2 framework, a new framework called
“SoC-Camera” framework was devised which is a subset of the V4L2 and provides a unified
API between camera host drivers and camera sensor drivers. It implements a V4L2 interface to the user (currently only the “mmap” method is supported).
This subsystem has been written to connect drivers for system-on-chip (SoC) video capture interfaces with drivers for CMOS camera sensor chips to enable the reuse of sensor drivers with various hosts. The subsystem has been designed to support multiple camera host interfaces and multiple cameras per interface, although most applications have only one camera sensor.
For the details of the SoC-Camera framework and how user space applications use the same please refer to Linux documentation at “Documentation/video4linux/soc-camera.txt”.
DocID028276 Rev 1 191/220
220
Video drivers
depicts the SoC-Camera subsystem data/control flows:
Figure 22. SoC-Camera software overview
Request for data/image data in expected format
Android application
Android library gstreamer
Camera applications v4l2-utils libv4l2
Application space
UM1942
SoC-camera framework
Camera interface driver v4l2 framework
Sensor driver
Kernel space
192/220
Control interface
I2C
Camera interface hardware
DATA + SYNC
Sensor hardware
Resolution handling
Camera interface
Data format handling
(YUV / RAW / JPEG ..)
Buffer
handling
Exposure control
Sensor module
Lens control
White balance control
Effect control
Zoom control
.
.
.
AM039730
The STreamPlug camera is only supposed to handle one camera on its transport stream
(TS) interface.
DocID028276 Rev 1
UM1942 Video drivers
The camera interface module acts a simple video capture device when interfaced with an external image sensor.
Camera host API
A host camera driver is registered using the following function: soc_camera_host_register(struct soc_camera_host *); where the parameter may be a struct like the following: static struct soc_camera_host streamplug_soc_camera_host = {
.drv_name = STREAMPLUG_CAM_DRV_NAME,
.ops = &streamplug_soc_camera_host_ops,
};
All camera host methods are passed in a struct soc_camera_host_ops: static struct soc_camera_host_ops streamplug_soc_camera_host_ops = {
.owner= THIS_MODULE,
.add= streamplug_camera_add_device,
.remove= streamplug_camera_remove_device,
.suspend= streamplug_camera_suspend,
.resume= streamplug_camera_resume,
.set_crop= streamplug_camera_set_crop,
.get_formats= streamplug_camera_get_formats,
.put_formats= streamplug_camera_put_formats,
.set_fmt= streamplug_camera_set_fmt,
.try_fmt= streamplug_camera_try_fmt,
.init_videobuf= streamplug_camera_init_videobuf,
.reqbufs= streamplug_camera_reqbufs,
.poll= streamplug_camera_poll,
.querycap= streamplug_camera_querycap,
.set_bus_param= streamplug_camera_set_bus_param,
}; where:
ï‚·
“.add” and “.remove” methods are called when a sensor is attached to or detached from the host, apart from performing host internal tasks they shall also call sensor driver's
“.init” and “.release” methods respectively.
ï‚·
“.suspend” and “.resume” methods implement host's power management functionality and it's their responsibility to call respective sensor's methods.
ï‚·
“.try_bus_param” and “.set_bus_param” are used to negotiate physical connection parameters between the host and the sensor.
ï‚·
“.init_videobuf” is called by SoC-Camera the core when a video device is opened.
Further video-buffer management is implemented completely by the specific camera host driver. The rest of the methods are called from respective V4L2 operations.
DocID028276 Rev 1 193/220
220
Video drivers UM1942
Camera API
Sensor drivers can use “struct soc_camera_link”, typically provided by the platform and used to specify to which camera host bus the sensor is connected and provide platform
“.power” and “.reset” methods for the camera. The “soc_camera_device_register()” and
“soc_camera_device_unregister()” functions are used to add a sensor driver to or remove one from the system. The registration function takes a pointer to “struct soc_camera_device” as the only parameter. This struct can be initialized, for example, as follows:
/* link to driver operations */ icd->ops = &mt9m001_ops;
/* link to the underlying physical (e.g., i2c) device */ icd->control = &client->dev;
/* window geometry */ icd->x_min = 20; icd->y_min = 12; icd->x_current = 20; icd->y_current = 12; icd->width_min = 48; icd->width_max = 1280; icd->height_min = 32; icd->height_max = 1024; icd->y_skip_top = 1;
/* camera bus ID, typically obtained from platform data */ icd->iface = icl->bus_id;
The struct “soc_camera_ops” provides “.probe” and “.remove” methods, which are called by the SoC-Camera core, when a camera is matched against or removed from a camera host bus, “.init”, “.release”, “.suspend”, and “.resume” are called from the camera host driver as discussed above. Other members of this struct provide respective V4L2 functionality.
The “struct soc_camera_device” also links to an array of “struct soc_camera_data_format”, listing pixel formats, supported by the camera.
Camera drivers are interfaced to the SoC-Camera core and to host drivers over the V4L2subdev API, but do not return any results. Therefore all camera drivers shall reply to
“.g_fmt()” requests with their current output geometry. This is necessary to correctly configure the camera bus. The “.s_fmt()” and “.try_fmt()” drivers have to be also implemented. The sensor window and scaling factors have to be maintained by camera drivers internally. According to the V4L2 API all capture drivers must support the
“VIDIOC_CROPCAP ioctl”, hence we rely on camera drivers implementing “.cropcap()”. If the camera driver does not support cropping, it may choose to not implement “.s_crop()”, but to enable cropping support by the camera host driver at least the “.g_crop” method must be implemented.
User window geometry is kept in “.user_width” and “.user_height” fields in “struct soc_camera_device” and used by the SoC-Camera core and host drivers. The core updates these fields upon successful completion of a “.s_fmt()” call, but if these fields change elsewhere, e.g.: during “.s_crop()” processing, the host driver is responsible for updating them.
194/220 DocID028276 Rev 1
UM1942 Video drivers
10.3 Video transport stream (TS)
The video transport stream (TS) is a byte-wide parallel port that provides the I/O interface to peripheral devices. This interface is typically used to interface to external devices that either generate or input 8-bit data streams, such as MPEG encoders and decoders. The interface can be configured as an input or as an output. The interface can either be the master of the
TS clock, or it can use an externally generated clock for the bus. The TS interface is a unidirectional interface.
As a transmitter the TS interface can control the flow of data. As a receiver the TS interface has no flow control. The receiver must be prepared to receive all data with no method of slowing down the interface or recapturing missed data.
In the STreamPlug the TS has been used to transfer the data from the image sensor to the
V4L2 framework.
10.3.1 TS software overview
illustrates how the TS driver is embedded into the camera interface to transfer data from the image sensor to the video for the Linux two framework (V4L2).
Figure 23. TS software overview
V4L2 application
User space
SoC-camera framework
Camera interface driver
TS
Sensor driver
Kernel space
Image sensor
DocID028276 Rev 1
Hardware
AM039727
195/220
220
Video drivers UM1942
10.3.2 TS kernel source and configuration
The most important files containing the source code for the TS device driver are following: arch/arm/plat-streamplug/misc.c arch/arm/mach-streamplug/ipswrst_ctrl.c arch/arm/mach-streamplug/include/mach/generic.h
arch/arm/mach-streamplug/include/mach/streamplug10.h arch/arm/mach-streamplug/clock.c
arch/arm/mach-streamplug/padmux.c arch/arm/mach-streamplug/streamplug1x.c drivers/media/video/streamplug_camera.c drivers/media/video/hm1355.c include/media/hm1355.h include/linux/streamplug_ts_reg.h
The “HM1355” is an image sensor used only for a demonstration purpose.
The Linux kernel must be built with the options listed in
in order to enable the support for the V4L2, the SoC-Camera and the TS device driver.
Table 35. TS Linux kernel configuration options
Configuration Description
CONFIG_MEDIA_SUPPORT
CONFIG_VIDEO_DEV
CONFIG_VIDEO_V4L2_COMMON
CONFIG_VIDEO_MEDIA
CONFIG_VIDEO_V4L2
CONFIG_VIDEOBUF_GEN
CONFIG_VIDEOBUF_DMA_CONTIG
CONFIG_VIDEO_CAPTURE_DRIVERS
CONFIG_VIDEO_ADV_DEBUG
CONFIG_VIDEO_HELPER_CHIPS_AUTO
CONFIG_VIDEO_IR_I2C
CONFIG_SOC_CAMERA
CONFIG_SOC_CAMERA_HM1355
CONFIG_VIDEO_STREAMPLUG
CONFIG_V4L_USB_DRIVERS
CONFIG_USB_VIDEO_CLASS
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
Enable framework for media support
Enable video devices
Enable common V4L2 support
Enable video media
Enable V4L2
Enable video buffer
Enable video buffer with DMA
Enable video capture device drivers
Enable I
2
C for video devices
Enable SoC-Camera framework
Enable STreamPlug specific video support
196/220 DocID028276 Rev 1
UM1942 Video drivers
The platform data associated to the TS are in “arch/arm/mach-streamplug/streamplug1x.c”.
/* camera interface 0 device registration */ static int soc_camera_set_bus_param(struct soc_camera_link *link,
unsigned long flags)
{
return 0;
} static unsigned long soc_camera_query_bus_param(struct soc_camera_link
*link)
{
return 0;
} static void soc_camera_free_bus(struct soc_camera_link *link)
{
} static struct i2c_board_info soc_camera_i2c[] = {
{
I2C_BOARD_INFO("hm1355", 0x24),
},
}; static struct streamplug_camera_pdata camera_pdata = {
.flags= HM1355_FLAG_VFLIP | HM1355_FLAG_HFLIP | \ HM1355_FLAG_8BIT,
.mclk_10khz = HM1355_MCLK_12MHZ,
.pclko_10khz = HM1355_PCLKO_18MHZ
}; static struct soc_camera_link iclink[] = {
{
.bus_id= 0, /* Must match with the camera ID */
.board_info= &soc_camera_i2c[0],
.i2c_adapter_id= 0,
.query_bus_param= soc_camera_query_bus_param,
.set_bus_param= soc_camera_set_bus_param,
.free_bus= soc_camera_free_bus,
.module_name= "hm1355",
.priv= &camera_pdata,
},
}; static struct platform_device soc_camera[] = {
DocID028276 Rev 1 197/220
220
Video drivers
{
.name= "soc-camera-pdrv",
.id = 0,
.dev= {
.platform_data = &iclink[0],
},
},
}; static struct resource streamplug_camera_resources[] = {
{
.start = STREAMPLUG1X_ICM2_TS_BASE,
.end = STREAMPLUG1X_ICM2_TS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name= "ts_irq",
.start= STREAMPLUG1X_IRQ_APP_SUBS_TS_SPORT,
.flags= IORESOURCE_IRQ,
}
};
/* camera interface 0 device registeration */ struct platform_device streamplug1x_ts_device = {
.name = "streamplug-ts",
.id = 0,
.dev = {
.coherent_dma_mask = ~0,
.platform_data = &camera_pdata,
},
.num_resources = ARRAY_SIZE(streamplug_camera_resources),
.resource = streamplug_camera_resources,
};
UM1942
198/220 DocID028276 Rev 1
UM1942 Video drivers
The TS device driver can be tested using a user space application like GStreamer to capture data from, for example, the image capture sensor peripheral. In Linux, such type of peripherals are accessed through the SoC-Camera framework. As the SoC-Camera framework is a subset of the V4L2 which provides a unified API between camera host drivers and camera sensor drivers, applications that are written using standard the V4L2
APIs and IOCTLs can directly work with the drivers written in the SoC-Camera framework, with the only limitation being that only the MMAP I/O method can be used. For details of the
V4L2 framework and how to write user space applications to access video capture devices using the V4L2, please refer to previous sections.
To enable the TS support at run-time it is necessary to configure the Linux kernel command line using one of the options listed in
.
Once the Linux kernel has finished the startup phase, some parameters of the V4L2 framework can be configured using the “v4l2-dbg” utilities provided with the root filesystem.
Then the GStreamer tool can be found either in the auxiliary filesystem or in an external one like a USB key or an SATA disk.
The following are the steps necessary to capture a stream of images from the image sensor:
1.
Mount the USB device (“mount /dev/sdX /mnt”).
2. Export the following environment variables: export PATH=:$PATH:/mnt/<gstreamer folder>/usr/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/<gstreamer folder>/usr/lib export GST_PLUGIN_PATH=/mnt/<gstreamer folder>/usr/lib:/mnt/<gstreamer folder>/usr/lib/ ?' gstreamer-0.10
export GST_PLUGIN_SCANNER=/mnt/<gstreamer folder>/usr/libexec/gstreamer-
0.10/gst-plugin- ?' scanner
3. [Optional] mount the SATA device if the data have to be stored on the SATA disk.
4. Configure the image sensor. These values set the minimum delay between 2 successive frames according to the target device: v4l2-dbg --set-register=16 0x01 v4l2-dbg --set-register=17 0x4F
Such values must be chosen depending on the peripheral used to save the image data stream.
Table 36. Image sensor delay parameter
Frame size
VGA (648 x 488)
FULL FRAME (1022 x 728)
FULL FRAME (1022 x 808)
FULL FRAME (1022 x 1032)
DDR
0x014F
0x014F
0x014F
0x014F
USB
0x08FF
0x18FF
0x18FF
0x18FF
SATA
0x18FF
0x18FF
0x18FF
0x28FF
DocID028276 Rev 1 199/220
220
Video drivers UM1942
Run the GStreamer application in the background mode using one of the following command:
Data stream stored on DDR: gst-launch v4l2src device=/dev/video0 num-buffers=100 ! 'video/x-rawyuv,width=648,height=488, framerate=20/1' ! filesink location=/tmp/<FileName>.raw &
Data stream stored on USB device: gst-launch v4l2src device=/dev/video0 num-buffers=100 ! 'video/x-rawyuv,width=648,height=488, framerate=20/1' ! filesink location=/mnt/<FileName>.raw &
Data stream stored on SATA: gst-launch v4l2src device=/dev/video0 num-buffers=100 ! 'video/x-rawyuv,width=648,height=488, framerate=20/1' ! filesink location=/sata/<FileName>.raw &
200/220 DocID028276 Rev 1
UM1942 Virtualized devices
The “Kernel Support Package” (KSP) is a software layer which allows the virtualized Linux kernel to access through an SoC interface the hardware components (timers, interrupts, etc.) and it is active only in the full configuration.
The KSP is composed by five interface classes:
ï‚·
Boot interface which provides the entry point of a boot image, performs CPU and platform initializations before starting the kernel.
ï‚·
System interface which provides generic functionalities for cache management, idle handling and so on.
ï‚·
Interrupt controller which provides interrupt decoding and management using the platform interrupt controller. The KSP is required to decode incoming interrupts, manage masking and unmasking of interrupts, and maintain interrupt registration data on behalf of the kernel.
ï‚·
Device drivers which provided device drivers needed by the kernel (serial console, timer, VIC, etc.)
ï‚·
Platform extensions.
Access to lower hardware configuration, or the shared information between different OSs is guaranteed by some APIs, provided by the SoC interface.
The KSP agent API is an object that mediates access to the KSP procedure call “syscall”.
It provides:
ï‚·
A unique user identifier to enable secure identification of the caller
ï‚·
A virtual interrupt line which supports signaling events from the SoC interface to the
Linux kernel interface
ï‚·
Support for reading a memory space of Linux kernel shared with the SoC interface.
The KSP agent interface is primarily intended for exporting services which otherwise would be difficult or impossible to implement in a guest OS.
DocID028276 Rev 1 201/220
220
Virtualized devices UM1942
The following paragraphs describe a list of device drivers “virtualized” that take advantage of the KSP agent API interface to access to the hardware and/or to share resources with other embedded systems.
ï‚·
The KSP interface controller is a device driver that handles the accesses of the various read/write to lower layers and/or the signaling coming from abstract layers to be dispatched to the target device.
ï‚·
The “Misc” manager is not a properly device driver. In order to configure the systems during the machine initialization phase, the accesses to basic miscellaneous registers are performed by calling read/write APIs provided by the KSP interface controller.
ï‚·
Virtual log (“Vlog”) is a virtual console to the RTOS.
ï‚·
Virtual Flash controllers are the device drivers that perform the SMI and FSMC NAND
Flash controllers, were updated in order to support a mechanism of accesses to the memories shared with the RTOS, regulated by KSP interface call procedures.
ï‚·
Virtual Ethernet (“VEth”), a device driver that exposes the HPAV modem to the Linux kernel as an Ethernet device, in order to integrate it in the Linux standard network stack.
ï‚·
“Image Validate” device (“imageval”) is a device driver, it is used to notify to the RTOS that the image is valid or not during the boot sequence. It is possible invalidate the firmware image in each time.
11.1 KSP interface controller
In order to support the KSP agent at the Linux kernel, a device driver was implemented at machine levels. It handles the signaling coming from the KSP interface and provides some primitives used by the virtualized drivers to access to lower layers than the Linux kernel.
11.1.1 KSP software overview
The software implementing the KSP interface controller is in: arch/arm/mach-streamplug/streamplug_ksp_agent.c.
In order to register the KSP interface to the STreamPlug machine: arch/arm/mach-streamplug/streamplu1x.c
the streamplug_ksp_intf_registration is called during machine initialization.
During the probe sequence, the KSP interface controller tries to:
ï‚·
Allocate space for its own data structures: struct streamplug_ksp_dev {
struct platform_device *pdev;
/* spin lock */
spinlock_t lock;
}; kspdev = kzalloc(sizeof(*kspdev), GFP_KERNEL);
202/220 DocID028276 Rev 1
UM1942 Virtualized devices
ï‚·
Recover the KSP agent unique identifier from platform data, provided by the KSP interface at start-up. The KSP agent is the key to access to the lower KSP interface.
ksp_agent = (struct okl4_tag_ksp_agent *)pdev->dev.platform_data;
ï‚·
Register the virtual interrupt line assigned by the KSP interface, in order to handle the signaling coming from below err = request_irq(ksp_agent->virq, streamplug_ksp_agent_int_handler, 0, pdev->name, kspdev) ; where the “streamplug_ksp_agent_int_handler” is the IRQ handler specific for the KSP agent. When interrupt arises, the handler will have to ask to the SoC interface for the payload that includes the information of signaling in order to dispatch it to the correspondent supported virtualized device drivers.
static irqreturn_t streamplug_ksp_agent_int_handler(int irq, void
*dev_id)
{
struct streamplug_ksp_dev *dev = dev_id;
okl4_channel_secondary_status_t payload = 0;
unsigned int i;
unsigned long flags;
spin_lock_irqsave(&dev->lock, flags);
A Linux kernel panic error is generated, during the startup sequence, in case of misalignment of the version number between the KSP interface and the RTOS.
payload = streamplug_ksp_get_irq_payload(); printk(KERN_DEBUG "%s: payload %x", func , (u32)payload); if (!payload){
printk(KERN_DEBUG "%s: Failed collect irq action ret=%x", func ,
(int)payload);
} else {
if(payload & (1 << (STREAMPLUG1X_VIRQ_SHUTDOWN -
STREAMPLUG1X_VIRQ_BASE)))
{
printk(KERN_WARNING "The system is going down NOW!");
/* Send signals to every process _except_ pid 1 */
sys_kill(-1, SIGTERM);
printk(KERN_WARNING "Sent SIG%s to all processes", "TERM");
sys_kill(-1, SIGKILL);
printk(KERN_WARNING "Sent SIG%s to all processes", "KILL");
// power off
Kernel_power_off();
}
for (i=0; i<STREAMPLUG1X_NUM_DEV_VIRQS; i++) {
if (payload & (1 << i)){
DocID028276 Rev 1 203/220
220
Virtualized devices UM1942
printk(KERN_DEBUG "%s: irq bit %d, virq %d", func , i,
(int)( ?'
STREAMPLUG1X_VIRQ_BASE + i));
generic_handle_irq((STREAMPLUG1X_VIRQ_BASE + i));
}
}
}
spin_unlock_irqrestore(&dev->lock, flags);
return IRQ_HANDLED;
} where “STREAMPLUG1X_VIRQ_BASE” is the base of the virtual interrupt lines list assigned statically to each virtualized device driver (Vlog, Virtual Flash Controller, VEth).
The definitions are in the “arch/arm/mach-streamplug/include/mach/irqs.h” and their assignment in the platform data structures of virtualised device drivers.
Below is a list of functions implemented in order to send commands to the KSP interface.
Each command is sent to lower layers using the API provided by the KSP agent
“_okl4_sys_ksp_procedure_call”. The list of commands supported are in the “arch/arm/macstreamplug/include/mach/streamplug_ksp_agent.h”.
ï‚·
“streamplug_ksp_get_irq_payload” performs the “GET_IRQ_PAYLOAD” in order to know which interrupt lines have to be dispatched at the kernel layer. Used by the
KSP interface controller driver.
ï‚·
“streamplug_ksp_vlog_open” performs the “VLOG_OPEN” command in order to notify to the RTOS the open of the Vlog Read/Write procedure. It is used by the Vlog device driver.
ï‚·
“streamplug_ksp_vlog_close” performs the “VLOG_CLOSE” command in order to notify to the RTOS the termination of Read/Write procedures. It is used by the Vlog device driver.
ï‚·
“streamplug_ksp_vlog_read” performs the “VLOG READ” command in order to read a character from the remote buffer. It is used by the VLog device driver.
ï‚·
“streamplug_ksp_vlog_write” performs the “VLOG WRITE” command in order to write a character into the remote buffer. It is used by the VLog device driver.
ï‚·
“streamplug_ksp_misc_read_reg” performs the “MISC_REG_READ” command in order to obtain the value of a certain “Misc” register of which offset is passed to the
KSP procedure call. It is used by “Misc”.
ï‚·
“streamplug_ksp_misc_read_reg” performs the “MISC_REG_WRITE” command in order to set a “Misc” register of which offset is passed to the KSP procedure call. It is used by “Misc”.
ï‚·
“streamplug_ksp_flash_mutex_handler” performs the request/release of “Mutex” by
Linux kernel in order to access to Flash memories when they are shared with remote embedded systems. Used by Flash controller drivers.
ï‚·
“streamplug_ksp_veth_generic_cmd” - it's a generic function that performs all the commands towards the KSP interface for the Virtual Ethernet device driver.
204/220 DocID028276 Rev 1
UM1942 Virtualized devices
lists the kernel configuration options associated with the KSP interface controller.
Table 37. KSP agent controller configurations
Configuration Description
CONFIG_KSP_AGENT_ENABLED It enables support of the KSP interface controller
The platform data associated to the KSP interface controller are in “arch/arm/machstreamplug/streamplug1x.c”.
struct platform_device streamplug1x_ksp_agent_device = {
.name = "okl4-ksp-agent",
.id = -1,
.dev = {
.platform_data = &okl4_ksp_agent,
},
}; where “okl4_ksp_agent” is a global structure that provides the capabilities of the KSP agent associated to the Linux kernel.
According to the peripheral configuration specified in the Linux kernel command line a set of miscellaneous registers have to be accessed during the startup procedure. The access is not performed directly into the miscellaneous register memory space, but through the KSP agent interface.
Misc software overview
During the machine initialization phase every time an access to a miscellaneous register is required, the correspondent function is called. The functions are provided by the KSP interface controller into “arch/arm/mach-streamplug/streamplug_ksp_agent.c”. For writing procedures use: void streamplug_ksp_misc_write_reg(unsigned int value, unsigned int *reg) and for reading procedures use: unsigned int streamplug_ksp_misc_read_reg(unsigned int *reg).
The “Virtual log” (VLog) is a device driver that virtualizes the UART interface of the RTOS.
DocID028276 Rev 1 205/220
220
Virtualized devices UM1942
11.3.1 Virtual log software overview
VLog is a simple char driver, implemented below the “drivers/char/streamplug_vlog.c” file.
During the probe phase, it will have to register two different IRQ handlers, read and write, each of them is associated to one interrupt line statically assigned by its own platform data.
Both of them will be notified to the VLog device driver by the KSP agent that will dispatch the interrupt request to the correspondent handler according to the payload it recovers from the lower KSP module.
READ
The procedure with which a user space application can ask to the
Vlog driver to read is: ssize_t dev_read(struct file *fil, char *buff, size_t len, loff_t *off)
{
int size = 0;
int i = 0;
int left = 0;
pr_debug("%s enter\n",__func__);
pr_debug("Read flag: %x \n", read_flag);
spin_lock(&sdev->lock);
if(read_flag)
{
read_flag = 0;
spin_unlock(&sdev->lock);
size = streamplug_ksp_vlog_read(buff, len, &left);
pr_debug("bytes left %d \n", left);
// if there are bytes into the buffer, set the flag again
if(left)
read_flag = 1;
}
else
spin_unlock(&sdev->lock);
pr_debug("%s exit\n",__func__);
return (ssize_t)size;
}
An interrupt for the reading procedure arises when at least one character is available in the buffer of the RTOS.
206/220 DocID028276 Rev 1
UM1942 Virtualized devices
The VLog driver may access to the buffer where data are stored until this interrupt is detected. Each read request coming from the user space is rejected with 0 bytes returned.
After its detection, at the first request from the user space, the VLog driver recovers char by char from the buffer and forwards them to the user space application that will display them in
“stdout”. The buffer is handled by the soc module of the KSP interface, so the Vlog driver will have to call the “streamplug_ksp_vlog_read” provided by the KSP agent controller, in order to access it.
The KSP interface for the VLOG READ byte command will return the number of characters still available within the remote buffer. The procedure will continue until no data will be available within the buffer and VLOG driver will send a 0 to the user space.
WRITE
The procedure with which a user space application can ask to the
Vlog driver to write is: ssize_t dev_write(struct file *fil, const char *buff, size_t len, loff_t
*off)
{
ssize_t ret = 0;
int size = (unsigned int)len;
pr_debug("%s enter\n",__func__);
if(write_flag)
{
// there isn't enough space, stop to write
if(!streamplug_ksp_vlog_write(buff,size))
write_flag = 0;
}
pr_debug("write_flag %x", write_flag);
pr_debug("%s exit\n",__func__);
return len;
}
Every time the VLog driver receives a write request from user space applications, it will forward the character passed from “stdin” to the remote buffer calling the procedure provided by the KSP interface controller “streamplug_ksp_vlog_write”. The KSP interface for the VLOG WRITE byte command will return the number of bytes the remote buffer may still accept. When the buffer is full, no more data have to be sent by the
VLog driver that will have to wait for arising the interrupt for “Write” procedure dispatched by the KSP interface controller. In that case the
VLog driver may continue to send data to the remote buffer.
DocID028276 Rev 1 207/220
220
Virtualized devices UM1942
11.3.2 Virtual kernel source and configuration
lists the kernel configuration options associated with the KSP interface controller.
Table 38. Virtual log configurations
Configuration Description
CONFIG_STREAMPLUG_VLOG It enables the virtual log driver support
11.3.3 Virtual platform configuration
The platform data associated to the KSP interface controller are in
“arch/arm/streamplug1x.c”.
/* vlog device registration */ static struct resource vlog_resources[] = {
{
.start = STREAMPLUG1X_VIRQ_VLOG_TO_RTOS,
.flags = IORESOURCE_IRQ,
}, {
.start = STREAMPLUG1X_VIRQ_VLOG_FROM_RTOS,
.flags = IORESOURCE_IRQ,
}
}; struct platform_device streamplug_vlog_device = {
.name = "streamplug-vlog",
.id = 0,
.num_resources = ARRAY_SIZE(vlog_resources),
.resource = vlog_resources,
}; struct platform_device streamplug_vlog_device = {
.name = "streamplug-vlog",
.id = 0,
.num_resources = ARRAY_SIZE(vlog_resources),
.resource = vlog_resources,
};
208/220 DocID028276 Rev 1
UM1942 Virtualized devices
11.3.4 Virtual usage
The steps to test the VLog device drivers are:
1.
Verify if the device is correctly registered:
$ cat /proc/devices | grep vlog
2. Create the correspondent node:
$ mknod /dev/vlog c 'cat /proc/devices | grep vlog | awk '{print
$1}'' 1
3. To run use the utilities provided by the Linux kernel, and wait for characters in “stdin” in the background:
$ tail -f /dev/vlog &
4. Send characters into “stdout”:
$ echo "<option>" > /dev/vlog
In addition, a small application named “stpconsole” is available in the example set and in the default root filesystem to expose the RTOS console in Linux. This application permits the access to the RTOS interface when the UARTs are not available because needed by the application.
11.4 SMI/FSMC NAND memory shared access
The Flash controllers device drivers (SMI and FSMC NAND) have been modified in order to support the shared access by two different software components such, for example, the
Linux kernel and the RTOS.
The Flash controllers allow the shared access through the use of a Mutex mechanism. This means that whenever a component accesses the Flash, it first has to obtain the corresponding Mutex. If this is not possible then it has to wait until the Mutex is freed from the other component.
The Flash controller has a virtual interrupt line assigned to, in order to be notified through the KSP interface controller that one of the components need to access to the Flash.
In the STreamPlug the Flash controllers have been modified to allow the shared access to the corresponding Flashes by the Linux kernel and the RTOS. However, only the Linux kernel Flash controller get notified of the access request by the RTOS.
11.4.1 SMI/FSMC NAND software overview
In order to be notified by the
KSP agent interface driver to locked/unlocked the Flash memory by remote systems, the SMI/FSMC NAND Flash controllers have to register their own virtual interrupt lines assigned statically and stored into platform data. For both controllers, the two IRQ handlers associated will have to handle the state of memory
(reserved to Linux kernel or RTOS), and the state of the driver when interrupt is detected.
The IRQs handling is the same for both SMI and FSMC NAND Flash controllers.
Flash memory status
As default, the Flash memory is reserved to the Linux kernel system. When the request interrupt arrives, the state of memory changes from reserved to RTOS. When the release interrupt occurs, the state comes back to reserved to Linux. Different actions are taken according to the current state of the driver such as: if there are no accesses ongoing, the state of the controller is IDLE and in case of a request from the ROTS state the Mutex is
DocID028276 Rev 1 209/220
220
Virtualized devices UM1942
immediately released, while in case of release indication the procedure to acquire the Mutex is started. If there is an access in memory ongoing, nothing is performed until the procedure ends, but internal flags are updated to force Flash memory area status change and to force the Mutex release of the request.
If a Mutex request or Mutex release is already ongoing, nothing is performed until the procedure ends, but internal flags are updated to force Flash memory area status change and to force the Mutex release of the request.
Mutex request/release
When the Flash memory status is reserved to the Linux kernel, no accesses to the KSP interface are performed in order to acquire/release the Mutex. This is done by calling the
“streamplug_ksp_flash_mutex_handler” with the appropriate command provided by the
KSP interface controller.
In case of Flash memory status is RTOS, the Flash controller has always to wait for a release indication and acquire the Mutex before the access to the memory.
11.4.2 SMI/FSMC NAND kernel source and configuration
The support of the virtual interrupt handler by the SMI/FSMC NAND is subordinated by enabling the “CONFIG_KSP_AGENT_ENABLED” option.
11.4.3 SMI/FSMC NAND platform configuration
The new interrupt lines were added and statically assigned to the resources of both SMI and
FSMC NAND.
11.5 HomePlug AV (HPAV) driver
The HomePlug AV (HPAV) driver is a virtualized device driver that exposes the HPAV modem to the Linux kernel as an Ethernet device, in order to integrate it in the Linux
standard network stack, as illustrated in
.
210/220 DocID028276 Rev 1
UM1942 Virtualized devices
FTP
Figure 24. HPAV stack software overview
HTTP SSH
User space
Socket interface
UDP - TCP/IP stack
NETIF interface
HPAV virtual device driver
Raw L2
Kernel space
HPAV MAC
RTOS
AM039814
11.5.1 HPAV software overview
The structure of the HomePlug AV device driver reflects the generic Ethernet device driver structure. Linux supports some standard “ioctl” commands to configure network devices at the user space level. In the future more “ioctl” commands will be provided to extend existing features.
The main difference is the new interaction with the KSP interface at the kernel space level.
The KSP interface interacts with the HPAV device driver via:
ï‚·
Interrupts
ï‚·
Commands
In both cases, there's a strict interaction with the KSP agent interface controller that provides the capabilities to send commands and the dispatcher to notify the signaling via interrupt routine of messages receptions.
During the probe phase, all the platform data of KSP info are recovered in order to register the interrupt to the KSP interface and acquire a shared memory buffer for memory operations. As for the other virtualized device driver, the HPAV has to register its own virtual interrupt, the line of which is passed through platform data by the machine definition.
DocID028276 Rev 1 211/220
220
Virtualized devices UM1942
This is performed during the device open function shown below:
...
set_irq_chip_and_handler_name(dev->irq, &stmmac_ksp_chip, stmmacvirt_interrupt, "vstmmac"); set_irq_flags(dev->irq, (IRQF_VALID|IRQF_SHARED)); set_irq_chip_data(dev->irq, dev);
...
where the “stmmacvirt_interrupt” is the virtual IRQ handler: static irqreturn_t stmmacvirt_interrupt(int irq, struct irq_desc *desc)
{
struct net_device *dev = desc->chip_data;
struct stmmac_virt_priv *priv = netdev_priv(dev);
#if defined(STMMAC_VIRT_XMIT_DEBUG) || defined(STMMAC_VIRT_RX_DEBUG)
printk(KERN_DEBUG "%s: interrupt occurred virq %d, desc %x", __func__, irq, desc);
#endif
if (unlikely(!dev)) {
pr_err("%s: invalid dev pointer\n", __func__);
return IRQ_NONE;
}
stmmacvirt_dma_interrupt(priv);
return IRQ_HANDLED;
}
11.5.2 HPAV kernel source and configuration
lists the kernel configuration options associated with the KSP interface controller.
Table 39. Virtual Ethernet configurations
Configuration Description
CONFIG_STMMAC_VIRT_ETH It enables the support of HomePlug AV driver
11.5.3 HPAV platform configuration
The platform data associated to HPAV are in “arch/arm/mach-streamplug/streamplug1x.c”.
static struct resource virteth_resources[] = {
{
.start = STREAMPLUG1X_VIRQ_ETH,
.flags = IORESOURCE_IRQ,
},
};
212/220 DocID028276 Rev 1
UM1942 Virtualized devices
/* virtual phy device */ static struct plat_stmmacvirtphy_data virtphy_private_data = {
.bus_id = 0,
.phy_addr = -1,
.phy_mask = 0,
.interface = PHY_INTERFACE_MODE_MII,
}; struct platform_device streamplug1x_virtphy_device = {
.name = "stmmacvirtphy",
.id = -1,
.dev.platform_data = &virtphy_private_data,
};
/* Virtual ethernet device registration */ struct plat_stmmacenet_data virtether_platform_data = {
.bus_id = 0,
.has_revmii = 0,
.has_gmac = 0,
.enh_desc = 0,
.pbl = 8,
.dev_addr = "01:80:e1:26:0a:5b",
}; static u64 virteth_dma_mask = ~(u32) 0; struct platform_device streamplug1x_virteth_device = {
.name = "stmmacvirteth",
.id = -1,
.num_resources = ARRAY_SIZE(virteth_resources),
.resource = virteth_resources,
.dev = {
.platform_data = &virtether_platform_data,
.dma_mask = &virteth_dma_mask,
.coherent_dma_mask = ~0,
},
};
11.6 Image validate device driver
Linux notifies to RTOS that the image is valid or not during the boot sequence and specifies the kernel version. It is also possible to set a user application version. Both versions are
16 bytes long.
DocID028276 Rev 1 213/220
220
Virtualized devices UM1942
11.6.1 Image validate device driver software overview
Image validity is a simple char driver, implemented below the
”drivers/char/streamplug_image_validity.c” file.
WRITE
During the write operation a KSP agent is sent to set the user version.
The procedure with which a user space application can ask to the image validity driver to write is: ssize_t dev_iv_write(struct file *fil, const char *buff, size_t len, loff_t
*off)
{
if (!buff)
return 0;
if (len > USER_IMAGE_VER_SIZE)
len = USER_IMAGE_VER_SIZE;
memcpy(idev->version, buff, len);
if (!streamplug_ksp_set_image_version_handler(idev->version, len))
return len;
else
return 0;
}
READ
The procedure with which a user space application can ask to the image validity driver to read is: ssize_t dev_iv_read(struct file *fil, char *buff, size_t len, loff_t *off)
{
if (len > USER_IMAGE_VER_SIZE)
len = USER_IMAGE_VER_SIZE;
memcpy(buff, idev->version, len);
return (ssize_t)len;
}
This operation permits to know the value of the image version and it is used to check the result of write procedure.
214/220 DocID028276 Rev 1
UM1942 Virtualized devices
IOCTL
This function is used to perform two operations: “SET_IMAGE_STATUS” and
“GET_IMAGE_STATUS”.
During the “SET_IMAGE_STATUS” operation a KSP agent is sent to notify to RTOS the validity of the image (0 and 1 are the only values allowed, 0 for an invalid image and 1 for a valid one). The image value is invalid by default and if the driver receives a new request to update a valid value, it issues the KSP, but if the value is already set valid, the driver doesn't issue the KSP agent. The “SET_IMAGE_STATUS” operation is a call at least of the Linux initialization process (at the end of “/etc/inittab”).
The “GET_IMAGE_STATUS” operation permits to know the value of image validity and it is used to check the result of the “SET_IMAGE_STATUS” operation.
static long dev_iv_ioctl(struct file* fil, unsigned int cmd, unsigned long arg)
{
long ret=0;
u32 status = arg;
switch (cmd) {
case SET_IMAGE_STATUS:
if ((status == IMAGE_GOOD) || (status == IMAGE_NO_GOOD))
{
if (idev->value != status)
{
printk(KERN_DEBUG "%s value = %u\n",__func__, status);
idev->value = status;
ret = streamplug_ksp_set_image_validity_handler(status);
}
}
else
ret = -EINVAL;
break;
case GET_IMAGE_STATUS:
printk(KERN_DEBUG "%s value is %d\n",__func__, idev->value);
ret = (long) idev->value;
break;
default:
ret = -EINVAL;
}
return ret;
}
DocID028276 Rev 1 215/220
220
Virtualized devices UM1942
11.6.2 Image validate device driver kernel source and configuration
lists the kernel configuration options associated with the KSP interface controller.
Table 40. Image validity configuration
Configuration Description
CONFIG_STREAMPLUG_IMAGE_VALIDITY
CONFIG_EARLY_SET_IMAGE_GOOD
It enables the image validity driver support
It enables the early set image good
When the “CONFIG_EARLY_SET_IMAGE_GOOD” is enabled the drivers are compatible with the old file systems. The kernel calls the KSP agent to notify to RTOS that the image is valid. The image value is good by default and if the driver receives some new request returns always success.
11.6.3 Image validate device driver platform configuration
The platform data associated to the KSP interface controller are in “arch/arm/machstreamplug/streamplug1x.c”.
/* image validity device registration */ struct platform_device streamplug_iv_device = {
.name = "streamplug-image-validity",
.id = 0,
}
11.6.4 Image validate device driver usage
The steps to test the image validity device drivers are:
1.
Verify if the device is correctly registered:
$ cat /proc/devices | grep imageval
2. Create the correspondent node, if it does not exist:
$ mknod /dev/imageval c 'cat /proc/devices | grep imageval | awk
'{print $1}'' 1
In addition, a small application named “stpimagevalidate” is available in the example set and in the default root file system to be used after the Linux initialization or to invalidate the firmware image. The option of this application are:
ï‚· Usage: stpimagevalidate [options]
ï‚· “-i “ sets the image as invalid
ï‚· “-v “sets the image as valid
ï‚· “-n <version>” sets the image version
ï‚· “-s” shows image information
ï‚· “-h” displays this usage information.
216/220 DocID028276 Rev 1
UM1942
Appendix A
Acronyms
Acronyms
Acronym
IPs
JFFS2
JPEG
JTAG
KSP
MFIO
MTD
NFS
OOB
DMA
DWC
EEPROM
EP
FS
FSMC
FW
GPIO
HID
I
2
C
I
2
S
IP
AMBA
ADC
ARM
AVB
BSP
C3
CAN
CPU
DDR
DHCP
contains a list of acronyms used within the document.
Table 41. List of acronyms
Definition
Advanced microcontroller bus architecture
Analog-to-digital converter
Advanced RISC machine
Audio Video Bridging
Board support package
Channel controller coprocessor
Controller area network
Central processing unit
Double data rate SDRAM
Dynamic host configuration protocol
Direct memory access
Designware cores
Electrically erasable programmable read only memory
PCIe endpoint device
File system
Flexible static memory controller
Firmware
General purpose input/output signal
Human interface device
Inter-integrated circuit
Inter-IC sound
Internet protocol
Intellectual Properties
Journaling Flash file system version 2
Joint photographic experts group
Joint test action group
Kernel support packages provided by OKL Microvisor
Multifunction input/output signal
Memory technology device
Network file system
Out-of-band
DocID028276 Rev 1 217/220
220
Acronyms
Acronym
SDK
SMI
SoC
SOC
SPI
SPORT
TAG
UART
USB
VIC
PC
PCIe
RevMII
RC
RTC
SATA
SCP
SDRAM
Table 41. List of acronyms (continued)
Definition
Personal computer
Peripheral component interconnect express
Reverse media independent interface
PCI-e root complex device
Real-time clock
Serial advanced technology attachment
Secure copy Linux command
Synchronous dynamic random access memory
OKL4 SDK
Serial Management Interface
System-on-chip
Definition of board the chip is mounted on
Serial Peripheral Interface bus
Serial port
Tagged List
Universal asynchronous receiver/transmitter
Universal serial bus
Vectored interrupt controller
UM1942
218/220 DocID028276 Rev 1
UM1942
Revision history
Date
26-Nov-2015
Table 42. Document revision history
Revision Changes
1 Initial release.
Revision history
DocID028276 Rev 1 219/220
220
UM1942
IMPORTANT NOTICE – PLEASE READ CAREFULLY
STMicroelectronics NV and its subsidiaries (“ST”) reserve the right to make changes, corrections, enhancements, modifications, and improvements to ST products and/or to this document at any time without notice. Purchasers should obtain the latest relevant information on
ST products before placing orders. ST products are sold pursuant to ST’s terms and conditions of sale in place at the time of order acknowledgement.
Purchasers are solely responsible for the choice, selection, and use of ST products and ST assumes no liability for application assistance or the design of Purchasers’ products.
No license, express or implied, to any intellectual property right is granted by ST herein.
Resale of ST products with provisions different from the information set forth herein shall void any warranty granted by ST for such product.
ST and the ST logo are trademarks of ST. All other product or service names are the property of their respective owners.
Information in this document supersedes and replaces information previously supplied in any prior versions of this document.
© 2015 STMicroelectronics – All rights reserved
220/220 DocID028276 Rev 1
advertisement
Key Features
- Runs on the STreamPlug ST2100 SoC, a highly integrated system-on-a-chip (SoC) device.
- Provides a comprehensive set of features and capabilities that make it ideal for a wide range of applications, including home automation, industrial control, and multimedia streaming.
- Supports the HomePlug AV standard, which allows for high-speed data transmission over existing power lines.
- Includes a powerful ARM-based core and a wide range of peripherals, making it a versatile and capable platform for a variety of embedded applications.
- Is open source and customizable, allowing users to tailor the operating system to their specific needs.
Frequently Answers and Questions
What is the STreamPlug ST2100?
What is ST Linux?
What are the key features of ST Linux?
What are some of the applications for ST Linux?
Related manuals
advertisement
Table of contents
- 10 STreamPlug full software architecture
- 11 Linux OS
- 11 Linux support package (LSP)
- 13 Platform
- 13 Platform description
- 13 Platform software overview
- 14 Platform kernel source and configuration
- 15 Platform configuration
- 15 Board support
- 16 Board registration
- 16 Board compilation support
- 18 Pad multiplexing support
- 19 Pad software overview
- 21 Pad kernel source and configuration
- 22 Pad usage
- 24 Clock framework
- 24 Clock framework software overview
- 26 Clock framework kernel source and configuration
- 26 Clock framework internals
- 29 Clock framework usage
- 30 Real-time clocks (RTC)
- 31 RTC software overview
- 31 RTC kernel source and configuration
- 32 RTC platform configuration
- 32 RTC usage
- 34 Communication drivers
- 34 Gigabit media access controller (GMAC) - Ethernet
- 34 GMAC software overview
- 36 GMAC kernel source and configuration
- 37 GMAC platform configuration
- 37 GMAC usage
- 38 Universal serial bus (USB) host
- 39 USB host kernel source and configuration
- 41 USB host platform configuration
- 42 USB host usage
- 45 Universal serial bus (USB) device
- 46 USB device software overview
- 47 USB device kernel source and configuration
- 47 USB device platform configuration
- 49 USB device usage
- 53 USB platform configuration
- 54 USB platform usage
- 59 C controller
- 59 C controller hardware overview
- 60 software overview
- 61 C controller kernel source and configuration
- 61 platform configuration
- 62 usage
- 67 Serial peripheral interface (SPI) controller
- 68 SPI software overview
- 72 SPI kernel source and configuration
- 72 SPI platform configuration
- 74 SPI usage
- 74 Linux TTY framework
- 74 Linux TTY framework software overview
- 74 kernel source
- 74 Linux TTY framework usage
- 76 Universal asynchronous receiver/transmitter (UART)
- 77 UART software overview
- 78 UART kernel source and configuration
- 78 UART platform configuration
- 79 UART usage
- 79 Control area network (CAN)
- 79 CAN software overview
- 80 CAN kernel source and configuration
- 81 CAN platform configuration
- 82 CAN usage
- 83 Fast infrared data association (FIrDA)
- 83 FIrDA software overview
- 83 FIrDA kernel source and configuration
- 84 FIrDA platform configuration
- 84 FIrDA usage
- 90 Peripheral component interconnect express (PCIe)
- 90 PCIe software overview
- 97 PCIe kernel source and configuration
- 98 PCIe platform configuration
- 100 PCIe usage
- 100 Serial advanced technology attachment (SATA)
- 100 SATA software overview
- 101 SATA kernel source and configuration
- 101 SATA platform configuration
- 101 SATA usage
- 107 Memory technology devices (MTD)
- 107 Linux MTD framework
- 107 MTD kernel configuration
- 108 Accessing to MTD devices
- 108 Raw access from user space
- 108 Raw access from kernel space
- 112 Access through file system from user space
- 112 Flexible static memory controller (FSMC)
- 113 NAND, FSMC
- 116 Parallel NOR, FSMC
- 119 Static RAM (SRAM), flexible static memory controller
- 122 Serial memory interface (SMI)
- 122 SMI hardware overview
- 123 SMI software overview
- 124 SMI kernel source and configuration
- 124 SMI platform configuration
- 127 Accelerators
- 127 JPEG encoder/decoder
- 127 JPEG encoder/decoder software overview
- 128 JPEG encoder/decoder kernel source and configuration
- 128 JPEG encoder/decoder platform configuration
- 128 JPEG encoder/decoder usage
- 139 Direct memory access (DMA)
- 140 DMA hardware overview
- 140 DMA software overview
- 144 DMA kernel source and configuration
- 144 DMA platform configuration
- 145 DMA usage
- 147 Channel controller coprocessor (C3)
- 148 C3 software overview
- 148 C3 kernel source and configuration
- 150 C3 platform configuration
- 150 C3 usage
- 153 Frame buffer drivers
- 153 Color liquid crystal display (CLCD)
- 153 CLCD software overview
- 153 CLCD kernel source and configuration
- 156 CLCD usage
- 158 Miscellaneous devices
- 158 General purpose input/output (GPIO)
- 158 GPIO software overview
- 159 GPIO kernel source and configuration
- 160 GPIO platform configuration
- 160 GPIO usage
- 162 Application specific GPIO (AS GPIO)
- 162 AS GPIO software overview
- 163 AS GPIO kernel source and configuration
- 163 AS GPIO platform configuration
- 164 AS GPIO usage
- 168 Watchdog timer (WDT) driver
- 168 WDT software overview
- 169 WDT kernel source and configuration
- 171 WDT usage
- 175 Audio drivers
- 175 SPORT controller
- 176 SPORT controller software overview
- 177 SPORT controller kernel source and configuration
- 178 SPORT controller platform configuration
- 180 SPORT controller usage
- 181 Video drivers
- 181 Video for Linux Two framework
- 182 Programming a V4L2 device
- 191 SoC-Camera framework
- 193 Camera interface
- 194 V4L2 subdev API
- 195 Video transport stream (TS)
- 195 TS software overview
- 196 TS kernel source and configuration
- 197 TS platform configuration
- 199 TS usage
- 201 Virtualized devices
- 202 KSP interface controller
- 202 KSP software overview
- 205 KSP kernel source and configuration
- 205 KSP platform configuration
- 205 Miscellaneous register access (Misc)
- 205 Misc software overview
- 205 Virtual log
- 206 Virtual log software overview
- 208 Virtual log kernel source and configuration
- 208 Virtual log platform configuration
- 209 Virtual log usage
- 209 SMI/FSMC NAND memory shared access
- 209 SMI/FSMC NAND software overview
- 210 SMI/FSMC NAND kernel source and configuration
- 210 SMI/FSMC NAND platform configuration
- 210 HomePlug AV (HPAV) driver
- 211 HPAV software overview
- 212 HPAV kernel source and configuration
- 212 HPAV platform configuration
- 213 Image validate device driver
- 214 Image validate device driver software overview
- 216 Image validate device driver kernel source and configuration
- 216 Image validate device driver platform configuration
- 216 Image validate device driver usage
- 217 Appendix A Acronyms
- 219 Revision history