Merge branch 'master' into 85xx
This commit is contained in:
commit
54c66f6d78
10
CREDITS
10
CREDITS
|
@ -2571,6 +2571,16 @@ S: Subiaco, 6008
|
||||||
S: Perth, Western Australia
|
S: Perth, Western Australia
|
||||||
S: Australia
|
S: Australia
|
||||||
|
|
||||||
|
N: Miguel Ojeda Sandonis
|
||||||
|
E: maxextreme@gmail.com
|
||||||
|
D: Author: Auxiliary LCD Controller driver (ks0108)
|
||||||
|
D: Author: Auxiliary LCD driver (cfag12864b)
|
||||||
|
D: Author: Auxiliary LCD framebuffer driver (cfag12864bfb)
|
||||||
|
D: Maintainer: Auxiliary display drivers tree (drivers/auxdisplay/*)
|
||||||
|
S: C/ Mieses 20, 9-B
|
||||||
|
S: Valladolid 47009
|
||||||
|
S: Spain
|
||||||
|
|
||||||
N: Greg Page
|
N: Greg Page
|
||||||
E: gpage@sovereign.org
|
E: gpage@sovereign.org
|
||||||
D: IPX development and support
|
D: IPX development and support
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
What: /debug/pktcdvd/pktcdvd[0-7]
|
What: /debug/pktcdvd/pktcdvd[0-7]
|
||||||
Date: Oct. 2006
|
Date: Oct. 2006
|
||||||
KernelVersion: 2.6.19
|
KernelVersion: 2.6.20
|
||||||
Contact: Thomas Maier <balagi@justmail.de>
|
Contact: Thomas Maier <balagi@justmail.de>
|
||||||
Description:
|
Description:
|
||||||
|
|
||||||
|
@ -11,8 +11,7 @@ The pktcdvd module (packet writing driver) creates
|
||||||
these files in debugfs:
|
these files in debugfs:
|
||||||
|
|
||||||
/debug/pktcdvd/pktcdvd[0-7]/
|
/debug/pktcdvd/pktcdvd[0-7]/
|
||||||
info (0444) Lots of human readable driver
|
info (0444) Lots of driver statistics and infos.
|
||||||
statistics and infos. Multiple lines!
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
What: /sys/class/pktcdvd/
|
What: /sys/class/pktcdvd/
|
||||||
Date: Oct. 2006
|
Date: Oct. 2006
|
||||||
KernelVersion: 2.6.19
|
KernelVersion: 2.6.20
|
||||||
Contact: Thomas Maier <balagi@justmail.de>
|
Contact: Thomas Maier <balagi@justmail.de>
|
||||||
Description:
|
Description:
|
||||||
|
|
||||||
|
|
|
@ -482,13 +482,13 @@ slightly.
|
||||||
<para>Gadget drivers
|
<para>Gadget drivers
|
||||||
rely on common USB structures and constants
|
rely on common USB structures and constants
|
||||||
defined in the
|
defined in the
|
||||||
<filename><linux/usb_ch9.h></filename>
|
<filename><linux/usb/ch9.h></filename>
|
||||||
header file, which is standard in Linux 2.6 kernels.
|
header file, which is standard in Linux 2.6 kernels.
|
||||||
These are the same types and constants used by host
|
These are the same types and constants used by host
|
||||||
side drivers (and usbcore).
|
side drivers (and usbcore).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
!Iinclude/linux/usb_ch9.h
|
!Iinclude/linux/usb/ch9.h
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="core"><title>Core Objects and Methods</title>
|
<sect1 id="core"><title>Core Objects and Methods</title>
|
||||||
|
|
|
@ -316,6 +316,9 @@ X!Earch/i386/kernel/mca.c
|
||||||
<sect1><title>DMI Interfaces</title>
|
<sect1><title>DMI Interfaces</title>
|
||||||
!Edrivers/firmware/dmi_scan.c
|
!Edrivers/firmware/dmi_scan.c
|
||||||
</sect1>
|
</sect1>
|
||||||
|
<sect1><title>EDD Interfaces</title>
|
||||||
|
!Idrivers/firmware/edd.c
|
||||||
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="security">
|
<chapter id="security">
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
<param name="funcsynopsis.style">ansi</param>
|
<param name="funcsynopsis.style">ansi</param>
|
||||||
<param name="funcsynopsis.tabular.threshold">80</param>
|
<param name="funcsynopsis.tabular.threshold">80</param>
|
||||||
<!-- <param name="paper.type">A4</param> -->
|
<!-- <param name="paper.type">A4</param> -->
|
||||||
|
<param name="generate.section.toc.level">2</param>
|
||||||
</stylesheet>
|
</stylesheet>
|
||||||
|
|
|
@ -187,13 +187,13 @@
|
||||||
|
|
||||||
<chapter><title>USB-Standard Types</title>
|
<chapter><title>USB-Standard Types</title>
|
||||||
|
|
||||||
<para>In <filename><linux/usb_ch9.h></filename> you will find
|
<para>In <filename><linux/usb/ch9.h></filename> you will find
|
||||||
the USB data types defined in chapter 9 of the USB specification.
|
the USB data types defined in chapter 9 of the USB specification.
|
||||||
These data types are used throughout USB, and in APIs including
|
These data types are used throughout USB, and in APIs including
|
||||||
this host side API, gadget APIs, and usbfs.
|
this host side API, gadget APIs, and usbfs.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
!Iinclude/linux/usb_ch9.h
|
!Iinclude/linux/usb/ch9.h
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
@ -574,7 +574,7 @@ for (;;) {
|
||||||
#include <asm/byteorder.h></programlisting>
|
#include <asm/byteorder.h></programlisting>
|
||||||
The standard USB device model requests, from "Chapter 9" of
|
The standard USB device model requests, from "Chapter 9" of
|
||||||
the USB 2.0 specification, are automatically included from
|
the USB 2.0 specification, are automatically included from
|
||||||
the <filename><linux/usb_ch9.h></filename> header.
|
the <filename><linux/usb/ch9.h></filename> header.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>Unless noted otherwise, the ioctl requests
|
<para>Unless noted otherwise, the ioctl requests
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
===================================
|
||||||
|
cfag12864b LCD Driver Documentation
|
||||||
|
===================================
|
||||||
|
|
||||||
|
License: GPLv2
|
||||||
|
Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com>
|
||||||
|
Date: 2006-10-27
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------
|
||||||
|
0. INDEX
|
||||||
|
--------
|
||||||
|
|
||||||
|
1. DRIVER INFORMATION
|
||||||
|
2. DEVICE INFORMATION
|
||||||
|
3. WIRING
|
||||||
|
4. USERSPACE PROGRAMMING
|
||||||
|
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
1. DRIVER INFORMATION
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This driver support one cfag12864b display at time.
|
||||||
|
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
2. DEVICE INFORMATION
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Manufacturer: Crystalfontz
|
||||||
|
Device Name: Crystalfontz 12864b LCD Series
|
||||||
|
Device Code: cfag12864b
|
||||||
|
Webpage: http://www.crystalfontz.com
|
||||||
|
Device Webpage: http://www.crystalfontz.com/products/12864b/
|
||||||
|
Type: LCD (Liquid Crystal Display)
|
||||||
|
Width: 128
|
||||||
|
Height: 64
|
||||||
|
Colors: 2 (B/N)
|
||||||
|
Controller: ks0108
|
||||||
|
Controllers: 2
|
||||||
|
Pages: 8 each controller
|
||||||
|
Addresses: 64 each page
|
||||||
|
Data size: 1 byte each address
|
||||||
|
Memory size: 2 * 8 * 64 * 1 = 1024 bytes = 1 Kbyte
|
||||||
|
|
||||||
|
|
||||||
|
---------
|
||||||
|
3. WIRING
|
||||||
|
---------
|
||||||
|
|
||||||
|
The cfag12864b LCD Series don't have official wiring.
|
||||||
|
|
||||||
|
The common wiring is done to the parallel port as shown:
|
||||||
|
|
||||||
|
Parallel Port cfag12864b
|
||||||
|
|
||||||
|
Name Pin# Pin# Name
|
||||||
|
|
||||||
|
Strobe ( 1)------------------------------(17) Enable
|
||||||
|
Data 0 ( 2)------------------------------( 4) Data 0
|
||||||
|
Data 1 ( 3)------------------------------( 5) Data 1
|
||||||
|
Data 2 ( 4)------------------------------( 6) Data 2
|
||||||
|
Data 3 ( 5)------------------------------( 7) Data 3
|
||||||
|
Data 4 ( 6)------------------------------( 8) Data 4
|
||||||
|
Data 5 ( 7)------------------------------( 9) Data 5
|
||||||
|
Data 6 ( 8)------------------------------(10) Data 6
|
||||||
|
Data 7 ( 9)------------------------------(11) Data 7
|
||||||
|
(10) [+5v]---( 1) Vdd
|
||||||
|
(11) [GND]---( 2) Ground
|
||||||
|
(12) [+5v]---(14) Reset
|
||||||
|
(13) [GND]---(15) Read / Write
|
||||||
|
Line (14)------------------------------(13) Controller Select 1
|
||||||
|
(15)
|
||||||
|
Init (16)------------------------------(12) Controller Select 2
|
||||||
|
Select (17)------------------------------(16) Data / Instruction
|
||||||
|
Ground (18)---[GND] [+5v]---(19) LED +
|
||||||
|
Ground (19)---[GND]
|
||||||
|
Ground (20)---[GND] E A Values:
|
||||||
|
Ground (21)---[GND] [GND]---[P1]---(18) Vee · R = Resistor = 22 ohm
|
||||||
|
Ground (22)---[GND] | · P1 = Preset = 10 Kohm
|
||||||
|
Ground (23)---[GND] ---- S ------( 3) V0 · P2 = Preset = 1 Kohm
|
||||||
|
Ground (24)---[GND] | |
|
||||||
|
Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED -
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
4. USERSPACE PROGRAMMING
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The cfag12864bfb describes a framebuffer device (/dev/fbX).
|
||||||
|
|
||||||
|
It has a size of 1024 bytes = 1 Kbyte.
|
||||||
|
Each bit represents one pixel. If the bit is high, the pixel will
|
||||||
|
turn on. If the pixel is low, the pixel will turn off.
|
||||||
|
|
||||||
|
You can use the framebuffer as a file: fopen, fwrite, fclose...
|
||||||
|
Although the LCD won't get updated until the next refresh time arrives.
|
||||||
|
|
||||||
|
Also, you can mmap the framebuffer: open & mmap, munmap & close...
|
||||||
|
which is the best option for most uses.
|
||||||
|
|
||||||
|
Check Documentation/auxdisplay/cfag12864b-example.c
|
||||||
|
for a real working userspace complete program with usage examples.
|
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
* Filename: cfag12864b-example.c
|
||||||
|
* Version: 0.1.0
|
||||||
|
* Description: cfag12864b LCD userspace example program
|
||||||
|
* License: GPLv2
|
||||||
|
*
|
||||||
|
* Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
|
||||||
|
* Date: 2006-10-31
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------
|
||||||
|
* start of cfag12864b code
|
||||||
|
* ------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#define CFAG12864B_WIDTH (128)
|
||||||
|
#define CFAG12864B_HEIGHT (64)
|
||||||
|
#define CFAG12864B_SIZE (128 * 64 / 8)
|
||||||
|
#define CFAG12864B_BPB (8)
|
||||||
|
#define CFAG12864B_ADDRESS(x, y) ((y) * CFAG12864B_WIDTH / \
|
||||||
|
CFAG12864B_BPB + (x) / CFAG12864B_BPB)
|
||||||
|
#define CFAG12864B_BIT(n) (((unsigned char) 1) << (n))
|
||||||
|
|
||||||
|
#undef CFAG12864B_DOCHECK
|
||||||
|
#ifdef CFAG12864B_DOCHECK
|
||||||
|
#define CFAG12864B_CHECK(x, y) ((x) < CFAG12864B_WIDTH && \
|
||||||
|
(y) < CFAG12864B_HEIGHT)
|
||||||
|
#else
|
||||||
|
#define CFAG12864B_CHECK(x, y) (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int cfag12864b_fd;
|
||||||
|
unsigned char * cfag12864b_mem;
|
||||||
|
unsigned char cfag12864b_buffer[CFAG12864B_SIZE];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init a cfag12864b framebuffer device
|
||||||
|
*
|
||||||
|
* No error: return = 0
|
||||||
|
* Unable to open: return = -1
|
||||||
|
* Unable to mmap: return = -2
|
||||||
|
*/
|
||||||
|
int cfag12864b_init(char *path)
|
||||||
|
{
|
||||||
|
cfag12864b_fd = open(path, O_RDWR);
|
||||||
|
if (cfag12864b_fd == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cfag12864b_mem = mmap(0, CFAG12864B_SIZE, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED, cfag12864b_fd, 0);
|
||||||
|
if (cfag12864b_mem == MAP_FAILED) {
|
||||||
|
close(cfag12864b_fd);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exit a cfag12864b framebuffer device
|
||||||
|
*/
|
||||||
|
void cfag12864b_exit(void)
|
||||||
|
{
|
||||||
|
munmap(cfag12864b_mem, CFAG12864B_SIZE);
|
||||||
|
close(cfag12864b_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set (x, y) pixel
|
||||||
|
*/
|
||||||
|
void cfag12864b_set(unsigned char x, unsigned char y)
|
||||||
|
{
|
||||||
|
if (CFAG12864B_CHECK(x, y))
|
||||||
|
cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] |=
|
||||||
|
CFAG12864B_BIT(x % CFAG12864B_BPB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unset (x, y) pixel
|
||||||
|
*/
|
||||||
|
void cfag12864b_unset(unsigned char x, unsigned char y)
|
||||||
|
{
|
||||||
|
if (CFAG12864B_CHECK(x, y))
|
||||||
|
cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &=
|
||||||
|
~CFAG12864B_BIT(x % CFAG12864B_BPB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* is set (x, y) pixel?
|
||||||
|
*
|
||||||
|
* Pixel off: return = 0
|
||||||
|
* Pixel on: return = 1
|
||||||
|
*/
|
||||||
|
unsigned char cfag12864b_isset(unsigned char x, unsigned char y)
|
||||||
|
{
|
||||||
|
if (CFAG12864B_CHECK(x, y))
|
||||||
|
if (cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &
|
||||||
|
CFAG12864B_BIT(x % CFAG12864B_BPB))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* not (x, y) pixel
|
||||||
|
*/
|
||||||
|
void cfag12864b_not(unsigned char x, unsigned char y)
|
||||||
|
{
|
||||||
|
if (cfag12864b_isset(x, y))
|
||||||
|
cfag12864b_unset(x, y);
|
||||||
|
else
|
||||||
|
cfag12864b_set(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill (set all pixels)
|
||||||
|
*/
|
||||||
|
void cfag12864b_fill(void)
|
||||||
|
{
|
||||||
|
unsigned short i;
|
||||||
|
|
||||||
|
for (i = 0; i < CFAG12864B_SIZE; i++)
|
||||||
|
cfag12864b_buffer[i] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clear (unset all pixels)
|
||||||
|
*/
|
||||||
|
void cfag12864b_clear(void)
|
||||||
|
{
|
||||||
|
unsigned short i;
|
||||||
|
|
||||||
|
for (i = 0; i < CFAG12864B_SIZE; i++)
|
||||||
|
cfag12864b_buffer[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* format a [128*64] matrix
|
||||||
|
*
|
||||||
|
* Pixel off: src[i] = 0
|
||||||
|
* Pixel on: src[i] > 0
|
||||||
|
*/
|
||||||
|
void cfag12864b_format(unsigned char * matrix)
|
||||||
|
{
|
||||||
|
unsigned char i, j, n;
|
||||||
|
|
||||||
|
for (i = 0; i < CFAG12864B_HEIGHT; i++)
|
||||||
|
for (j = 0; j < CFAG12864B_WIDTH / CFAG12864B_BPB; j++) {
|
||||||
|
cfag12864b_buffer[i * CFAG12864B_WIDTH / CFAG12864B_BPB +
|
||||||
|
j] = 0;
|
||||||
|
for (n = 0; n < CFAG12864B_BPB; n++)
|
||||||
|
if (matrix[i * CFAG12864B_WIDTH +
|
||||||
|
j * CFAG12864B_BPB + n])
|
||||||
|
cfag12864b_buffer[i * CFAG12864B_WIDTH /
|
||||||
|
CFAG12864B_BPB + j] |=
|
||||||
|
CFAG12864B_BIT(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* blit buffer to lcd
|
||||||
|
*/
|
||||||
|
void cfag12864b_blit(void)
|
||||||
|
{
|
||||||
|
memcpy(cfag12864b_mem, cfag12864b_buffer, CFAG12864B_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------
|
||||||
|
* end of cfag12864b code
|
||||||
|
* ----------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define EXAMPLES 6
|
||||||
|
|
||||||
|
void example(unsigned char n)
|
||||||
|
{
|
||||||
|
unsigned short i, j;
|
||||||
|
unsigned char matrix[CFAG12864B_WIDTH * CFAG12864B_HEIGHT];
|
||||||
|
|
||||||
|
if (n > EXAMPLES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf("Example %i/%i - ", n, EXAMPLES);
|
||||||
|
|
||||||
|
switch (n) {
|
||||||
|
case 1:
|
||||||
|
printf("Draw points setting bits");
|
||||||
|
cfag12864b_clear();
|
||||||
|
for (i = 0; i < CFAG12864B_WIDTH; i += 2)
|
||||||
|
for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
|
||||||
|
cfag12864b_set(i, j);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
printf("Clear the LCD");
|
||||||
|
cfag12864b_clear();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
printf("Draw rows formatting a [128*64] matrix");
|
||||||
|
memset(matrix, 0, CFAG12864B_WIDTH * CFAG12864B_HEIGHT);
|
||||||
|
for (i = 0; i < CFAG12864B_WIDTH; i++)
|
||||||
|
for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
|
||||||
|
matrix[j * CFAG12864B_WIDTH + i] = 1;
|
||||||
|
cfag12864b_format(matrix);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
printf("Fill the lcd");
|
||||||
|
cfag12864b_fill();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
printf("Draw columns unsetting bits");
|
||||||
|
for (i = 0; i < CFAG12864B_WIDTH; i += 2)
|
||||||
|
for (j = 0; j < CFAG12864B_HEIGHT; j++)
|
||||||
|
cfag12864b_unset(i, j);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
printf("Do negative not-ing all bits");
|
||||||
|
for (i = 0; i < CFAG12864B_WIDTH; i++)
|
||||||
|
for (j = 0; j < CFAG12864B_HEIGHT; j ++)
|
||||||
|
cfag12864b_not(i, j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts(" - [Press Enter]");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned char n;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf(
|
||||||
|
"Sintax: %s fbdev\n"
|
||||||
|
"Usually: /dev/fb0, /dev/fb1...\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfag12864b_init(argv[1])) {
|
||||||
|
printf("Can't init %s fbdev\n", argv[1]);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 1; n <= EXAMPLES; n++) {
|
||||||
|
example(n);
|
||||||
|
cfag12864b_blit();
|
||||||
|
while (getchar() != '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
cfag12864b_exit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
==========================================
|
||||||
|
ks0108 LCD Controller Driver Documentation
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
License: GPLv2
|
||||||
|
Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com>
|
||||||
|
Date: 2006-10-27
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------
|
||||||
|
0. INDEX
|
||||||
|
--------
|
||||||
|
|
||||||
|
1. DRIVER INFORMATION
|
||||||
|
2. DEVICE INFORMATION
|
||||||
|
3. WIRING
|
||||||
|
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
1. DRIVER INFORMATION
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This driver support the ks0108 LCD controller.
|
||||||
|
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
2. DEVICE INFORMATION
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Manufacturer: Samsung
|
||||||
|
Device Name: KS0108 LCD Controller
|
||||||
|
Device Code: ks0108
|
||||||
|
Webpage: -
|
||||||
|
Device Webpage: -
|
||||||
|
Type: LCD Controller (Liquid Crystal Display Controller)
|
||||||
|
Width: 64
|
||||||
|
Height: 64
|
||||||
|
Colors: 2 (B/N)
|
||||||
|
Pages: 8
|
||||||
|
Addresses: 64 each page
|
||||||
|
Data size: 1 byte each address
|
||||||
|
Memory size: 8 * 64 * 1 = 512 bytes
|
||||||
|
|
||||||
|
|
||||||
|
---------
|
||||||
|
3. WIRING
|
||||||
|
---------
|
||||||
|
|
||||||
|
The driver supports data parallel port wiring.
|
||||||
|
|
||||||
|
If you aren't building LCD related hardware, you should check
|
||||||
|
your LCD specific wiring information in the same folder.
|
||||||
|
|
||||||
|
For example, check Documentation/auxdisplay/cfag12864b.
|
|
@ -93,7 +93,7 @@ Notes
|
||||||
Using the pktcdvd sysfs interface
|
Using the pktcdvd sysfs interface
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
Since Linux 2.6.19, the pktcdvd module has a sysfs interface
|
Since Linux 2.6.20, the pktcdvd module has a sysfs interface
|
||||||
and can be controlled by it. For example the "pktcdvd" tool uses
|
and can be controlled by it. For example the "pktcdvd" tool uses
|
||||||
this interface. (see http://people.freenet.de/BalaGi#pktcdvd )
|
this interface. (see http://people.freenet.de/BalaGi#pktcdvd )
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,7 @@ Original developers of the crypto algorithms:
|
||||||
Kartikey Mahendra Bhatt (CAST6)
|
Kartikey Mahendra Bhatt (CAST6)
|
||||||
Jon Oberheide (ARC4)
|
Jon Oberheide (ARC4)
|
||||||
Jouni Malinen (Michael MIC)
|
Jouni Malinen (Michael MIC)
|
||||||
|
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
|
||||||
|
|
||||||
SHA1 algorithm contributors:
|
SHA1 algorithm contributors:
|
||||||
Jean-Francois Dive
|
Jean-Francois Dive
|
||||||
|
@ -246,6 +247,9 @@ Tiger algorithm contributors:
|
||||||
VIA PadLock contributors:
|
VIA PadLock contributors:
|
||||||
Michal Ludvig
|
Michal Ludvig
|
||||||
|
|
||||||
|
Camellia algorithm contributors:
|
||||||
|
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
|
||||||
|
|
||||||
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
|
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
|
||||||
|
|
||||||
Please send any credits updates or corrections to:
|
Please send any credits updates or corrections to:
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
Devres - Managed Device Resource
|
||||||
|
================================
|
||||||
|
|
||||||
|
Tejun Heo <teheo@suse.de>
|
||||||
|
|
||||||
|
First draft 10 January 2007
|
||||||
|
|
||||||
|
|
||||||
|
1. Intro : Huh? Devres?
|
||||||
|
2. Devres : Devres in a nutshell
|
||||||
|
3. Devres Group : Group devres'es and release them together
|
||||||
|
4. Details : Life time rules, calling context, ...
|
||||||
|
5. Overhead : How much do we have to pay for this?
|
||||||
|
6. List of managed interfaces : Currently implemented managed interfaces
|
||||||
|
|
||||||
|
|
||||||
|
1. Intro
|
||||||
|
--------
|
||||||
|
|
||||||
|
devres came up while trying to convert libata to use iomap. Each
|
||||||
|
iomapped address should be kept and unmapped on driver detach. For
|
||||||
|
example, a plain SFF ATA controller (that is, good old PCI IDE) in
|
||||||
|
native mode makes use of 5 PCI BARs and all of them should be
|
||||||
|
maintained.
|
||||||
|
|
||||||
|
As with many other device drivers, libata low level drivers have
|
||||||
|
sufficient bugs in ->remove and ->probe failure path. Well, yes,
|
||||||
|
that's probably because libata low level driver developers are lazy
|
||||||
|
bunch, but aren't all low level driver developers? After spending a
|
||||||
|
day fiddling with braindamaged hardware with no document or
|
||||||
|
braindamaged document, if it's finally working, well, it's working.
|
||||||
|
|
||||||
|
For one reason or another, low level drivers don't receive as much
|
||||||
|
attention or testing as core code, and bugs on driver detach or
|
||||||
|
initilaization failure doesn't happen often enough to be noticeable.
|
||||||
|
Init failure path is worse because it's much less travelled while
|
||||||
|
needs to handle multiple entry points.
|
||||||
|
|
||||||
|
So, many low level drivers end up leaking resources on driver detach
|
||||||
|
and having half broken failure path implementation in ->probe() which
|
||||||
|
would leak resources or even cause oops when failure occurs. iomap
|
||||||
|
adds more to this mix. So do msi and msix.
|
||||||
|
|
||||||
|
|
||||||
|
2. Devres
|
||||||
|
---------
|
||||||
|
|
||||||
|
devres is basically linked list of arbitrarily sized memory areas
|
||||||
|
associated with a struct device. Each devres entry is associated with
|
||||||
|
a release function. A devres can be released in several ways. No
|
||||||
|
matter what, all devres entries are released on driver detach. On
|
||||||
|
release, the associated release function is invoked and then the
|
||||||
|
devres entry is freed.
|
||||||
|
|
||||||
|
Managed interface is created for resources commonly used by device
|
||||||
|
drivers using devres. For example, coherent DMA memory is acquired
|
||||||
|
using dma_alloc_coherent(). The managed version is called
|
||||||
|
dmam_alloc_coherent(). It is identical to dma_alloc_coherent() except
|
||||||
|
for the DMA memory allocated using it is managed and will be
|
||||||
|
automatically released on driver detach. Implementation looks like
|
||||||
|
the following.
|
||||||
|
|
||||||
|
struct dma_devres {
|
||||||
|
size_t size;
|
||||||
|
void *vaddr;
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dmam_coherent_release(struct device *dev, void *res)
|
||||||
|
{
|
||||||
|
struct dma_devres *this = res;
|
||||||
|
|
||||||
|
dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
dmam_alloc_coherent(dev, size, dma_handle, gfp)
|
||||||
|
{
|
||||||
|
struct dma_devres *dr;
|
||||||
|
void *vaddr;
|
||||||
|
|
||||||
|
dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
|
||||||
|
...
|
||||||
|
|
||||||
|
/* alloc DMA memory as usual */
|
||||||
|
vaddr = dma_alloc_coherent(...);
|
||||||
|
...
|
||||||
|
|
||||||
|
/* record size, vaddr, dma_handle in dr */
|
||||||
|
dr->vaddr = vaddr;
|
||||||
|
...
|
||||||
|
|
||||||
|
devres_add(dev, dr);
|
||||||
|
|
||||||
|
return vaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
If a driver uses dmam_alloc_coherent(), the area is guaranteed to be
|
||||||
|
freed whether initialization fails half-way or the device gets
|
||||||
|
detached. If most resources are acquired using managed interface, a
|
||||||
|
driver can have much simpler init and exit code. Init path basically
|
||||||
|
looks like the following.
|
||||||
|
|
||||||
|
my_init_one()
|
||||||
|
{
|
||||||
|
struct mydev *d;
|
||||||
|
|
||||||
|
d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
|
||||||
|
if (!d)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
d->ring = dmam_alloc_coherent(...);
|
||||||
|
if (!d->ring)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (check something)
|
||||||
|
return -EINVAL;
|
||||||
|
...
|
||||||
|
|
||||||
|
return register_to_upper_layer(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
And exit path,
|
||||||
|
|
||||||
|
my_remove_one()
|
||||||
|
{
|
||||||
|
unregister_from_upper_layer(d);
|
||||||
|
shutdown_my_hardware();
|
||||||
|
}
|
||||||
|
|
||||||
|
As shown above, low level drivers can be simplified a lot by using
|
||||||
|
devres. Complexity is shifted from less maintained low level drivers
|
||||||
|
to better maintained higher layer. Also, as init failure path is
|
||||||
|
shared with exit path, both can get more testing.
|
||||||
|
|
||||||
|
|
||||||
|
3. Devres group
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Devres entries can be grouped using devres group. When a group is
|
||||||
|
released, all contained normal devres entries and properly nested
|
||||||
|
groups are released. One usage is to rollback series of acquired
|
||||||
|
resources on failure. For example,
|
||||||
|
|
||||||
|
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
acquire A;
|
||||||
|
if (failed)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
acquire B;
|
||||||
|
if (failed)
|
||||||
|
goto err;
|
||||||
|
...
|
||||||
|
|
||||||
|
devres_remove_group(dev, NULL);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
devres_release_group(dev, NULL);
|
||||||
|
return err_code;
|
||||||
|
|
||||||
|
As resource acquision failure usually means probe failure, constructs
|
||||||
|
like above are usually useful in midlayer driver (e.g. libata core
|
||||||
|
layer) where interface function shouldn't have side effect on failure.
|
||||||
|
For LLDs, just returning error code suffices in most cases.
|
||||||
|
|
||||||
|
Each group is identified by void *id. It can either be explicitly
|
||||||
|
specified by @id argument to devres_open_group() or automatically
|
||||||
|
created by passing NULL as @id as in the above example. In both
|
||||||
|
cases, devres_open_group() returns the group's id. The returned id
|
||||||
|
can be passed to other devres functions to select the target group.
|
||||||
|
If NULL is given to those functions, the latest open group is
|
||||||
|
selected.
|
||||||
|
|
||||||
|
For example, you can do something like the following.
|
||||||
|
|
||||||
|
int my_midlayer_create_something()
|
||||||
|
{
|
||||||
|
if (!devres_open_group(dev, my_midlayer_create_something, GFP_KERNEL))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
devres_close_group(dev, my_midlayer_something);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void my_midlayer_destroy_something()
|
||||||
|
{
|
||||||
|
devres_release_group(dev, my_midlayer_create_soemthing);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
4. Details
|
||||||
|
----------
|
||||||
|
|
||||||
|
Lifetime of a devres entry begins on devres allocation and finishes
|
||||||
|
when it is released or destroyed (removed and freed) - no reference
|
||||||
|
counting.
|
||||||
|
|
||||||
|
devres core guarantees atomicity to all basic devres operations and
|
||||||
|
has support for single-instance devres types (atomic
|
||||||
|
lookup-and-add-if-not-found). Other than that, synchronizing
|
||||||
|
concurrent accesses to allocated devres data is caller's
|
||||||
|
responsibility. This is usually non-issue because bus ops and
|
||||||
|
resource allocations already do the job.
|
||||||
|
|
||||||
|
For an example of single-instance devres type, read pcim_iomap_table()
|
||||||
|
in lib/iomap.c.
|
||||||
|
|
||||||
|
All devres interface functions can be called without context if the
|
||||||
|
right gfp mask is given.
|
||||||
|
|
||||||
|
|
||||||
|
5. Overhead
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Each devres bookkeeping info is allocated together with requested data
|
||||||
|
area. With debug option turned off, bookkeeping info occupies 16
|
||||||
|
bytes on 32bit machines and 24 bytes on 64bit (three pointers rounded
|
||||||
|
up to ull alignment). If singly linked list is used, it can be
|
||||||
|
reduced to two pointers (8 bytes on 32bit, 16 bytes on 64bit).
|
||||||
|
|
||||||
|
Each devres group occupies 8 pointers. It can be reduced to 6 if
|
||||||
|
singly linked list is used.
|
||||||
|
|
||||||
|
Memory space overhead on ahci controller with two ports is between 300
|
||||||
|
and 400 bytes on 32bit machine after naive conversion (we can
|
||||||
|
certainly invest a bit more effort into libata core layer).
|
||||||
|
|
||||||
|
|
||||||
|
6. List of managed interfaces
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
IO region
|
||||||
|
devm_request_region()
|
||||||
|
devm_request_mem_region()
|
||||||
|
devm_release_region()
|
||||||
|
devm_release_mem_region()
|
||||||
|
|
||||||
|
IRQ
|
||||||
|
devm_request_irq()
|
||||||
|
devm_free_irq()
|
||||||
|
|
||||||
|
DMA
|
||||||
|
dmam_alloc_coherent()
|
||||||
|
dmam_free_coherent()
|
||||||
|
dmam_alloc_noncoherent()
|
||||||
|
dmam_free_noncoherent()
|
||||||
|
dmam_declare_coherent_memory()
|
||||||
|
dmam_pool_create()
|
||||||
|
dmam_pool_destroy()
|
||||||
|
|
||||||
|
PCI
|
||||||
|
pcim_enable_device() : after success, all PCI ops become managed
|
||||||
|
pcim_pin_device() : keep PCI device enabled after release
|
||||||
|
|
||||||
|
IOMAP
|
||||||
|
devm_ioport_map()
|
||||||
|
devm_ioport_unmap()
|
||||||
|
devm_ioremap()
|
||||||
|
devm_ioremap_nocache()
|
||||||
|
devm_iounmap()
|
||||||
|
pcim_iomap()
|
||||||
|
pcim_iounmap()
|
||||||
|
pcim_iomap_table() : array of mapped addresses indexed by BAR
|
||||||
|
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
|
|
@ -339,7 +339,21 @@ Device Symlink:
|
||||||
|
|
||||||
'device'
|
'device'
|
||||||
|
|
||||||
Symlink to the memory controller device
|
Symlink to the memory controller device.
|
||||||
|
|
||||||
|
Sdram memory scrubbing rate:
|
||||||
|
|
||||||
|
'sdram_scrub_rate'
|
||||||
|
|
||||||
|
Read/Write attribute file that controls memory scrubbing. The scrubbing
|
||||||
|
rate is set by writing a minimum bandwith in bytes/sec to the attribute
|
||||||
|
file. The rate will be translated to an internal value that gives at
|
||||||
|
least the specified rate.
|
||||||
|
|
||||||
|
Reading the file will return the actual scrubbing rate employed.
|
||||||
|
|
||||||
|
If configuration fails or memory scrubbing is not implemented, the value
|
||||||
|
of the attribute file will be -1.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
|
||||||
|
s3fb - fbdev driver for S3 Trio/Virge chips
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
|
||||||
|
Supported Hardware
|
||||||
|
==================
|
||||||
|
|
||||||
|
S3 Trio32
|
||||||
|
S3 Trio64 (and variants V+, UV+, V2/DX, V2/GX)
|
||||||
|
S3 Virge (and variants VX, DX, GX and GX2+)
|
||||||
|
S3 Plato/PX (completely untested)
|
||||||
|
S3 Aurora64V+ (completely untested)
|
||||||
|
|
||||||
|
- only PCI bus supported
|
||||||
|
- only BIOS initialized VGA devices supported
|
||||||
|
- probably not working on big endian
|
||||||
|
|
||||||
|
I tested s3fb on Trio64 (plain, V+ and V2/DX) and Virge (plain, VX, DX),
|
||||||
|
all on i386.
|
||||||
|
|
||||||
|
|
||||||
|
Supported Features
|
||||||
|
==================
|
||||||
|
|
||||||
|
* 4 bpp pseudocolor modes (with 18bit palette, two variants)
|
||||||
|
* 8 bpp pseudocolor mode (with 18bit palette)
|
||||||
|
* 16 bpp truecolor modes (RGB 555 and RGB 565)
|
||||||
|
* 24 bpp truecolor mode (RGB 888) on (only on Virge VX)
|
||||||
|
* 32 bpp truecolor mode (RGB 888) on (not on Virge VX)
|
||||||
|
* text mode (activated by bpp = 0)
|
||||||
|
* interlaced mode variant (not available in text mode)
|
||||||
|
* doublescan mode variant (not available in text mode)
|
||||||
|
* panning in both directions
|
||||||
|
* suspend/resume support
|
||||||
|
* DPMS support
|
||||||
|
|
||||||
|
Text mode is supported even in higher resolutions, but there is limitation
|
||||||
|
to lower pixclocks (maximum between 50-60 MHz, depending on specific hardware).
|
||||||
|
This limitation is not enforced by driver. Text mode supports 8bit wide fonts
|
||||||
|
only (hardware limitation) and 16bit tall fonts (driver limitation).
|
||||||
|
|
||||||
|
There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with
|
||||||
|
packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode
|
||||||
|
with interleaved planes (1 byte interleave), MSB first. Both modes support
|
||||||
|
8bit wide fonts only (driver limitation).
|
||||||
|
|
||||||
|
Suspend/resume works on systems that initialize video card during resume and
|
||||||
|
if device is active (for example used by fbcon).
|
||||||
|
|
||||||
|
|
||||||
|
Missing Features
|
||||||
|
================
|
||||||
|
(alias TODO list)
|
||||||
|
|
||||||
|
* secondary (not initialized by BIOS) device support
|
||||||
|
* big endian support
|
||||||
|
* Zorro bus support
|
||||||
|
* MMIO support
|
||||||
|
* 24 bpp mode support on more cards
|
||||||
|
* support for fontwidths != 8 in 4 bpp modes
|
||||||
|
* support for fontheight != 16 in text mode
|
||||||
|
* composite and external sync (is anyone able to test this?)
|
||||||
|
* hardware cursor
|
||||||
|
* video overlay support
|
||||||
|
* vsync synchronization
|
||||||
|
* feature connector support
|
||||||
|
* acceleration support (8514-like 2D, Virge 3D, busmaster transfers)
|
||||||
|
* better values for some magic registers (performance issues)
|
||||||
|
|
||||||
|
|
||||||
|
Known bugs
|
||||||
|
==========
|
||||||
|
|
||||||
|
* cursor disable in text mode doesn't work
|
||||||
|
|
||||||
|
--
|
||||||
|
Ondrej Zajicek <santiago@crfreenet.org>
|
|
@ -50,22 +50,6 @@ Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: ieee1394 core's unused exports (CONFIG_IEEE1394_EXPORT_FULL_API)
|
|
||||||
When: January 2007
|
|
||||||
Why: There are no projects known to use these exported symbols, except
|
|
||||||
dfg1394 (uses one symbol whose functionality is core-internal now).
|
|
||||||
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: ieee1394's *_oui sysfs attributes (CONFIG_IEEE1394_OUI_DB)
|
|
||||||
When: January 2007
|
|
||||||
Files: drivers/ieee1394/: oui.db, oui2c.sh
|
|
||||||
Why: big size, little value
|
|
||||||
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
||||||
When: December 2006
|
When: December 2006
|
||||||
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
|
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
|
||||||
|
@ -186,18 +170,6 @@ Who: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: find_trylock_page
|
|
||||||
When: January 2007
|
|
||||||
Why: The interface no longer has any callers left in the kernel. It
|
|
||||||
is an odd interface (compared with other find_*_page functions), in
|
|
||||||
that it does not take a refcount to the page, only the page lock.
|
|
||||||
It should be replaced with find_get_page or find_lock_page if possible.
|
|
||||||
This feature removal can be reevaluated if users of the interface
|
|
||||||
cannot cleanly use something else.
|
|
||||||
Who: Nick Piggin <npiggin@suse.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: Interrupt only SA_* flags
|
What: Interrupt only SA_* flags
|
||||||
When: Januar 2007
|
When: Januar 2007
|
||||||
Why: The interrupt related SA_* flags are replaced by IRQF_* to move them
|
Why: The interrupt related SA_* flags are replaced by IRQF_* to move them
|
||||||
|
@ -243,6 +215,13 @@ Who: Jean Delvare <khali@linux-fr.org>,
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
What: drivers depending on OBSOLETE_OSS
|
||||||
|
When: options in 2.6.22, code in 2.6.24
|
||||||
|
Why: OSS drivers with ALSA replacements
|
||||||
|
Who: Adrian Bunk <bunk@stusta.de>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
What: IPv4 only connection tracking/NAT/helpers
|
What: IPv4 only connection tracking/NAT/helpers
|
||||||
When: 2.6.22
|
When: 2.6.22
|
||||||
Why: The new layer 3 independant connection tracking replaces the old
|
Why: The new layer 3 independant connection tracking replaces the old
|
||||||
|
@ -340,3 +319,18 @@ Why: In kernel tree version of driver is unmaintained. Sk98lin driver
|
||||||
replaced by the skge driver.
|
replaced by the skge driver.
|
||||||
Who: Stephen Hemminger <shemminger@osdl.org>
|
Who: Stephen Hemminger <shemminger@osdl.org>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: Compaq touchscreen device emulation
|
||||||
|
When: Oct 2007
|
||||||
|
Files: drivers/input/tsdev.c
|
||||||
|
Why: The code says it was obsolete when it was written in 2001.
|
||||||
|
tslib is a userspace library which does anything tsdev can do and
|
||||||
|
much more besides in userspace where this code belongs. There is no
|
||||||
|
longer any need for tsdev and applications should have converted to
|
||||||
|
use tslib by now.
|
||||||
|
The name "tsdev" is also extremely confusing and lots of people have
|
||||||
|
it loaded when they don't need/use it.
|
||||||
|
Who: Richard Purdie <rpurdie@rpsys.net>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
|
@ -157,7 +157,7 @@ TBD(curr. line MT:/API/)
|
||||||
channel management functions:
|
channel management functions:
|
||||||
|
|
||||||
relay_open(base_filename, parent, subbuf_size, n_subbufs,
|
relay_open(base_filename, parent, subbuf_size, n_subbufs,
|
||||||
callbacks)
|
callbacks, private_data)
|
||||||
relay_close(chan)
|
relay_close(chan)
|
||||||
relay_flush(chan)
|
relay_flush(chan)
|
||||||
relay_reset(chan)
|
relay_reset(chan)
|
||||||
|
@ -251,7 +251,7 @@ static struct rchan_callbacks relay_callbacks =
|
||||||
|
|
||||||
And an example relay_open() invocation using them:
|
And an example relay_open() invocation using them:
|
||||||
|
|
||||||
chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks);
|
chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks, NULL);
|
||||||
|
|
||||||
If the create_buf_file() callback fails, or isn't defined, channel
|
If the create_buf_file() callback fails, or isn't defined, channel
|
||||||
creation and thus relay_open() will fail.
|
creation and thus relay_open() will fail.
|
||||||
|
@ -289,6 +289,11 @@ they use the proper locking for such a buffer, either by wrapping
|
||||||
writes in a spinlock, or by copying a write function from relay.h and
|
writes in a spinlock, or by copying a write function from relay.h and
|
||||||
creating a local version that internally does the proper locking.
|
creating a local version that internally does the proper locking.
|
||||||
|
|
||||||
|
The private_data passed into relay_open() allows clients to associate
|
||||||
|
user-defined data with a channel, and is immediately available
|
||||||
|
(including in create_buf_file()) via chan->private_data or
|
||||||
|
buf->chan->private_data.
|
||||||
|
|
||||||
Channel 'modes'
|
Channel 'modes'
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ ufstype=type_of_ufs
|
||||||
supported as read-write
|
supported as read-write
|
||||||
|
|
||||||
ufs2 used in FreeBSD 5.x
|
ufs2 used in FreeBSD 5.x
|
||||||
supported as read-only
|
supported as read-write
|
||||||
|
|
||||||
5xbsd synonym for ufs2
|
5xbsd synonym for ufs2
|
||||||
|
|
||||||
|
@ -50,12 +50,11 @@ ufstype=type_of_ufs
|
||||||
POSSIBLE PROBLEMS
|
POSSIBLE PROBLEMS
|
||||||
=================
|
=================
|
||||||
|
|
||||||
There is still bug in reallocation of fragment, in file fs/ufs/balloc.c,
|
See next section, if you have any.
|
||||||
line 364. But it seems working on current buffer cache configuration.
|
|
||||||
|
|
||||||
|
|
||||||
BUG REPORTS
|
BUG REPORTS
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Any ufs bug report you can send to daniel.pirkl@email.cz (do not send
|
Any ufs bug report you can send to daniel.pirkl@email.cz or
|
||||||
partition tables bug reports.)
|
to dushistov@mail.ru (do not send partition tables bug reports).
|
||||||
|
|
|
@ -0,0 +1,271 @@
|
||||||
|
GPIO Interfaces
|
||||||
|
|
||||||
|
This provides an overview of GPIO access conventions on Linux.
|
||||||
|
|
||||||
|
|
||||||
|
What is a GPIO?
|
||||||
|
===============
|
||||||
|
A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
|
||||||
|
digital signal. They are provided from many kinds of chip, and are familiar
|
||||||
|
to Linux developers working with embedded and custom hardware. 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. Drivers can be written generically, so that board setup code
|
||||||
|
passes such pin configuration data to drivers.
|
||||||
|
|
||||||
|
System-on-Chip (SOC) processors heavily rely on GPIOs. In some cases, every
|
||||||
|
non-dedicated pin can be configured as a GPIO; and most chips have at least
|
||||||
|
several dozen of them. Programmable logic devices (like FPGAs) can easily
|
||||||
|
provide GPIOs; multifunction chips like power managers, and audio codecs
|
||||||
|
often have a few such pins to help with pin scarcity on SOCs; and there are
|
||||||
|
also "GPIO Expander" chips that connect using the I2C or SPI serial busses.
|
||||||
|
Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
|
||||||
|
firmware knowing how they're used).
|
||||||
|
|
||||||
|
The exact capabilities of GPIOs vary between systems. Common options:
|
||||||
|
|
||||||
|
- Output values are writable (high=1, low=0). Some chips also have
|
||||||
|
options about how that value is driven, so that for example only one
|
||||||
|
value might be driven ... supporting "wire-OR" and similar schemes
|
||||||
|
for the other value.
|
||||||
|
|
||||||
|
- Input values are likewise readable (1, 0). Some chips support readback
|
||||||
|
of pins configured as "output", which is very useful in such "wire-OR"
|
||||||
|
cases (to support bidirectional signaling). GPIO controllers may have
|
||||||
|
input de-glitch logic, sometimes with software controls.
|
||||||
|
|
||||||
|
- Inputs can often be used as IRQ signals, often edge triggered but
|
||||||
|
sometimes level triggered. Such IRQs may be configurable as system
|
||||||
|
wakeup events, to wake the system from a low power state.
|
||||||
|
|
||||||
|
- Usually a GPIO will be configurable as either input or output, as needed
|
||||||
|
by different product boards; single direction ones exist too.
|
||||||
|
|
||||||
|
- Most GPIOs can be accessed while holding spinlocks, but those accessed
|
||||||
|
through a serial bus normally can't. Some systems support both types.
|
||||||
|
|
||||||
|
On a given board each GPIO is used for one specific purpose like monitoring
|
||||||
|
MMC/SD card insertion/removal, detecting card writeprotect status, driving
|
||||||
|
a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
|
||||||
|
watchdog, sensing a switch, and so on.
|
||||||
|
|
||||||
|
|
||||||
|
GPIO conventions
|
||||||
|
================
|
||||||
|
Note that this is called a "convention" because you don't need to do it this
|
||||||
|
way, and it's no crime if you don't. There **are** cases where portability
|
||||||
|
is not the main issue; GPIOs are often used for the kind of board-specific
|
||||||
|
glue logic that may even change between board revisions, and can't ever be
|
||||||
|
used on a board that's wired differently. Only least-common-denominator
|
||||||
|
functionality can be very portable. Other features are platform-specific,
|
||||||
|
and that can be critical for glue logic.
|
||||||
|
|
||||||
|
Plus, this doesn't define an implementation framework, just an interface.
|
||||||
|
One platform might implement it as simple inline functions accessing chip
|
||||||
|
registers; another might implement it by delegating through abstractions
|
||||||
|
used for several very different kinds of GPIO controller.
|
||||||
|
|
||||||
|
That said, if the convention is supported on their platform, drivers should
|
||||||
|
use it when possible:
|
||||||
|
|
||||||
|
#include <asm/gpio.h>
|
||||||
|
|
||||||
|
If you stick to this convention then it'll be easier for other developers to
|
||||||
|
see what your code is doing, and help maintain it.
|
||||||
|
|
||||||
|
|
||||||
|
Identifying GPIOs
|
||||||
|
-----------------
|
||||||
|
GPIOs are identified by unsigned integers in the range 0..MAX_INT. That
|
||||||
|
reserves "negative" numbers for other purposes like marking signals as
|
||||||
|
"not available on this board", or indicating faults.
|
||||||
|
|
||||||
|
Platforms define how they use those integers, and usually #define symbols
|
||||||
|
for the GPIO lines so that board-specific setup code directly corresponds
|
||||||
|
to the relevant schematics. In contrast, drivers should only use GPIO
|
||||||
|
numbers passed to them from that setup code, using platform_data to hold
|
||||||
|
board-specific pin configuration data (along with other board specific
|
||||||
|
data they need). That avoids portability problems.
|
||||||
|
|
||||||
|
So for example one platform uses numbers 32-159 for GPIOs; while another
|
||||||
|
uses numbers 0..63 with one set of GPIO controllers, 64-79 with another
|
||||||
|
type of GPIO controller, and on one particular board 80-95 with an FPGA.
|
||||||
|
The numbers need not be contiguous; either of those platforms could also
|
||||||
|
use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
|
||||||
|
|
||||||
|
Whether a platform supports multiple GPIO controllers is currently a
|
||||||
|
platform-specific implementation issue.
|
||||||
|
|
||||||
|
|
||||||
|
Using GPIOs
|
||||||
|
-----------
|
||||||
|
One of the first things to do with a GPIO, often in board setup code when
|
||||||
|
setting up a platform_device using the GPIO, is mark its direction:
|
||||||
|
|
||||||
|
/* set as input or output, returning 0 or negative errno */
|
||||||
|
int gpio_direction_input(unsigned gpio);
|
||||||
|
int gpio_direction_output(unsigned gpio);
|
||||||
|
|
||||||
|
The return value is zero for success, else a negative errno. It should
|
||||||
|
be checked, since the get/set calls don't have error returns and since
|
||||||
|
misconfiguration is possible. (These calls could sleep.)
|
||||||
|
|
||||||
|
Setting the direction can fail if the GPIO number is invalid, or when
|
||||||
|
that particular GPIO can't be used in that mode. It's generally a bad
|
||||||
|
idea to rely on boot firmware to have set the direction correctly, since
|
||||||
|
it probably wasn't validated to do more than boot Linux. (Similarly,
|
||||||
|
that board setup code probably needs to multiplex that pin as a GPIO,
|
||||||
|
and configure pullups/pulldowns appropriately.)
|
||||||
|
|
||||||
|
|
||||||
|
Spinlock-Safe GPIO access
|
||||||
|
-------------------------
|
||||||
|
Most GPIO controllers can be accessed with memory read/write instructions.
|
||||||
|
That doesn't need to sleep, and can safely be done from inside IRQ handlers.
|
||||||
|
|
||||||
|
Use these calls to access such GPIOs:
|
||||||
|
|
||||||
|
/* GPIO INPUT: return zero or nonzero */
|
||||||
|
int gpio_get_value(unsigned gpio);
|
||||||
|
|
||||||
|
/* GPIO OUTPUT */
|
||||||
|
void gpio_set_value(unsigned gpio, int value);
|
||||||
|
|
||||||
|
The values are boolean, zero for low, nonzero for high. When reading the
|
||||||
|
value of an output pin, the value returned should be what's seen on the
|
||||||
|
pin ... that won't always match the specified output value, because of
|
||||||
|
issues including wire-OR and output latencies.
|
||||||
|
|
||||||
|
The get/set calls have no error returns because "invalid GPIO" should have
|
||||||
|
been reported earlier in gpio_set_direction(). However, note that not all
|
||||||
|
platforms can read the value of output pins; those that can't should always
|
||||||
|
return zero. Also, these calls will be ignored for GPIOs that can't safely
|
||||||
|
be accessed wihtout sleeping (see below).
|
||||||
|
|
||||||
|
Platform-specific implementations are encouraged to optimise the two
|
||||||
|
calls to access the GPIO value in cases where the GPIO number (and for
|
||||||
|
output, value) are constant. It's normal for them to need only a couple
|
||||||
|
of instructions in such cases (reading or writing a hardware register),
|
||||||
|
and not to need spinlocks. Such optimized calls can make bitbanging
|
||||||
|
applications a lot more efficient (in both space and time) than spending
|
||||||
|
dozens of instructions on subroutine calls.
|
||||||
|
|
||||||
|
|
||||||
|
GPIO access that may sleep
|
||||||
|
--------------------------
|
||||||
|
Some GPIO controllers must be accessed using message based busses like I2C
|
||||||
|
or SPI. Commands to read or write those GPIO values require waiting to
|
||||||
|
get to the head of a queue to transmit a command and get its response.
|
||||||
|
This requires sleeping, which can't be done from inside IRQ handlers.
|
||||||
|
|
||||||
|
Platforms that support this type of GPIO distinguish them from other GPIOs
|
||||||
|
by returning nonzero from this call:
|
||||||
|
|
||||||
|
int gpio_cansleep(unsigned gpio);
|
||||||
|
|
||||||
|
To access such GPIOs, a different set of accessors is defined:
|
||||||
|
|
||||||
|
/* GPIO INPUT: return zero or nonzero, might sleep */
|
||||||
|
int gpio_get_value_cansleep(unsigned gpio);
|
||||||
|
|
||||||
|
/* GPIO OUTPUT, might sleep */
|
||||||
|
void gpio_set_value_cansleep(unsigned gpio, int value);
|
||||||
|
|
||||||
|
Other than the fact that these calls might sleep, and will not be ignored
|
||||||
|
for GPIOs that can't be accessed from IRQ handlers, these calls act the
|
||||||
|
same as the spinlock-safe calls.
|
||||||
|
|
||||||
|
|
||||||
|
Claiming and Releasing GPIOs (OPTIONAL)
|
||||||
|
---------------------------------------
|
||||||
|
To help catch system configuration errors, two calls are defined.
|
||||||
|
However, many platforms don't currently support this mechanism.
|
||||||
|
|
||||||
|
/* request GPIO, returning 0 or negative errno.
|
||||||
|
* non-null labels may be useful for diagnostics.
|
||||||
|
*/
|
||||||
|
int gpio_request(unsigned gpio, const char *label);
|
||||||
|
|
||||||
|
/* release previously-claimed GPIO */
|
||||||
|
void gpio_free(unsigned gpio);
|
||||||
|
|
||||||
|
Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
|
||||||
|
GPIOs that have already been claimed with that call. The return value of
|
||||||
|
gpio_request() must be checked. (These calls could sleep.)
|
||||||
|
|
||||||
|
These calls serve two basic purposes. One is marking the signals which
|
||||||
|
are actually in use as GPIOs, for better diagnostics; systems may have
|
||||||
|
several hundred potential GPIOs, but often only a dozen are used on any
|
||||||
|
given board. Another is to catch conflicts between drivers, reporting
|
||||||
|
errors when drivers wrongly think they have exclusive use of that signal.
|
||||||
|
|
||||||
|
These two calls are optional because not not all current Linux platforms
|
||||||
|
offer such functionality in their GPIO support; a valid implementation
|
||||||
|
could return success for all gpio_request() calls. Unlike the other calls,
|
||||||
|
the state they represent doesn't normally match anything from a hardware
|
||||||
|
register; it's just a software bitmap which clearly is not necessary for
|
||||||
|
correct operation of hardware or (bug free) drivers.
|
||||||
|
|
||||||
|
Note that requesting a GPIO does NOT cause it to be configured in any
|
||||||
|
way; it just marks that GPIO as in use. Separate code must handle any
|
||||||
|
pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
|
||||||
|
|
||||||
|
|
||||||
|
GPIOs mapped to IRQs
|
||||||
|
--------------------
|
||||||
|
GPIO numbers are unsigned integers; so are IRQ numbers. These make up
|
||||||
|
two logically distinct namespaces (GPIO 0 need not use IRQ 0). You can
|
||||||
|
map between them using calls like:
|
||||||
|
|
||||||
|
/* map GPIO numbers to IRQ numbers */
|
||||||
|
int gpio_to_irq(unsigned gpio);
|
||||||
|
|
||||||
|
/* map IRQ numbers to GPIO numbers */
|
||||||
|
int irq_to_gpio(unsigned irq);
|
||||||
|
|
||||||
|
Those return either the corresponding number in the other namespace, or
|
||||||
|
else a negative errno code if the mapping can't be done. (For example,
|
||||||
|
some GPIOs can't used as IRQs.) It is an unchecked error to use a GPIO
|
||||||
|
number that hasn't been marked as an input using gpio_set_direction(), or
|
||||||
|
to use an IRQ number that didn't originally come from gpio_to_irq().
|
||||||
|
|
||||||
|
These two mapping calls are expected to cost on the order of a single
|
||||||
|
addition or subtraction. They're not allowed to sleep.
|
||||||
|
|
||||||
|
Non-error values returned from gpio_to_irq() can be passed to request_irq()
|
||||||
|
or free_irq(). They will often be stored into IRQ resources for platform
|
||||||
|
devices, by the board-specific initialization code. Note that IRQ trigger
|
||||||
|
options are part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are
|
||||||
|
system wakeup capabilities.
|
||||||
|
|
||||||
|
Non-error values returned from irq_to_gpio() would most commonly be used
|
||||||
|
with gpio_get_value().
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
What do these conventions omit?
|
||||||
|
===============================
|
||||||
|
One of the biggest things these conventions omit is pin multiplexing, since
|
||||||
|
this is highly chip-specific and nonportable. One platform might not need
|
||||||
|
explicit multiplexing; another might have just two options for use of any
|
||||||
|
given pin; another might have eight options per pin; another might be able
|
||||||
|
to route a given GPIO to any one of several pins. (Yes, those examples all
|
||||||
|
come from systems that run Linux today.)
|
||||||
|
|
||||||
|
Related to multiplexing is configuration and enabling of the pullups or
|
||||||
|
pulldowns integrated on some platforms. Not all platforms support them,
|
||||||
|
or support them in the same way; and any given board might use external
|
||||||
|
pullups (or pulldowns) so that the on-chip ones should not be used.
|
||||||
|
|
||||||
|
There are other system-specific mechanisms that are not specified here,
|
||||||
|
like the aforementioned options for input de-glitching and wire-OR output.
|
||||||
|
Hardware may support reading or writing GPIOs in gangs, but that's usually
|
||||||
|
configuration dependednt: for GPIOs sharing the same bank. (GPIOs are
|
||||||
|
commonly grouped in banks of 16 or 32, with a given SOC having several such
|
||||||
|
banks.) Code relying on such mechanisms will necessarily be nonportable.
|
||||||
|
|
||||||
|
Dynamic definition of GPIOs is not currently supported; for example, as
|
||||||
|
a side effect of configuring an add-on board with some GPIO expanders.
|
||||||
|
|
||||||
|
These calls are purely for kernel space, but a userspace API could be built
|
||||||
|
on top of it.
|
|
@ -94,8 +94,7 @@ Code Seq# Include File Comments
|
||||||
'L' 00-1F linux/loop.h
|
'L' 00-1F linux/loop.h
|
||||||
'L' E0-FF linux/ppdd.h encrypted disk device driver
|
'L' E0-FF linux/ppdd.h encrypted disk device driver
|
||||||
<http://linux01.gwdg.de/~alatham/ppdd.html>
|
<http://linux01.gwdg.de/~alatham/ppdd.html>
|
||||||
'M' all linux/soundcard.h conflict!
|
'M' all linux/soundcard.h
|
||||||
'M' 00-1F linux/isicom.h conflict!
|
|
||||||
'N' 00-1F drivers/usb/scanner.h
|
'N' 00-1F drivers/usb/scanner.h
|
||||||
'P' all linux/soundcard.h
|
'P' all linux/soundcard.h
|
||||||
'Q' all linux/soundcard.h
|
'Q' all linux/soundcard.h
|
||||||
|
|
|
@ -8,29 +8,33 @@ GigaSet 307x Device Driver
|
||||||
This release supports the connection of the Gigaset 307x/417x family of
|
This release supports the connection of the Gigaset 307x/417x family of
|
||||||
ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
|
ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
|
||||||
connection. The following devices are reported to be compatible:
|
connection. The following devices are reported to be compatible:
|
||||||
307x/417x:
|
|
||||||
Gigaset SX255isdn
|
Bases:
|
||||||
Gigaset SX353isdn
|
Siemens Gigaset 3070/3075 isdn
|
||||||
Sinus 45 [AB] isdn (Deutsche Telekom)
|
Siemens Gigaset 4170/4175 isdn
|
||||||
Sinus 721X/XA
|
Siemens Gigaset SX205/255
|
||||||
|
Siemens Gigaset SX353
|
||||||
|
T-Com Sinus 45 [AB] isdn
|
||||||
|
T-Com Sinus 721X[A] [SE]
|
||||||
Vox Chicago 390 ISDN (KPN Telecom)
|
Vox Chicago 390 ISDN (KPN Telecom)
|
||||||
M101:
|
|
||||||
Sinus 45 Data 1 (Telekom)
|
RS232 data boxes:
|
||||||
M105:
|
Siemens Gigaset M101 Data
|
||||||
Gigaset USB Adapter DECT
|
T-Com Sinus 45 Data 1
|
||||||
Sinus 45 Data 2 (Telekom)
|
|
||||||
Sinus 721 data
|
USB data boxes:
|
||||||
|
Siemens Gigaset M105 Data
|
||||||
|
Siemens Gigaset USB Adapter DECT
|
||||||
|
T-Com Sinus 45 Data 2
|
||||||
|
T-Com Sinus 721 data
|
||||||
Chicago 390 USB (KPN)
|
Chicago 390 USB (KPN)
|
||||||
|
|
||||||
See also http://www.erbze.info/sinus_gigaset.htm and
|
See also http://www.erbze.info/sinus_gigaset.htm and
|
||||||
http://gigaset307x.sourceforge.net/
|
http://gigaset307x.sourceforge.net/
|
||||||
|
|
||||||
We had also reports from users of Gigaset M105 who could use the drivers
|
We had also reports from users of Gigaset M105 who could use the drivers
|
||||||
with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
|
with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
|
||||||
If you have another device that works with our driver, please let us know.
|
If you have another device that works with our driver, please let us know.
|
||||||
For example, Gigaset SX205isdn/Sinus 721 X SE and Gigaset SX303isdn bases
|
|
||||||
are just versions without answering machine of models known to work, so
|
|
||||||
they should work just as well; but so far we are lacking positive reports
|
|
||||||
on these.
|
|
||||||
|
|
||||||
Chances of getting an USB device to work are good if the output of
|
Chances of getting an USB device to work are good if the output of
|
||||||
lsusb
|
lsusb
|
||||||
|
@ -60,14 +64,28 @@ GigaSet 307x Device Driver
|
||||||
To get the device working, you have to load the proper kernel module. You
|
To get the device working, you have to load the proper kernel module. You
|
||||||
can do this using
|
can do this using
|
||||||
modprobe modulename
|
modprobe modulename
|
||||||
where modulename is usb_gigaset (M105) or bas_gigaset (direct USB
|
where modulename is ser_gigaset (M101), usb_gigaset (M105), or
|
||||||
connection to the base).
|
bas_gigaset (direct USB connection to the base).
|
||||||
|
|
||||||
|
The module ser_gigaset provides a serial line discipline N_GIGASET_M101
|
||||||
|
which drives the device through the regular serial line driver. To use it,
|
||||||
|
run the Gigaset M101 daemon "gigasetm101d" (also available from
|
||||||
|
http://sourceforge.net/projects/gigaset307x/) with the device file of the
|
||||||
|
RS232 port to the M101 as an argument, for example:
|
||||||
|
gigasetm101d /dev/ttyS1
|
||||||
|
This will open the device file, set its line discipline to N_GIGASET_M101,
|
||||||
|
and then sleep in the background, keeping the device open so that the
|
||||||
|
line discipline remains active. To deactivate it, kill the daemon, for
|
||||||
|
example with
|
||||||
|
killall gigasetm101d
|
||||||
|
before disconnecting the device.
|
||||||
|
|
||||||
2.2. Device nodes for user space programs
|
2.2. Device nodes for user space programs
|
||||||
------------------------------------
|
------------------------------------
|
||||||
The device can be accessed from user space (eg. by the user space tools
|
The device can be accessed from user space (eg. by the user space tools
|
||||||
mentioned in 1.2.) through the device nodes:
|
mentioned in 1.2.) through the device nodes:
|
||||||
|
|
||||||
|
- /dev/ttyGS0 for M101 (RS232 data boxes)
|
||||||
- /dev/ttyGU0 for M105 (USB data boxes)
|
- /dev/ttyGU0 for M105 (USB data boxes)
|
||||||
- /dev/ttyGB0 for the base driver (direct USB connection)
|
- /dev/ttyGB0 for the base driver (direct USB connection)
|
||||||
|
|
||||||
|
@ -168,6 +186,19 @@ GigaSet 307x Device Driver
|
||||||
You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
|
You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
|
||||||
setting (ttyGxy is ttyGU0 or ttyGB0).
|
setting (ttyGxy is ttyGU0 or ttyGB0).
|
||||||
|
|
||||||
|
2.6. M105 Undocumented USB Requests
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
The Gigaset M105 USB data box understands a couple of useful, but
|
||||||
|
undocumented USB commands. These requests are not used in normal
|
||||||
|
operation (for wireless access to the base), but are needed for access
|
||||||
|
to the M105's own configuration mode (registration to the base, baudrate
|
||||||
|
and line format settings, device status queries) via the gigacontr
|
||||||
|
utility. Their use is disabled in the driver by default for safety
|
||||||
|
reasons but can be enabled by setting the kernel configuration option
|
||||||
|
"Support for undocumented USB requests" (GIGASET_UNDOCREQ) to "Y" and
|
||||||
|
recompiling.
|
||||||
|
|
||||||
|
|
||||||
3. Troubleshooting
|
3. Troubleshooting
|
||||||
---------------
|
---------------
|
||||||
|
|
|
@ -311,10 +311,10 @@ Following are the arch specific command line options to be used while
|
||||||
loading dump-capture kernel.
|
loading dump-capture kernel.
|
||||||
|
|
||||||
For i386, x86_64 and ia64:
|
For i386, x86_64 and ia64:
|
||||||
"init 1 irqpoll maxcpus=1"
|
"1 irqpoll maxcpus=1"
|
||||||
|
|
||||||
For ppc64:
|
For ppc64:
|
||||||
"init 1 maxcpus=1 noirqdistrib"
|
"1 maxcpus=1 noirqdistrib"
|
||||||
|
|
||||||
|
|
||||||
Notes on loading the dump-capture kernel:
|
Notes on loading the dump-capture kernel:
|
||||||
|
@ -332,8 +332,8 @@ Notes on loading the dump-capture kernel:
|
||||||
* You must specify <root-dev> in the format corresponding to the root
|
* You must specify <root-dev> in the format corresponding to the root
|
||||||
device name in the output of mount command.
|
device name in the output of mount command.
|
||||||
|
|
||||||
* "init 1" boots the dump-capture kernel into single-user mode without
|
* Boot parameter "1" boots the dump-capture kernel into single-user
|
||||||
networking. If you want networking, use "init 3."
|
mode without networking. If you want networking, use "3".
|
||||||
|
|
||||||
* We generally don' have to bring up a SMP kernel just to capture the
|
* We generally don' have to bring up a SMP kernel just to capture the
|
||||||
dump. Hence generally it is useful either to build a UP dump-capture
|
dump. Hence generally it is useful either to build a UP dump-capture
|
||||||
|
|
|
@ -101,16 +101,20 @@ The format of the block comment is like this:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function_name(:)? (- short description)?
|
* function_name(:)? (- short description)?
|
||||||
(* @parameterx: (description of parameter x)?)*
|
(* @parameterx(space)*: (description of parameter x)?)*
|
||||||
(* a blank line)?
|
(* a blank line)?
|
||||||
* (Description:)? (Description of function)?
|
* (Description:)? (Description of function)?
|
||||||
* (section header: (section description)? )*
|
* (section header: (section description)? )*
|
||||||
(*)?*/
|
(*)?*/
|
||||||
|
|
||||||
The short function description cannot be multiline, but the other
|
The short function description ***cannot be multiline***, but the other
|
||||||
descriptions can be (and they can contain blank lines). Avoid putting a
|
descriptions can be (and they can contain blank lines). If you continue
|
||||||
spurious blank line after the function name, or else the description will
|
that initial short description onto a second line, that second line will
|
||||||
be repeated!
|
appear further down at the beginning of the description section, which is
|
||||||
|
almost certainly not what you had in mind.
|
||||||
|
|
||||||
|
Avoid putting a spurious blank line after the function name, or else the
|
||||||
|
description will be repeated!
|
||||||
|
|
||||||
All descriptive text is further processed, scanning for the following special
|
All descriptive text is further processed, scanning for the following special
|
||||||
patterns, which are highlighted appropriately.
|
patterns, which are highlighted appropriately.
|
||||||
|
@ -121,6 +125,31 @@ patterns, which are highlighted appropriately.
|
||||||
'@parameter' - name of a parameter
|
'@parameter' - name of a parameter
|
||||||
'%CONST' - name of a constant.
|
'%CONST' - name of a constant.
|
||||||
|
|
||||||
|
NOTE 1: The multi-line descriptive text you provide does *not* recognize
|
||||||
|
line breaks, so if you try to format some text nicely, as in:
|
||||||
|
|
||||||
|
Return codes
|
||||||
|
0 - cool
|
||||||
|
1 - invalid arg
|
||||||
|
2 - out of memory
|
||||||
|
|
||||||
|
this will all run together and produce:
|
||||||
|
|
||||||
|
Return codes 0 - cool 1 - invalid arg 2 - out of memory
|
||||||
|
|
||||||
|
NOTE 2: If the descriptive text you provide has lines that begin with
|
||||||
|
some phrase followed by a colon, each of those phrases will be taken as
|
||||||
|
a new section heading, which means you should similarly try to avoid text
|
||||||
|
like:
|
||||||
|
|
||||||
|
Return codes:
|
||||||
|
0: cool
|
||||||
|
1: invalid arg
|
||||||
|
2: out of memory
|
||||||
|
|
||||||
|
every line of which would start a new section. Again, probably not
|
||||||
|
what you were after.
|
||||||
|
|
||||||
Take a look around the source tree for examples.
|
Take a look around the source tree for examples.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1396,6 +1396,8 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
in <PAGE_SIZE> units (needed only for swap files).
|
in <PAGE_SIZE> units (needed only for swap files).
|
||||||
See Documentation/power/swsusp-and-swap-files.txt
|
See Documentation/power/swsusp-and-swap-files.txt
|
||||||
|
|
||||||
|
retain_initrd [RAM] Keep initrd memory after extraction
|
||||||
|
|
||||||
rhash_entries= [KNL,NET]
|
rhash_entries= [KNL,NET]
|
||||||
Set number of hash buckets for route cache
|
Set number of hash buckets for route cache
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
Semantics and Behavior of Local Atomic Operations
|
||||||
|
|
||||||
|
Mathieu Desnoyers
|
||||||
|
|
||||||
|
|
||||||
|
This document explains the purpose of the local atomic operations, how
|
||||||
|
to implement them for any given architecture and shows how they can be used
|
||||||
|
properly. It also stresses on the precautions that must be taken when reading
|
||||||
|
those local variables across CPUs when the order of memory writes matters.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* Purpose of local atomic operations
|
||||||
|
|
||||||
|
Local atomic operations are meant to provide fast and highly reentrant per CPU
|
||||||
|
counters. They minimize the performance cost of standard atomic operations by
|
||||||
|
removing the LOCK prefix and memory barriers normally required to synchronize
|
||||||
|
across CPUs.
|
||||||
|
|
||||||
|
Having fast per CPU atomic counters is interesting in many cases : it does not
|
||||||
|
require disabling interrupts to protect from interrupt handlers and it permits
|
||||||
|
coherent counters in NMI handlers. It is especially useful for tracing purposes
|
||||||
|
and for various performance monitoring counters.
|
||||||
|
|
||||||
|
Local atomic operations only guarantee variable modification atomicity wrt the
|
||||||
|
CPU which owns the data. Therefore, care must taken to make sure that only one
|
||||||
|
CPU writes to the local_t data. This is done by using per cpu data and making
|
||||||
|
sure that we modify it from within a preemption safe context. It is however
|
||||||
|
permitted to read local_t data from any CPU : it will then appear to be written
|
||||||
|
out of order wrt other memory writes on the owner CPU.
|
||||||
|
|
||||||
|
|
||||||
|
* Implementation for a given architecture
|
||||||
|
|
||||||
|
It can be done by slightly modifying the standard atomic operations : only
|
||||||
|
their UP variant must be kept. It typically means removing LOCK prefix (on
|
||||||
|
i386 and x86_64) and any SMP sychronization barrier. If the architecture does
|
||||||
|
not have a different behavior between SMP and UP, including asm-generic/local.h
|
||||||
|
in your archtecture's local.h is sufficient.
|
||||||
|
|
||||||
|
The local_t type is defined as an opaque signed long by embedding an
|
||||||
|
atomic_long_t inside a structure. This is made so a cast from this type to a
|
||||||
|
long fails. The definition looks like :
|
||||||
|
|
||||||
|
typedef struct { atomic_long_t a; } local_t;
|
||||||
|
|
||||||
|
|
||||||
|
* How to use local atomic operations
|
||||||
|
|
||||||
|
#include <linux/percpu.h>
|
||||||
|
#include <asm/local.h>
|
||||||
|
|
||||||
|
static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
|
||||||
|
|
||||||
|
|
||||||
|
* Counting
|
||||||
|
|
||||||
|
Counting is done on all the bits of a signed long.
|
||||||
|
|
||||||
|
In preemptible context, use get_cpu_var() and put_cpu_var() around local atomic
|
||||||
|
operations : it makes sure that preemption is disabled around write access to
|
||||||
|
the per cpu variable. For instance :
|
||||||
|
|
||||||
|
local_inc(&get_cpu_var(counters));
|
||||||
|
put_cpu_var(counters);
|
||||||
|
|
||||||
|
If you are already in a preemption-safe context, you can directly use
|
||||||
|
__get_cpu_var() instead.
|
||||||
|
|
||||||
|
local_inc(&__get_cpu_var(counters));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* Reading the counters
|
||||||
|
|
||||||
|
Those local counters can be read from foreign CPUs to sum the count. Note that
|
||||||
|
the data seen by local_read across CPUs must be considered to be out of order
|
||||||
|
relatively to other memory writes happening on the CPU that owns the data.
|
||||||
|
|
||||||
|
long sum = 0;
|
||||||
|
for_each_online_cpu(cpu)
|
||||||
|
sum += local_read(&per_cpu(counters, cpu));
|
||||||
|
|
||||||
|
If you want to use a remote local_read to synchronize access to a resource
|
||||||
|
between CPUs, explicit smp_wmb() and smp_rmb() memory barriers must be used
|
||||||
|
respectively on the writer and the reader CPUs. It would be the case if you use
|
||||||
|
the local_t variable as a counter of bytes written in a buffer : there should
|
||||||
|
be a smp_wmb() between the buffer write and the counter increment and also a
|
||||||
|
smp_rmb() between the counter read and the buffer read.
|
||||||
|
|
||||||
|
|
||||||
|
Here is a sample module which implements a basic per cpu counter using local.h.
|
||||||
|
|
||||||
|
--- BEGIN ---
|
||||||
|
/* test-local.c
|
||||||
|
*
|
||||||
|
* Sample module for local.h usage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <asm/local.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
|
||||||
|
static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
|
||||||
|
|
||||||
|
static struct timer_list test_timer;
|
||||||
|
|
||||||
|
/* IPI called on each CPU. */
|
||||||
|
static void test_each(void *info)
|
||||||
|
{
|
||||||
|
/* Increment the counter from a non preemptible context */
|
||||||
|
printk("Increment on cpu %d\n", smp_processor_id());
|
||||||
|
local_inc(&__get_cpu_var(counters));
|
||||||
|
|
||||||
|
/* This is what incrementing the variable would look like within a
|
||||||
|
* preemptible context (it disables preemption) :
|
||||||
|
*
|
||||||
|
* local_inc(&get_cpu_var(counters));
|
||||||
|
* put_cpu_var(counters);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_test_timer(unsigned long data)
|
||||||
|
{
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
/* Increment the counters */
|
||||||
|
on_each_cpu(test_each, NULL, 0, 1);
|
||||||
|
/* Read all the counters */
|
||||||
|
printk("Counters read from CPU %d\n", smp_processor_id());
|
||||||
|
for_each_online_cpu(cpu) {
|
||||||
|
printk("Read : CPU %d, count %ld\n", cpu,
|
||||||
|
local_read(&per_cpu(counters, cpu)));
|
||||||
|
}
|
||||||
|
del_timer(&test_timer);
|
||||||
|
test_timer.expires = jiffies + 1000;
|
||||||
|
add_timer(&test_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init test_init(void)
|
||||||
|
{
|
||||||
|
/* initialize the timer that will increment the counter */
|
||||||
|
init_timer(&test_timer);
|
||||||
|
test_timer.function = do_test_timer;
|
||||||
|
test_timer.expires = jiffies + 1;
|
||||||
|
add_timer(&test_timer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit test_exit(void)
|
||||||
|
{
|
||||||
|
del_timer_sync(&test_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(test_init);
|
||||||
|
module_exit(test_exit);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_AUTHOR("Mathieu Desnoyers");
|
||||||
|
MODULE_DESCRIPTION("Local Atomic Ops");
|
||||||
|
--- END ---
|
|
@ -67,8 +67,8 @@ nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
|
||||||
<nfs-options> Standard NFS options. All options are separated by commas.
|
<nfs-options> Standard NFS options. All options are separated by commas.
|
||||||
The following defaults are used:
|
The following defaults are used:
|
||||||
port = as given by server portmap daemon
|
port = as given by server portmap daemon
|
||||||
rsize = 1024
|
rsize = 4096
|
||||||
wsize = 1024
|
wsize = 4096
|
||||||
timeo = 7
|
timeo = 7
|
||||||
retrans = 3
|
retrans = 3
|
||||||
acregmin = 3
|
acregmin = 3
|
||||||
|
|
|
@ -1334,6 +1334,9 @@ platforms are moved over to use the flattened-device-tree model.
|
||||||
fsl-usb2-mph compatible controllers. Either this property or
|
fsl-usb2-mph compatible controllers. Either this property or
|
||||||
"port0" (or both) must be defined for "fsl-usb2-mph" compatible
|
"port0" (or both) must be defined for "fsl-usb2-mph" compatible
|
||||||
controllers.
|
controllers.
|
||||||
|
- dr_mode : indicates the working mode for "fsl-usb2-dr" compatible
|
||||||
|
controllers. Can be "host", "peripheral", or "otg". Default to
|
||||||
|
"host" if not defined for backward compatibility.
|
||||||
|
|
||||||
Recommended properties :
|
Recommended properties :
|
||||||
- interrupts : <a b> where a is the interrupt number and b is a
|
- interrupts : <a b> where a is the interrupt number and b is a
|
||||||
|
@ -1367,6 +1370,7 @@ platforms are moved over to use the flattened-device-tree model.
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
interrupt-parent = <700>;
|
interrupt-parent = <700>;
|
||||||
interrupts = <26 1>;
|
interrupts = <26 1>;
|
||||||
|
dr_mode = "otg";
|
||||||
phy = "ulpi";
|
phy = "ulpi";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
MPC52xx Device Tree Bindings
|
MPC5200 Device Tree Bindings
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
(c) 2006 Secret Lab Technologies Ltd
|
(c) 2006-2007 Secret Lab Technologies Ltd
|
||||||
Grant Likely <grant.likely at secretlab.ca>
|
Grant Likely <grant.likely at secretlab.ca>
|
||||||
|
|
||||||
********** DRAFT ***********
|
********** DRAFT ***********
|
||||||
|
@ -20,11 +20,11 @@ described in Documentation/powerpc/booting-without-of.txt), or passed
|
||||||
by Open Firmare (IEEE 1275) compatible firmware using an OF compatible
|
by Open Firmare (IEEE 1275) compatible firmware using an OF compatible
|
||||||
client interface API.
|
client interface API.
|
||||||
|
|
||||||
This document specifies the requirements on the device-tree for mpc52xx
|
This document specifies the requirements on the device-tree for mpc5200
|
||||||
based boards. These requirements are above and beyond the details
|
based boards. These requirements are above and beyond the details
|
||||||
specified in either the OpenFirmware spec or booting-without-of.txt
|
specified in either the OpenFirmware spec or booting-without-of.txt
|
||||||
|
|
||||||
All new mpc52xx-based boards are expected to match this document. In
|
All new mpc5200-based boards are expected to match this document. In
|
||||||
cases where this document is not sufficient to support a new board port,
|
cases where this document is not sufficient to support a new board port,
|
||||||
this document should be updated as part of adding the new board support.
|
this document should be updated as part of adding the new board support.
|
||||||
|
|
||||||
|
@ -32,26 +32,26 @@ II - Philosophy
|
||||||
===============
|
===============
|
||||||
The core of this document is naming convention. The whole point of
|
The core of this document is naming convention. The whole point of
|
||||||
defining this convention is to reduce or eliminate the number of
|
defining this convention is to reduce or eliminate the number of
|
||||||
special cases required to support a 52xx board. If all 52xx boards
|
special cases required to support a 5200 board. If all 5200 boards
|
||||||
follow the same convention, then generic 52xx support code will work
|
follow the same convention, then generic 5200 support code will work
|
||||||
rather than coding special cases for each new board.
|
rather than coding special cases for each new board.
|
||||||
|
|
||||||
This section tries to capture the thought process behind why the naming
|
This section tries to capture the thought process behind why the naming
|
||||||
convention is what it is.
|
convention is what it is.
|
||||||
|
|
||||||
1. Node names
|
1. names
|
||||||
-------------
|
---------
|
||||||
There is strong convention/requirements already established for children
|
There is strong convention/requirements already established for children
|
||||||
of the root node. 'cpus' describes the processor cores, 'memory'
|
of the root node. 'cpus' describes the processor cores, 'memory'
|
||||||
describes memory, and 'chosen' provides boot configuration. Other nodes
|
describes memory, and 'chosen' provides boot configuration. Other nodes
|
||||||
are added to describe devices attached to the processor local bus.
|
are added to describe devices attached to the processor local bus.
|
||||||
Following convention already established with other system-on-chip
|
|
||||||
processors, MPC52xx boards must have an 'soc5200' node as a child of the
|
|
||||||
root node.
|
|
||||||
|
|
||||||
The soc5200 node holds child nodes for all on chip devices. Child nodes
|
Following convention already established with other system-on-chip
|
||||||
are typically named after the configured function. ie. the FEC node is
|
processors, 5200 device trees should use the name 'soc5200' for the
|
||||||
named 'ethernet', and a PSC in uart mode is named 'serial'.
|
parent node of on chip devices, and the root node should be its parent.
|
||||||
|
|
||||||
|
Child nodes are typically named after the configured function. ie.
|
||||||
|
the FEC node is named 'ethernet', and a PSC in uart mode is named 'serial'.
|
||||||
|
|
||||||
2. device_type property
|
2. device_type property
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -66,28 +66,47 @@ exactly.
|
||||||
Since device_type isn't enough to match devices to drivers, there also
|
Since device_type isn't enough to match devices to drivers, there also
|
||||||
needs to be a naming convention for the compatible property. Compatible
|
needs to be a naming convention for the compatible property. Compatible
|
||||||
is an list of device descriptions sorted from specific to generic. For
|
is an list of device descriptions sorted from specific to generic. For
|
||||||
the mpc52xx, the required format for each compatible value is
|
the mpc5200, the required format for each compatible value is
|
||||||
<chip>-<device>[-<mode>]. At the minimum, the list shall contain two
|
<chip>-<device>[-<mode>]. The OS should be able to match a device driver
|
||||||
items; the first specifying the exact chip, and the second specifying
|
to the device based solely on the compatible value. If two drivers
|
||||||
mpc52xx for the chip.
|
match on the compatible list; the 'most compatible' driver should be
|
||||||
|
selected.
|
||||||
|
|
||||||
ie. ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc52xx-ethernet"
|
The split between the MPC5200 and the MPC5200B leaves a bit of a
|
||||||
|
connundrum. How should the compatible property be set up to provide
|
||||||
|
maximum compatability information; but still acurately describe the
|
||||||
|
chip? For the MPC5200; the answer is easy. Most of the SoC devices
|
||||||
|
originally appeared on the MPC5200. Since they didn't exist anywhere
|
||||||
|
else; the 5200 compatible properties will contain only one item;
|
||||||
|
"mpc5200-<device>".
|
||||||
|
|
||||||
The idea here is that most drivers will match to the most generic field
|
The 5200B is almost the same as the 5200, but not quite. It fixes
|
||||||
in the compatible list (mpc52xx-*), but can also test the more specific
|
silicon bugs and it adds a small number of enhancements. Most of the
|
||||||
field for enabling bug fixes or extra features.
|
devices either provide exactly the same interface as on the 5200. A few
|
||||||
|
devices have extra functions but still have a backwards compatible mode.
|
||||||
|
To express this infomation as completely as possible, 5200B device trees
|
||||||
|
should have two items in the compatible list;
|
||||||
|
"mpc5200b-<device>\0mpc5200-<device>". It is *strongly* recommended
|
||||||
|
that 5200B device trees follow this convention (instead of only listing
|
||||||
|
the base mpc5200 item).
|
||||||
|
|
||||||
|
If another chip appear on the market with one of the mpc5200 SoC
|
||||||
|
devices, then the compatible list should include mpc5200-<device>.
|
||||||
|
|
||||||
|
ie. ethernet on mpc5200: compatible = "mpc5200-ethernet"
|
||||||
|
ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc5200-ethernet"
|
||||||
|
|
||||||
Modal devices, like PSCs, also append the configured function to the
|
Modal devices, like PSCs, also append the configured function to the
|
||||||
end of the compatible field. ie. A PSC in i2s mode would specify
|
end of the compatible field. ie. A PSC in i2s mode would specify
|
||||||
"mpc52xx-psc-i2s", not "mpc52xx-i2s". This convention is chosen to
|
"mpc5200-psc-i2s", not "mpc5200-i2s". This convention is chosen to
|
||||||
avoid naming conflicts with non-psc devices providing the same
|
avoid naming conflicts with non-psc devices providing the same
|
||||||
function. For example, "mpc52xx-spi" and "mpc52xx-psc-spi" describe
|
function. For example, "mpc5200-spi" and "mpc5200-psc-spi" describe
|
||||||
the mpc5200 simple spi device and a PSC spi mode respectively.
|
the mpc5200 simple spi device and a PSC spi mode respectively.
|
||||||
|
|
||||||
If the soc device is more generic and present on other SOCs, the
|
If the soc device is more generic and present on other SOCs, the
|
||||||
compatible property can specify the more generic device type also.
|
compatible property can specify the more generic device type also.
|
||||||
|
|
||||||
ie. mscan: compatible = "mpc5200-mscan\0mpc52xx-mscan\0fsl,mscan";
|
ie. mscan: compatible = "mpc5200-mscan\0fsl,mscan";
|
||||||
|
|
||||||
At the time of writing, exact chip may be either 'mpc5200' or
|
At the time of writing, exact chip may be either 'mpc5200' or
|
||||||
'mpc5200b'.
|
'mpc5200b'.
|
||||||
|
@ -96,7 +115,7 @@ Device drivers should always try to match as generically as possible.
|
||||||
|
|
||||||
III - Structure
|
III - Structure
|
||||||
===============
|
===============
|
||||||
The device tree for an mpc52xx board follows the structure defined in
|
The device tree for an mpc5200 board follows the structure defined in
|
||||||
booting-without-of.txt with the following additional notes:
|
booting-without-of.txt with the following additional notes:
|
||||||
|
|
||||||
0) the root node
|
0) the root node
|
||||||
|
@ -115,7 +134,7 @@ Typical memory description node; see booting-without-of.
|
||||||
|
|
||||||
3) The soc5200 node
|
3) The soc5200 node
|
||||||
-------------------
|
-------------------
|
||||||
This node describes the on chip SOC peripherals. Every mpc52xx based
|
This node describes the on chip SOC peripherals. Every mpc5200 based
|
||||||
board will have this node, and as such there is a common naming
|
board will have this node, and as such there is a common naming
|
||||||
convention for SOC devices.
|
convention for SOC devices.
|
||||||
|
|
||||||
|
@ -125,71 +144,111 @@ name type description
|
||||||
device_type string must be "soc"
|
device_type string must be "soc"
|
||||||
ranges int should be <0 baseaddr baseaddr+10000>
|
ranges int should be <0 baseaddr baseaddr+10000>
|
||||||
reg int must be <baseaddr 10000>
|
reg int must be <baseaddr 10000>
|
||||||
|
compatible string mpc5200: "mpc5200-soc"
|
||||||
|
mpc5200b: "mpc5200b-soc\0mpc5200-soc"
|
||||||
|
system-frequency int Fsystem frequency; source of all
|
||||||
|
other clocks.
|
||||||
|
bus-frequency int IPB bus frequency in HZ. Clock rate
|
||||||
|
used by most of the soc devices.
|
||||||
|
#interrupt-cells int must be <3>.
|
||||||
|
|
||||||
Recommended properties:
|
Recommended properties:
|
||||||
name type description
|
name type description
|
||||||
---- ---- -----------
|
---- ---- -----------
|
||||||
compatible string should be "<chip>-soc\0mpc52xx-soc"
|
model string Exact model of the chip;
|
||||||
ie. "mpc5200b-soc\0mpc52xx-soc"
|
ie: model="fsl,mpc5200"
|
||||||
#interrupt-cells int must be <3>. If it is not defined
|
revision string Silicon revision of chip
|
||||||
here then it must be defined in every
|
ie: revision="M08A"
|
||||||
soc device node.
|
|
||||||
bus-frequency int IPB bus frequency in HZ. Clock rate
|
The 'model' and 'revision' properties are *strongly* recommended. Having
|
||||||
used by most of the soc devices.
|
them presence acts as a bit of a safety net for working around as yet
|
||||||
Defining it here avoids needing it
|
undiscovered bugs on one version of silicon. For example, device drivers
|
||||||
added to every device node.
|
can use the model and revision properties to decide if a bug fix should
|
||||||
|
be turned on.
|
||||||
|
|
||||||
4) soc5200 child nodes
|
4) soc5200 child nodes
|
||||||
----------------------
|
----------------------
|
||||||
Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
|
Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
|
||||||
|
|
||||||
Note: in the tables below, '*' matches all <chip> values. ie.
|
Note: The tables below show the value for the mpc5200. A mpc5200b device
|
||||||
*-pic would translate to "mpc5200-pic\0mpc52xx-pic"
|
tree should use the "mpc5200b-<device>\0mpc5200-<device> form.
|
||||||
|
|
||||||
Required soc5200 child nodes:
|
Required soc5200 child nodes:
|
||||||
name device_type compatible Description
|
name device_type compatible Description
|
||||||
---- ----------- ---------- -----------
|
---- ----------- ---------- -----------
|
||||||
cdm@<addr> cdm *-cmd Clock Distribution
|
cdm@<addr> cdm mpc5200-cmd Clock Distribution
|
||||||
pic@<addr> interrupt-controller *-pic need an interrupt
|
pic@<addr> interrupt-controller mpc5200-pic need an interrupt
|
||||||
controller to boot
|
controller to boot
|
||||||
bestcomm@<addr> dma-controller *-bestcomm 52xx pic also requires
|
bestcomm@<addr> dma-controller mpc5200-bestcomm 5200 pic also requires
|
||||||
the bestcomm device
|
the bestcomm device
|
||||||
|
|
||||||
Recommended soc5200 child nodes; populate as needed for your board
|
Recommended soc5200 child nodes; populate as needed for your board
|
||||||
name device_type compatible Description
|
name device_type compatible Description
|
||||||
---- ----------- ---------- -----------
|
---- ----------- ---------- -----------
|
||||||
gpt@<addr> gpt *-gpt General purpose timers
|
gpt@<addr> gpt mpc5200-gpt General purpose timers
|
||||||
rtc@<addr> rtc *-rtc Real time clock
|
rtc@<addr> rtc mpc5200-rtc Real time clock
|
||||||
mscan@<addr> mscan *-mscan CAN bus controller
|
mscan@<addr> mscan mpc5200-mscan CAN bus controller
|
||||||
pci@<addr> pci *-pci PCI bridge
|
pci@<addr> pci mpc5200-pci PCI bridge
|
||||||
serial@<addr> serial *-psc-uart PSC in serial mode
|
serial@<addr> serial mpc5200-psc-uart PSC in serial mode
|
||||||
i2s@<addr> sound *-psc-i2s PSC in i2s mode
|
i2s@<addr> sound mpc5200-psc-i2s PSC in i2s mode
|
||||||
ac97@<addr> sound *-psc-ac97 PSC in ac97 mode
|
ac97@<addr> sound mpc5200-psc-ac97 PSC in ac97 mode
|
||||||
spi@<addr> spi *-psc-spi PSC in spi mode
|
spi@<addr> spi mpc5200-psc-spi PSC in spi mode
|
||||||
irda@<addr> irda *-psc-irda PSC in IrDA mode
|
irda@<addr> irda mpc5200-psc-irda PSC in IrDA mode
|
||||||
spi@<addr> spi *-spi MPC52xx spi device
|
spi@<addr> spi mpc5200-spi MPC5200 spi device
|
||||||
ethernet@<addr> network *-fec MPC52xx ethernet device
|
ethernet@<addr> network mpc5200-fec MPC5200 ethernet device
|
||||||
ata@<addr> ata *-ata IDE ATA interface
|
ata@<addr> ata mpc5200-ata IDE ATA interface
|
||||||
i2c@<addr> i2c *-i2c I2C controller
|
i2c@<addr> i2c mpc5200-i2c I2C controller
|
||||||
usb@<addr> usb-ohci-be *-ohci,ohci-be USB controller
|
usb@<addr> usb-ohci-be mpc5200-ohci,ohci-be USB controller
|
||||||
xlb@<addr> xlb *-xlb XLB arbritrator
|
xlb@<addr> xlb mpc5200-xlb XLB arbritrator
|
||||||
|
|
||||||
|
Important child node properties
|
||||||
|
name type description
|
||||||
|
---- ---- -----------
|
||||||
|
cell-index int When multiple devices are present, is the
|
||||||
|
index of the device in the hardware (ie. There
|
||||||
|
are 6 PSC on the 5200 numbered PSC1 to PSC6)
|
||||||
|
PSC1 has 'cell-index = <0>'
|
||||||
|
PSC4 has 'cell-index = <3>'
|
||||||
|
|
||||||
|
5) General Purpose Timer nodes (child of soc5200 node)
|
||||||
|
On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board
|
||||||
|
design supports the internal wdt, then the device node for GPT0 should
|
||||||
|
include the empty property 'has-wdt'.
|
||||||
|
|
||||||
|
6) PSC nodes (child of soc5200 node)
|
||||||
|
PSC nodes can define the optional 'port-number' property to force assignment
|
||||||
|
order of serial ports. For example, PSC5 might be physically connected to
|
||||||
|
the port labeled 'COM1' and PSC1 wired to 'COM1'. In this case, PSC5 would
|
||||||
|
have a "port-number = <0>" property, and PSC1 would have "port-number = <1>".
|
||||||
|
|
||||||
|
PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in
|
||||||
|
i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
|
||||||
|
compatible field.
|
||||||
|
|
||||||
IV - Extra Notes
|
IV - Extra Notes
|
||||||
================
|
================
|
||||||
|
|
||||||
1. Interrupt mapping
|
1. Interrupt mapping
|
||||||
--------------------
|
--------------------
|
||||||
The mpc52xx pic driver splits hardware IRQ numbers into two levels. The
|
The mpc5200 pic driver splits hardware IRQ numbers into two levels. The
|
||||||
split reflects the layout of the PIC hardware itself, which groups
|
split reflects the layout of the PIC hardware itself, which groups
|
||||||
interrupts into one of three groups; CRIT, MAIN or PERP. Also, the
|
interrupts into one of three groups; CRIT, MAIN or PERP. Also, the
|
||||||
Bestcomm dma engine has it's own set of interrupt sources which are
|
Bestcomm dma engine has it's own set of interrupt sources which are
|
||||||
cascaded off of peripheral interrupt 0, which the driver interprets as a
|
cascaded off of peripheral interrupt 0, which the driver interprets as a
|
||||||
fourth group, SDMA.
|
fourth group, SDMA.
|
||||||
|
|
||||||
The interrupts property for device nodes using the mpc52xx pic consists
|
The interrupts property for device nodes using the mpc5200 pic consists
|
||||||
of three cells; <L1 L2 level>
|
of three cells; <L1 L2 level>
|
||||||
|
|
||||||
L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
|
L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
|
||||||
L2 := interrupt number; directly mapped from the value in the
|
L2 := interrupt number; directly mapped from the value in the
|
||||||
"ICTL PerStat, MainStat, CritStat Encoded Register"
|
"ICTL PerStat, MainStat, CritStat Encoded Register"
|
||||||
level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]
|
level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]
|
||||||
|
|
||||||
|
2. Shared registers
|
||||||
|
-------------------
|
||||||
|
Some SoC devices share registers between them. ie. the i2c devices use
|
||||||
|
a single clock control register, and almost all device are affected by
|
||||||
|
the port_config register. Devices which need to manipulate shared regs
|
||||||
|
should look to the parent SoC node. The soc node is responsible
|
||||||
|
for arbitrating all shared register access.
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
Red-black Trees (rbtree) in Linux
|
||||||
|
January 18, 2007
|
||||||
|
Rob Landley <rob@landley.net>
|
||||||
|
=============================
|
||||||
|
|
||||||
|
What are red-black trees, and what are they for?
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
Red-black trees are a type of self-balancing binary search tree, used for
|
||||||
|
storing sortable key/value data pairs. This differs from radix trees (which
|
||||||
|
are used to efficiently store sparse arrays and thus use long integer indexes
|
||||||
|
to insert/access/delete nodes) and hash tables (which are not kept sorted to
|
||||||
|
be easily traversed in order, and must be tuned for a specific size and
|
||||||
|
hash function where rbtrees scale gracefully storing arbitrary keys).
|
||||||
|
|
||||||
|
Red-black trees are similar to AVL trees, but provide faster real-time bounded
|
||||||
|
worst case performance for insertion and deletion (at most two rotations and
|
||||||
|
three rotations, respectively, to balance the tree), with slightly slower
|
||||||
|
(but still O(log n)) lookup time.
|
||||||
|
|
||||||
|
To quote Linux Weekly News:
|
||||||
|
|
||||||
|
There are a number of red-black trees in use in the kernel.
|
||||||
|
The anticipatory, deadline, and CFQ I/O schedulers all employ
|
||||||
|
rbtrees to track requests; the packet CD/DVD driver does the same.
|
||||||
|
The high-resolution timer code uses an rbtree to organize outstanding
|
||||||
|
timer requests. The ext3 filesystem tracks directory entries in a
|
||||||
|
red-black tree. Virtual memory areas (VMAs) are tracked with red-black
|
||||||
|
trees, as are epoll file descriptors, cryptographic keys, and network
|
||||||
|
packets in the "hierarchical token bucket" scheduler.
|
||||||
|
|
||||||
|
This document covers use of the Linux rbtree implementation. For more
|
||||||
|
information on the nature and implementation of Red Black Trees, see:
|
||||||
|
|
||||||
|
Linux Weekly News article on red-black trees
|
||||||
|
http://lwn.net/Articles/184495/
|
||||||
|
|
||||||
|
Wikipedia entry on red-black trees
|
||||||
|
http://en.wikipedia.org/wiki/Red-black_tree
|
||||||
|
|
||||||
|
Linux implementation of red-black trees
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Linux's rbtree implementation lives in the file "lib/rbtree.c". To use it,
|
||||||
|
"#include <linux/rbtree.h>".
|
||||||
|
|
||||||
|
The Linux rbtree implementation is optimized for speed, and thus has one
|
||||||
|
less layer of indirection (and better cache locality) than more traditional
|
||||||
|
tree implementations. Instead of using pointers to separate rb_node and data
|
||||||
|
structures, each instance of struct rb_node is embedded in the data structure
|
||||||
|
it organizes. And instead of using a comparison callback function pointer,
|
||||||
|
users are expected to write their own tree search and insert functions
|
||||||
|
which call the provided rbtree functions. Locking is also left up to the
|
||||||
|
user of the rbtree code.
|
||||||
|
|
||||||
|
Creating a new rbtree
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Data nodes in an rbtree tree are structures containing a struct rb_node member:
|
||||||
|
|
||||||
|
struct mytype {
|
||||||
|
struct rb_node node;
|
||||||
|
char *keystring;
|
||||||
|
};
|
||||||
|
|
||||||
|
When dealing with a pointer to the embedded struct rb_node, the containing data
|
||||||
|
structure may be accessed with the standard container_of() macro. In addition,
|
||||||
|
individual members may be accessed directly via rb_entry(node, type, member).
|
||||||
|
|
||||||
|
At the root of each rbtree is an rb_root structure, which is initialized to be
|
||||||
|
empty via:
|
||||||
|
|
||||||
|
struct rb_root mytree = RB_ROOT;
|
||||||
|
|
||||||
|
Searching for a value in an rbtree
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Writing a search function for your tree is fairly straightforward: start at the
|
||||||
|
root, compare each value, and follow the left or right branch as necessary.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
struct mytype *my_search(struct rb_root *root, char *string)
|
||||||
|
{
|
||||||
|
struct rb_node *node = root->rb_node;
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
struct mytype *data = container_of(node, struct mytype, node);
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = strcmp(string, data->keystring);
|
||||||
|
|
||||||
|
if (result < 0)
|
||||||
|
node = node->rb_left;
|
||||||
|
else if (result > 0)
|
||||||
|
node = node->rb_right;
|
||||||
|
else
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inserting data into an rbtree
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Inserting data in the tree involves first searching for the place to insert the
|
||||||
|
new node, then inserting the node and rebalancing ("recoloring") the tree.
|
||||||
|
|
||||||
|
The search for insertion differs from the previous search by finding the
|
||||||
|
location of the pointer on which to graft the new node. The new node also
|
||||||
|
needs a link to its parent node for rebalancing purposes.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
int my_insert(struct rb_root *root, struct mytype *data)
|
||||||
|
{
|
||||||
|
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
||||||
|
|
||||||
|
/* Figure out where to put new node */
|
||||||
|
while (*new) {
|
||||||
|
struct mytype *this = container_of(*new, struct mytype, node);
|
||||||
|
int result = strcmp(data->keystring, this->keystring);
|
||||||
|
|
||||||
|
parent = *new;
|
||||||
|
if (result < 0)
|
||||||
|
new = &((*new)->rb_left);
|
||||||
|
else if (result > 0)
|
||||||
|
new = &((*new)->rb_right);
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new node and rebalance tree. */
|
||||||
|
rb_link_node(data->node, parent, new);
|
||||||
|
rb_insert_color(data->node, root);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Removing or replacing existing data in an rbtree
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
To remove an existing node from a tree, call:
|
||||||
|
|
||||||
|
void rb_erase(struct rb_node *victim, struct rb_root *tree);
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
struct mytype *data = mysearch(mytree, "walrus");
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
rb_erase(data->node, mytree);
|
||||||
|
myfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
To replace an existing node in a tree with a new one with the same key, call:
|
||||||
|
|
||||||
|
void rb_replace_node(struct rb_node *old, struct rb_node *new,
|
||||||
|
struct rb_root *tree);
|
||||||
|
|
||||||
|
Replacing a node this way does not re-sort the tree: If the new node doesn't
|
||||||
|
have the same key as the old node, the rbtree will probably become corrupted.
|
||||||
|
|
||||||
|
Iterating through the elements stored in an rbtree (in sort order)
|
||||||
|
------------------------------------------------------------------
|
||||||
|
|
||||||
|
Four functions are provided for iterating through an rbtree's contents in
|
||||||
|
sorted order. These work on arbitrary trees, and should not need to be
|
||||||
|
modified or wrapped (except for locking purposes):
|
||||||
|
|
||||||
|
struct rb_node *rb_first(struct rb_root *tree);
|
||||||
|
struct rb_node *rb_last(struct rb_root *tree);
|
||||||
|
struct rb_node *rb_next(struct rb_node *node);
|
||||||
|
struct rb_node *rb_prev(struct rb_node *node);
|
||||||
|
|
||||||
|
To start iterating, call rb_first() or rb_last() with a pointer to the root
|
||||||
|
of the tree, which will return a pointer to the node structure contained in
|
||||||
|
the first or last element in the tree. To continue, fetch the next or previous
|
||||||
|
node by calling rb_next() or rb_prev() on the current node. This will return
|
||||||
|
NULL when there are no more nodes left.
|
||||||
|
|
||||||
|
The iterator functions return a pointer to the embedded struct rb_node, from
|
||||||
|
which the containing data structure may be accessed with the container_of()
|
||||||
|
macro, and individual members may be accessed directly via
|
||||||
|
rb_entry(node, type, member).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
struct rb_node *node;
|
||||||
|
for (node = rb_first(&mytree); node; node = rb_next(node))
|
||||||
|
printk("key=%s\n", rb_entry(node, int, keystring));
|
||||||
|
|
|
@ -149,7 +149,7 @@ RTC class framework, but can't be supported by the older driver.
|
||||||
is connected to an IRQ line, it can often issue an alarm IRQ up to
|
is connected to an IRQ line, it can often issue an alarm IRQ up to
|
||||||
24 hours in the future.
|
24 hours in the future.
|
||||||
|
|
||||||
* RTC_WKALM_SET, RTC_WKALM_READ ... RTCs that can issue alarms beyond
|
* RTC_WKALM_SET, RTC_WKALM_RD ... RTCs that can issue alarms beyond
|
||||||
the next 24 hours use a slightly more powerful API, which supports
|
the next 24 hours use a slightly more powerful API, which supports
|
||||||
setting the longer alarm time and enabling its IRQ using a single
|
setting the longer alarm time and enabling its IRQ using a single
|
||||||
request (using the same model as EFI firmware).
|
request (using the same model as EFI firmware).
|
||||||
|
@ -167,6 +167,28 @@ Linux out of a low power sleep state (or hibernation) back to a fully
|
||||||
operational state. For example, a system could enter a deep power saving
|
operational state. For example, a system could enter a deep power saving
|
||||||
state until it's time to execute some scheduled tasks.
|
state until it's time to execute some scheduled tasks.
|
||||||
|
|
||||||
|
Note that many of these ioctls need not actually be implemented by your
|
||||||
|
driver. The common rtc-dev interface handles many of these nicely if your
|
||||||
|
driver returns ENOIOCTLCMD. Some common examples:
|
||||||
|
|
||||||
|
* RTC_RD_TIME, RTC_SET_TIME: the read_time/set_time functions will be
|
||||||
|
called with appropriate values.
|
||||||
|
|
||||||
|
* RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: the
|
||||||
|
set_alarm/read_alarm functions will be called. To differentiate
|
||||||
|
between the ALM and WKALM, check the larger fields of the rtc_wkalrm
|
||||||
|
struct (like tm_year). These will be set to -1 when using ALM and
|
||||||
|
will be set to proper values when using WKALM.
|
||||||
|
|
||||||
|
* RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
|
||||||
|
to set the frequency while the framework will handle the read for you
|
||||||
|
since the frequency is stored in the irq_freq member of the rtc_device
|
||||||
|
structure. Also make sure you set the max_user_freq member in your
|
||||||
|
initialization routines so the framework can sanity check the user
|
||||||
|
input for you.
|
||||||
|
|
||||||
|
If all else fails, check out the rtc-test.c driver!
|
||||||
|
|
||||||
|
|
||||||
-------------------- 8< ---------------- 8< -----------------------------
|
-------------------- 8< ---------------- 8< -----------------------------
|
||||||
|
|
||||||
|
@ -237,7 +259,7 @@ int main(int argc, char **argv)
|
||||||
"\n...Update IRQs not supported.\n");
|
"\n...Update IRQs not supported.\n");
|
||||||
goto test_READ;
|
goto test_READ;
|
||||||
}
|
}
|
||||||
perror("ioctl");
|
perror("RTC_UIE_ON ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +306,7 @@ int main(int argc, char **argv)
|
||||||
/* Turn off update interrupts */
|
/* Turn off update interrupts */
|
||||||
retval = ioctl(fd, RTC_UIE_OFF, 0);
|
retval = ioctl(fd, RTC_UIE_OFF, 0);
|
||||||
if (retval == -1) {
|
if (retval == -1) {
|
||||||
perror("ioctl");
|
perror("RTC_UIE_OFF ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +314,7 @@ test_READ:
|
||||||
/* Read the RTC time/date */
|
/* Read the RTC time/date */
|
||||||
retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
|
retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
|
||||||
if (retval == -1) {
|
if (retval == -1) {
|
||||||
perror("ioctl");
|
perror("RTC_RD_TIME ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,14 +342,14 @@ test_READ:
|
||||||
"\n...Alarm IRQs not supported.\n");
|
"\n...Alarm IRQs not supported.\n");
|
||||||
goto test_PIE;
|
goto test_PIE;
|
||||||
}
|
}
|
||||||
perror("ioctl");
|
perror("RTC_ALM_SET ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the current alarm settings */
|
/* Read the current alarm settings */
|
||||||
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
|
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
|
||||||
if (retval == -1) {
|
if (retval == -1) {
|
||||||
perror("ioctl");
|
perror("RTC_ALM_READ ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +359,7 @@ test_READ:
|
||||||
/* Enable alarm interrupts */
|
/* Enable alarm interrupts */
|
||||||
retval = ioctl(fd, RTC_AIE_ON, 0);
|
retval = ioctl(fd, RTC_AIE_ON, 0);
|
||||||
if (retval == -1) {
|
if (retval == -1) {
|
||||||
perror("ioctl");
|
perror("RTC_AIE_ON ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,7 +377,7 @@ test_READ:
|
||||||
/* Disable alarm interrupts */
|
/* Disable alarm interrupts */
|
||||||
retval = ioctl(fd, RTC_AIE_OFF, 0);
|
retval = ioctl(fd, RTC_AIE_OFF, 0);
|
||||||
if (retval == -1) {
|
if (retval == -1) {
|
||||||
perror("ioctl");
|
perror("RTC_AIE_OFF ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +390,7 @@ test_PIE:
|
||||||
fprintf(stderr, "\nNo periodic IRQ support\n");
|
fprintf(stderr, "\nNo periodic IRQ support\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
perror("ioctl");
|
perror("RTC_IRQP_READ ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
|
fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
|
||||||
|
@ -387,7 +409,7 @@ test_PIE:
|
||||||
"\n...Periodic IRQ rate is fixed\n");
|
"\n...Periodic IRQ rate is fixed\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
perror("ioctl");
|
perror("RTC_IRQP_SET ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +419,7 @@ test_PIE:
|
||||||
/* Enable periodic interrupts */
|
/* Enable periodic interrupts */
|
||||||
retval = ioctl(fd, RTC_PIE_ON, 0);
|
retval = ioctl(fd, RTC_PIE_ON, 0);
|
||||||
if (retval == -1) {
|
if (retval == -1) {
|
||||||
perror("ioctl");
|
perror("RTC_PIE_ON ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,7 +438,7 @@ test_PIE:
|
||||||
/* Disable periodic interrupts */
|
/* Disable periodic interrupts */
|
||||||
retval = ioctl(fd, RTC_PIE_OFF, 0);
|
retval = ioctl(fd, RTC_PIE_OFF, 0);
|
||||||
if (retval == -1) {
|
if (retval == -1) {
|
||||||
perror("ioctl");
|
perror("RTC_PIE_OFF ioctl");
|
||||||
exit(errno);
|
exit(errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
Release Date : Thu Nov 16 15:32:35 EST 2006 -
|
||||||
|
Sumant Patro <sumant.patro@lsi.com>
|
||||||
|
Current Version : 2.20.5.1 (scsi module), 2.20.2.6 (cmm module)
|
||||||
|
Older Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
|
||||||
|
|
||||||
|
1. Changes in Initialization to fix kdump failure.
|
||||||
|
Send SYNC command on loading.
|
||||||
|
This command clears the pending commands in the adapter
|
||||||
|
and re-initialize its internal RAID structure.
|
||||||
|
Without this change, megaraid driver either panics or fails to
|
||||||
|
initialize the adapter during kdump's second kernel boot
|
||||||
|
if there are pending commands or interrupts from other devices
|
||||||
|
sharing the same IRQ.
|
||||||
|
2. Authors email-id domain name changed from lsil.com to lsi.com.
|
||||||
|
Also modified the MODULE_AUTHOR to megaraidlinux@lsi.com
|
||||||
|
|
||||||
Release Date : Fri May 19 09:31:45 EST 2006 - Seokmann Ju <sju@lsil.com>
|
Release Date : Fri May 19 09:31:45 EST 2006 - Seokmann Ju <sju@lsil.com>
|
||||||
Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
|
Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
|
||||||
Older Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
|
Older Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
|
||||||
|
|
|
@ -242,6 +242,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
ac97_clock - AC'97 clock (default = 48000)
|
ac97_clock - AC'97 clock (default = 48000)
|
||||||
ac97_quirk - AC'97 workaround for strange hardware
|
ac97_quirk - AC'97 workaround for strange hardware
|
||||||
See "AC97 Quirk Option" section below.
|
See "AC97 Quirk Option" section below.
|
||||||
|
ac97_codec - Workaround to specify which AC'97 codec
|
||||||
|
instead of probing. If this works for you
|
||||||
|
file a bug with your `lspci -vn` output.
|
||||||
|
-2 -- Force probing.
|
||||||
|
-1 -- Default behavior.
|
||||||
|
0-2 -- Use the specified codec.
|
||||||
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
|
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
|
||||||
|
|
||||||
This module supports one card and autoprobe.
|
This module supports one card and autoprobe.
|
||||||
|
@ -779,6 +785,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
asus-dig ASUS with SPDIF out
|
asus-dig ASUS with SPDIF out
|
||||||
asus-dig2 ASUS with SPDIF out (using GPIO2)
|
asus-dig2 ASUS with SPDIF out (using GPIO2)
|
||||||
uniwill 3-jack
|
uniwill 3-jack
|
||||||
|
fujitsu Fujitsu Laptops (Pi1536)
|
||||||
F1734 2-jack
|
F1734 2-jack
|
||||||
lg LG laptop (m1 express dual)
|
lg LG laptop (m1 express dual)
|
||||||
lg-lw LG LW20/LW25 laptop
|
lg-lw LG LW20/LW25 laptop
|
||||||
|
@ -800,14 +807,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
ALC262
|
ALC262
|
||||||
fujitsu Fujitsu Laptop
|
fujitsu Fujitsu Laptop
|
||||||
hp-bpc HP xw4400/6400/8400/9400 laptops
|
hp-bpc HP xw4400/6400/8400/9400 laptops
|
||||||
|
hp-bpc-d7000 HP BPC D7000
|
||||||
benq Benq ED8
|
benq Benq ED8
|
||||||
|
hippo Hippo (ATI) with jack detection, Sony UX-90s
|
||||||
|
hippo_1 Hippo (Benq) with jack detection
|
||||||
basic fixed pin assignment w/o SPDIF
|
basic fixed pin assignment w/o SPDIF
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
ALC882/885
|
ALC882/885
|
||||||
3stack-dig 3-jack with SPDIF I/O
|
3stack-dig 3-jack with SPDIF I/O
|
||||||
6stck-dig 6-jack digital with SPDIF I/O
|
6stack-dig 6-jack digital with SPDIF I/O
|
||||||
arima Arima W820Di1
|
arima Arima W820Di1
|
||||||
|
macpro MacPro support
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
ALC883/888
|
ALC883/888
|
||||||
|
@ -817,6 +828,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
|
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
|
||||||
6stack-dig-demo 6-jack digital for Intel demo board
|
6stack-dig-demo 6-jack digital for Intel demo board
|
||||||
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
|
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
|
||||||
|
medion Medion Laptops
|
||||||
|
targa-dig Targa/MSI
|
||||||
|
targa-2ch-dig Targs/MSI with 2-channel
|
||||||
|
laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
ALC861/660
|
ALC861/660
|
||||||
|
@ -825,6 +840,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
6stack-dig 6-jack with SPDIF I/O
|
6stack-dig 6-jack with SPDIF I/O
|
||||||
3stack-660 3-jack (for ALC660)
|
3stack-660 3-jack (for ALC660)
|
||||||
uniwill-m31 Uniwill M31 laptop
|
uniwill-m31 Uniwill M31 laptop
|
||||||
|
toshiba Toshiba laptop support
|
||||||
|
asus Asus laptop support
|
||||||
|
asus-laptop ASUS F2/F3 laptops
|
||||||
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
|
ALC861VD/660VD
|
||||||
|
3stack 3-jack
|
||||||
|
3stack-dig 3-jack with SPDIF OUT
|
||||||
|
6stack-dig 6-jack with SPDIF OUT
|
||||||
|
3stack-660 3-jack (for ALC660VD)
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
CMI9880
|
CMI9880
|
||||||
|
@ -845,6 +870,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
3stack 3-stack, shared surrounds
|
3stack 3-stack, shared surrounds
|
||||||
laptop 2-channel only (FSC V2060, Samsung M50)
|
laptop 2-channel only (FSC V2060, Samsung M50)
|
||||||
laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
|
laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
|
||||||
|
ultra 2-channel with EAPD (Samsung Ultra tablet PC)
|
||||||
|
|
||||||
AD1988
|
AD1988
|
||||||
6stack 6-jack
|
6stack 6-jack
|
||||||
|
@ -854,12 +880,31 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
laptop 3-jack with hp-jack automute
|
laptop 3-jack with hp-jack automute
|
||||||
laptop-dig ditto with SPDIF
|
laptop-dig ditto with SPDIF
|
||||||
auto auto-config reading BIOS (default)
|
auto auto-config reading BIOS (default)
|
||||||
|
|
||||||
|
Conexant 5045
|
||||||
|
laptop Laptop config
|
||||||
|
test for testing/debugging purpose, almost all controls
|
||||||
|
can be adjusted. Appearing only when compiled with
|
||||||
|
$CONFIG_SND_DEBUG=y
|
||||||
|
|
||||||
|
Conexant 5047
|
||||||
|
laptop Basic Laptop config
|
||||||
|
laptop-hp Laptop config for some HP models (subdevice 30A5)
|
||||||
|
laptop-eapd Laptop config with EAPD support
|
||||||
|
test for testing/debugging purpose, almost all controls
|
||||||
|
can be adjusted. Appearing only when compiled with
|
||||||
|
$CONFIG_SND_DEBUG=y
|
||||||
|
|
||||||
STAC9200/9205/9220/9221/9254
|
STAC9200/9205/9220/9221/9254
|
||||||
ref Reference board
|
ref Reference board
|
||||||
3stack D945 3stack
|
3stack D945 3stack
|
||||||
5stack D945 5stack + SPDIF
|
5stack D945 5stack + SPDIF
|
||||||
|
|
||||||
|
STAC9202/9250/9251
|
||||||
|
ref Reference board, base config
|
||||||
|
m2-2 Some Gateway MX series laptops
|
||||||
|
m6 Some Gateway NX series laptops
|
||||||
|
|
||||||
STAC9227/9228/9229/927x
|
STAC9227/9228/9229/927x
|
||||||
ref Reference board
|
ref Reference board
|
||||||
3stack D965 3stack
|
3stack D965 3stack
|
||||||
|
@ -974,6 +1019,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
|
Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
|
||||||
* MidiMan M Audio Revolution 5.1
|
* MidiMan M Audio Revolution 5.1
|
||||||
* MidiMan M Audio Revolution 7.1
|
* MidiMan M Audio Revolution 7.1
|
||||||
|
* MidiMan M Audio Audiophile 192
|
||||||
* AMP Ltd AUDIO2000
|
* AMP Ltd AUDIO2000
|
||||||
* TerraTec Aureon 5.1 Sky
|
* TerraTec Aureon 5.1 Sky
|
||||||
* TerraTec Aureon 7.1 Space
|
* TerraTec Aureon 7.1 Space
|
||||||
|
@ -993,7 +1039,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
|
|
||||||
model - Use the given board model, one of the following:
|
model - Use the given board model, one of the following:
|
||||||
revo51, revo71, amp2000, prodigy71, prodigy71lt,
|
revo51, revo71, amp2000, prodigy71, prodigy71lt,
|
||||||
prodigy192, aureon51, aureon71, universe,
|
prodigy192, aureon51, aureon71, universe, ap192,
|
||||||
k8x800, phase22, phase28, ms300, av710
|
k8x800, phase22, phase28, ms300, av710
|
||||||
|
|
||||||
This module supports multiple cards and autoprobe.
|
This module supports multiple cards and autoprobe.
|
||||||
|
@ -1049,6 +1095,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
buggy_semaphore - Enable workaround for hardwares with buggy
|
buggy_semaphore - Enable workaround for hardwares with buggy
|
||||||
semaphores (e.g. on some ASUS laptops)
|
semaphores (e.g. on some ASUS laptops)
|
||||||
(default off)
|
(default off)
|
||||||
|
spdif_aclink - Use S/PDIF over AC-link instead of direct connection
|
||||||
|
from the controller chip
|
||||||
|
(0 = off, 1 = on, -1 = default)
|
||||||
|
|
||||||
This module supports one chip and autoprobe.
|
This module supports one chip and autoprobe.
|
||||||
|
|
||||||
|
@ -1371,6 +1420,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
|
|
||||||
This module supports multiple cards.
|
This module supports multiple cards.
|
||||||
|
|
||||||
|
Module snd-portman2x4
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Module for Midiman Portman 2x4 parallel port MIDI interface
|
||||||
|
|
||||||
|
This module supports multiple cards.
|
||||||
|
|
||||||
Module snd-powermac (on ppc only)
|
Module snd-powermac (on ppc only)
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
</bookinfo>
|
</bookinfo>
|
||||||
|
|
||||||
<chapter><title>Management of Cards and Devices</title>
|
<chapter><title>Management of Cards and Devices</title>
|
||||||
<sect1><title>Card Managment</title>
|
<sect1><title>Card Management</title>
|
||||||
!Esound/core/init.c
|
!Esound/core/init.c
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1><title>Device Components</title>
|
<sect1><title>Device Components</title>
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
<sect1><title>PCM Format Helpers</title>
|
<sect1><title>PCM Format Helpers</title>
|
||||||
!Esound/core/pcm_misc.c
|
!Esound/core/pcm_misc.c
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1><title>PCM Memory Managment</title>
|
<sect1><title>PCM Memory Management</title>
|
||||||
!Esound/core/pcm_memory.c
|
!Esound/core/pcm_memory.c
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -1360,8 +1360,7 @@
|
||||||
<informalexample>
|
<informalexample>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct mychip *chip = dev_id;
|
struct mychip *chip = dev_id;
|
||||||
....
|
....
|
||||||
|
@ -2127,7 +2126,7 @@
|
||||||
accessible via <constant>substream->runtime</constant>.
|
accessible via <constant>substream->runtime</constant>.
|
||||||
This runtime pointer holds the various information; it holds
|
This runtime pointer holds the various information; it holds
|
||||||
the copy of hw_params and sw_params configurations, the buffer
|
the copy of hw_params and sw_params configurations, the buffer
|
||||||
pointers, mmap records, spinlocks, etc. Almost everyhing you
|
pointers, mmap records, spinlocks, etc. Almost everything you
|
||||||
need for controlling the PCM can be found there.
|
need for controlling the PCM can be found there.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -2340,7 +2339,7 @@ struct _snd_pcm_runtime {
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When the PCM substreams can be synchronized (typically,
|
When the PCM substreams can be synchronized (typically,
|
||||||
synchorinized start/stop of a playback and a capture streams),
|
synchronized start/stop of a playback and a capture streams),
|
||||||
you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
|
you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
|
||||||
too. In this case, you'll need to check the linked-list of
|
too. In this case, you'll need to check the linked-list of
|
||||||
PCM substreams in the trigger callback. This will be
|
PCM substreams in the trigger callback. This will be
|
||||||
|
@ -3062,8 +3061,7 @@ struct _snd_pcm_runtime {
|
||||||
<title>Interrupt Handler Case #1</title>
|
<title>Interrupt Handler Case #1</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct mychip *chip = dev_id;
|
struct mychip *chip = dev_id;
|
||||||
spin_lock(&chip->lock);
|
spin_lock(&chip->lock);
|
||||||
|
@ -3106,8 +3104,7 @@ struct _snd_pcm_runtime {
|
||||||
<title>Interrupt Handler Case #2</title>
|
<title>Interrupt Handler Case #2</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct mychip *chip = dev_id;
|
struct mychip *chip = dev_id;
|
||||||
spin_lock(&chip->lock);
|
spin_lock(&chip->lock);
|
||||||
|
@ -3247,7 +3244,7 @@ struct _snd_pcm_runtime {
|
||||||
You can even define your own constraint rules.
|
You can even define your own constraint rules.
|
||||||
For example, let's suppose my_chip can manage a substream of 1 channel
|
For example, let's suppose my_chip can manage a substream of 1 channel
|
||||||
if and only if the format is S16_LE, otherwise it supports any format
|
if and only if the format is S16_LE, otherwise it supports any format
|
||||||
specified in the <structname>snd_pcm_hardware</structname> stucture (or in any
|
specified in the <structname>snd_pcm_hardware</structname> structure (or in any
|
||||||
other constraint_list). You can build a rule like this:
|
other constraint_list). You can build a rule like this:
|
||||||
|
|
||||||
<example>
|
<example>
|
||||||
|
@ -3690,16 +3687,6 @@ struct _snd_pcm_runtime {
|
||||||
</example>
|
</example>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
Here, the chip instance is retrieved via
|
|
||||||
<function>snd_kcontrol_chip()</function> macro. This macro
|
|
||||||
just accesses to kcontrol->private_data. The
|
|
||||||
kcontrol->private_data field is
|
|
||||||
given as the argument of <function>snd_ctl_new()</function>
|
|
||||||
(see the later subsection
|
|
||||||
<link linkend="control-interface-constructor"><citetitle>Constructor</citetitle></link>).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <structfield>value</structfield> field is depending on
|
The <structfield>value</structfield> field is depending on
|
||||||
the type of control as well as on info callback. For example,
|
the type of control as well as on info callback. For example,
|
||||||
|
@ -3780,7 +3767,7 @@ struct _snd_pcm_runtime {
|
||||||
<para>
|
<para>
|
||||||
Like <structfield>get</structfield> callback,
|
Like <structfield>get</structfield> callback,
|
||||||
when the control has more than one elements,
|
when the control has more than one elements,
|
||||||
all elemehts must be evaluated in this callback, too.
|
all elements must be evaluated in this callback, too.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -5541,12 +5528,12 @@ struct _snd_pcm_runtime {
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
|
static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
|
||||||
{
|
{
|
||||||
.... /* do things for suspsend */
|
.... /* do things for suspend */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int snd_my_resume(struct pci_dev *pci)
|
static int snd_my_resume(struct pci_dev *pci)
|
||||||
{
|
{
|
||||||
.... /* do things for suspsend */
|
.... /* do things for suspend */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -6111,7 +6098,7 @@ struct _snd_pcm_runtime {
|
||||||
<!-- ****************************************************** -->
|
<!-- ****************************************************** -->
|
||||||
<!-- Acknowledgments -->
|
<!-- Acknowledgments -->
|
||||||
<!-- ****************************************************** -->
|
<!-- ****************************************************** -->
|
||||||
<chapter id="acknowledments">
|
<chapter id="acknowledgments">
|
||||||
<title>Acknowledgments</title>
|
<title>Acknowledgments</title>
|
||||||
<para>
|
<para>
|
||||||
I would like to thank Phil Kerr for his help for improvement and
|
I would like to thank Phil Kerr for his help for improvement and
|
||||||
|
|
|
@ -277,11 +277,11 @@ Helper Functions
|
||||||
snd_hda_get_codec_name() stores the codec name on the given string.
|
snd_hda_get_codec_name() stores the codec name on the given string.
|
||||||
|
|
||||||
snd_hda_check_board_config() can be used to obtain the configuration
|
snd_hda_check_board_config() can be used to obtain the configuration
|
||||||
information matching with the device. Define the table with struct
|
information matching with the device. Define the model string table
|
||||||
hda_board_config entries (zero-terminated), and pass it to the
|
and the table with struct snd_pci_quirk entries (zero-terminated),
|
||||||
function. The function checks the modelname given as a module
|
and pass it to the function. The function checks the modelname given
|
||||||
parameter, and PCI subsystem IDs. If the matching entry is found, it
|
as a module parameter, and PCI subsystem IDs. If the matching entry
|
||||||
returns the config field value.
|
is found, it returns the config field value.
|
||||||
|
|
||||||
snd_hda_add_new_ctls() can be used to create and add control entries.
|
snd_hda_add_new_ctls() can be used to create and add control entries.
|
||||||
Pass the zero-terminated array of struct snd_kcontrol_new. The same array
|
Pass the zero-terminated array of struct snd_kcontrol_new. The same array
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
|
||||||
|
SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM.
|
||||||
|
|
||||||
|
|
||||||
|
AC97
|
||||||
|
====
|
||||||
|
|
||||||
|
AC97 is a five wire interface commonly found on many PC sound cards. It is
|
||||||
|
now also popular in many portable devices. This DAI has a reset line and time
|
||||||
|
multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
|
||||||
|
The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
|
||||||
|
frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
|
||||||
|
frame is 21uS long and is divided into 13 time slots.
|
||||||
|
|
||||||
|
The AC97 specification can be found at :-
|
||||||
|
http://www.intel.com/design/chipsets/audio/ac97_r23.pdf
|
||||||
|
|
||||||
|
|
||||||
|
I2S
|
||||||
|
===
|
||||||
|
|
||||||
|
I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
|
||||||
|
Rx lines are used for audio transmision, whilst the bit clock (BCLK) and
|
||||||
|
left/right clock (LRC) synchronise the link. I2S is flexible in that either the
|
||||||
|
controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
|
||||||
|
usually varies depending on the sample rate and the master system clock
|
||||||
|
(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
|
||||||
|
ADC and DAC LRCLK's, this allows for similtanious capture and playback at
|
||||||
|
different sample rates.
|
||||||
|
|
||||||
|
I2S has several different operating modes:-
|
||||||
|
|
||||||
|
o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
|
||||||
|
transition.
|
||||||
|
|
||||||
|
o Left Justified - MSB is transmitted on transition of LRC.
|
||||||
|
|
||||||
|
o Right Justified - MSB is transmitted sample size BCLK's before LRC
|
||||||
|
transition.
|
||||||
|
|
||||||
|
PCM
|
||||||
|
===
|
||||||
|
|
||||||
|
PCM is another 4 wire interface, very similar to I2S, that can support a more
|
||||||
|
flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
|
||||||
|
to synchronise the link whilst the Tx and Rx lines are used to transmit and
|
||||||
|
receive the audio data. Bit clock usually varies depending on sample rate
|
||||||
|
whilst sync runs at the sample rate. PCM also supports Time Division
|
||||||
|
Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This
|
||||||
|
is sometimes referred to as network mode).
|
||||||
|
|
||||||
|
Common PCM operating modes:-
|
||||||
|
|
||||||
|
o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
|
||||||
|
|
||||||
|
o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
|
|
@ -0,0 +1,51 @@
|
||||||
|
Audio Clocking
|
||||||
|
==============
|
||||||
|
|
||||||
|
This text describes the audio clocking terms in ASoC and digital audio in
|
||||||
|
general. Note: Audio clocking can be complex !
|
||||||
|
|
||||||
|
|
||||||
|
Master Clock
|
||||||
|
------------
|
||||||
|
|
||||||
|
Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
|
||||||
|
or SYSCLK). This audio master clock can be derived from a number of sources
|
||||||
|
(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
|
||||||
|
audio playback and capture sample rates.
|
||||||
|
|
||||||
|
Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
|
||||||
|
their speed can be altered by software (depending on the system use and to save
|
||||||
|
power). Other master clocks are fixed at at set frequency (i.e. crystals).
|
||||||
|
|
||||||
|
|
||||||
|
DAI Clocks
|
||||||
|
----------
|
||||||
|
The Digital Audio Interface is usually driven by a Bit Clock (often referred to
|
||||||
|
as BCLK). This clock is used to drive the digital audio data across the link
|
||||||
|
between the codec and CPU.
|
||||||
|
|
||||||
|
The DAI also has a frame clock to signal the start of each audio frame. This
|
||||||
|
clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
|
||||||
|
runs at exactly the sample rate (LRC = Rate).
|
||||||
|
|
||||||
|
Bit Clock can be generated as follows:-
|
||||||
|
|
||||||
|
BCLK = MCLK / x
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
BCLK = LRC * x
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
BCLK = LRC * Channels * Word Size
|
||||||
|
|
||||||
|
This relationship depends on the codec or SoC CPU in particular. In general
|
||||||
|
it's best to configure BCLK to the lowest possible speed (depending on your
|
||||||
|
rate, number of channels and wordsize) to save on power.
|
||||||
|
|
||||||
|
It's also desireable to use the codec (if possible) to drive (or master) the
|
||||||
|
audio clocks as it's usually gives more accurate sample rates than the CPU.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
ASoC Codec Driver
|
||||||
|
=================
|
||||||
|
|
||||||
|
The codec driver is generic and hardware independent code that configures the
|
||||||
|
codec to provide audio capture and playback. It should contain no code that is
|
||||||
|
specific to the target platform or machine. All platform and machine specific
|
||||||
|
code should be added to the platform and machine drivers respectively.
|
||||||
|
|
||||||
|
Each codec driver *must* provide the following features:-
|
||||||
|
|
||||||
|
1) Codec DAI and PCM configuration
|
||||||
|
2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
|
||||||
|
3) Mixers and audio controls
|
||||||
|
4) Codec audio operations
|
||||||
|
|
||||||
|
Optionally, codec drivers can also provide:-
|
||||||
|
|
||||||
|
5) DAPM description.
|
||||||
|
6) DAPM event handler.
|
||||||
|
7) DAC Digital mute control.
|
||||||
|
|
||||||
|
It's probably best to use this guide in conjuction with the existing codec
|
||||||
|
driver code in sound/soc/codecs/
|
||||||
|
|
||||||
|
ASoC Codec driver breakdown
|
||||||
|
===========================
|
||||||
|
|
||||||
|
1 - Codec DAI and PCM configuration
|
||||||
|
-----------------------------------
|
||||||
|
Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
|
||||||
|
PCM's capablities and operations. This struct is exported so that it can be
|
||||||
|
registered with the core by your machine driver.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
struct snd_soc_codec_dai wm8731_dai = {
|
||||||
|
.name = "WM8731",
|
||||||
|
/* playback capabilities */
|
||||||
|
.playback = {
|
||||||
|
.stream_name = "Playback",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = WM8731_RATES,
|
||||||
|
.formats = WM8731_FORMATS,},
|
||||||
|
/* capture capabilities */
|
||||||
|
.capture = {
|
||||||
|
.stream_name = "Capture",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = WM8731_RATES,
|
||||||
|
.formats = WM8731_FORMATS,},
|
||||||
|
/* pcm operations - see section 4 below */
|
||||||
|
.ops = {
|
||||||
|
.prepare = wm8731_pcm_prepare,
|
||||||
|
.hw_params = wm8731_hw_params,
|
||||||
|
.shutdown = wm8731_shutdown,
|
||||||
|
},
|
||||||
|
/* DAI operations - see DAI.txt */
|
||||||
|
.dai_ops = {
|
||||||
|
.digital_mute = wm8731_mute,
|
||||||
|
.set_sysclk = wm8731_set_dai_sysclk,
|
||||||
|
.set_fmt = wm8731_set_dai_fmt,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(wm8731_dai);
|
||||||
|
|
||||||
|
|
||||||
|
2 - Codec control IO
|
||||||
|
--------------------
|
||||||
|
The codec can ususally be controlled via an I2C or SPI style interface (AC97
|
||||||
|
combines control with data in the DAI). The codec drivers will have to provide
|
||||||
|
functions to read and write the codec registers along with supplying a register
|
||||||
|
cache:-
|
||||||
|
|
||||||
|
/* IO control data and register cache */
|
||||||
|
void *control_data; /* codec control (i2c/3wire) data */
|
||||||
|
void *reg_cache;
|
||||||
|
|
||||||
|
Codec read/write should do any data formatting and call the hardware read write
|
||||||
|
below to perform the IO. These functions are called by the core and alsa when
|
||||||
|
performing DAPM or changing the mixer:-
|
||||||
|
|
||||||
|
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||||
|
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||||
|
|
||||||
|
Codec hardware IO functions - usually points to either the I2C, SPI or AC97
|
||||||
|
read/write:-
|
||||||
|
|
||||||
|
hw_write_t hw_write;
|
||||||
|
hw_read_t hw_read;
|
||||||
|
|
||||||
|
|
||||||
|
3 - Mixers and audio controls
|
||||||
|
-----------------------------
|
||||||
|
All the codec mixers and audio controls can be defined using the convenience
|
||||||
|
macros defined in soc.h.
|
||||||
|
|
||||||
|
#define SOC_SINGLE(xname, reg, shift, mask, invert)
|
||||||
|
|
||||||
|
Defines a single control as follows:-
|
||||||
|
|
||||||
|
xname = Control name e.g. "Playback Volume"
|
||||||
|
reg = codec register
|
||||||
|
shift = control bit(s) offset in register
|
||||||
|
mask = control bit size(s) e.g. mask of 7 = 3 bits
|
||||||
|
invert = the control is inverted
|
||||||
|
|
||||||
|
Other macros include:-
|
||||||
|
|
||||||
|
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
|
||||||
|
|
||||||
|
A stereo control
|
||||||
|
|
||||||
|
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
|
||||||
|
|
||||||
|
A stereo control spanning 2 registers
|
||||||
|
|
||||||
|
#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
|
||||||
|
|
||||||
|
Defines an single enumerated control as follows:-
|
||||||
|
|
||||||
|
xreg = register
|
||||||
|
xshift = control bit(s) offset in register
|
||||||
|
xmask = control bit(s) size
|
||||||
|
xtexts = pointer to array of strings that describe each setting
|
||||||
|
|
||||||
|
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
|
||||||
|
|
||||||
|
Defines a stereo enumerated control
|
||||||
|
|
||||||
|
|
||||||
|
4 - Codec Audio Operations
|
||||||
|
--------------------------
|
||||||
|
The codec driver also supports the following alsa operations:-
|
||||||
|
|
||||||
|
/* SoC audio ops */
|
||||||
|
struct snd_soc_ops {
|
||||||
|
int (*startup)(struct snd_pcm_substream *);
|
||||||
|
void (*shutdown)(struct snd_pcm_substream *);
|
||||||
|
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||||
|
int (*hw_free)(struct snd_pcm_substream *);
|
||||||
|
int (*prepare)(struct snd_pcm_substream *);
|
||||||
|
};
|
||||||
|
|
||||||
|
Please refer to the alsa driver PCM documentation for details.
|
||||||
|
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||||
|
|
||||||
|
|
||||||
|
5 - DAPM description.
|
||||||
|
---------------------
|
||||||
|
The Dynamic Audio Power Management description describes the codec's power
|
||||||
|
components, their relationships and registers to the ASoC core. Please read
|
||||||
|
dapm.txt for details of building the description.
|
||||||
|
|
||||||
|
Please also see the examples in other codec drivers.
|
||||||
|
|
||||||
|
|
||||||
|
6 - DAPM event handler
|
||||||
|
----------------------
|
||||||
|
This function is a callback that handles codec domain PM calls and system
|
||||||
|
domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
|
||||||
|
when not in use.
|
||||||
|
|
||||||
|
Power states:-
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D0: /* full On */
|
||||||
|
/* vref/mid, clk and osc on, active */
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D1: /* partial On */
|
||||||
|
SNDRV_CTL_POWER_D2: /* partial On */
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D3hot: /* Off, with power */
|
||||||
|
/* everything off except vref/vmid, inactive */
|
||||||
|
|
||||||
|
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
|
||||||
|
|
||||||
|
|
||||||
|
7 - Codec DAC digital mute control.
|
||||||
|
------------------------------------
|
||||||
|
Most codecs have a digital mute before the DAC's that can be used to minimise
|
||||||
|
any system noise. The mute stops any digital data from entering the DAC.
|
||||||
|
|
||||||
|
A callback can be created that is called by the core for each codec DAI when the
|
||||||
|
mute is applied or freed.
|
||||||
|
|
||||||
|
i.e.
|
||||||
|
|
||||||
|
static int wm8974_mute(struct snd_soc_codec *codec,
|
||||||
|
struct snd_soc_codec_dai *dai, int mute)
|
||||||
|
{
|
||||||
|
u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
|
||||||
|
if(mute)
|
||||||
|
wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
|
||||||
|
else
|
||||||
|
wm8974_write(codec, WM8974_DAC, mute_reg);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,297 @@
|
||||||
|
Dynamic Audio Power Management for Portable Devices
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
1. Description
|
||||||
|
==============
|
||||||
|
|
||||||
|
Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
|
||||||
|
to use the minimum amount of power within the audio subsystem at all times. It
|
||||||
|
is independent of other kernel PM and as such, can easily co-exist with the
|
||||||
|
other PM systems.
|
||||||
|
|
||||||
|
DAPM is also completely transparent to all user space applications as all power
|
||||||
|
switching is done within the ASoC core. No code changes or recompiling are
|
||||||
|
required for user space applications. DAPM makes power switching descisions based
|
||||||
|
upon any audio stream (capture/playback) activity and audio mixer settings
|
||||||
|
within the device.
|
||||||
|
|
||||||
|
DAPM spans the whole machine. It covers power control within the entire audio
|
||||||
|
subsystem, this includes internal codec power blocks and machine level power
|
||||||
|
systems.
|
||||||
|
|
||||||
|
There are 4 power domains within DAPM
|
||||||
|
|
||||||
|
1. Codec domain - VREF, VMID (core codec and audio power)
|
||||||
|
Usually controlled at codec probe/remove and suspend/resume, although
|
||||||
|
can be set at stream time if power is not needed for sidetone, etc.
|
||||||
|
|
||||||
|
2. Platform/Machine domain - physically connected inputs and outputs
|
||||||
|
Is platform/machine and user action specific, is configured by the
|
||||||
|
machine driver and responds to asynchronous events e.g when HP
|
||||||
|
are inserted
|
||||||
|
|
||||||
|
3. Path domain - audio susbsystem signal paths
|
||||||
|
Automatically set when mixer and mux settings are changed by the user.
|
||||||
|
e.g. alsamixer, amixer.
|
||||||
|
|
||||||
|
4. Stream domain - DAC's and ADC's.
|
||||||
|
Enabled and disabled when stream playback/capture is started and
|
||||||
|
stopped respectively. e.g. aplay, arecord.
|
||||||
|
|
||||||
|
All DAPM power switching descisons are made automatically by consulting an audio
|
||||||
|
routing map of the whole machine. This map is specific to each machine and
|
||||||
|
consists of the interconnections between every audio component (including
|
||||||
|
internal codec components). All audio components that effect power are called
|
||||||
|
widgets hereafter.
|
||||||
|
|
||||||
|
|
||||||
|
2. DAPM Widgets
|
||||||
|
===============
|
||||||
|
|
||||||
|
Audio DAPM widgets fall into a number of types:-
|
||||||
|
|
||||||
|
o Mixer - Mixes several analog signals into a single analog signal.
|
||||||
|
o Mux - An analog switch that outputs only 1 of it's inputs.
|
||||||
|
o PGA - A programmable gain amplifier or attenuation widget.
|
||||||
|
o ADC - Analog to Digital Converter
|
||||||
|
o DAC - Digital to Analog Converter
|
||||||
|
o Switch - An analog switch
|
||||||
|
o Input - A codec input pin
|
||||||
|
o Output - A codec output pin
|
||||||
|
o Headphone - Headphone (and optional Jack)
|
||||||
|
o Mic - Mic (and optional Jack)
|
||||||
|
o Line - Line Input/Output (and optional Jack)
|
||||||
|
o Speaker - Speaker
|
||||||
|
o Pre - Special PRE widget (exec before all others)
|
||||||
|
o Post - Special POST widget (exec after all others)
|
||||||
|
|
||||||
|
(Widgets are defined in include/sound/soc-dapm.h)
|
||||||
|
|
||||||
|
Widgets are usually added in the codec driver and the machine driver. There are
|
||||||
|
convience macros defined in soc-dapm.h that can be used to quickly build a
|
||||||
|
list of widgets of the codecs and machines DAPM widgets.
|
||||||
|
|
||||||
|
Most widgets have a name, register, shift and invert. Some widgets have extra
|
||||||
|
parameters for stream name and kcontrols.
|
||||||
|
|
||||||
|
|
||||||
|
2.1 Stream Domain Widgets
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Stream Widgets relate to the stream power domain and only consist of ADC's
|
||||||
|
(analog to digital converters) and DAC's (digital to analog converters).
|
||||||
|
|
||||||
|
Stream widgets have the following format:-
|
||||||
|
|
||||||
|
SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
|
||||||
|
|
||||||
|
NOTE: the stream name must match the corresponding stream name in your codecs
|
||||||
|
snd_soc_codec_dai.
|
||||||
|
|
||||||
|
e.g. stream widgets for HiFi playback and capture
|
||||||
|
|
||||||
|
SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
|
||||||
|
SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
|
||||||
|
|
||||||
|
|
||||||
|
2.2 Path Domain Widgets
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Path domain widgets have a ability to control or effect the audio signal or
|
||||||
|
audio paths within the audio subsystem. They have the following form:-
|
||||||
|
|
||||||
|
SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
|
||||||
|
|
||||||
|
Any widget kcontrols can be set using the controls and num_controls members.
|
||||||
|
|
||||||
|
e.g. Mixer widget (the kcontrols are declared first)
|
||||||
|
|
||||||
|
/* Output Mixer */
|
||||||
|
static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
|
||||||
|
SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
|
||||||
|
SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
|
||||||
|
SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
|
||||||
|
ARRAY_SIZE(wm8731_output_mixer_controls)),
|
||||||
|
|
||||||
|
|
||||||
|
2.3 Platform/Machine domain Widgets
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Machine widgets are different from codec widgets in that they don't have a
|
||||||
|
codec register bit associated with them. A machine widget is assigned to each
|
||||||
|
machine audio component (non codec) that can be independently powered. e.g.
|
||||||
|
|
||||||
|
o Speaker Amp
|
||||||
|
o Microphone Bias
|
||||||
|
o Jack connectors
|
||||||
|
|
||||||
|
A machine widget can have an optional call back.
|
||||||
|
|
||||||
|
e.g. Jack connector widget for an external Mic that enables Mic Bias
|
||||||
|
when the Mic is inserted:-
|
||||||
|
|
||||||
|
static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
|
||||||
|
{
|
||||||
|
if(SND_SOC_DAPM_EVENT_ON(event))
|
||||||
|
set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
||||||
|
else
|
||||||
|
reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
|
||||||
|
|
||||||
|
|
||||||
|
2.4 Codec Domain
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The Codec power domain has no widgets and is handled by the codecs DAPM event
|
||||||
|
handler. This handler is called when the codec powerstate is changed wrt to any
|
||||||
|
stream event or by kernel PM events.
|
||||||
|
|
||||||
|
|
||||||
|
2.5 Virtual Widgets
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Sometimes widgets exist in the codec or machine audio map that don't have any
|
||||||
|
corresponding register bit for power control. In this case it's necessary to
|
||||||
|
create a virtual widget - a widget with no control bits e.g.
|
||||||
|
|
||||||
|
SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
|
||||||
|
|
||||||
|
This can be used to merge to signal paths together in software.
|
||||||
|
|
||||||
|
After all the widgets have been defined, they can then be added to the DAPM
|
||||||
|
subsystem individually with a call to snd_soc_dapm_new_control().
|
||||||
|
|
||||||
|
|
||||||
|
3. Codec Widget Interconnections
|
||||||
|
================================
|
||||||
|
|
||||||
|
Widgets are connected to each other within the codec and machine by audio
|
||||||
|
paths (called interconnections). Each interconnection must be defined in order
|
||||||
|
to create a map of all audio paths between widgets.
|
||||||
|
This is easiest with a diagram of the codec (and schematic of the machine audio
|
||||||
|
system), as it requires joining widgets together via their audio signal paths.
|
||||||
|
|
||||||
|
i.e. from the WM8731 codec's output mixer (wm8731.c)
|
||||||
|
|
||||||
|
The WM8731 output mixer has 3 inputs (sources)
|
||||||
|
|
||||||
|
1. Line Bypass Input
|
||||||
|
2. DAC (HiFi playback)
|
||||||
|
3. Mic Sidetone Input
|
||||||
|
|
||||||
|
Each input in this example has a kcontrol associated with it (defined in example
|
||||||
|
above) and is connected to the output mixer via it's kcontrol name. We can now
|
||||||
|
connect the destination widget (wrt audio signal) with it's source widgets.
|
||||||
|
|
||||||
|
/* output mixer */
|
||||||
|
{"Output Mixer", "Line Bypass Switch", "Line Input"},
|
||||||
|
{"Output Mixer", "HiFi Playback Switch", "DAC"},
|
||||||
|
{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
|
||||||
|
|
||||||
|
So we have :-
|
||||||
|
|
||||||
|
Destination Widget <=== Path Name <=== Source Widget
|
||||||
|
|
||||||
|
Or:-
|
||||||
|
|
||||||
|
Sink, Path, Source
|
||||||
|
|
||||||
|
Or :-
|
||||||
|
|
||||||
|
"Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
|
||||||
|
|
||||||
|
When there is no path name connecting widgets (e.g. a direct connection) we
|
||||||
|
pass NULL for the path name.
|
||||||
|
|
||||||
|
Interconnections are created with a call to:-
|
||||||
|
|
||||||
|
snd_soc_dapm_connect_input(codec, sink, path, source);
|
||||||
|
|
||||||
|
Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
|
||||||
|
interconnections have been registered with the core. This causes the core to
|
||||||
|
scan the codec and machine so that the internal DAPM state matches the
|
||||||
|
physical state of the machine.
|
||||||
|
|
||||||
|
|
||||||
|
3.1 Machine Widget Interconnections
|
||||||
|
-----------------------------------
|
||||||
|
Machine widget interconnections are created in the same way as codec ones and
|
||||||
|
directly connect the codec pins to machine level widgets.
|
||||||
|
|
||||||
|
e.g. connects the speaker out codec pins to the internal speaker.
|
||||||
|
|
||||||
|
/* ext speaker connected to codec pins LOUT2, ROUT2 */
|
||||||
|
{"Ext Spk", NULL , "ROUT2"},
|
||||||
|
{"Ext Spk", NULL , "LOUT2"},
|
||||||
|
|
||||||
|
This allows the DAPM to power on and off pins that are connected (and in use)
|
||||||
|
and pins that are NC respectively.
|
||||||
|
|
||||||
|
|
||||||
|
4 Endpoint Widgets
|
||||||
|
===================
|
||||||
|
An endpoint is a start or end point (widget) of an audio signal within the
|
||||||
|
machine and includes the codec. e.g.
|
||||||
|
|
||||||
|
o Headphone Jack
|
||||||
|
o Internal Speaker
|
||||||
|
o Internal Mic
|
||||||
|
o Mic Jack
|
||||||
|
o Codec Pins
|
||||||
|
|
||||||
|
When a codec pin is NC it can be marked as not used with a call to
|
||||||
|
|
||||||
|
snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
|
||||||
|
|
||||||
|
The last argument is 0 for inactive and 1 for active. This way the pin and its
|
||||||
|
input widget will never be powered up and consume power.
|
||||||
|
|
||||||
|
This also applies to machine widgets. e.g. if a headphone is connected to a
|
||||||
|
jack then the jack can be marked active. If the headphone is removed, then
|
||||||
|
the headphone jack can be marked inactive.
|
||||||
|
|
||||||
|
|
||||||
|
5 DAPM Widget Events
|
||||||
|
====================
|
||||||
|
|
||||||
|
Some widgets can register their interest with the DAPM core in PM events.
|
||||||
|
e.g. A Speaker with an amplifier registers a widget so the amplifier can be
|
||||||
|
powered only when the spk is in use.
|
||||||
|
|
||||||
|
/* turn speaker amplifier on/off depending on use */
|
||||||
|
static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
|
||||||
|
{
|
||||||
|
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||||
|
set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
||||||
|
else
|
||||||
|
reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* corgi machine dapm widgets */
|
||||||
|
static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
|
||||||
|
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
|
||||||
|
|
||||||
|
Please see soc-dapm.h for all other widgets that support events.
|
||||||
|
|
||||||
|
|
||||||
|
5.1 Event types
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The following event types are supported by event widgets.
|
||||||
|
|
||||||
|
/* dapm event types */
|
||||||
|
#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
|
||||||
|
#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
|
||||||
|
#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
|
||||||
|
#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
|
||||||
|
#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
|
||||||
|
#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
|
|
@ -0,0 +1,113 @@
|
||||||
|
ASoC Machine Driver
|
||||||
|
===================
|
||||||
|
|
||||||
|
The ASoC machine (or board) driver is the code that glues together the platform
|
||||||
|
and codec drivers.
|
||||||
|
|
||||||
|
The machine driver can contain codec and platform specific code. It registers
|
||||||
|
the audio subsystem with the kernel as a platform device and is represented by
|
||||||
|
the following struct:-
|
||||||
|
|
||||||
|
/* SoC machine */
|
||||||
|
struct snd_soc_machine {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
int (*probe)(struct platform_device *pdev);
|
||||||
|
int (*remove)(struct platform_device *pdev);
|
||||||
|
|
||||||
|
/* the pre and post PM functions are used to do any PM work before and
|
||||||
|
* after the codec and DAI's do any PM work. */
|
||||||
|
int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
|
||||||
|
int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
|
||||||
|
int (*resume_pre)(struct platform_device *pdev);
|
||||||
|
int (*resume_post)(struct platform_device *pdev);
|
||||||
|
|
||||||
|
/* machine stream operations */
|
||||||
|
struct snd_soc_ops *ops;
|
||||||
|
|
||||||
|
/* CPU <--> Codec DAI links */
|
||||||
|
struct snd_soc_dai_link *dai_link;
|
||||||
|
int num_links;
|
||||||
|
};
|
||||||
|
|
||||||
|
probe()/remove()
|
||||||
|
----------------
|
||||||
|
probe/remove are optional. Do any machine specific probe here.
|
||||||
|
|
||||||
|
|
||||||
|
suspend()/resume()
|
||||||
|
------------------
|
||||||
|
The machine driver has pre and post versions of suspend and resume to take care
|
||||||
|
of any machine audio tasks that have to be done before or after the codec, DAI's
|
||||||
|
and DMA is suspended and resumed. Optional.
|
||||||
|
|
||||||
|
|
||||||
|
Machine operations
|
||||||
|
------------------
|
||||||
|
The machine specific audio operations can be set here. Again this is optional.
|
||||||
|
|
||||||
|
|
||||||
|
Machine DAI Configuration
|
||||||
|
-------------------------
|
||||||
|
The machine DAI configuration glues all the codec and CPU DAI's together. It can
|
||||||
|
also be used to set up the DAI system clock and for any machine related DAI
|
||||||
|
initialisation e.g. the machine audio map can be connected to the codec audio
|
||||||
|
map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
|
||||||
|
for examples.
|
||||||
|
|
||||||
|
struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
|
||||||
|
|
||||||
|
/* corgi digital audio interface glue - connects codec <--> CPU */
|
||||||
|
static struct snd_soc_dai_link corgi_dai = {
|
||||||
|
.name = "WM8731",
|
||||||
|
.stream_name = "WM8731",
|
||||||
|
.cpu_dai = &pxa_i2s_dai,
|
||||||
|
.codec_dai = &wm8731_dai,
|
||||||
|
.init = corgi_wm8731_init,
|
||||||
|
.ops = &corgi_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
|
||||||
|
|
||||||
|
/* corgi audio machine driver */
|
||||||
|
static struct snd_soc_machine snd_soc_machine_corgi = {
|
||||||
|
.name = "Corgi",
|
||||||
|
.dai_link = &corgi_dai,
|
||||||
|
.num_links = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Machine Audio Subsystem
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The machine soc device glues the platform, machine and codec driver together.
|
||||||
|
Private data can also be set here. e.g.
|
||||||
|
|
||||||
|
/* corgi audio private data */
|
||||||
|
static struct wm8731_setup_data corgi_wm8731_setup = {
|
||||||
|
.i2c_address = 0x1b,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* corgi audio subsystem */
|
||||||
|
static struct snd_soc_device corgi_snd_devdata = {
|
||||||
|
.machine = &snd_soc_machine_corgi,
|
||||||
|
.platform = &pxa2xx_soc_platform,
|
||||||
|
.codec_dev = &soc_codec_dev_wm8731,
|
||||||
|
.codec_data = &corgi_wm8731_setup,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Machine Power Map
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The machine driver can optionally extend the codec power map and to become an
|
||||||
|
audio power map of the audio subsystem. This allows for automatic power up/down
|
||||||
|
of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
|
||||||
|
sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
|
||||||
|
details.
|
||||||
|
|
||||||
|
|
||||||
|
Machine Controls
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Machine specific audio mixer controls can be added in the dai init function.
|
|
@ -0,0 +1,83 @@
|
||||||
|
ALSA SoC Layer
|
||||||
|
==============
|
||||||
|
|
||||||
|
The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
|
||||||
|
better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
|
||||||
|
iMX, etc) and portable audio codecs. Currently there is some support in the
|
||||||
|
kernel for SoC audio, however it has some limitations:-
|
||||||
|
|
||||||
|
* Currently, codec drivers are often tightly coupled to the underlying SoC
|
||||||
|
cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
|
||||||
|
different wm8731 drivers for 4 different SoC platforms.
|
||||||
|
|
||||||
|
* There is no standard method to signal user initiated audio events.
|
||||||
|
e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
|
||||||
|
event. These are quite common events on portable devices and ofter require
|
||||||
|
machine specific code to re route audio, enable amps etc after such an event.
|
||||||
|
|
||||||
|
* Current drivers tend to power up the entire codec when playing
|
||||||
|
(or recording) audio. This is fine for a PC, but tends to waste a lot of
|
||||||
|
power on portable devices. There is also no support for saving power via
|
||||||
|
changing codec oversampling rates, bias currents, etc.
|
||||||
|
|
||||||
|
|
||||||
|
ASoC Design
|
||||||
|
===========
|
||||||
|
|
||||||
|
The ASoC layer is designed to address these issues and provide the following
|
||||||
|
features :-
|
||||||
|
|
||||||
|
* Codec independence. Allows reuse of codec drivers on other platforms
|
||||||
|
and machines.
|
||||||
|
|
||||||
|
* Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
|
||||||
|
and codec registers it's audio interface capabilities with the core and are
|
||||||
|
subsequently matched and configured when the application hw params are known.
|
||||||
|
|
||||||
|
* Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
|
||||||
|
it's minimum power state at all times. This includes powering up/down
|
||||||
|
internal power blocks depending on the internal codec audio routing and any
|
||||||
|
active streams.
|
||||||
|
|
||||||
|
* Pop and click reduction. Pops and clicks can be reduced by powering the
|
||||||
|
codec up/down in the correct sequence (including using digital mute). ASoC
|
||||||
|
signals the codec when to change power states.
|
||||||
|
|
||||||
|
* Machine specific controls: Allow machines to add controls to the sound card
|
||||||
|
e.g. volume control for speaker amp.
|
||||||
|
|
||||||
|
To achieve all this, ASoC basically splits an embedded audio system into 3
|
||||||
|
components :-
|
||||||
|
|
||||||
|
* Codec driver: The codec driver is platform independent and contains audio
|
||||||
|
controls, audio interface capabilities, codec dapm definition and codec IO
|
||||||
|
functions.
|
||||||
|
|
||||||
|
* Platform driver: The platform driver contains the audio dma engine and audio
|
||||||
|
interface drivers (e.g. I2S, AC97, PCM) for that platform.
|
||||||
|
|
||||||
|
* Machine driver: The machine driver handles any machine specific controls and
|
||||||
|
audio events. i.e. turing on an amp at start of playback.
|
||||||
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
=============
|
||||||
|
|
||||||
|
The documentation is spilt into the following sections:-
|
||||||
|
|
||||||
|
overview.txt: This file.
|
||||||
|
|
||||||
|
codec.txt: Codec driver internals.
|
||||||
|
|
||||||
|
DAI.txt: Description of Digital Audio Interface standards and how to configure
|
||||||
|
a DAI within your codec and CPU DAI drivers.
|
||||||
|
|
||||||
|
dapm.txt: Dynamic Audio Power Management
|
||||||
|
|
||||||
|
platform.txt: Platform audio DMA and DAI.
|
||||||
|
|
||||||
|
machine.txt: Machine driver internals.
|
||||||
|
|
||||||
|
pop_clicks.txt: How to minimise audio artifacts.
|
||||||
|
|
||||||
|
clocking.txt: ASoC clocking for best power performance.
|
|
@ -0,0 +1,58 @@
|
||||||
|
ASoC Platform Driver
|
||||||
|
====================
|
||||||
|
|
||||||
|
An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
|
||||||
|
and control. The platform drivers only target the SoC CPU and must have no board
|
||||||
|
specific code.
|
||||||
|
|
||||||
|
Audio DMA
|
||||||
|
=========
|
||||||
|
|
||||||
|
The platform DMA driver optionally supports the following alsa operations:-
|
||||||
|
|
||||||
|
/* SoC audio ops */
|
||||||
|
struct snd_soc_ops {
|
||||||
|
int (*startup)(struct snd_pcm_substream *);
|
||||||
|
void (*shutdown)(struct snd_pcm_substream *);
|
||||||
|
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||||
|
int (*hw_free)(struct snd_pcm_substream *);
|
||||||
|
int (*prepare)(struct snd_pcm_substream *);
|
||||||
|
int (*trigger)(struct snd_pcm_substream *, int);
|
||||||
|
};
|
||||||
|
|
||||||
|
The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
|
||||||
|
|
||||||
|
struct snd_soc_platform {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
int (*probe)(struct platform_device *pdev);
|
||||||
|
int (*remove)(struct platform_device *pdev);
|
||||||
|
int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
|
||||||
|
int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
|
||||||
|
|
||||||
|
/* pcm creation and destruction */
|
||||||
|
int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
|
||||||
|
void (*pcm_free)(struct snd_pcm *);
|
||||||
|
|
||||||
|
/* platform stream ops */
|
||||||
|
struct snd_pcm_ops *pcm_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
Please refer to the alsa driver documentation for details of audio DMA.
|
||||||
|
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||||
|
|
||||||
|
An example DMA driver is soc/pxa/pxa2xx-pcm.c
|
||||||
|
|
||||||
|
|
||||||
|
SoC DAI Drivers
|
||||||
|
===============
|
||||||
|
|
||||||
|
Each SoC DAI driver must provide the following features:-
|
||||||
|
|
||||||
|
1) Digital audio interface (DAI) description
|
||||||
|
2) Digital audio interface configuration
|
||||||
|
3) PCM's description
|
||||||
|
4) Sysclk configuration
|
||||||
|
5) Suspend and resume (optional)
|
||||||
|
|
||||||
|
Please see codec.txt for a description of items 1 - 4.
|
|
@ -0,0 +1,52 @@
|
||||||
|
Audio Pops and Clicks
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Pops and clicks are unwanted audio artifacts caused by the powering up and down
|
||||||
|
of components within the audio subsystem. This is noticable on PC's when an
|
||||||
|
audio module is either loaded or unloaded (at module load time the sound card is
|
||||||
|
powered up and causes a popping noise on the speakers).
|
||||||
|
|
||||||
|
Pops and clicks can be more frequent on portable systems with DAPM. This is
|
||||||
|
because the components within the subsystem are being dynamically powered
|
||||||
|
depending on the audio usage and this can subsequently cause a small pop or
|
||||||
|
click every time a component power state is changed.
|
||||||
|
|
||||||
|
|
||||||
|
Minimising Playback Pops and Clicks
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Playback pops in portable audio subsystems cannot be completely eliminated atm,
|
||||||
|
however future audio codec hardware will have better pop and click supression.
|
||||||
|
Pops can be reduced within playback by powering the audio components in a
|
||||||
|
specific order. This order is different for startup and shutdown and follows
|
||||||
|
some basic rules:-
|
||||||
|
|
||||||
|
Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
|
||||||
|
|
||||||
|
Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
|
||||||
|
|
||||||
|
This assumes that the codec PCM output path from the DAC is via a mixer and then
|
||||||
|
a PGA (programmable gain amplifier) before being output to the speakers.
|
||||||
|
|
||||||
|
|
||||||
|
Minimising Capture Pops and Clicks
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Capture artifacts are somewhat easier to get rid as we can delay activating the
|
||||||
|
ADC until all the pops have occured. This follows similar power rules to
|
||||||
|
playback in that components are powered in a sequence depending upon stream
|
||||||
|
startup or shutdown.
|
||||||
|
|
||||||
|
Startup Order - Input PGA --> Mixers --> ADC
|
||||||
|
|
||||||
|
Shutdown Order - ADC --> Mixers --> Input PGA
|
||||||
|
|
||||||
|
|
||||||
|
Zipper Noise
|
||||||
|
============
|
||||||
|
An unwanted zipper noise can occur within the audio playback or capture stream
|
||||||
|
when a volume control is changed near its maximum gain value. The zipper noise
|
||||||
|
is heard when the gain increase or decrease changes the mean audio signal
|
||||||
|
amplitude too quickly. It can be minimised by enabling the zero cross setting
|
||||||
|
for each volume control. The ZC forces the gain change to occur when the signal
|
||||||
|
crosses the zero amplitude line.
|
|
@ -284,7 +284,6 @@ SPI protocol drivers somewhat resemble platform device drivers:
|
||||||
static struct spi_driver CHIP_driver = {
|
static struct spi_driver CHIP_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "CHIP",
|
.name = "CHIP",
|
||||||
.bus = &spi_bus_type,
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -312,7 +311,7 @@ might look like this unless you're creating a class_device:
|
||||||
chip = kzalloc(sizeof *chip, GFP_KERNEL);
|
chip = kzalloc(sizeof *chip, GFP_KERNEL);
|
||||||
if (!chip)
|
if (!chip)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
dev_set_drvdata(&spi->dev, chip);
|
spi_set_drvdata(spi, chip);
|
||||||
|
|
||||||
... etc
|
... etc
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -64,11 +64,6 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
|
||||||
|
|
||||||
* What are the 'command' keys?
|
* What are the 'command' keys?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
'r' - Turns off keyboard raw mode and sets it to XLATE.
|
|
||||||
|
|
||||||
'k' - Secure Access Key (SAK) Kills all programs on the current virtual
|
|
||||||
console. NOTE: See important comments below in SAK section.
|
|
||||||
|
|
||||||
'b' - Will immediately reboot the system without syncing or unmounting
|
'b' - Will immediately reboot the system without syncing or unmounting
|
||||||
your disks.
|
your disks.
|
||||||
|
|
||||||
|
@ -76,21 +71,37 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
|
||||||
|
|
||||||
'd' - Shows all locks that are held.
|
'd' - Shows all locks that are held.
|
||||||
|
|
||||||
'o' - Will shut your system off (if configured and supported).
|
'e' - Send a SIGTERM to all processes, except for init.
|
||||||
|
|
||||||
's' - Will attempt to sync all mounted filesystems.
|
'f' - Will call oom_kill to kill a memory hog process.
|
||||||
|
|
||||||
'u' - Will attempt to remount all mounted filesystems read-only.
|
'g' - Used by kgdb on ppc platforms.
|
||||||
|
|
||||||
'p' - Will dump the current registers and flags to your console.
|
'h' - Will display help (actually any other key than those listed
|
||||||
|
above will display help. but 'h' is easy to remember :-)
|
||||||
|
|
||||||
't' - Will dump a list of current tasks and their information to your
|
'i' - Send a SIGKILL to all processes, except for init.
|
||||||
console.
|
|
||||||
|
'k' - Secure Access Key (SAK) Kills all programs on the current virtual
|
||||||
|
console. NOTE: See important comments below in SAK section.
|
||||||
|
|
||||||
'm' - Will dump current memory info to your console.
|
'm' - Will dump current memory info to your console.
|
||||||
|
|
||||||
'n' - Used to make RT tasks nice-able
|
'n' - Used to make RT tasks nice-able
|
||||||
|
|
||||||
|
'o' - Will shut your system off (if configured and supported).
|
||||||
|
|
||||||
|
'p' - Will dump the current registers and flags to your console.
|
||||||
|
|
||||||
|
'r' - Turns off keyboard raw mode and sets it to XLATE.
|
||||||
|
|
||||||
|
's' - Will attempt to sync all mounted filesystems.
|
||||||
|
|
||||||
|
't' - Will dump a list of current tasks and their information to your
|
||||||
|
console.
|
||||||
|
|
||||||
|
'u' - Will attempt to remount all mounted filesystems read-only.
|
||||||
|
|
||||||
'v' - Dumps Voyager SMP processor info to your console.
|
'v' - Dumps Voyager SMP processor info to your console.
|
||||||
|
|
||||||
'w' - Dumps tasks that are in uninterruptable (blocked) state.
|
'w' - Dumps tasks that are in uninterruptable (blocked) state.
|
||||||
|
@ -102,17 +113,6 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
|
||||||
it so that only emergency messages like PANICs or OOPSes would
|
it so that only emergency messages like PANICs or OOPSes would
|
||||||
make it to your console.)
|
make it to your console.)
|
||||||
|
|
||||||
'f' - Will call oom_kill to kill a memory hog process.
|
|
||||||
|
|
||||||
'e' - Send a SIGTERM to all processes, except for init.
|
|
||||||
|
|
||||||
'g' - Used by kgdb on ppc platforms.
|
|
||||||
|
|
||||||
'i' - Send a SIGKILL to all processes, except for init.
|
|
||||||
|
|
||||||
'h' - Will display help (actually any other key than those listed
|
|
||||||
above will display help. but 'h' is easy to remember :-)
|
|
||||||
|
|
||||||
* Okay, so what can I use them for?
|
* Okay, so what can I use them for?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Well, un'R'aw is very handy when your X server or a svgalib program crashes.
|
Well, un'R'aw is very handy when your X server or a svgalib program crashes.
|
||||||
|
|
45
MAINTAINERS
45
MAINTAINERS
|
@ -635,6 +635,12 @@ W: http://people.redhat.com/sgrubb/audit/
|
||||||
T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
|
T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
AUXILIARY DISPLAY DRIVERS
|
||||||
|
P: Miguel Ojeda Sandonis
|
||||||
|
M: maxextreme@gmail.com
|
||||||
|
L: linux-kernel@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
AVR32 ARCHITECTURE
|
AVR32 ARCHITECTURE
|
||||||
P: Haavard Skinnemoen
|
P: Haavard Skinnemoen
|
||||||
M: hskinnemoen@atmel.com
|
M: hskinnemoen@atmel.com
|
||||||
|
@ -836,6 +842,18 @@ L: linux-kernel@vger.kernel.org
|
||||||
L: discuss@x86-64.org
|
L: discuss@x86-64.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
CFAG12864B LCD DRIVER
|
||||||
|
P: Miguel Ojeda Sandonis
|
||||||
|
M: maxextreme@gmail.com
|
||||||
|
L: linux-kernel@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
|
CFAG12864BFB LCD FRAMEBUFFER DRIVER
|
||||||
|
P: Miguel Ojeda Sandonis
|
||||||
|
M: maxextreme@gmail.com
|
||||||
|
L: linux-kernel@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
COMMON INTERNET FILE SYSTEM (CIFS)
|
COMMON INTERNET FILE SYSTEM (CIFS)
|
||||||
P: Steve French
|
P: Steve French
|
||||||
M: sfrench@samba.org
|
M: sfrench@samba.org
|
||||||
|
@ -984,14 +1002,12 @@ L: cycsyn-devel@bazar.conectiva.com.br
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
CYCLADES ASYNC MUX DRIVER
|
CYCLADES ASYNC MUX DRIVER
|
||||||
M: async@cyclades.com
|
|
||||||
W: http://www.cyclades.com/
|
W: http://www.cyclades.com/
|
||||||
S: Supported
|
S: Orphan
|
||||||
|
|
||||||
CYCLADES PC300 DRIVER
|
CYCLADES PC300 DRIVER
|
||||||
M: pc300@cyclades.com
|
|
||||||
W: http://www.cyclades.com/
|
W: http://www.cyclades.com/
|
||||||
S: Supported
|
S: Orphan
|
||||||
|
|
||||||
DAMA SLAVE for AX.25
|
DAMA SLAVE for AX.25
|
||||||
P: Joerg Reuter
|
P: Joerg Reuter
|
||||||
|
@ -1114,7 +1130,7 @@ S: Supported
|
||||||
DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
|
DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
|
||||||
P: Tobias Ringstrom
|
P: Tobias Ringstrom
|
||||||
M: tori@unhappy.mine.nu
|
M: tori@unhappy.mine.nu
|
||||||
L: linux-kernel@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
DOCBOOK FOR DOCUMENTATION
|
DOCBOOK FOR DOCUMENTATION
|
||||||
|
@ -1971,6 +1987,12 @@ M: davem@davemloft.net
|
||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
KS0108 LCD CONTROLLER DRIVER
|
||||||
|
P: Miguel Ojeda Sandonis
|
||||||
|
M: maxextreme@gmail.com
|
||||||
|
L: linux-kernel@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
LAPB module
|
LAPB module
|
||||||
L: linux-x25@vger.kernel.org
|
L: linux-x25@vger.kernel.org
|
||||||
S: Orphan
|
S: Orphan
|
||||||
|
@ -2361,7 +2383,7 @@ S: Maintained
|
||||||
NETWORKING [WIRELESS]
|
NETWORKING [WIRELESS]
|
||||||
P: John W. Linville
|
P: John W. Linville
|
||||||
M: linville@tuxdriver.com
|
M: linville@tuxdriver.com
|
||||||
L: netdev@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
@ -3037,6 +3059,12 @@ M: perex@suse.cz
|
||||||
L: alsa-devel@alsa-project.org
|
L: alsa-devel@alsa-project.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
|
||||||
|
P: Liam Girdwood
|
||||||
|
M: liam.girdwood@wolfsonmicro.com
|
||||||
|
L: alsa-devel@alsa-project.org
|
||||||
|
S: Supported
|
||||||
|
|
||||||
SPI SUBSYSTEM
|
SPI SUBSYSTEM
|
||||||
P: David Brownell
|
P: David Brownell
|
||||||
M: dbrownell@users.sourceforge.net
|
M: dbrownell@users.sourceforge.net
|
||||||
|
@ -3287,6 +3315,11 @@ L: vtun@office.satix.net
|
||||||
W: http://vtun.sourceforge.net/tun
|
W: http://vtun.sourceforge.net/tun
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
TURBOCHANNEL SUBSYSTEM
|
||||||
|
P: Maciej W. Rozycki
|
||||||
|
M: macro@linux-mips.org
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
U14-34F SCSI DRIVER
|
U14-34F SCSI DRIVER
|
||||||
P: Dario Ballabio
|
P: Dario Ballabio
|
||||||
M: ballabio_dario@emc.com
|
M: ballabio_dario@emc.com
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -789,7 +789,7 @@ $(vmlinux-dirs): prepare scripts
|
||||||
|
|
||||||
pattern = ".*/localversion[^~]*"
|
pattern = ".*/localversion[^~]*"
|
||||||
string = $(shell cat /dev/null \
|
string = $(shell cat /dev/null \
|
||||||
`find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort`)
|
`find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)
|
||||||
|
|
||||||
localver = $(subst $(space),, $(string) \
|
localver = $(subst $(space),, $(string) \
|
||||||
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
||||||
|
|
|
@ -41,6 +41,10 @@ config GENERIC_CALIBRATE_DELAY
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ZONE_DMA
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config GENERIC_ISA_DMA
|
config GENERIC_ISA_DMA
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -122,7 +122,7 @@ static void get_sysnames(unsigned long, unsigned long, unsigned long,
|
||||||
char **, char **);
|
char **, char **);
|
||||||
static void determine_cpu_caches (unsigned int);
|
static void determine_cpu_caches (unsigned int);
|
||||||
|
|
||||||
static char command_line[COMMAND_LINE_SIZE];
|
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The format of "screen_info" is strange, and due to early
|
* The format of "screen_info" is strange, and due to early
|
||||||
|
@ -547,7 +547,7 @@ setup_arch(char **cmdline_p)
|
||||||
} else {
|
} else {
|
||||||
strlcpy(command_line, COMMAND_LINE, sizeof command_line);
|
strlcpy(command_line, COMMAND_LINE, sizeof command_line);
|
||||||
}
|
}
|
||||||
strcpy(saved_command_line, command_line);
|
strcpy(boot_command_line, command_line);
|
||||||
*cmdline_p = command_line;
|
*cmdline_p = command_line;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -589,7 +589,7 @@ setup_arch(char **cmdline_p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace the command line, now that we've killed it with strsep. */
|
/* Replace the command line, now that we've killed it with strsep. */
|
||||||
strcpy(command_line, saved_command_line);
|
strcpy(command_line, boot_command_line);
|
||||||
|
|
||||||
/* If we want SRM console printk echoing early, do it now. */
|
/* If we want SRM console printk echoing early, do it now. */
|
||||||
if (alpha_using_srm && srmcons_output) {
|
if (alpha_using_srm && srmcons_output) {
|
||||||
|
|
|
@ -90,17 +90,6 @@ static inline __u32 rpcc(void)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Scheduler clock - returns current time in nanosec units.
|
|
||||||
*
|
|
||||||
* Copied from ARM code for expediency... ;-}
|
|
||||||
*/
|
|
||||||
unsigned long long sched_clock(void)
|
|
||||||
{
|
|
||||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* timer_interrupt() needs to keep up the real-time clock,
|
* timer_interrupt() needs to keep up the real-time clock,
|
||||||
* as well as call the "do_timer()" routine every clocktick
|
* as well as call the "do_timer()" routine every clocktick
|
||||||
|
|
|
@ -52,10 +52,12 @@ SECTIONS
|
||||||
}
|
}
|
||||||
__initcall_end = .;
|
__initcall_end = .;
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
. = ALIGN(8192);
|
. = ALIGN(8192);
|
||||||
__initramfs_start = .;
|
__initramfs_start = .;
|
||||||
.init.ramfs : { *(.init.ramfs) }
|
.init.ramfs : { *(.init.ramfs) }
|
||||||
__initramfs_end = .;
|
__initramfs_end = .;
|
||||||
|
#endif
|
||||||
|
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
.con_initcall.init : {
|
.con_initcall.init : {
|
||||||
|
|
|
@ -9,6 +9,7 @@ config ARM
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
select RTC_LIB
|
select RTC_LIB
|
||||||
|
select SYS_SUPPORTS_APM_EMULATION
|
||||||
help
|
help
|
||||||
The ARM series is a line of low-power-consumption RISC chip designs
|
The ARM series is a line of low-power-consumption RISC chip designs
|
||||||
licensed by ARM Ltd and targeted at embedded applications and
|
licensed by ARM Ltd and targeted at embedded applications and
|
||||||
|
@ -17,6 +18,9 @@ config ARM
|
||||||
Europe. There is an ARM Linux project with a web page at
|
Europe. There is an ARM Linux project with a web page at
|
||||||
<http://www.arm.linux.org.uk/>.
|
<http://www.arm.linux.org.uk/>.
|
||||||
|
|
||||||
|
config SYS_SUPPORTS_APM_EMULATION
|
||||||
|
bool
|
||||||
|
|
||||||
config GENERIC_TIME
|
config GENERIC_TIME
|
||||||
bool
|
bool
|
||||||
default n
|
default n
|
||||||
|
@ -25,6 +29,10 @@ config MMU
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config NO_IOPORT
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
|
||||||
config EISA
|
config EISA
|
||||||
bool
|
bool
|
||||||
---help---
|
---help---
|
||||||
|
@ -96,6 +104,10 @@ config GENERIC_BUST_SPINLOCK
|
||||||
config ARCH_MAY_HAVE_PC_FDC
|
config ARCH_MAY_HAVE_PC_FDC
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config ZONE_DMA
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config GENERIC_ISA_DMA
|
config GENERIC_ISA_DMA
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -290,6 +302,7 @@ config ARCH_RPC
|
||||||
select TIMER_ACORN
|
select TIMER_ACORN
|
||||||
select ARCH_MAY_HAVE_PC_FDC
|
select ARCH_MAY_HAVE_PC_FDC
|
||||||
select ISA_DMA_API
|
select ISA_DMA_API
|
||||||
|
select NO_IOPORT
|
||||||
help
|
help
|
||||||
On the Acorn Risc-PC, Linux can support the internal IDE disk and
|
On the Acorn Risc-PC, Linux can support the internal IDE disk and
|
||||||
CD-ROM interface, serial and parallel port, and the floppy drive.
|
CD-ROM interface, serial and parallel port, and the floppy drive.
|
||||||
|
@ -856,31 +869,6 @@ menu "Power management options"
|
||||||
|
|
||||||
source "kernel/power/Kconfig"
|
source "kernel/power/Kconfig"
|
||||||
|
|
||||||
config APM
|
|
||||||
tristate "Advanced Power Management Emulation"
|
|
||||||
---help---
|
|
||||||
APM is a BIOS specification for saving power using several different
|
|
||||||
techniques. This is mostly useful for battery powered laptops with
|
|
||||||
APM compliant BIOSes. If you say Y here, the system time will be
|
|
||||||
reset after a RESUME operation, the /proc/apm device will provide
|
|
||||||
battery status information, and user-space programs will receive
|
|
||||||
notification of APM "events" (e.g. battery status change).
|
|
||||||
|
|
||||||
In order to use APM, you will need supporting software. For location
|
|
||||||
and more information, read <file:Documentation/pm.txt> and the
|
|
||||||
Battery Powered Linux mini-HOWTO, available from
|
|
||||||
<http://www.tldp.org/docs.html#howto>.
|
|
||||||
|
|
||||||
This driver does not spin down disk drives (see the hdparm(8)
|
|
||||||
manpage ("man 8 hdparm") for that), and it doesn't turn off
|
|
||||||
VESA-compliant "green" monitors.
|
|
||||||
|
|
||||||
Generally, if you don't have a battery in your machine, there isn't
|
|
||||||
much point in using this driver and you should say N. If you get
|
|
||||||
random kernel OOPSes or reboots that don't seem to be related to
|
|
||||||
anything, try disabling/enabling this option (or disabling/enabling
|
|
||||||
APM in your BIOS).
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
source "net/Kconfig"
|
source "net/Kconfig"
|
||||||
|
|
|
@ -329,7 +329,7 @@ static int rtc_fasync(int fd, struct file *file, int on)
|
||||||
return fasync_helper(fd, file, on, &rtc_async_queue);
|
return fasync_helper(fd, file, on, &rtc_async_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file_operations rtc_fops = {
|
static const struct file_operations rtc_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
.read = rtc_read,
|
.read = rtc_read,
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/arch/pm.h>
|
#include <asm/arch/pm.h>
|
||||||
#include <asm/arch/pxa-regs.h>
|
#include <asm/arch/pxa-regs.h>
|
||||||
#include <asm/arch/sharpsl.h>
|
#include <asm/arch/sharpsl.h>
|
||||||
|
|
|
@ -10,7 +10,6 @@ obj-y := compat.o entry-armv.o entry-common.o irq.o \
|
||||||
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
|
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
|
||||||
time.o traps.o
|
time.o traps.o
|
||||||
|
|
||||||
obj-$(CONFIG_APM) += apm.o
|
|
||||||
obj-$(CONFIG_ISA_DMA_API) += dma.o
|
obj-$(CONFIG_ISA_DMA_API) += dma.o
|
||||||
obj-$(CONFIG_ARCH_ACORN) += ecard.o
|
obj-$(CONFIG_ARCH_ACORN) += ecard.o
|
||||||
obj-$(CONFIG_FIQ) += fiq.o
|
obj-$(CONFIG_FIQ) += fiq.o
|
||||||
|
|
|
@ -106,7 +106,7 @@ unsigned long phys_initrd_size __initdata = 0;
|
||||||
static struct meminfo meminfo __initdata = { 0, };
|
static struct meminfo meminfo __initdata = { 0, };
|
||||||
static const char *cpu_name;
|
static const char *cpu_name;
|
||||||
static const char *machine_name;
|
static const char *machine_name;
|
||||||
static char command_line[COMMAND_LINE_SIZE];
|
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||||
|
|
||||||
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
||||||
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
|
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
|
||||||
|
@ -803,8 +803,8 @@ void __init setup_arch(char **cmdline_p)
|
||||||
init_mm.end_data = (unsigned long) &_edata;
|
init_mm.end_data = (unsigned long) &_edata;
|
||||||
init_mm.brk = (unsigned long) &_end;
|
init_mm.brk = (unsigned long) &_end;
|
||||||
|
|
||||||
memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
|
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||||
saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||||
parse_cmdline(cmdline_p, from);
|
parse_cmdline(cmdline_p, from);
|
||||||
paging_init(&meminfo, mdesc);
|
paging_init(&meminfo, mdesc);
|
||||||
request_standard_resources(&meminfo, mdesc);
|
request_standard_resources(&meminfo, mdesc);
|
||||||
|
|
|
@ -77,16 +77,6 @@ static unsigned long dummy_gettimeoffset(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Scheduler clock - returns current time in nanosec units.
|
|
||||||
* This is the default implementation. Sub-architecture
|
|
||||||
* implementations can override this.
|
|
||||||
*/
|
|
||||||
unsigned long long __attribute__((weak)) sched_clock(void)
|
|
||||||
{
|
|
||||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An implementation of printk_clock() independent from
|
* An implementation of printk_clock() independent from
|
||||||
* sched_clock(). This avoids non-bootable kernels when
|
* sched_clock(). This avoids non-bootable kernels when
|
||||||
|
|
|
@ -53,10 +53,12 @@ SECTIONS
|
||||||
__security_initcall_start = .;
|
__security_initcall_start = .;
|
||||||
*(.security_initcall.init)
|
*(.security_initcall.init)
|
||||||
__security_initcall_end = .;
|
__security_initcall_end = .;
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
__initramfs_start = .;
|
__initramfs_start = .;
|
||||||
usr/built-in.o(.init.ramfs)
|
usr/built-in.o(.init.ramfs)
|
||||||
__initramfs_end = .;
|
__initramfs_end = .;
|
||||||
|
#endif
|
||||||
. = ALIGN(64);
|
. = ALIGN(64);
|
||||||
__per_cpu_start = .;
|
__per_cpu_start = .;
|
||||||
*(.data.percpu)
|
*(.data.percpu)
|
||||||
|
|
|
@ -407,7 +407,7 @@ static int at91_clk_open(struct inode *inode, struct file *file)
|
||||||
return single_open(file, at91_clk_show, NULL);
|
return single_open(file, at91_clk_show, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file_operations at91_clk_operations = {
|
static const struct file_operations at91_clk_operations = {
|
||||||
.open = at91_clk_open,
|
.open = at91_clk_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.llseek = seq_lseek,
|
.llseek = seq_lseek,
|
||||||
|
|
|
@ -64,6 +64,24 @@ static inline unsigned pin_to_mask(unsigned pin)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mux the pin to the "GPIO" peripheral role.
|
||||||
|
*/
|
||||||
|
int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup)
|
||||||
|
{
|
||||||
|
void __iomem *pio = pin_to_controller(pin);
|
||||||
|
unsigned mask = pin_to_mask(pin);
|
||||||
|
|
||||||
|
if (!pio)
|
||||||
|
return -EINVAL;
|
||||||
|
__raw_writel(mask, pio + PIO_IDR);
|
||||||
|
__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
|
||||||
|
__raw_writel(mask, pio + PIO_PER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(at91_set_GPIO_periph);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mux the pin to the "A" internal peripheral role.
|
* mux the pin to the "A" internal peripheral role.
|
||||||
*/
|
*/
|
||||||
|
@ -181,6 +199,36 @@ EXPORT_SYMBOL(at91_set_multi_drive);
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* new-style GPIO calls; these expect at91_set_GPIO_periph to have been
|
||||||
|
* called, and maybe at91_set_multi_drive() for putout pins.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int gpio_direction_input(unsigned pin)
|
||||||
|
{
|
||||||
|
void __iomem *pio = pin_to_controller(pin);
|
||||||
|
unsigned mask = pin_to_mask(pin);
|
||||||
|
|
||||||
|
if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
|
||||||
|
return -EINVAL;
|
||||||
|
__raw_writel(mask, pio + PIO_OER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_direction_input);
|
||||||
|
|
||||||
|
int gpio_direction_output(unsigned pin)
|
||||||
|
{
|
||||||
|
void __iomem *pio = pin_to_controller(pin);
|
||||||
|
unsigned mask = pin_to_mask(pin);
|
||||||
|
|
||||||
|
if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
|
||||||
|
return -EINVAL;
|
||||||
|
__raw_writel(mask, pio + PIO_OER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_direction_output);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* assuming the pin is muxed as a gpio output, set its value.
|
* assuming the pin is muxed as a gpio output, set its value.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/arch/pm.h>
|
#include <asm/arch/pm.h>
|
||||||
#include <asm/arch/pxa-regs.h>
|
#include <asm/arch/pxa-regs.h>
|
||||||
#include <asm/arch/sharpsl.h>
|
#include <asm/arch/sharpsl.h>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <asm/apm.h>
|
#include <asm/apm-emulation.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/hardware.h>
|
#include <asm/hardware.h>
|
||||||
|
|
|
@ -60,6 +60,10 @@ config GENERIC_CALIBRATE_DELAY
|
||||||
config GENERIC_BUST_SPINLOCK
|
config GENERIC_BUST_SPINLOCK
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config ZONE_DMA
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config GENERIC_ISA_DMA
|
config GENERIC_ISA_DMA
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
|
|
@ -665,7 +665,7 @@ ecard_probe(int slot, card_type_t type)
|
||||||
ec->fiqmask = 4;
|
ec->fiqmask = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
|
for (i = 0; i < ARRAY_SIZE(blacklist); i++)
|
||||||
if (blacklist[i].manufacturer == ec->cid.manufacturer &&
|
if (blacklist[i].manufacturer == ec->cid.manufacturer &&
|
||||||
blacklist[i].product == ec->cid.product) {
|
blacklist[i].product == ec->cid.product) {
|
||||||
ec->card_desc = blacklist[i].type;
|
ec->card_desc = blacklist[i].type;
|
||||||
|
|
|
@ -80,7 +80,7 @@ unsigned long phys_initrd_size __initdata = 0;
|
||||||
static struct meminfo meminfo __initdata = { 0, };
|
static struct meminfo meminfo __initdata = { 0, };
|
||||||
static struct proc_info_item proc_info;
|
static struct proc_info_item proc_info;
|
||||||
static const char *machine_name;
|
static const char *machine_name;
|
||||||
static char command_line[COMMAND_LINE_SIZE];
|
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||||
|
|
||||||
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
||||||
|
|
||||||
|
@ -492,8 +492,8 @@ void __init setup_arch(char **cmdline_p)
|
||||||
init_mm.end_data = (unsigned long) &_edata;
|
init_mm.end_data = (unsigned long) &_edata;
|
||||||
init_mm.brk = (unsigned long) &_end;
|
init_mm.brk = (unsigned long) &_end;
|
||||||
|
|
||||||
memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
|
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||||
saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||||
parse_cmdline(&meminfo, cmdline_p, from);
|
parse_cmdline(&meminfo, cmdline_p, from);
|
||||||
bootmem_init(&meminfo);
|
bootmem_init(&meminfo);
|
||||||
paging_init(&meminfo);
|
paging_init(&meminfo);
|
||||||
|
|
|
@ -89,14 +89,6 @@ static unsigned long gettimeoffset(void)
|
||||||
return (offset + LATCH/2) / LATCH;
|
return (offset + LATCH/2) / LATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Scheduler clock - returns current time in nanosec units.
|
|
||||||
*/
|
|
||||||
unsigned long long sched_clock(void)
|
|
||||||
{
|
|
||||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long next_rtc_update;
|
static unsigned long next_rtc_update;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -46,10 +46,12 @@ SECTIONS
|
||||||
__con_initcall_start = .;
|
__con_initcall_start = .;
|
||||||
*(.con_initcall.init)
|
*(.con_initcall.init)
|
||||||
__con_initcall_end = .;
|
__con_initcall_end = .;
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
__initramfs_start = .;
|
__initramfs_start = .;
|
||||||
usr/built-in.o(.init.ramfs)
|
usr/built-in.o(.init.ramfs)
|
||||||
__initramfs_end = .;
|
__initramfs_end = .;
|
||||||
|
#endif
|
||||||
. = ALIGN(32768);
|
. = ALIGN(32768);
|
||||||
__init_end = .;
|
__init_end = .;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,10 +47,12 @@ SECTIONS
|
||||||
__con_initcall_start = .;
|
__con_initcall_start = .;
|
||||||
*(.con_initcall.init)
|
*(.con_initcall.init)
|
||||||
__con_initcall_end = .;
|
__con_initcall_end = .;
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
__initramfs_start = .;
|
__initramfs_start = .;
|
||||||
usr/built-in.o(.init.ramfs)
|
usr/built-in.o(.init.ramfs)
|
||||||
__initramfs_end = .;
|
__initramfs_end = .;
|
||||||
|
#endif
|
||||||
. = ALIGN(32768);
|
. = ALIGN(32768);
|
||||||
__init_end = .;
|
__init_end = .;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
obj-y += setup.o spi.o flash.o
|
obj-y += setup.o flash.o
|
||||||
obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
|
obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
|
||||||
|
|
|
@ -8,17 +8,24 @@
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
#include <asm/arch/at32ap7000.h>
|
||||||
#include <asm/arch/board.h>
|
#include <asm/arch/board.h>
|
||||||
#include <asm/arch/init.h>
|
#include <asm/arch/init.h>
|
||||||
|
#include <asm/arch/portmux.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SW2_DEFAULT /* MMCI and UART_A available */
|
||||||
|
|
||||||
struct eth_addr {
|
struct eth_addr {
|
||||||
u8 addr[6];
|
u8 addr[6];
|
||||||
|
@ -29,6 +36,16 @@ static struct eth_addr __initdata hw_addr[2];
|
||||||
static struct eth_platform_data __initdata eth_data[2];
|
static struct eth_platform_data __initdata eth_data[2];
|
||||||
extern struct lcdc_platform_data atstk1000_fb0_data;
|
extern struct lcdc_platform_data atstk1000_fb0_data;
|
||||||
|
|
||||||
|
static struct spi_board_info spi_board_info[] __initdata = {
|
||||||
|
{
|
||||||
|
.modalias = "ltv350qv",
|
||||||
|
.controller_data = (void *)GPIO_PIN_PA(4),
|
||||||
|
.max_speed_hz = 16000000,
|
||||||
|
.bus_num = 0,
|
||||||
|
.chip_select = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The next two functions should go away as the boot loader is
|
* The next two functions should go away as the boot loader is
|
||||||
* supposed to initialize the macb address registers with a valid
|
* supposed to initialize the macb address registers with a valid
|
||||||
|
@ -86,23 +103,53 @@ static void __init set_hw_addr(struct platform_device *pdev)
|
||||||
|
|
||||||
void __init setup_board(void)
|
void __init setup_board(void)
|
||||||
{
|
{
|
||||||
at32_map_usart(1, 0); /* /dev/ttyS0 */
|
#ifdef SW2_DEFAULT
|
||||||
at32_map_usart(2, 1); /* /dev/ttyS1 */
|
at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
|
||||||
at32_map_usart(3, 2); /* /dev/ttyS2 */
|
#else
|
||||||
|
at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */
|
||||||
|
#endif
|
||||||
|
/* USART 2/unused: expansion connector */
|
||||||
|
at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */
|
||||||
|
|
||||||
at32_setup_serial_console(0);
|
at32_setup_serial_console(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init atstk1002_init(void)
|
static int __init atstk1002_init(void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* ATSTK1000 uses 32-bit SDRAM interface. Reserve the
|
||||||
|
* SDRAM-specific pins so that nobody messes with them.
|
||||||
|
*/
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
|
||||||
|
at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
|
||||||
|
|
||||||
at32_add_system_devices();
|
at32_add_system_devices();
|
||||||
|
|
||||||
|
#ifdef SW2_DEFAULT
|
||||||
at32_add_device_usart(0);
|
at32_add_device_usart(0);
|
||||||
|
#else
|
||||||
at32_add_device_usart(1);
|
at32_add_device_usart(1);
|
||||||
|
#endif
|
||||||
at32_add_device_usart(2);
|
at32_add_device_usart(2);
|
||||||
|
|
||||||
set_hw_addr(at32_add_device_eth(0, ð_data[0]));
|
set_hw_addr(at32_add_device_eth(0, ð_data[0]));
|
||||||
|
|
||||||
|
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
|
||||||
at32_add_device_spi(0);
|
at32_add_device_spi(0);
|
||||||
at32_add_device_lcdc(0, &atstk1000_fb0_data);
|
at32_add_device_lcdc(0, &atstk1000_fb0_data);
|
||||||
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* ATSTK1000 SPI devices
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 Atmel Norway
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/spi/spi.h>
|
|
||||||
|
|
||||||
static struct spi_board_info spi_board_info[] __initdata = {
|
|
||||||
{
|
|
||||||
.modalias = "ltv350qv",
|
|
||||||
.max_speed_hz = 16000000,
|
|
||||||
.bus_num = 0,
|
|
||||||
.chip_select = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int board_init_spi(void)
|
|
||||||
{
|
|
||||||
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
arch_initcall(board_init_spi);
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/module.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <linux/param.h>
|
#include <linux/param.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
|
|
@ -57,6 +57,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
||||||
seq_printf(p, "%3d: ", i);
|
seq_printf(p, "%3d: ", i);
|
||||||
for_each_online_cpu(cpu)
|
for_each_online_cpu(cpu)
|
||||||
seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
|
seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
|
||||||
|
seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
|
||||||
seq_printf(p, " %s", action->name);
|
seq_printf(p, " %s", action->name);
|
||||||
for (action = action->next; action; action = action->next)
|
for (action = action->next; action; action = action->next)
|
||||||
seq_printf(p, ", %s", action->name);
|
seq_printf(p, ", %s", action->name);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/root_dev.h>
|
#include <linux/root_dev.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
@ -44,7 +45,7 @@ struct avr32_cpuinfo boot_cpu_data = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(boot_cpu_data);
|
EXPORT_SYMBOL(boot_cpu_data);
|
||||||
|
|
||||||
static char command_line[COMMAND_LINE_SIZE];
|
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Should be more than enough, but if you have a _really_ complex
|
* Should be more than enough, but if you have a _really_ complex
|
||||||
|
@ -174,8 +175,7 @@ static int __init parse_tag_mem_range(struct tag *tag,
|
||||||
* Copy the data so the bootmem init code doesn't need to care
|
* Copy the data so the bootmem init code doesn't need to care
|
||||||
* about it.
|
* about it.
|
||||||
*/
|
*/
|
||||||
if (mem_range_next_free >=
|
if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache))
|
||||||
(sizeof(mem_range_cache) / sizeof(mem_range_cache[0])))
|
|
||||||
panic("Physical memory map too complex!\n");
|
panic("Physical memory map too complex!\n");
|
||||||
|
|
||||||
new = &mem_range_cache[mem_range_next_free++];
|
new = &mem_range_cache[mem_range_next_free++];
|
||||||
|
@ -202,7 +202,7 @@ __tagtable(ATAG_MEM, parse_tag_mem);
|
||||||
|
|
||||||
static int __init parse_tag_cmdline(struct tag *tag)
|
static int __init parse_tag_cmdline(struct tag *tag)
|
||||||
{
|
{
|
||||||
strlcpy(saved_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
|
strlcpy(boot_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
|
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
|
||||||
|
@ -294,7 +294,7 @@ void __init setup_arch (char **cmdline_p)
|
||||||
init_mm.end_data = (unsigned long) &_edata;
|
init_mm.end_data = (unsigned long) &_edata;
|
||||||
init_mm.brk = (unsigned long) &_end;
|
init_mm.brk = (unsigned long) &_end;
|
||||||
|
|
||||||
strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
|
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||||
*cmdline_p = command_line;
|
*cmdline_p = command_line;
|
||||||
parse_early_param();
|
parse_early_param();
|
||||||
|
|
||||||
|
|
|
@ -109,15 +109,6 @@ static void avr32_hpt_init(unsigned int count)
|
||||||
sysreg_write(COUNT, count);
|
sysreg_write(COUNT, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Scheduler clock - returns current time in nanosec units.
|
|
||||||
*/
|
|
||||||
unsigned long long sched_clock(void)
|
|
||||||
{
|
|
||||||
/* There must be better ways...? */
|
|
||||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* local_timer_interrupt() does profiling and process accounting on a
|
* local_timer_interrupt() does profiling and process accounting on a
|
||||||
* per-CPU basis.
|
* per-CPU basis.
|
||||||
|
|
|
@ -46,10 +46,12 @@ SECTIONS
|
||||||
__security_initcall_start = .;
|
__security_initcall_start = .;
|
||||||
*(.security_initcall.init)
|
*(.security_initcall.init)
|
||||||
__security_initcall_end = .;
|
__security_initcall_end = .;
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
__initramfs_start = .;
|
__initramfs_start = .;
|
||||||
*(.init.ramfs)
|
*(.init.ramfs)
|
||||||
__initramfs_end = .;
|
__initramfs_end = .;
|
||||||
|
#endif
|
||||||
. = ALIGN(4096);
|
. = ALIGN(4096);
|
||||||
__init_end = .;
|
__init_end = .;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/* Definitions for various functions 'borrowed' from gcc-3.4.3 */
|
|
||||||
|
|
||||||
#define BITS_PER_UNIT 8
|
|
||||||
|
|
||||||
typedef int QItype __attribute__ ((mode (QI)));
|
|
||||||
typedef unsigned int UQItype __attribute__ ((mode (QI)));
|
|
||||||
typedef int HItype __attribute__ ((mode (HI)));
|
|
||||||
typedef unsigned int UHItype __attribute__ ((mode (HI)));
|
|
||||||
typedef int SItype __attribute__ ((mode (SI)));
|
|
||||||
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
|
||||||
typedef int DItype __attribute__ ((mode (DI)));
|
|
||||||
typedef unsigned int UDItype __attribute__ ((mode (DI)));
|
|
||||||
typedef float SFtype __attribute__ ((mode (SF)));
|
|
||||||
typedef float DFtype __attribute__ ((mode (DF)));
|
|
||||||
typedef int word_type __attribute__ ((mode (__word__)));
|
|
||||||
|
|
||||||
#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
|
|
||||||
#define Wtype SItype
|
|
||||||
#define UWtype USItype
|
|
||||||
#define HWtype SItype
|
|
||||||
#define UHWtype USItype
|
|
||||||
#define DWtype DItype
|
|
||||||
#define UDWtype UDItype
|
|
||||||
#define __NW(a,b) __ ## a ## si ## b
|
|
||||||
#define __NDW(a,b) __ ## a ## di ## b
|
|
||||||
|
|
||||||
struct DWstruct {Wtype high, low;};
|
|
||||||
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
struct DWstruct s;
|
|
||||||
DWtype ll;
|
|
||||||
} DWunion;
|
|
|
@ -1,98 +0,0 @@
|
||||||
/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
|
|
||||||
Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This definition file is free software; you can redistribute it
|
|
||||||
and/or modify it under the terms of the GNU General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2, or (at your option) any later version.
|
|
||||||
|
|
||||||
This definition file is distributed in the hope that it will be
|
|
||||||
useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
Boston, MA 02111-1307, USA. */
|
|
||||||
|
|
||||||
/* Borrowed from gcc-3.4.3 */
|
|
||||||
|
|
||||||
#define __BITS4 (W_TYPE_SIZE / 4)
|
|
||||||
#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
|
|
||||||
#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
|
|
||||||
#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
|
|
||||||
|
|
||||||
#define count_leading_zeros(count, x) ((count) = __builtin_clz(x))
|
|
||||||
|
|
||||||
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
|
|
||||||
do { \
|
|
||||||
UWtype __d1, __d0, __q1, __q0; \
|
|
||||||
UWtype __r1, __r0, __m; \
|
|
||||||
__d1 = __ll_highpart (d); \
|
|
||||||
__d0 = __ll_lowpart (d); \
|
|
||||||
\
|
|
||||||
__r1 = (n1) % __d1; \
|
|
||||||
__q1 = (n1) / __d1; \
|
|
||||||
__m = (UWtype) __q1 * __d0; \
|
|
||||||
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
|
|
||||||
if (__r1 < __m) \
|
|
||||||
{ \
|
|
||||||
__q1--, __r1 += (d); \
|
|
||||||
if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
|
|
||||||
if (__r1 < __m) \
|
|
||||||
__q1--, __r1 += (d); \
|
|
||||||
} \
|
|
||||||
__r1 -= __m; \
|
|
||||||
\
|
|
||||||
__r0 = __r1 % __d1; \
|
|
||||||
__q0 = __r1 / __d1; \
|
|
||||||
__m = (UWtype) __q0 * __d0; \
|
|
||||||
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
|
|
||||||
if (__r0 < __m) \
|
|
||||||
{ \
|
|
||||||
__q0--, __r0 += (d); \
|
|
||||||
if (__r0 >= (d)) \
|
|
||||||
if (__r0 < __m) \
|
|
||||||
__q0--, __r0 += (d); \
|
|
||||||
} \
|
|
||||||
__r0 -= __m; \
|
|
||||||
\
|
|
||||||
(q) = (UWtype) __q1 * __ll_B | __q0; \
|
|
||||||
(r) = __r0; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define udiv_qrnnd __udiv_qrnnd_c
|
|
||||||
|
|
||||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
|
||||||
do { \
|
|
||||||
UWtype __x; \
|
|
||||||
__x = (al) - (bl); \
|
|
||||||
(sh) = (ah) - (bh) - (__x > (al)); \
|
|
||||||
(sl) = __x; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define umul_ppmm(w1, w0, u, v) \
|
|
||||||
do { \
|
|
||||||
UWtype __x0, __x1, __x2, __x3; \
|
|
||||||
UHWtype __ul, __vl, __uh, __vh; \
|
|
||||||
\
|
|
||||||
__ul = __ll_lowpart (u); \
|
|
||||||
__uh = __ll_highpart (u); \
|
|
||||||
__vl = __ll_lowpart (v); \
|
|
||||||
__vh = __ll_highpart (v); \
|
|
||||||
\
|
|
||||||
__x0 = (UWtype) __ul * __vl; \
|
|
||||||
__x1 = (UWtype) __ul * __vh; \
|
|
||||||
__x2 = (UWtype) __uh * __vl; \
|
|
||||||
__x3 = (UWtype) __uh * __vh; \
|
|
||||||
\
|
|
||||||
__x1 += __ll_highpart (__x0);/* this can't give carry */ \
|
|
||||||
__x1 += __x2; /* but this indeed can */ \
|
|
||||||
if (__x1 < __x2) /* did we get it? */ \
|
|
||||||
__x3 += __ll_B; /* yes, add it in the proper pos. */ \
|
|
||||||
\
|
|
||||||
(w1) = __x3 + __ll_highpart (__x1); \
|
|
||||||
(w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
|
|
||||||
} while (0)
|
|
|
@ -1,2 +1,2 @@
|
||||||
obj-y += at32ap.o clock.o pio.o intc.o extint.o hsmc.o
|
obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
|
||||||
obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
|
obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
|
||||||
|
|
|
@ -496,9 +496,16 @@ static struct resource pio3_resource[] = {
|
||||||
DEFINE_DEV(pio, 3);
|
DEFINE_DEV(pio, 3);
|
||||||
DEV_CLK(mck, pio3, pba, 13);
|
DEV_CLK(mck, pio3, pba, 13);
|
||||||
|
|
||||||
|
static struct resource pio4_resource[] = {
|
||||||
|
PBMEM(0xffe03800),
|
||||||
|
IRQ(17),
|
||||||
|
};
|
||||||
|
DEFINE_DEV(pio, 4);
|
||||||
|
DEV_CLK(mck, pio4, pba, 14);
|
||||||
|
|
||||||
void __init at32_add_system_devices(void)
|
void __init at32_add_system_devices(void)
|
||||||
{
|
{
|
||||||
system_manager.eim_first_irq = NR_INTERNAL_IRQS;
|
system_manager.eim_first_irq = EIM_IRQ_BASE;
|
||||||
|
|
||||||
platform_device_register(&at32_sm_device);
|
platform_device_register(&at32_sm_device);
|
||||||
platform_device_register(&at32_intc0_device);
|
platform_device_register(&at32_intc0_device);
|
||||||
|
@ -509,6 +516,7 @@ void __init at32_add_system_devices(void)
|
||||||
platform_device_register(&pio1_device);
|
platform_device_register(&pio1_device);
|
||||||
platform_device_register(&pio2_device);
|
platform_device_register(&pio2_device);
|
||||||
platform_device_register(&pio3_device);
|
platform_device_register(&pio3_device);
|
||||||
|
platform_device_register(&pio4_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
|
@ -521,7 +529,7 @@ static struct atmel_uart_data atmel_usart0_data = {
|
||||||
};
|
};
|
||||||
static struct resource atmel_usart0_resource[] = {
|
static struct resource atmel_usart0_resource[] = {
|
||||||
PBMEM(0xffe00c00),
|
PBMEM(0xffe00c00),
|
||||||
IRQ(7),
|
IRQ(6),
|
||||||
};
|
};
|
||||||
DEFINE_DEV_DATA(atmel_usart, 0);
|
DEFINE_DEV_DATA(atmel_usart, 0);
|
||||||
DEV_CLK(usart, atmel_usart0, pba, 4);
|
DEV_CLK(usart, atmel_usart0, pba, 4);
|
||||||
|
@ -583,7 +591,7 @@ static inline void configure_usart3_pins(void)
|
||||||
select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
|
select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_device *at32_usarts[4];
|
static struct platform_device *__initdata at32_usarts[4];
|
||||||
|
|
||||||
void __init at32_map_usart(unsigned int hw_id, unsigned int line)
|
void __init at32_map_usart(unsigned int hw_id, unsigned int line)
|
||||||
{
|
{
|
||||||
|
@ -728,12 +736,19 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* SPI
|
* SPI
|
||||||
* -------------------------------------------------------------------- */
|
* -------------------------------------------------------------------- */
|
||||||
static struct resource spi0_resource[] = {
|
static struct resource atmel_spi0_resource[] = {
|
||||||
PBMEM(0xffe00000),
|
PBMEM(0xffe00000),
|
||||||
IRQ(3),
|
IRQ(3),
|
||||||
};
|
};
|
||||||
DEFINE_DEV(spi, 0);
|
DEFINE_DEV(atmel_spi, 0);
|
||||||
DEV_CLK(mck, spi0, pba, 0);
|
DEV_CLK(spi_clk, atmel_spi0, pba, 0);
|
||||||
|
|
||||||
|
static struct resource atmel_spi1_resource[] = {
|
||||||
|
PBMEM(0xffe00400),
|
||||||
|
IRQ(4),
|
||||||
|
};
|
||||||
|
DEFINE_DEV(atmel_spi, 1);
|
||||||
|
DEV_CLK(spi_clk, atmel_spi1, pba, 1);
|
||||||
|
|
||||||
struct platform_device *__init at32_add_device_spi(unsigned int id)
|
struct platform_device *__init at32_add_device_spi(unsigned int id)
|
||||||
{
|
{
|
||||||
|
@ -741,13 +756,33 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0:
|
case 0:
|
||||||
pdev = &spi0_device;
|
pdev = &atmel_spi0_device;
|
||||||
select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
|
select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
|
||||||
select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
|
select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
|
||||||
select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
|
select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
|
||||||
select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */
|
|
||||||
select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */
|
/* NPCS[2:0] */
|
||||||
select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */
|
at32_select_gpio(GPIO_PIN_PA(3),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PA(4),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PA(5),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
pdev = &atmel_spi1_device;
|
||||||
|
select_peripheral(PB(0), PERIPH_B, 0); /* MISO */
|
||||||
|
select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */
|
||||||
|
select_peripheral(PB(5), PERIPH_B, 0); /* SCK */
|
||||||
|
|
||||||
|
/* NPCS[2:0] */
|
||||||
|
at32_select_gpio(GPIO_PIN_PB(2),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PB(3),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
|
at32_select_gpio(GPIO_PIN_PB(4),
|
||||||
|
AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -860,6 +895,7 @@ struct clk *at32_clock_list[] = {
|
||||||
&pio1_mck,
|
&pio1_mck,
|
||||||
&pio2_mck,
|
&pio2_mck,
|
||||||
&pio3_mck,
|
&pio3_mck,
|
||||||
|
&pio4_mck,
|
||||||
&atmel_usart0_usart,
|
&atmel_usart0_usart,
|
||||||
&atmel_usart1_usart,
|
&atmel_usart1_usart,
|
||||||
&atmel_usart2_usart,
|
&atmel_usart2_usart,
|
||||||
|
@ -868,7 +904,8 @@ struct clk *at32_clock_list[] = {
|
||||||
&macb0_pclk,
|
&macb0_pclk,
|
||||||
&macb1_hclk,
|
&macb1_hclk,
|
||||||
&macb1_pclk,
|
&macb1_pclk,
|
||||||
&spi0_mck,
|
&atmel_spi0_spi_clk,
|
||||||
|
&atmel_spi1_spi_clk,
|
||||||
&lcdc0_hclk,
|
&lcdc0_hclk,
|
||||||
&lcdc0_pixclk,
|
&lcdc0_pixclk,
|
||||||
};
|
};
|
||||||
|
@ -880,6 +917,7 @@ void __init at32_portmux_init(void)
|
||||||
at32_init_pio(&pio1_device);
|
at32_init_pio(&pio1_device);
|
||||||
at32_init_pio(&pio2_device);
|
at32_init_pio(&pio2_device);
|
||||||
at32_init_pio(&pio3_device);
|
at32_init_pio(&pio3_device);
|
||||||
|
at32_init_pio(&pio4_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init at32_clock_init(void)
|
void __init at32_clock_init(void)
|
||||||
|
|
|
@ -55,20 +55,11 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||||
if (flow_type == IRQ_TYPE_NONE)
|
if (flow_type == IRQ_TYPE_NONE)
|
||||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||||
|
|
||||||
desc = &irq_desc[irq];
|
desc = &irq_desc[irq];
|
||||||
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
|
||||||
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
|
|
||||||
|
|
||||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
|
|
||||||
desc->status |= IRQ_LEVEL;
|
|
||||||
set_irq_handler(irq, handle_level_irq);
|
|
||||||
} else {
|
|
||||||
set_irq_handler(irq, handle_edge_irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sm->lock, flags);
|
spin_lock_irqsave(&sm->lock, flags);
|
||||||
|
|
||||||
mode = sm_readl(sm, EIM_MODE);
|
mode = sm_readl(sm, EIM_MODE);
|
||||||
|
@ -97,9 +88,16 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sm_writel(sm, EIM_MODE, mode);
|
if (ret == 0) {
|
||||||
sm_writel(sm, EIM_EDGE, edge);
|
sm_writel(sm, EIM_MODE, mode);
|
||||||
sm_writel(sm, EIM_LEVEL, level);
|
sm_writel(sm, EIM_EDGE, edge);
|
||||||
|
sm_writel(sm, EIM_LEVEL, level);
|
||||||
|
|
||||||
|
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||||
|
flow_type |= IRQ_LEVEL;
|
||||||
|
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
||||||
|
desc->status |= flow_type;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&sm->lock, flags);
|
spin_unlock_irqrestore(&sm->lock, flags);
|
||||||
|
|
||||||
|
@ -122,8 +120,6 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
unsigned long status, pending;
|
unsigned long status, pending;
|
||||||
unsigned int i, ext_irq;
|
unsigned int i, ext_irq;
|
||||||
|
|
||||||
spin_lock(&sm->lock);
|
|
||||||
|
|
||||||
status = sm_readl(sm, EIM_ISR);
|
status = sm_readl(sm, EIM_ISR);
|
||||||
pending = status & sm_readl(sm, EIM_IMR);
|
pending = status & sm_readl(sm, EIM_IMR);
|
||||||
|
|
||||||
|
@ -133,10 +129,11 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
|
|
||||||
ext_irq = i + sm->eim_first_irq;
|
ext_irq = i + sm->eim_first_irq;
|
||||||
ext_desc = irq_desc + ext_irq;
|
ext_desc = irq_desc + ext_irq;
|
||||||
ext_desc->handle_irq(ext_irq, ext_desc);
|
if (ext_desc->status & IRQ_LEVEL)
|
||||||
|
handle_level_irq(ext_irq, ext_desc);
|
||||||
|
else
|
||||||
|
handle_edge_irq(ext_irq, ext_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&sm->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init eim_init(void)
|
static int __init eim_init(void)
|
||||||
|
@ -168,8 +165,9 @@ static int __init eim_init(void)
|
||||||
sm->eim_chip = &eim_chip;
|
sm->eim_chip = &eim_chip;
|
||||||
|
|
||||||
for (i = 0; i < nr_irqs; i++) {
|
for (i = 0; i < nr_irqs; i++) {
|
||||||
|
/* NOTE the handler we set here is ignored by the demux */
|
||||||
set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
|
set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
|
||||||
handle_edge_irq);
|
handle_level_irq);
|
||||||
set_irq_chip_data(sm->eim_first_irq + i, sm);
|
set_irq_chip_data(sm->eim_first_irq + i, sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
|
||||||
|
#include <asm/gpio.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <asm/arch/portmux.h>
|
#include <asm/arch/portmux.h>
|
||||||
|
@ -26,7 +28,8 @@ struct pio_device {
|
||||||
const struct platform_device *pdev;
|
const struct platform_device *pdev;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
u32 pinmux_mask;
|
u32 pinmux_mask;
|
||||||
char name[32];
|
u32 gpio_mask;
|
||||||
|
char name[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
|
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
|
||||||
|
@ -76,6 +79,9 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
|
||||||
if (!(flags & AT32_GPIOF_PULLUP))
|
if (!(flags & AT32_GPIOF_PULLUP))
|
||||||
pio_writel(pio, PUDR, mask);
|
pio_writel(pio, PUDR, mask);
|
||||||
|
|
||||||
|
/* gpio_request NOT allowed */
|
||||||
|
set_bit(pin_index, &pio->gpio_mask);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -99,19 +105,29 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pio_writel(pio, PUER, mask);
|
if (flags & AT32_GPIOF_OUTPUT) {
|
||||||
if (flags & AT32_GPIOF_HIGH)
|
if (flags & AT32_GPIOF_HIGH)
|
||||||
pio_writel(pio, SODR, mask);
|
pio_writel(pio, SODR, mask);
|
||||||
else
|
else
|
||||||
pio_writel(pio, CODR, mask);
|
pio_writel(pio, CODR, mask);
|
||||||
if (flags & AT32_GPIOF_OUTPUT)
|
pio_writel(pio, PUDR, mask);
|
||||||
pio_writel(pio, OER, mask);
|
pio_writel(pio, OER, mask);
|
||||||
else
|
} else {
|
||||||
|
if (flags & AT32_GPIOF_PULLUP)
|
||||||
|
pio_writel(pio, PUER, mask);
|
||||||
|
else
|
||||||
|
pio_writel(pio, PUDR, mask);
|
||||||
|
if (flags & AT32_GPIOF_DEGLITCH)
|
||||||
|
pio_writel(pio, IFER, mask);
|
||||||
|
else
|
||||||
|
pio_writel(pio, IFDR, mask);
|
||||||
pio_writel(pio, ODR, mask);
|
pio_writel(pio, ODR, mask);
|
||||||
|
}
|
||||||
|
|
||||||
pio_writel(pio, PER, mask);
|
pio_writel(pio, PER, mask);
|
||||||
if (!(flags & AT32_GPIOF_PULLUP))
|
|
||||||
pio_writel(pio, PUDR, mask);
|
/* gpio_request now allowed */
|
||||||
|
clear_bit(pin_index, &pio->gpio_mask);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -119,20 +135,220 @@ fail:
|
||||||
dump_stack();
|
dump_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reserve a pin, preventing anyone else from changing its configuration. */
|
||||||
|
void __init at32_reserve_pin(unsigned int pin)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin_index = pin & 0x1f;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(pin);
|
||||||
|
if (unlikely(!pio)) {
|
||||||
|
printk("pio: invalid pin %u\n", pin);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
|
||||||
|
printk("%s: pin %u is busy\n", pio->name, pin_index);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
dump_stack();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* GPIO API */
|
||||||
|
|
||||||
|
int gpio_request(unsigned int gpio, const char *label)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
if (test_and_set_bit(pin, &pio->gpio_mask))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_request);
|
||||||
|
|
||||||
|
void gpio_free(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"gpio: attempted to free invalid pin %u\n", gpio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
if (!test_and_clear_bit(pin, &pio->gpio_mask))
|
||||||
|
printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
|
||||||
|
pio->name, pin);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_free);
|
||||||
|
|
||||||
|
int gpio_direction_input(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
pio_writel(pio, ODR, 1 << pin);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_direction_input);
|
||||||
|
|
||||||
|
int gpio_direction_output(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio;
|
||||||
|
unsigned int pin;
|
||||||
|
|
||||||
|
pio = gpio_to_pio(gpio);
|
||||||
|
if (!pio)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pin = gpio & 0x1f;
|
||||||
|
pio_writel(pio, OER, 1 << pin);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_direction_output);
|
||||||
|
|
||||||
|
int gpio_get_value(unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
|
||||||
|
return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_get_value);
|
||||||
|
|
||||||
|
void gpio_set_value(unsigned int gpio, int value)
|
||||||
|
{
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
mask = 1 << (gpio & 0x1f);
|
||||||
|
if (value)
|
||||||
|
pio_writel(pio, SODR, mask);
|
||||||
|
else
|
||||||
|
pio_writel(pio, CODR, mask);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gpio_set_value);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* GPIO IRQ support */
|
||||||
|
|
||||||
|
static void gpio_irq_mask(unsigned irq)
|
||||||
|
{
|
||||||
|
unsigned gpio = irq_to_gpio(irq);
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
|
||||||
|
pio_writel(pio, IDR, 1 << (gpio & 0x1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gpio_irq_unmask(unsigned irq)
|
||||||
|
{
|
||||||
|
unsigned gpio = irq_to_gpio(irq);
|
||||||
|
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||||
|
|
||||||
|
pio_writel(pio, IER, 1 << (gpio & 0x1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gpio_irq_type(unsigned irq, unsigned type)
|
||||||
|
{
|
||||||
|
if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct irq_chip gpio_irqchip = {
|
||||||
|
.name = "gpio",
|
||||||
|
.mask = gpio_irq_mask,
|
||||||
|
.unmask = gpio_irq_unmask,
|
||||||
|
.set_type = gpio_irq_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||||
|
{
|
||||||
|
struct pio_device *pio = get_irq_chip_data(irq);
|
||||||
|
unsigned gpio_irq;
|
||||||
|
|
||||||
|
gpio_irq = (unsigned) get_irq_data(irq);
|
||||||
|
for (;;) {
|
||||||
|
u32 isr;
|
||||||
|
struct irq_desc *d;
|
||||||
|
|
||||||
|
/* ack pending GPIO interrupts */
|
||||||
|
isr = pio_readl(pio, ISR) & pio_readl(pio, IMR);
|
||||||
|
if (!isr)
|
||||||
|
break;
|
||||||
|
do {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = ffs(isr) - 1;
|
||||||
|
isr &= ~(1 << i);
|
||||||
|
|
||||||
|
i += gpio_irq;
|
||||||
|
d = &irq_desc[i];
|
||||||
|
|
||||||
|
d->handle_irq(i, d);
|
||||||
|
} while (isr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init
|
||||||
|
gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
set_irq_chip_data(irq, pio);
|
||||||
|
set_irq_data(irq, (void *) gpio_irq);
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++, gpio_irq++) {
|
||||||
|
set_irq_chip_data(gpio_irq, pio);
|
||||||
|
set_irq_chip_and_handler(gpio_irq, &gpio_irqchip,
|
||||||
|
handle_simple_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_irq_chained_handler(irq, gpio_irq_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int __init pio_probe(struct platform_device *pdev)
|
static int __init pio_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct pio_device *pio = NULL;
|
struct pio_device *pio = NULL;
|
||||||
|
int irq = platform_get_irq(pdev, 0);
|
||||||
|
int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32;
|
||||||
|
|
||||||
BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
|
BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
|
||||||
pio = &pio_dev[pdev->id];
|
pio = &pio_dev[pdev->id];
|
||||||
BUG_ON(!pio->regs);
|
BUG_ON(!pio->regs);
|
||||||
|
|
||||||
/* TODO: Interrupts */
|
gpio_irq_setup(pio, irq, gpio_irq_base);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, pio);
|
platform_set_drvdata(pdev, pio);
|
||||||
|
|
||||||
printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n",
|
printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n",
|
||||||
pio->name, pio->regs, platform_get_irq(pdev, 0));
|
pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +364,7 @@ static int __init pio_init(void)
|
||||||
{
|
{
|
||||||
return platform_driver_register(&pio_driver);
|
return platform_driver_register(&pio_driver);
|
||||||
}
|
}
|
||||||
subsys_initcall(pio_init);
|
postcore_initcall(pio_init);
|
||||||
|
|
||||||
void __init at32_init_pio(struct platform_device *pdev)
|
void __init at32_init_pio(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
@ -184,6 +400,13 @@ void __init at32_init_pio(struct platform_device *pdev)
|
||||||
pio->pdev = pdev;
|
pio->pdev = pdev;
|
||||||
pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
|
pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
|
||||||
|
|
||||||
pio_writel(pio, ODR, ~0UL);
|
/*
|
||||||
pio_writel(pio, PER, ~0UL);
|
* request_gpio() is only valid for pins that have been
|
||||||
|
* explicitly configured as GPIO and not previously requested
|
||||||
|
*/
|
||||||
|
pio->gpio_mask = ~0UL;
|
||||||
|
|
||||||
|
/* start with irqs disabled and acked */
|
||||||
|
pio_writel(pio, IDR, ~0UL);
|
||||||
|
(void) pio_readl(pio, ISR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,18 +22,34 @@
|
||||||
|
|
||||||
void invalidate_dcache_region(void *start, size_t size)
|
void invalidate_dcache_region(void *start, size_t size)
|
||||||
{
|
{
|
||||||
unsigned long v, begin, end, linesz;
|
unsigned long v, begin, end, linesz, mask;
|
||||||
|
int flush = 0;
|
||||||
|
|
||||||
linesz = boot_cpu_data.dcache.linesz;
|
linesz = boot_cpu_data.dcache.linesz;
|
||||||
|
mask = linesz - 1;
|
||||||
|
|
||||||
//printk("invalidate dcache: %p + %u\n", start, size);
|
/* when first and/or last cachelines are shared, flush them
|
||||||
|
* instead of invalidating ... never discard valid data!
|
||||||
|
*/
|
||||||
|
begin = (unsigned long)start;
|
||||||
|
end = begin + size - 1;
|
||||||
|
|
||||||
/* You asked for it, you got it */
|
if (begin & mask) {
|
||||||
begin = (unsigned long)start & ~(linesz - 1);
|
flush_dcache_line(start);
|
||||||
end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
|
begin += linesz;
|
||||||
|
flush = 1;
|
||||||
|
}
|
||||||
|
if ((end & mask) != mask) {
|
||||||
|
flush_dcache_line((void *)end);
|
||||||
|
end -= linesz;
|
||||||
|
flush = 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (v = begin; v < end; v += linesz)
|
/* remaining cachelines only need invalidation */
|
||||||
|
for (v = begin; v <= end; v += linesz)
|
||||||
invalidate_dcache_line((void *)v);
|
invalidate_dcache_line((void *)v);
|
||||||
|
if (flush)
|
||||||
|
flush_write_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean_dcache_region(void *start, size_t size)
|
void clean_dcache_region(void *start, size_t size)
|
||||||
|
|
|
@ -360,7 +360,7 @@ static int tlb_open(struct inode *inode, struct file *file)
|
||||||
return seq_open(file, &tlb_ops);
|
return seq_open(file, &tlb_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file_operations proc_tlb_operations = {
|
static const struct file_operations proc_tlb_operations = {
|
||||||
.open = tlb_open,
|
.open = tlb_open,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.llseek = seq_lseek,
|
.llseek = seq_lseek,
|
||||||
|
|
|
@ -9,6 +9,10 @@ config MMU
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config ZONE_DMA
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config RWSEM_GENERIC_SPINLOCK
|
config RWSEM_GENERIC_SPINLOCK
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
@ -40,6 +44,9 @@ config IRQ_PER_CPU
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config NO_IOPORT
|
||||||
|
def_bool y
|
||||||
|
|
||||||
config CRIS
|
config CRIS
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -359,8 +359,7 @@ static struct mtd_info *flash_probe(void)
|
||||||
* So we use the MTD concatenation layer instead of further
|
* So we use the MTD concatenation layer instead of further
|
||||||
* complicating the probing procedure.
|
* complicating the probing procedure.
|
||||||
*/
|
*/
|
||||||
mtd_cse = mtd_concat_create(mtds,
|
mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds),
|
||||||
sizeof(mtds) / sizeof(mtds[0]),
|
|
||||||
"cse0+cse1");
|
"cse0+cse1");
|
||||||
#else
|
#else
|
||||||
printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
|
printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
|
||||||
|
|
|
@ -499,7 +499,7 @@ print_rtc_status(void)
|
||||||
|
|
||||||
/* The various file operations we support. */
|
/* The various file operations we support. */
|
||||||
|
|
||||||
static struct file_operations rtc_fops = {
|
static const struct file_operations rtc_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.ioctl = rtc_ioctl,
|
.ioctl = rtc_ioctl,
|
||||||
};
|
};
|
||||||
|
|
|
@ -172,7 +172,7 @@ static const char eeprom_name[] = "eeprom";
|
||||||
static struct eeprom_type eeprom;
|
static struct eeprom_type eeprom;
|
||||||
|
|
||||||
/* This is the exported file-operations structure for this device. */
|
/* This is the exported file-operations structure for this device. */
|
||||||
struct file_operations eeprom_fops =
|
const struct file_operations eeprom_fops =
|
||||||
{
|
{
|
||||||
.llseek = eeprom_lseek,
|
.llseek = eeprom_lseek,
|
||||||
.read = eeprom_read,
|
.read = eeprom_read,
|
||||||
|
|
|
@ -838,7 +838,7 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_operations gpio_fops = {
|
const struct file_operations gpio_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.poll = gpio_poll,
|
.poll = gpio_poll,
|
||||||
.ioctl = gpio_ioctl,
|
.ioctl = gpio_ioctl,
|
||||||
|
|
|
@ -692,7 +692,7 @@ i2c_ioctl(struct inode *inode, struct file *file,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file_operations i2c_fops = {
|
static const struct file_operations i2c_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.ioctl = i2c_ioctl,
|
.ioctl = i2c_ioctl,
|
||||||
.open = i2c_open,
|
.open = i2c_open,
|
||||||
|
|
|
@ -56,7 +56,7 @@ static const unsigned char days_in_month[] =
|
||||||
|
|
||||||
int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
||||||
|
|
||||||
static struct file_operations pcf8563_fops = {
|
static const struct file_operations pcf8563_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.ioctl = pcf8563_ioctl,
|
.ioctl = pcf8563_ioctl,
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,7 +38,6 @@ unsigned long get_ns_in_jiffie(void)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
local_irq_disable();
|
|
||||||
timer_count = *R_TIMER0_DATA;
|
timer_count = *R_TIMER0_DATA;
|
||||||
presc_count = *R_TIM_PRESC_STATUS;
|
presc_count = *R_TIM_PRESC_STATUS;
|
||||||
/* presc_count might be wrapped */
|
/* presc_count might be wrapped */
|
||||||
|
|
|
@ -42,8 +42,7 @@ flush_tlb_all(void)
|
||||||
* in the same 4-way entry group. details..
|
* in the same 4-way entry group. details..
|
||||||
*/
|
*/
|
||||||
|
|
||||||
local_save_flags(flags);
|
local_irq_save(flags);
|
||||||
local_irq_disable();
|
|
||||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||||
*R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
|
*R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
|
||||||
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
|
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
|
||||||
|
@ -78,8 +77,7 @@ flush_tlb_mm(struct mm_struct *mm)
|
||||||
* global pages. is it worth the extra I/O ?
|
* global pages. is it worth the extra I/O ?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
local_save_flags(flags);
|
local_irq_save(flags);
|
||||||
local_irq_disable();
|
|
||||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||||
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
||||||
if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
|
if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
|
||||||
|
@ -118,8 +116,7 @@ flush_tlb_page(struct vm_area_struct *vma,
|
||||||
* and the virtual address requested
|
* and the virtual address requested
|
||||||
*/
|
*/
|
||||||
|
|
||||||
local_save_flags(flags);
|
local_irq_save(flags);
|
||||||
local_irq_disable();
|
|
||||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||||
unsigned long tlb_hi;
|
unsigned long tlb_hi;
|
||||||
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
||||||
|
|
|
@ -82,7 +82,8 @@ SECTIONS
|
||||||
__con_initcall_end = .;
|
__con_initcall_end = .;
|
||||||
}
|
}
|
||||||
SECURITY_INIT
|
SECURITY_INIT
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
.init.ramfs : {
|
.init.ramfs : {
|
||||||
__initramfs_start = .;
|
__initramfs_start = .;
|
||||||
*(.init.ramfs)
|
*(.init.ramfs)
|
||||||
|
@ -93,6 +94,7 @@ SECTIONS
|
||||||
FILL (0);
|
FILL (0);
|
||||||
. = ALIGN (8192);
|
. = ALIGN (8192);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
__vmlinux_end = .; /* last address of the physical file */
|
__vmlinux_end = .; /* last address of the physical file */
|
||||||
__init_end = .;
|
__init_end = .;
|
||||||
|
|
|
@ -266,7 +266,7 @@ static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct file_operations cryptocop_fops = {
|
const struct file_operations cryptocop_fops = {
|
||||||
owner: THIS_MODULE,
|
owner: THIS_MODULE,
|
||||||
open: cryptocop_open,
|
open: cryptocop_open,
|
||||||
release: cryptocop_release,
|
release: cryptocop_release,
|
||||||
|
|
|
@ -705,7 +705,7 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_operations gpio_fops = {
|
const struct file_operations gpio_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.poll = gpio_poll,
|
.poll = gpio_poll,
|
||||||
.ioctl = gpio_ioctl,
|
.ioctl = gpio_ioctl,
|
||||||
|
|
|
@ -573,7 +573,7 @@ i2c_ioctl(struct inode *inode, struct file *file,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file_operations i2c_fops = {
|
static const struct file_operations i2c_fops = {
|
||||||
owner: THIS_MODULE,
|
owner: THIS_MODULE,
|
||||||
ioctl: i2c_ioctl,
|
ioctl: i2c_ioctl,
|
||||||
open: i2c_open,
|
open: i2c_open,
|
||||||
|
|
|
@ -50,7 +50,7 @@ int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
||||||
int pcf8563_open(struct inode *, struct file *);
|
int pcf8563_open(struct inode *, struct file *);
|
||||||
int pcf8563_release(struct inode *, struct file *);
|
int pcf8563_release(struct inode *, struct file *);
|
||||||
|
|
||||||
static struct file_operations pcf8563_fops = {
|
static const struct file_operations pcf8563_fops = {
|
||||||
owner: THIS_MODULE,
|
owner: THIS_MODULE,
|
||||||
ioctl: pcf8563_ioctl,
|
ioctl: pcf8563_ioctl,
|
||||||
open: pcf8563_open,
|
open: pcf8563_open,
|
||||||
|
|
|
@ -187,7 +187,7 @@ static struct sync_port ports[]=
|
||||||
|
|
||||||
#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
|
#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
|
||||||
|
|
||||||
static struct file_operations sync_serial_fops = {
|
static const struct file_operations sync_serial_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.write = sync_serial_write,
|
.write = sync_serial_write,
|
||||||
.read = sync_serial_read,
|
.read = sync_serial_read,
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue