Merge branch 'for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6 into devel

This commit is contained in:
Russell King 2008-12-29 18:08:11 +00:00 committed by Russell King
commit 47992cbdae
16 changed files with 1548 additions and 308 deletions

View File

@ -0,0 +1,286 @@
MFP Configuration for PXA2xx/PXA3xx Processors
Eric Miao <eric.miao@marvell.com>
MFP stands for Multi-Function Pin, which is the pin-mux logic on PXA3xx and
later PXA series processors. This document describes the existing MFP API,
and how board/platform driver authors could make use of it.
Basic Concept
===============
Unlike the GPIO alternate function settings on PXA25x and PXA27x, a new MFP
mechanism is introduced from PXA3xx to completely move the pin-mux functions
out of the GPIO controller. In addition to pin-mux configurations, the MFP
also controls the low power state, driving strength, pull-up/down and event
detection of each pin. Below is a diagram of internal connections between
the MFP logic and the remaining SoC peripherals:
+--------+
| |--(GPIO19)--+
| GPIO | |
| |--(GPIO...) |
+--------+ |
| +---------+
+--------+ +------>| |
| PWM2 |--(PWM_OUT)-------->| MFP |
+--------+ +------>| |-------> to external PAD
| +---->| |
+--------+ | | +-->| |
| SSP2 |---(TXD)----+ | | +---------+
+--------+ | |
| |
+--------+ | |
| Keypad |--(MKOUT4)----+ |
+--------+ |
|
+--------+ |
| UART2 |---(TXD)--------+
+--------+
NOTE: the external pad is named as MFP_PIN_GPIO19, it doesn't necessarily
mean it's dedicated for GPIO19, only as a hint that internally this pin
can be routed from GPIO19 of the GPIO controller.
To better understand the change from PXA25x/PXA27x GPIO alternate function
to this new MFP mechanism, here are several key points:
1. GPIO controller on PXA3xx is now a dedicated controller, same as other
internal controllers like PWM, SSP and UART, with 128 internal signals
which can be routed to external through one or more MFPs (e.g. GPIO<0>
can be routed through either MFP_PIN_GPIO0 as well as MFP_PIN_GPIO0_2,
see arch/arm/mach-pxa/mach/include/mfp-pxa300.h)
2. Alternate function configuration is removed from this GPIO controller,
the remaining functions are pure GPIO-specific, i.e.
- GPIO signal level control
- GPIO direction control
- GPIO level change detection
3. Low power state for each pin is now controlled by MFP, this means the
PGSRx registers on PXA2xx are now useless on PXA3xx
4. Wakeup detection is now controlled by MFP, PWER does not control the
wakeup from GPIO(s) any more, depending on the sleeping state, ADxER
(as defined in pxa3xx-regs.h) controls the wakeup from MFP
NOTE: with such a clear separation of MFP and GPIO, by GPIO<xx> we normally
mean it is a GPIO signal, and by MFP<xxx> or pin xxx, we mean a physical
pad (or ball).
MFP API Usage
===============
For board code writers, here are some guidelines:
1. include ONE of the following header files in your <board>.c:
- #include <mach/mfp-pxa25x.h>
- #include <mach/mfp-pxa27x.h>
- #include <mach/mfp-pxa300.h>
- #include <mach/mfp-pxa320.h>
- #include <mach/mfp-pxa930.h>
NOTE: only one file in your <board>.c, depending on the processors used,
because pin configuration definitions may conflict in these file (i.e.
same name, different meaning and settings on different processors). E.g.
for zylonite platform, which support both PXA300/PXA310 and PXA320, two
separate files are introduced: zylonite_pxa300.c and zylonite_pxa320.c
(in addition to handle MFP configuration differences, they also handle
the other differences between the two combinations).
NOTE: PXA300 and PXA310 are almost identical in pin configurations (with
PXA310 supporting some additional ones), thus the difference is actually
covered in a single mfp-pxa300.h.
2. prepare an array for the initial pin configurations, e.g.:
static unsigned long mainstone_pin_config[] __initdata = {
/* Chip Select */
GPIO15_nCS_1,
/* LCD - 16bpp Active TFT */
GPIOxx_TFT_LCD_16BPP,
GPIO16_PWM0_OUT, /* Backlight */
/* MMC */
GPIO32_MMC_CLK,
GPIO112_MMC_CMD,
GPIO92_MMC_DAT_0,
GPIO109_MMC_DAT_1,
GPIO110_MMC_DAT_2,
GPIO111_MMC_DAT_3,
...
/* GPIO */
GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
};
a) once the pin configurations are passed to pxa{2xx,3xx}_mfp_config(),
and written to the actual registers, they are useless and may discard,
adding '__initdata' will help save some additional bytes here.
b) when there is only one possible pin configurations for a component,
some simplified definitions can be used, e.g. GPIOxx_TFT_LCD_16BPP on
PXA25x and PXA27x processors
c) if by board design, a pin can be configured to wake up the system
from low power state, it can be 'OR'ed with any of:
WAKEUP_ON_EDGE_BOTH
WAKEUP_ON_EDGE_RISE
WAKEUP_ON_EDGE_FALL
WAKEUP_ON_LEVEL_HIGH - specifically for enabling of keypad GPIOs,
to indicate that this pin has the capability of wake-up the system,
and on which edge(s). This, however, doesn't necessarily mean the
pin _will_ wakeup the system, it will only when set_irq_wake() is
invoked with the corresponding GPIO IRQ (GPIO_IRQ(xx) or gpio_to_irq())
and eventually calls gpio_set_wake() for the actual register setting.
d) although PXA3xx MFP supports edge detection on each pin, the
internal logic will only wakeup the system when those specific bits
in ADxER registers are set, which can be well mapped to the
corresponding peripheral, thus set_irq_wake() can be called with
the peripheral IRQ to enable the wakeup.
MFP on PXA3xx
===============
Every external I/O pad on PXA3xx (excluding those for special purpose) has
one MFP logic associated, and is controlled by one MFP register (MFPR).
The MFPR has the following bit definitions (for PXA300/PXA310/PXA320):
31 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+-------------------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| RESERVED |PS|PU|PD| DRIVE |SS|SD|SO|EC|EF|ER|--| AF_SEL |
+-------------------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Bit 3: RESERVED
Bit 4: EDGE_RISE_EN - enable detection of rising edge on this pin
Bit 5: EDGE_FALL_EN - enable detection of falling edge on this pin
Bit 6: EDGE_CLEAR - disable edge detection on this pin
Bit 7: SLEEP_OE_N - enable outputs during low power modes
Bit 8: SLEEP_DATA - output data on the pin during low power modes
Bit 9: SLEEP_SEL - selection control for low power modes signals
Bit 13: PULLDOWN_EN - enable the internal pull-down resistor on this pin
Bit 14: PULLUP_EN - enable the internal pull-up resistor on this pin
Bit 15: PULL_SEL - pull state controlled by selected alternate function
(0) or by PULL{UP,DOWN}_EN bits (1)
Bit 0 - 2: AF_SEL - alternate function selection, 8 possibilities, from 0-7
Bit 10-12: DRIVE - drive strength and slew rate
0b000 - fast 1mA
0b001 - fast 2mA
0b002 - fast 3mA
0b003 - fast 4mA
0b004 - slow 6mA
0b005 - fast 6mA
0b006 - slow 10mA
0b007 - fast 10mA
MFP Design for PXA2xx/PXA3xx
==============================
Due to the difference of pin-mux handling between PXA2xx and PXA3xx, a unified
MFP API is introduced to cover both series of processors.
The basic idea of this design is to introduce definitions for all possible pin
configurations, these definitions are processor and platform independent, and
the actual API invoked to convert these definitions into register settings and
make them effective there-after.
Files Involved
--------------
- arch/arm/mach-pxa/include/mach/mfp.h
for
1. Unified pin definitions - enum constants for all configurable pins
2. processor-neutral bit definitions for a possible MFP configuration
- arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h
for PXA3xx specific MFPR register bit definitions and PXA3xx common pin
configurations
- arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
for PXA2xx specific definitions and PXA25x/PXA27x common pin configurations
- arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
arch/arm/mach-pxa/include/mach/mfp-pxa300.h
arch/arm/mach-pxa/include/mach/mfp-pxa320.h
arch/arm/mach-pxa/include/mach/mfp-pxa930.h
for processor specific definitions
- arch/arm/mach-pxa/mfp-pxa3xx.c
- arch/arm/mach-pxa/mfp-pxa2xx.c
for implementation of the pin configuration to take effect for the actual
processor.
Pin Configuration
-----------------
The following comments are copied from mfp.h (see the actual source code
for most updated info)
/*
* a possible MFP configuration is represented by a 32-bit integer
*
* bit 0.. 9 - MFP Pin Number (1024 Pins Maximum)
* bit 10..12 - Alternate Function Selection
* bit 13..15 - Drive Strength
* bit 16..18 - Low Power Mode State
* bit 19..20 - Low Power Mode Edge Detection
* bit 21..22 - Run Mode Pull State
*
* to facilitate the definition, the following macros are provided
*
* MFP_CFG_DEFAULT - default MFP configuration value, with
* alternate function = 0,
* drive strength = fast 3mA (MFP_DS03X)
* low power mode = default
* edge detection = none
*
* MFP_CFG - default MFPR value with alternate function
* MFP_CFG_DRV - default MFPR value with alternate function and
* pin drive strength
* MFP_CFG_LPM - default MFPR value with alternate function and
* low power mode
* MFP_CFG_X - default MFPR value with alternate function,
* pin drive strength and low power mode
*/
Examples of pin configurations are:
#define GPIO94_SSP3_RXD MFP_CFG_X(GPIO94, AF1, DS08X, FLOAT)
which reads GPIO94 can be configured as SSP3_RXD, with alternate function
selection of 1, driving strength of 0b101, and a float state in low power
modes.
NOTE: this is the default setting of this pin being configured as SSP3_RXD
which can be modified a bit in board code, though it is not recommended to
do so, simply because this default setting is usually carefully encoded,
and is supposed to work in most cases.
Register Settings
-----------------
Register settings on PXA3xx for a pin configuration is actually very
straight-forward, most bits can be converted directly into MFPR value
in a easier way. Two sets of MFPR values are calculated: the run-time
ones and the low power mode ones, to allow different settings.
The conversion from a generic pin configuration to the actual register
settings on PXA2xx is a bit complicated: many registers are involved,
including GAFRx, GPDRx, PGSRx, PWER, PKWR, PFER and PRER. Please see
mfp-pxa2xx.c for how the conversion is made.

View File

@ -5,9 +5,13 @@ The driver supports the following options, either via
options=<OPTIONS> when modular or video=pxafb:<OPTIONS> when built in.
For example:
modprobe pxafb options=mode:640x480-8,passive
modprobe pxafb options=vmem:2M,mode:640x480-8,passive
or on the kernel command line
video=pxafb:mode:640x480-8,passive
video=pxafb:vmem:2M,mode:640x480-8,passive
vmem: VIDEO_MEM_SIZE
Amount of video memory to allocate (can be suffixed with K or M
for kilobytes or megabytes)
mode:XRESxYRES[-BPP]
XRES == LCCR1_PPL + 1
@ -52,3 +56,87 @@ outputen:POLARITY
pixclockpol:POLARITY
pixel clock polarity
0 => falling edge, 1 => rising edge
Overlay Support for PXA27x and later LCD controllers
====================================================
PXA27x and later processors support overlay1 and overlay2 on-top of the
base framebuffer (although under-neath the base is also possible). They
support palette and no-palette RGB formats, as well as YUV formats (only
available on overlay2). These overlays have dedicated DMA channels and
behave in a similar way as a framebuffer.
However, there are some differences between these overlay framebuffers
and normal framebuffers, as listed below:
1. overlay can start at a 32-bit word aligned position within the base
framebuffer, which means they have a start (x, y). This information
is encoded into var->nonstd (no, var->xoffset and var->yoffset are
not for such purpose).
2. overlay framebuffer is allocated dynamically according to specified
'struct fb_var_screeninfo', the amount is decided by:
var->xres_virtual * var->yres_virtual * bpp
bpp = 16 -- for RGB565 or RGBT555
= 24 -- for YUV444 packed
= 24 -- for YUV444 planar
= 16 -- for YUV422 planar (1 pixel = 1 Y + 1/2 Cb + 1/2 Cr)
= 12 -- for YUV420 planar (1 pixel = 1 Y + 1/4 Cb + 1/4 Cr)
NOTE:
a. overlay does not support panning in x-direction, thus
var->xres_virtual will always be equal to var->xres
b. line length of overlay(s) must be on a 32-bit word boundary,
for YUV planar modes, it is a requirement for the component
with minimum bits per pixel, e.g. for YUV420, Cr component
for one pixel is actually 2-bits, it means the line length
should be a multiple of 16-pixels
c. starting horizontal position (XPOS) should start on a 32-bit
word boundary, otherwise the fb_check_var() will just fail.
d. the rectangle of the overlay should be within the base plane,
otherwise fail
Applications should follow the sequence below to operate an overlay
framebuffer:
a. open("/dev/fb[1-2]", ...)
b. ioctl(fd, FBIOGET_VSCREENINFO, ...)
c. modify 'var' with desired parameters:
1) var->xres and var->yres
2) larger var->yres_virtual if more memory is required,
usually for double-buffering
3) var->nonstd for starting (x, y) and color format
4) var->{red, green, blue, transp} if RGB mode is to be used
d. ioctl(fd, FBIOPUT_VSCREENINFO, ...)
e. ioctl(fd, FBIOGET_FSCREENINFO, ...)
f. mmap
g. ...
3. for YUV planar formats, these are actually not supported within the
framebuffer framework, application has to take care of the offsets
and lengths of each component within the framebuffer.
4. var->nonstd is used to pass starting (x, y) position and color format,
the detailed bit fields are shown below:
31 23 20 10 0
+-----------------+---+----------+----------+
| ... unused ... |FOR| XPOS | YPOS |
+-----------------+---+----------+----------+
FOR - color format, as defined by OVERLAY_FORMAT_* in pxafb.h
0 - RGB
1 - YUV444 PACKED
2 - YUV444 PLANAR
3 - YUV422 PLANAR
4 - YUR420 PLANAR
XPOS - starting horizontal position
YPOS - starting vertical position

View File

@ -24,6 +24,7 @@
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
#include <asm/mach-types.h>
#include <mach/pxa-regs.h>
#include <mach/reset.h>
@ -39,6 +40,21 @@ void clear_reset_status(unsigned int mask)
pxa3xx_clear_reset_status(mask);
}
unsigned long get_clock_tick_rate(void)
{
unsigned long clock_tick_rate;
if (cpu_is_pxa25x())
clock_tick_rate = 3686400;
else if (machine_is_mainstone())
clock_tick_rate = 3249600;
else
clock_tick_rate = 3250000;
return clock_tick_rate;
}
EXPORT_SYMBOL(get_clock_tick_rate);
/*
* Get the clock frequency as reflected by CCCR and the turbo flag.
* We assume these values have been applied via a fcs.

View File

@ -291,6 +291,8 @@
*/
extern unsigned int get_memclk_frequency_10khz(void);
/* return the clock tick rate of the OS timer */
extern unsigned long get_clock_tick_rate(void);
#endif
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)

View File

@ -421,6 +421,7 @@
#define GPIO20_PWM0 MFP_CFG_LPM(GPIO20, AF2, PULL_LOW)
#define GPIO21_PWM2 MFP_CFG_LPM(GPIO21, AF3, PULL_LOW)
#define GPIO22_PWM3 MFP_CFG_LPM(GPIO22, AF3, PULL_LOW)
#define GPIO32_PWM0 MFP_CFG_LPM(GPIO32, AF4, PULL_LOW)
/* CIR */
#define GPIO46_CIR_OUT MFP_CFG(GPIO46, AF1)

View File

@ -113,6 +113,7 @@ struct pxafb_mach_info {
unsigned int num_modes;
unsigned int lcd_conn;
unsigned long video_mem_size;
u_int fixed_modes:1,
cmap_inverse:1,

View File

@ -12,27 +12,29 @@
#define LCCR3 (0x00C) /* LCD Controller Control Register 3 */
#define LCCR4 (0x010) /* LCD Controller Control Register 4 */
#define LCCR5 (0x014) /* LCD Controller Control Register 5 */
#define DFBR0 (0x020) /* DMA Channel 0 Frame Branch Register */
#define DFBR1 (0x024) /* DMA Channel 1 Frame Branch Register */
#define LCSR (0x038) /* LCD Controller Status Register */
#define LCSR (0x038) /* LCD Controller Status Register 0 */
#define LCSR1 (0x034) /* LCD Controller Status Register 1 */
#define LIIDR (0x03C) /* LCD Controller Interrupt ID Register */
#define TMEDRGBR (0x040) /* TMED RGB Seed Register */
#define TMEDCR (0x044) /* TMED Control Register */
#define FBR0 (0x020) /* DMA Channel 0 Frame Branch Register */
#define FBR1 (0x024) /* DMA Channel 1 Frame Branch Register */
#define FBR2 (0x028) /* DMA Channel 2 Frame Branch Register */
#define FBR3 (0x02C) /* DMA Channel 2 Frame Branch Register */
#define FBR4 (0x030) /* DMA Channel 2 Frame Branch Register */
#define FBR5 (0x110) /* DMA Channel 2 Frame Branch Register */
#define FBR6 (0x114) /* DMA Channel 2 Frame Branch Register */
#define OVL1C1 (0x050) /* Overlay 1 Control Register 1 */
#define OVL1C2 (0x060) /* Overlay 1 Control Register 2 */
#define OVL2C1 (0x070) /* Overlay 2 Control Register 1 */
#define OVL2C2 (0x080) /* Overlay 2 Control Register 2 */
#define CMDCR (0x100) /* Command Control Register */
#define PRSR (0x104) /* Panel Read Status Register */
#define LCCR3_1BPP (0 << 24)
#define LCCR3_2BPP (1 << 24)
#define LCCR3_4BPP (2 << 24)
#define LCCR3_8BPP (3 << 24)
#define LCCR3_16BPP (4 << 24)
#define LCCR3_18BPP (5 << 24)
#define LCCR3_18BPP_P (6 << 24)
#define LCCR3_19BPP (7 << 24)
#define LCCR3_19BPP_P (1 << 29)
#define LCCR3_24BPP ((1 << 29) | (1 << 24))
#define LCCR3_25BPP ((1 << 29) | (2 << 24))
#define LCCR3_BPP(x) ((((x) & 0x7) << 24) | (((x) & 0x8) ? (1 << 29) : 0))
#define LCCR3_PDFOR_0 (0 << 30)
#define LCCR3_PDFOR_1 (1 << 30)
@ -42,19 +44,16 @@
#define LCCR4_PAL_FOR_0 (0 << 15)
#define LCCR4_PAL_FOR_1 (1 << 15)
#define LCCR4_PAL_FOR_2 (2 << 15)
#define LCCR4_PAL_FOR_3 (3 << 15)
#define LCCR4_PAL_FOR_MASK (3 << 15)
#define FDADR0 (0x200) /* DMA Channel 0 Frame Descriptor Address Register */
#define FSADR0 (0x204) /* DMA Channel 0 Frame Source Address Register */
#define FIDR0 (0x208) /* DMA Channel 0 Frame ID Register */
#define LDCMD0 (0x20C) /* DMA Channel 0 Command Register */
#define FDADR1 (0x210) /* DMA Channel 1 Frame Descriptor Address Register */
#define FSADR1 (0x214) /* DMA Channel 1 Frame Source Address Register */
#define FIDR1 (0x218) /* DMA Channel 1 Frame ID Register */
#define LDCMD1 (0x21C) /* DMA Channel 1 Command Register */
#define FDADR2 (0x220) /* DMA Channel 2 Frame Descriptor Address Register */
#define FDADR3 (0x230) /* DMA Channel 3 Frame Descriptor Address Register */
#define FDADR4 (0x240) /* DMA Channel 4 Frame Descriptor Address Register */
#define FDADR5 (0x250) /* DMA Channel 5 Frame Descriptor Address Register */
#define FDADR6 (0x260) /* DMA Channel 6 Frame Descriptor Address Register */
#define FSADR6 (0x264) /* DMA Channel 6 Frame Source Address Register */
#define FIDR6 (0x268) /* DMA Channel 6 Frame ID Register */
#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */
@ -126,9 +125,6 @@
#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */
#define LCCR3_PixClkDiv(Div) (((Div) << FShft (LCCR3_PCD)))
#define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */
#define LCCR3_Bpp(Bpp) (((Bpp) << FShft (LCCR3_BPP)))
#define LCCR3_ACB Fld (8, 8) /* AC Bias */
#define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB)))
@ -157,8 +153,22 @@
#define LCSR_RD_ST (1 << 11) /* read status */
#define LCSR_CMD_INT (1 << 12) /* command interrupt */
#define LCSR1_IU(x) (1 << ((x) + 23)) /* Input FIFO underrun */
#define LCSR1_BS(x) (1 << ((x) + 15)) /* Branch Status */
#define LCSR1_EOF(x) (1 << ((x) + 7)) /* End of Frame Status */
#define LCSR1_SOF(x) (1 << ((x) - 1)) /* Start of Frame Status */
#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
/* overlay control registers */
#define OVLxC1_PPL(x) ((((x) - 1) & 0x3ff) << 0) /* Pixels Per Line */
#define OVLxC1_LPO(x) ((((x) - 1) & 0x3ff) << 10) /* Number of Lines */
#define OVLxC1_BPP(x) (((x) & 0xf) << 20) /* Bits Per Pixel */
#define OVLxC1_OEN (1 << 31) /* Enable bit for Overlay */
#define OVLxC2_XPOS(x) (((x) & 0x3ff) << 0) /* Horizontal Position */
#define OVLxC2_YPOS(x) (((x) & 0x3ff) << 10) /* Vertical Position */
#define OVL2C2_PFOR(x) (((x) & 0x7) << 20) /* Pixel Format */
/* smartpanel related */
#define PRSR_DATA(x) ((x) & 0xff) /* Panel Data */
#define PRSR_A0 (1 << 8) /* Read Data Source */

View File

@ -10,6 +10,14 @@
* published by the Free Software Foundation.
*/
/* Various drivers are still using the constant of CLOCK_TICK_RATE, for
* those drivers to at least work, the definition is provided here.
*
* NOTE: this is no longer accurate when multiple processors and boards
* are selected, newer drivers should not depend on this any more. Use
* either the clocksource/clockevent or get this at run-time by calling
* get_clock_tick_rate() (as defined in generic.c).
*/
#if defined(CONFIG_PXA25x)
/* PXA250/210 timer base */

View File

@ -18,12 +18,15 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/smc91x.h>
#include <linux/pwm_backlight.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/hardware.h>
#include <mach/pxa3xx-regs.h>
#include <mach/mfp-pxa930.h>
#include <mach/pxafb.h>
#include <mach/pxa27x_keypad.h>
#include "devices.h"
#include "generic.h"
@ -33,6 +36,45 @@ static mfp_cfg_t tavorevb_mfp_cfg[] __initdata = {
/* Ethernet */
DF_nCS1_nCS3,
GPIO47_GPIO,
/* LCD */
GPIO23_LCD_DD0,
GPIO24_LCD_DD1,
GPIO25_LCD_DD2,
GPIO26_LCD_DD3,
GPIO27_LCD_DD4,
GPIO28_LCD_DD5,
GPIO29_LCD_DD6,
GPIO44_LCD_DD7,
GPIO21_LCD_CS,
GPIO22_LCD_CS2,
GPIO17_LCD_FCLK_RD,
GPIO18_LCD_LCLK_A0,
GPIO19_LCD_PCLK_WR,
/* LCD Backlight */
GPIO43_PWM3, /* primary backlight */
GPIO32_PWM0, /* secondary backlight */
/* Keypad */
GPIO0_KP_MKIN_0,
GPIO2_KP_MKIN_1,
GPIO4_KP_MKIN_2,
GPIO6_KP_MKIN_3,
GPIO8_KP_MKIN_4,
GPIO10_KP_MKIN_5,
GPIO12_KP_MKIN_6,
GPIO1_KP_MKOUT_0,
GPIO3_KP_MKOUT_1,
GPIO5_KP_MKOUT_2,
GPIO7_KP_MKOUT_3,
GPIO9_KP_MKOUT_4,
GPIO11_KP_MKOUT_5,
GPIO13_KP_MKOUT_6,
GPIO14_KP_DKIN_2,
GPIO15_KP_DKIN_3,
};
#define TAVOREVB_ETH_PHYS (0x14000000)
@ -64,12 +106,382 @@ static struct platform_device smc91x_device = {
},
};
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int tavorevb_matrix_key_map[] = {
/* KEY(row, col, key_code) */
KEY(0, 4, KEY_A), KEY(0, 5, KEY_B), KEY(0, 6, KEY_C),
KEY(1, 4, KEY_E), KEY(1, 5, KEY_F), KEY(1, 6, KEY_G),
KEY(2, 4, KEY_I), KEY(2, 5, KEY_J), KEY(2, 6, KEY_K),
KEY(3, 4, KEY_M), KEY(3, 5, KEY_N), KEY(3, 6, KEY_O),
KEY(4, 5, KEY_R), KEY(4, 6, KEY_S),
KEY(5, 4, KEY_U), KEY(5, 4, KEY_V), KEY(5, 6, KEY_W),
KEY(6, 4, KEY_Y), KEY(6, 5, KEY_Z),
KEY(0, 3, KEY_0), KEY(2, 0, KEY_1), KEY(2, 1, KEY_2), KEY(2, 2, KEY_3),
KEY(2, 3, KEY_4), KEY(1, 0, KEY_5), KEY(1, 1, KEY_6), KEY(1, 2, KEY_7),
KEY(1, 3, KEY_8), KEY(0, 2, KEY_9),
KEY(6, 6, KEY_SPACE),
KEY(0, 0, KEY_KPASTERISK), /* * */
KEY(0, 1, KEY_KPDOT), /* # */
KEY(4, 1, KEY_UP),
KEY(4, 3, KEY_DOWN),
KEY(4, 0, KEY_LEFT),
KEY(4, 2, KEY_RIGHT),
KEY(6, 0, KEY_HOME),
KEY(3, 2, KEY_END),
KEY(6, 1, KEY_DELETE),
KEY(5, 2, KEY_BACK),
KEY(6, 3, KEY_CAPSLOCK), /* KEY_LEFTSHIFT), */
KEY(4, 4, KEY_ENTER), /* scroll push */
KEY(6, 2, KEY_ENTER), /* keypad action */
KEY(3, 1, KEY_SEND),
KEY(5, 3, KEY_RECORD),
KEY(5, 0, KEY_VOLUMEUP),
KEY(5, 1, KEY_VOLUMEDOWN),
KEY(3, 0, KEY_F22), /* soft1 */
KEY(3, 3, KEY_F23), /* soft2 */
};
static struct pxa27x_keypad_platform_data tavorevb_keypad_info = {
.matrix_key_rows = 7,
.matrix_key_cols = 7,
.matrix_key_map = tavorevb_matrix_key_map,
.matrix_key_map_size = ARRAY_SIZE(tavorevb_matrix_key_map),
.debounce_interval = 30,
};
static void __init tavorevb_init_keypad(void)
{
pxa_set_keypad_info(&tavorevb_keypad_info);
}
#else
static inline void tavorevb_init_keypad(void) {}
#endif /* CONFIG_KEYBOARD_PXA27x || CONFIG_KEYBOARD_PXA27x_MODULE */
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct platform_pwm_backlight_data tavorevb_backlight_data[] = {
[0] = {
/* primary backlight */
.pwm_id = 2,
.max_brightness = 100,
.dft_brightness = 100,
.pwm_period_ns = 100000,
},
[1] = {
/* secondary backlight */
.pwm_id = 0,
.max_brightness = 100,
.dft_brightness = 100,
.pwm_period_ns = 100000,
},
};
static struct platform_device tavorevb_backlight_devices[] = {
[0] = {
.name = "pwm-backlight",
.id = 0,
.dev = {
.platform_data = &tavorevb_backlight_data[0],
},
},
[1] = {
.name = "pwm-backlight",
.id = 1,
.dev = {
.platform_data = &tavorevb_backlight_data[1],
},
},
};
static uint16_t panel_init[] = {
/* DSTB OUT */
SMART_CMD(0x00),
SMART_CMD_NOOP,
SMART_DELAY(1),
SMART_CMD(0x00),
SMART_CMD_NOOP,
SMART_DELAY(1),
SMART_CMD(0x00),
SMART_CMD_NOOP,
SMART_DELAY(1),
/* STB OUT */
SMART_CMD(0x00),
SMART_CMD(0x1D),
SMART_DAT(0x00),
SMART_DAT(0x05),
SMART_DELAY(1),
/* P-ON Init sequence */
SMART_CMD(0x00), /* OSC ON */
SMART_CMD(0x00),
SMART_DAT(0x00),
SMART_DAT(0x01),
SMART_CMD(0x00),
SMART_CMD(0x01), /* SOURCE DRIVER SHIFT DIRECTION and display RAM setting */
SMART_DAT(0x01),
SMART_DAT(0x27),
SMART_CMD(0x00),
SMART_CMD(0x02), /* LINE INV */
SMART_DAT(0x02),
SMART_DAT(0x00),
SMART_CMD(0x00),
SMART_CMD(0x03), /* IF mode(1) */
SMART_DAT(0x01), /* 8bit smart mode(8-8),high speed write mode */
SMART_DAT(0x30),
SMART_CMD(0x07),
SMART_CMD(0x00), /* RAM Write Mode */
SMART_DAT(0x00),
SMART_DAT(0x03),
SMART_CMD(0x00),
/* DISPLAY Setting, 262K, fixed(NO scroll), no split screen */
SMART_CMD(0x07),
SMART_DAT(0x40), /* 16/18/19 BPP */
SMART_DAT(0x00),
SMART_CMD(0x00),
SMART_CMD(0x08), /* BP, FP Seting, BP=2H, FP=3H */
SMART_DAT(0x03),
SMART_DAT(0x02),
SMART_CMD(0x00),
SMART_CMD(0x0C), /* IF mode(2), using internal clock & MPU */
SMART_DAT(0x00),
SMART_DAT(0x00),
SMART_CMD(0x00),
SMART_CMD(0x0D), /* Frame setting, 1Min. Frequence, 16CLK */
SMART_DAT(0x00),
SMART_DAT(0x10),
SMART_CMD(0x00),
SMART_CMD(0x12), /* Timing(1),ASW W=4CLK, ASW ST=1CLK */
SMART_DAT(0x03),
SMART_DAT(0x02),
SMART_CMD(0x00),
SMART_CMD(0x13), /* Timing(2),OEV ST=0.5CLK, OEV ED=1CLK */
SMART_DAT(0x01),
SMART_DAT(0x02),
SMART_CMD(0x00),
SMART_CMD(0x14), /* Timing(3), ASW HOLD=0.5CLK */
SMART_DAT(0x00),
SMART_DAT(0x00),
SMART_CMD(0x00),
SMART_CMD(0x15), /* Timing(4), CKV ST=0CLK, CKV ED=1CLK */
SMART_DAT(0x20),
SMART_DAT(0x00),
SMART_CMD(0x00),
SMART_CMD(0x1C),
SMART_DAT(0x00),
SMART_DAT(0x00),
SMART_CMD(0x03),
SMART_CMD(0x00),
SMART_DAT(0x04),
SMART_DAT(0x03),
SMART_CMD(0x03),
SMART_CMD(0x01),
SMART_DAT(0x03),
SMART_DAT(0x04),
SMART_CMD(0x03),
SMART_CMD(0x02),
SMART_DAT(0x04),
SMART_DAT(0x03),
SMART_CMD(0x03),
SMART_CMD(0x03),
SMART_DAT(0x03),
SMART_DAT(0x03),
SMART_CMD(0x03),
SMART_CMD(0x04),
SMART_DAT(0x01),
SMART_DAT(0x01),
SMART_CMD(0x03),
SMART_CMD(0x05),
SMART_DAT(0x00),
SMART_DAT(0x00),
SMART_CMD(0x04),
SMART_CMD(0x02),
SMART_DAT(0x00),
SMART_DAT(0x00),
SMART_CMD(0x04),
SMART_CMD(0x03),
SMART_DAT(0x01),
SMART_DAT(0x3F),
SMART_DELAY(0),
/* DISP RAM setting: 240*320 */
SMART_CMD(0x04), /* HADDR, START 0 */
SMART_CMD(0x06),
SMART_DAT(0x00),
SMART_DAT(0x00), /* x1,3 */
SMART_CMD(0x04), /* HADDR, END 4 */
SMART_CMD(0x07),
SMART_DAT(0x00),
SMART_DAT(0xEF), /* x2, 7 */
SMART_CMD(0x04), /* VADDR, START 8 */
SMART_CMD(0x08),
SMART_DAT(0x00), /* y1, 10 */
SMART_DAT(0x00), /* y1, 11 */
SMART_CMD(0x04), /* VADDR, END 12 */
SMART_CMD(0x09),
SMART_DAT(0x01), /* y2, 14 */
SMART_DAT(0x3F), /* y2, 15 */
SMART_CMD(0x02), /* RAM ADDR SETTING 16 */
SMART_CMD(0x00),
SMART_DAT(0x00),
SMART_DAT(0x00), /* x1, 19 */
SMART_CMD(0x02), /* RAM ADDR SETTING 20 */
SMART_CMD(0x01),
SMART_DAT(0x00), /* y1, 22 */
SMART_DAT(0x00), /* y1, 23 */
};
static uint16_t panel_on[] = {
/* Power-IC ON */
SMART_CMD(0x01),
SMART_CMD(0x02),
SMART_DAT(0x07),
SMART_DAT(0x7D),
SMART_CMD(0x01),
SMART_CMD(0x03),
SMART_DAT(0x00),
SMART_DAT(0x05),
SMART_CMD(0x01),
SMART_CMD(0x04),
SMART_DAT(0x00),
SMART_DAT(0x00),
SMART_CMD(0x01),
SMART_CMD(0x05),
SMART_DAT(0x00),
SMART_DAT(0x15),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0xC0),
SMART_DAT(0x10),
SMART_DELAY(30),
/* DISP ON */
SMART_CMD(0x01),
SMART_CMD(0x01),
SMART_DAT(0x00),
SMART_DAT(0x01),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0xFF),
SMART_DAT(0xFE),
SMART_DELAY(150),
};
static uint16_t panel_off[] = {
SMART_CMD(0x00),
SMART_CMD(0x1E),
SMART_DAT(0x00),
SMART_DAT(0x0A),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0xFF),
SMART_DAT(0xEE),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0xF8),
SMART_DAT(0x12),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0xE8),
SMART_DAT(0x11),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0xC0),
SMART_DAT(0x11),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0x40),
SMART_DAT(0x11),
SMART_CMD(0x01),
SMART_CMD(0x00),
SMART_DAT(0x00),
SMART_DAT(0x10),
};
static uint16_t update_framedata[] = {
/* write ram */
SMART_CMD(0x02),
SMART_CMD(0x02),
/* write frame data */
SMART_CMD_WRITE_FRAME,
};
static void ltm020d550_lcd_power(int on, struct fb_var_screeninfo *var)
{
struct fb_info *info = container_of(var, struct fb_info, var);
if (on) {
pxafb_smart_queue(info, ARRAY_AND_SIZE(panel_init));
pxafb_smart_queue(info, ARRAY_AND_SIZE(panel_on));
} else {
pxafb_smart_queue(info, ARRAY_AND_SIZE(panel_off));
}
if (pxafb_smart_flush(info))
pr_err("%s: timed out\n", __func__);
}
static void ltm020d550_update(struct fb_info *info)
{
pxafb_smart_queue(info, ARRAY_AND_SIZE(update_framedata));
pxafb_smart_flush(info);
}
static struct pxafb_mode_info toshiba_ltm020d550_modes[] = {
[0] = {
.xres = 240,
.yres = 320,
.bpp = 16,
.a0csrd_set_hld = 30,
.a0cswr_set_hld = 30,
.wr_pulse_width = 30,
.rd_pulse_width = 170,
.op_hold_time = 30,
.cmd_inh_time = 60,
/* L_LCLK_A0 and L_LCLK_RD active low */
.sync = FB_SYNC_HOR_HIGH_ACT |
FB_SYNC_VERT_HIGH_ACT,
},
};
static struct pxafb_mach_info tavorevb_lcd_info = {
.modes = toshiba_ltm020d550_modes,
.num_modes = 1,
.lcd_conn = LCD_SMART_PANEL_8BPP | LCD_PCLK_EDGE_FALL,
.pxafb_lcd_power = ltm020d550_lcd_power,
.smart_update = ltm020d550_update,
};
static void __init tavorevb_init_lcd(void)
{
platform_device_register(&tavorevb_backlight_devices[0]);
platform_device_register(&tavorevb_backlight_devices[1]);
set_pxa_fb_info(&tavorevb_lcd_info);
}
#else
static inline void tavorevb_init_lcd(void) {}
#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */
static void __init tavorevb_init(void)
{
/* initialize MFP configurations */
pxa3xx_mfp_config(ARRAY_AND_SIZE(tavorevb_mfp_cfg));
platform_device_register(&smc91x_device);
tavorevb_init_lcd();
tavorevb_init_keypad();
}
MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")

View File

@ -24,7 +24,6 @@
#include <asm/mach/time.h>
#include <mach/hardware.h>
#include <mach/pxa-regs.h>
#include <asm/mach-types.h>
/*
* This is PXA's sched_clock implementation. This has a resolution
@ -151,18 +150,11 @@ static struct irqaction pxa_ost0_irq = {
static void __init pxa_timer_init(void)
{
unsigned long clock_tick_rate;
unsigned long clock_tick_rate = get_clock_tick_rate();
OIER = 0;
OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
if (cpu_is_pxa25x())
clock_tick_rate = 3686400;
else if (machine_is_mainstone())
clock_tick_rate = 3249600;
else
clock_tick_rate = 3250000;
set_oscr2ns_scale(clock_tick_rate);
ckevt_pxa_osmr0.mult =

View File

@ -59,6 +59,10 @@
# define __REG(x) (*((volatile unsigned long *)io_p2v(x)))
# define __PREG(x) (io_v2p((unsigned long)&(x)))
static inline unsigned long get_clock_tick_rate(void)
{
return 3686400;
}
#else
# define __REG(x) io_p2v(x)

View File

@ -38,11 +38,11 @@
#include <mach/pxa-regs.h>
#endif
#define TIMER_FREQ CLOCK_TICK_RATE
#define RTC_DEF_DIVIDER 32768 - 1
#define RTC_DEF_TRIM 0
static unsigned long rtc_freq = 1024;
static unsigned long timer_freq;
static struct rtc_time rtc_alarm;
static DEFINE_SPINLOCK(sa1100_rtc_lock);
@ -157,7 +157,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
if (rtc_timer1_count == 1)
rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2)));
rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
return IRQ_HANDLED;
}
@ -166,7 +166,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
{
if (data & RTC_PF) {
/* interpolate missed periods and set match for the next */
unsigned long period = TIMER_FREQ/rtc_freq;
unsigned long period = timer_freq / rtc_freq;
unsigned long oscr = OSCR;
unsigned long osmr1 = OSMR1;
unsigned long missed = (oscr - osmr1)/period;
@ -263,7 +263,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
return 0;
case RTC_PIE_ON:
spin_lock_irq(&sa1100_rtc_lock);
OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
OSMR1 = timer_freq / rtc_freq + OSCR;
OIER |= OIER_E1;
rtc_timer1_count = 1;
spin_unlock_irq(&sa1100_rtc_lock);
@ -271,7 +271,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
case RTC_IRQP_READ:
return put_user(rtc_freq, (unsigned long *)arg);
case RTC_IRQP_SET:
if (arg < 1 || arg > TIMER_FREQ)
if (arg < 1 || arg > timer_freq)
return -EINVAL;
rtc_freq = arg;
return 0;
@ -352,6 +352,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
timer_freq = get_clock_tick_rate();
/*
* According to the manual we should be able to let RTTR be zero
* and then a default diviser for a 32.768KHz clock is used.

View File

@ -1817,6 +1817,11 @@ config FB_PXA
If unsure, say N.
config FB_PXA_OVERLAY
bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer"
default n
depends on FB_PXA && (PXA27x || PXA3xx)
config FB_PXA_SMARTPANEL
bool "PXA Smartpanel LCD support"
default n

File diff suppressed because it is too large Load Diff

View File

@ -54,11 +54,55 @@ enum {
#define PALETTE_SIZE (256 * 4)
#define CMD_BUFF_SIZE (1024 * 50)
/* NOTE: the palette and frame dma descriptors are doubled to allow
* the 2nd set for branch settings (FBRx)
*/
struct pxafb_dma_buff {
unsigned char palette[PAL_MAX * PALETTE_SIZE];
uint16_t cmd_buff[CMD_BUFF_SIZE];
struct pxafb_dma_descriptor pal_desc[PAL_MAX];
struct pxafb_dma_descriptor dma_desc[DMA_MAX];
struct pxafb_dma_descriptor pal_desc[PAL_MAX * 2];
struct pxafb_dma_descriptor dma_desc[DMA_MAX * 2];
};
enum {
OVERLAY1,
OVERLAY2,
};
enum {
OVERLAY_FORMAT_RGB = 0,
OVERLAY_FORMAT_YUV444_PACKED,
OVERLAY_FORMAT_YUV444_PLANAR,
OVERLAY_FORMAT_YUV422_PLANAR,
OVERLAY_FORMAT_YUV420_PLANAR,
};
#define NONSTD_TO_XPOS(x) (((x) >> 0) & 0x3ff)
#define NONSTD_TO_YPOS(x) (((x) >> 10) & 0x3ff)
#define NONSTD_TO_PFOR(x) (((x) >> 20) & 0x7)
struct pxafb_layer;
struct pxafb_layer_ops {
void (*enable)(struct pxafb_layer *);
void (*disable)(struct pxafb_layer *);
void (*setup)(struct pxafb_layer *);
};
struct pxafb_layer {
struct fb_info fb;
int id;
atomic_t usage;
uint32_t control[2];
struct pxafb_layer_ops *ops;
void __iomem *video_mem;
unsigned long video_mem_phys;
size_t video_mem_size;
struct completion branch_done;
struct pxafb_info *fbi;
};
struct pxafb_info {
@ -69,24 +113,15 @@ struct pxafb_info {
void __iomem *mmio_base;
struct pxafb_dma_buff *dma_buff;
size_t dma_buff_size;
dma_addr_t dma_buff_phys;
dma_addr_t fdadr[DMA_MAX];
dma_addr_t fdadr[DMA_MAX * 2];
/*
* These are the addresses we mapped
* the framebuffer memory region to.
*/
/* raw memory addresses */
dma_addr_t map_dma; /* physical */
u_char * map_cpu; /* virtual */
u_int map_size;
/* addresses of pieces placed in raw buffer */
u_char * screen_cpu; /* virtual address of frame buffer */
dma_addr_t screen_dma; /* physical address of frame buffer */
void __iomem *video_mem; /* virtual address of frame buffer */
unsigned long video_mem_phys; /* physical address of frame buffer */
size_t video_mem_size; /* size of the frame buffer */
u16 * palette_cpu; /* virtual address of palette memory */
u_int palette_size;
ssize_t video_offset;
u_int lccr0;
u_int lccr3;
@ -120,6 +155,10 @@ struct pxafb_info {
struct task_struct *smart_thread;
#endif
#ifdef CONFIG_FB_PXA_OVERLAY
struct pxafb_layer overlay[2];
#endif
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
struct notifier_block freq_policy;
@ -151,4 +190,10 @@ struct pxafb_info {
#define MIN_XRES 64
#define MIN_YRES 64
/* maximum X and Y resolutions - note these are limits from the register
* bits length instead of the real ones
*/
#define MAX_XRES 1024
#define MAX_YRES 1024
#endif /* __PXAFB_H__ */

View File

@ -36,8 +36,7 @@
#include <mach/reset.h>
#include <mach/hardware.h>
#define OSCR_FREQ CLOCK_TICK_RATE
static unsigned long oscr_freq;
static unsigned long sa1100wdt_users;
static int pre_margin;
static int boot_status;
@ -124,12 +123,12 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd,
break;
}
pre_margin = OSCR_FREQ * time;
pre_margin = oscr_freq * time;
OSMR3 = OSCR + pre_margin;
/*fall through*/
case WDIOC_GETTIMEOUT:
ret = put_user(pre_margin / OSCR_FREQ, p);
ret = put_user(pre_margin / oscr_freq, p);
break;
}
return ret;
@ -156,6 +155,8 @@ static int __init sa1100dog_init(void)
{
int ret;
oscr_freq = get_clock_tick_rate();
/*
* Read the reset status, and save it for later. If
* we suspend, RCSR will be cleared, and the watchdog
@ -163,7 +164,7 @@ static int __init sa1100dog_init(void)
*/
boot_status = (reset_status & RESET_STATUS_WATCHDOG) ?
WDIOF_CARDRESET : 0;
pre_margin = OSCR_FREQ * margin;
pre_margin = oscr_freq * margin;
ret = misc_register(&sa1100dog_miscdev);
if (ret == 0)