Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
69758ab7
Commit
69758ab7
authored
Oct 01, 2010
by
Kevin Hilman
Browse files
Options
Browse Files
Download
Plain Diff
manual merge for pm-hwmod-uart due to conflicts
parents
963bfb09
257f23d8
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
2707 additions
and
296 deletions
+2707
-296
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Kconfig
+8
-3
arch/arm/mach-omap2/board-3630sdp.c
arch/arm/mach-omap2/board-3630sdp.c
+0
-1
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/board-zoom-peripherals.c
+1
-0
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock3xxx_data.c
+22
-0
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm-regbits-34xx.h
+2
-0
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
+193
-0
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
+193
-0
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+251
-2
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+235
-0
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm34xx.c
+15
-2
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/prcm-common.h
+5
-0
arch/arm/mach-omap2/prm-regbits-34xx.h
arch/arm/mach-omap2/prm-regbits-34xx.h
+1
-0
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/serial.c
+284
-271
arch/arm/plat-omap/common.c
arch/arm/plat-omap/common.c
+0
-16
arch/arm/plat-omap/include/plat/common.h
arch/arm/plat-omap/include/plat/common.h
+0
-1
arch/arm/plat-omap/include/plat/dma.h
arch/arm/plat-omap/include/plat/dma.h
+2
-0
arch/arm/plat-omap/include/plat/irqs.h
arch/arm/plat-omap/include/plat/irqs.h
+2
-0
arch/arm/plat-omap/include/plat/omap-serial.h
arch/arm/plat-omap/include/plat/omap-serial.h
+129
-0
drivers/serial/Kconfig
drivers/serial/Kconfig
+27
-0
drivers/serial/Makefile
drivers/serial/Makefile
+1
-0
drivers/serial/omap-serial.c
drivers/serial/omap-serial.c
+1333
-0
include/linux/serial_core.h
include/linux/serial_core.h
+3
-0
No files found.
arch/arm/mach-omap2/Kconfig
View file @
69758ab7
...
...
@@ -11,9 +11,8 @@ config ARCH_OMAP2PLUS_TYPICAL
select PM_RUNTIME
select VFP
select NEON if ARCH_OMAP3 || ARCH_OMAP4
select SERIAL_8250
select SERIAL_CORE_CONSOLE
select SERIAL_8250_CONSOLE
select SERIAL_OMAP
select SERIAL_OMAP_CONSOLE
select I2C
select I2C_OMAP
select MFD
...
...
@@ -222,12 +221,18 @@ config MACH_OMAP_ZOOM2
depends on ARCH_OMAP3
default y
select OMAP_PACKAGE_CBB
select SERIAL_8250
select SERIAL_CORE_CONSOLE
select SERIAL_8250_CONSOLE
config MACH_OMAP_ZOOM3
bool "OMAP3630 Zoom3 board"
depends on ARCH_OMAP3
default y
select OMAP_PACKAGE_CBP
select SERIAL_8250
select SERIAL_CORE_CONSOLE
select SERIAL_8250_CONSOLE
config MACH_CM_T35
bool "CompuLab CM-T35 module"
...
...
arch/arm/mach-omap2/board-3630sdp.c
View file @
69758ab7
...
...
@@ -208,7 +208,6 @@ static struct flash_partitions sdp_flash_partitions[] = {
static
void
__init
omap_sdp_init
(
void
)
{
omap3_mux_init
(
board_mux
,
OMAP_PACKAGE_CBP
);
omap_serial_init
();
zoom_peripherals_init
();
board_smc91x_init
();
board_flash_init
(
sdp_flash_partitions
,
chip_sel_sdp
);
...
...
arch/arm/mach-omap2/board-zoom-peripherals.c
View file @
69758ab7
...
...
@@ -283,4 +283,5 @@ void __init zoom_peripherals_init(void)
omap_i2c_init
();
usb_musb_init
(
&
musb_board_data
);
enable_board_wakeup_source
();
omap_serial_init
();
}
arch/arm/mach-omap2/clock3xxx_data.c
View file @
69758ab7
...
...
@@ -2465,6 +2465,16 @@ static struct clk uart3_fck = {
.
recalc
=
&
followparent_recalc
,
};
static
struct
clk
uart4_fck
=
{
.
name
=
"uart4_fck"
,
.
ops
=
&
clkops_omap2_dflt_wait
,
.
parent
=
&
per_48m_fck
,
.
enable_reg
=
OMAP_CM_REGADDR
(
OMAP3430_PER_MOD
,
CM_FCLKEN
),
.
enable_bit
=
OMAP3630_EN_UART4_SHIFT
,
.
clkdm_name
=
"per_clkdm"
,
.
recalc
=
&
followparent_recalc
,
};
static
struct
clk
gpt2_fck
=
{
.
name
=
"gpt2_fck"
,
.
ops
=
&
clkops_omap2_dflt_wait
,
...
...
@@ -2715,6 +2725,16 @@ static struct clk uart3_ick = {
.
recalc
=
&
followparent_recalc
,
};
static
struct
clk
uart4_ick
=
{
.
name
=
"uart4_ick"
,
.
ops
=
&
clkops_omap2_dflt_wait
,
.
parent
=
&
per_l4_ick
,
.
enable_reg
=
OMAP_CM_REGADDR
(
OMAP3430_PER_MOD
,
CM_ICLKEN
),
.
enable_bit
=
OMAP3630_EN_UART4_SHIFT
,
.
clkdm_name
=
"per_clkdm"
,
.
recalc
=
&
followparent_recalc
,
};
static
struct
clk
gpt9_ick
=
{
.
name
=
"gpt9_ick"
,
.
ops
=
&
clkops_omap2_dflt_wait
,
...
...
@@ -3349,6 +3369,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK
(
NULL
,
"per_96m_fck"
,
&
per_96m_fck
,
CK_3XXX
),
CLK
(
NULL
,
"per_48m_fck"
,
&
per_48m_fck
,
CK_3XXX
),
CLK
(
NULL
,
"uart3_fck"
,
&
uart3_fck
,
CK_3XXX
),
CLK
(
NULL
,
"uart4_fck"
,
&
uart4_fck
,
CK_36XX
),
CLK
(
NULL
,
"gpt2_fck"
,
&
gpt2_fck
,
CK_3XXX
),
CLK
(
NULL
,
"gpt3_fck"
,
&
gpt3_fck
,
CK_3XXX
),
CLK
(
NULL
,
"gpt4_fck"
,
&
gpt4_fck
,
CK_3XXX
),
...
...
@@ -3372,6 +3393,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK
(
NULL
,
"gpio2_ick"
,
&
gpio2_ick
,
CK_3XXX
),
CLK
(
NULL
,
"wdt3_ick"
,
&
wdt3_ick
,
CK_3XXX
),
CLK
(
NULL
,
"uart3_ick"
,
&
uart3_ick
,
CK_3XXX
),
CLK
(
NULL
,
"uart4_ick"
,
&
uart4_ick
,
CK_36XX
),
CLK
(
NULL
,
"gpt9_ick"
,
&
gpt9_ick
,
CK_3XXX
),
CLK
(
NULL
,
"gpt8_ick"
,
&
gpt8_ick
,
CK_3XXX
),
CLK
(
NULL
,
"gpt7_ick"
,
&
gpt7_ick
,
CK_3XXX
),
...
...
arch/arm/mach-omap2/cm-regbits-34xx.h
View file @
69758ab7
...
...
@@ -649,6 +649,8 @@
#define OMAP3430_ST_MCBSP2_MASK (1 << 0)
/* CM_AUTOIDLE_PER */
#define OMAP3630_AUTO_UART4_MASK (1 << 18)
#define OMAP3630_AUTO_UART4_SHIFT 18
#define OMAP3430_AUTO_GPIO6_MASK (1 << 17)
#define OMAP3430_AUTO_GPIO6_SHIFT 17
#define OMAP3430_AUTO_GPIO5_MASK (1 << 16)
...
...
arch/arm/mach-omap2/omap_hwmod_2420_data.c
View file @
69758ab7
...
...
@@ -15,6 +15,7 @@
#include <mach/irqs.h>
#include <plat/cpu.h>
#include <plat/dma.h>
#include <plat/serial.h>
#include "omap_hwmod_common_data.h"
...
...
@@ -73,6 +74,9 @@ static struct omap_hwmod omap2420_l3_main_hwmod = {
};
static
struct
omap_hwmod
omap2420_l4_wkup_hwmod
;
static
struct
omap_hwmod
omap2420_uart1_hwmod
;
static
struct
omap_hwmod
omap2420_uart2_hwmod
;
static
struct
omap_hwmod
omap2420_uart3_hwmod
;
/* L4_CORE -> L4_WKUP interface */
static
struct
omap_hwmod_ocp_if
omap2420_l4_core__l4_wkup
=
{
...
...
@@ -81,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 CORE -> UART1 interface */
static
struct
omap_hwmod_addr_space
omap2420_uart1_addr_space
[]
=
{
{
.
pa_start
=
OMAP2_UART1_BASE
,
.
pa_end
=
OMAP2_UART1_BASE
+
SZ_8K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap2_l4_core__uart1
=
{
.
master
=
&
omap2420_l4_core_hwmod
,
.
slave
=
&
omap2420_uart1_hwmod
,
.
clk
=
"uart1_ick"
,
.
addr
=
omap2420_uart1_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap2420_uart1_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 CORE -> UART2 interface */
static
struct
omap_hwmod_addr_space
omap2420_uart2_addr_space
[]
=
{
{
.
pa_start
=
OMAP2_UART2_BASE
,
.
pa_end
=
OMAP2_UART2_BASE
+
SZ_1K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap2_l4_core__uart2
=
{
.
master
=
&
omap2420_l4_core_hwmod
,
.
slave
=
&
omap2420_uart2_hwmod
,
.
clk
=
"uart2_ick"
,
.
addr
=
omap2420_uart2_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap2420_uart2_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 PER -> UART3 interface */
static
struct
omap_hwmod_addr_space
omap2420_uart3_addr_space
[]
=
{
{
.
pa_start
=
OMAP2_UART3_BASE
,
.
pa_end
=
OMAP2_UART3_BASE
+
SZ_1K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap2_l4_core__uart3
=
{
.
master
=
&
omap2420_l4_core_hwmod
,
.
slave
=
&
omap2420_uart3_hwmod
,
.
clk
=
"uart3_ick"
,
.
addr
=
omap2420_uart3_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap2420_uart3_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* Slave interfaces on the L4_CORE interconnect */
static
struct
omap_hwmod_ocp_if
*
omap2420_l4_core_slaves
[]
=
{
&
omap2420_l3_main__l4_core
,
...
...
@@ -89,6 +147,9 @@ static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
/* Master interfaces on the L4_CORE interconnect */
static
struct
omap_hwmod_ocp_if
*
omap2420_l4_core_masters
[]
=
{
&
omap2420_l4_core__l4_wkup
,
&
omap2_l4_core__uart1
,
&
omap2_l4_core__uart2
,
&
omap2_l4_core__uart3
,
};
/* L4 CORE */
...
...
@@ -228,6 +289,135 @@ static struct omap_hwmod omap2420_wd_timer2_hwmod = {
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2420
),
};
/* UART */
static
struct
omap_hwmod_class_sysconfig
uart_sysc
=
{
.
rev_offs
=
0x50
,
.
sysc_offs
=
0x54
,
.
syss_offs
=
0x58
,
.
sysc_flags
=
(
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_AUTOIDLE
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
static
struct
omap_hwmod_class
uart_class
=
{
.
name
=
"uart"
,
.
sysc
=
&
uart_sysc
,
};
/* UART1 */
static
struct
omap_hwmod_irq_info
uart1_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART1_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart1_sdma_reqs
[]
=
{
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART1_RX
,
},
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART1_TX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap2420_uart1_slaves
[]
=
{
&
omap2_l4_core__uart1
,
};
static
struct
omap_hwmod
omap2420_uart1_hwmod
=
{
.
name
=
"uart1"
,
.
mpu_irqs
=
uart1_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart1_mpu_irqs
),
.
sdma_reqs
=
uart1_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart1_sdma_reqs
),
.
main_clk
=
"uart1_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP24XX_EN_UART1_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP24XX_EN_UART1_SHIFT
,
},
},
.
slaves
=
omap2420_uart1_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap2420_uart1_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2420
),
};
/* UART2 */
static
struct
omap_hwmod_irq_info
uart2_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART2_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart2_sdma_reqs
[]
=
{
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART2_RX
,
},
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART2_TX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap2420_uart2_slaves
[]
=
{
&
omap2_l4_core__uart2
,
};
static
struct
omap_hwmod
omap2420_uart2_hwmod
=
{
.
name
=
"uart2"
,
.
mpu_irqs
=
uart2_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart2_mpu_irqs
),
.
sdma_reqs
=
uart2_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart2_sdma_reqs
),
.
main_clk
=
"uart2_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP24XX_EN_UART2_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP24XX_EN_UART2_SHIFT
,
},
},
.
slaves
=
omap2420_uart2_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap2420_uart2_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2420
),
};
/* UART3 */
static
struct
omap_hwmod_irq_info
uart3_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART3_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart3_sdma_reqs
[]
=
{
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART3_RX
,
},
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART3_TX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap2420_uart3_slaves
[]
=
{
&
omap2_l4_core__uart3
,
};
static
struct
omap_hwmod
omap2420_uart3_hwmod
=
{
.
name
=
"uart3"
,
.
mpu_irqs
=
uart3_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart3_mpu_irqs
),
.
sdma_reqs
=
uart3_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart3_sdma_reqs
),
.
main_clk
=
"uart3_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
2
,
.
module_bit
=
OMAP24XX_EN_UART3_SHIFT
,
.
idlest_reg_id
=
2
,
.
idlest_idle_bit
=
OMAP24XX_EN_UART3_SHIFT
,
},
},
.
slaves
=
omap2420_uart3_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap2420_uart3_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2420
),
};
static
__initdata
struct
omap_hwmod
*
omap2420_hwmods
[]
=
{
&
omap2420_l3_main_hwmod
,
&
omap2420_l4_core_hwmod
,
...
...
@@ -235,6 +425,9 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = {
&
omap2420_mpu_hwmod
,
&
omap2420_iva_hwmod
,
&
omap2420_wd_timer2_hwmod
,
&
omap2420_uart1_hwmod
,
&
omap2420_uart2_hwmod
,
&
omap2420_uart3_hwmod
,
NULL
,
};
...
...
arch/arm/mach-omap2/omap_hwmod_2430_data.c
View file @
69758ab7
...
...
@@ -15,6 +15,7 @@
#include <mach/irqs.h>
#include <plat/cpu.h>
#include <plat/dma.h>
#include <plat/serial.h>
#include "omap_hwmod_common_data.h"
...
...
@@ -73,6 +74,9 @@ static struct omap_hwmod omap2430_l3_main_hwmod = {
};
static
struct
omap_hwmod
omap2430_l4_wkup_hwmod
;
static
struct
omap_hwmod
omap2430_uart1_hwmod
;
static
struct
omap_hwmod
omap2430_uart2_hwmod
;
static
struct
omap_hwmod
omap2430_uart3_hwmod
;
/* L4_CORE -> L4_WKUP interface */
static
struct
omap_hwmod_ocp_if
omap2430_l4_core__l4_wkup
=
{
...
...
@@ -81,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 CORE -> UART1 interface */
static
struct
omap_hwmod_addr_space
omap2430_uart1_addr_space
[]
=
{
{
.
pa_start
=
OMAP2_UART1_BASE
,
.
pa_end
=
OMAP2_UART1_BASE
+
SZ_8K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap2_l4_core__uart1
=
{
.
master
=
&
omap2430_l4_core_hwmod
,
.
slave
=
&
omap2430_uart1_hwmod
,
.
clk
=
"uart1_ick"
,
.
addr
=
omap2430_uart1_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap2430_uart1_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 CORE -> UART2 interface */
static
struct
omap_hwmod_addr_space
omap2430_uart2_addr_space
[]
=
{
{
.
pa_start
=
OMAP2_UART2_BASE
,
.
pa_end
=
OMAP2_UART2_BASE
+
SZ_1K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap2_l4_core__uart2
=
{
.
master
=
&
omap2430_l4_core_hwmod
,
.
slave
=
&
omap2430_uart2_hwmod
,
.
clk
=
"uart2_ick"
,
.
addr
=
omap2430_uart2_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap2430_uart2_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 PER -> UART3 interface */
static
struct
omap_hwmod_addr_space
omap2430_uart3_addr_space
[]
=
{
{
.
pa_start
=
OMAP2_UART3_BASE
,
.
pa_end
=
OMAP2_UART3_BASE
+
SZ_1K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap2_l4_core__uart3
=
{
.
master
=
&
omap2430_l4_core_hwmod
,
.
slave
=
&
omap2430_uart3_hwmod
,
.
clk
=
"uart3_ick"
,
.
addr
=
omap2430_uart3_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap2430_uart3_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* Slave interfaces on the L4_CORE interconnect */
static
struct
omap_hwmod_ocp_if
*
omap2430_l4_core_slaves
[]
=
{
&
omap2430_l3_main__l4_core
,
...
...
@@ -106,6 +164,9 @@ static struct omap_hwmod omap2430_l4_core_hwmod = {
/* Slave interfaces on the L4_WKUP interconnect */
static
struct
omap_hwmod_ocp_if
*
omap2430_l4_wkup_slaves
[]
=
{
&
omap2430_l4_core__l4_wkup
,
&
omap2_l4_core__uart1
,
&
omap2_l4_core__uart2
,
&
omap2_l4_core__uart3
,
};
/* Master interfaces on the L4_WKUP interconnect */
...
...
@@ -228,6 +289,135 @@ static struct omap_hwmod omap2430_wd_timer2_hwmod = {
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2430
),
};
/* UART */
static
struct
omap_hwmod_class_sysconfig
uart_sysc
=
{
.
rev_offs
=
0x50
,
.
sysc_offs
=
0x54
,
.
syss_offs
=
0x58
,
.
sysc_flags
=
(
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_AUTOIDLE
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
static
struct
omap_hwmod_class
uart_class
=
{
.
name
=
"uart"
,
.
sysc
=
&
uart_sysc
,
};
/* UART1 */
static
struct
omap_hwmod_irq_info
uart1_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART1_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart1_sdma_reqs
[]
=
{
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART1_RX
,
},
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART1_TX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap2430_uart1_slaves
[]
=
{
&
omap2_l4_core__uart1
,
};
static
struct
omap_hwmod
omap2430_uart1_hwmod
=
{
.
name
=
"uart1"
,
.
mpu_irqs
=
uart1_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart1_mpu_irqs
),
.
sdma_reqs
=
uart1_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart1_sdma_reqs
),
.
main_clk
=
"uart1_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP24XX_EN_UART1_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP24XX_EN_UART1_SHIFT
,
},
},
.
slaves
=
omap2430_uart1_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap2430_uart1_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2430
),
};
/* UART2 */
static
struct
omap_hwmod_irq_info
uart2_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART2_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart2_sdma_reqs
[]
=
{
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART2_RX
,
},
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART2_TX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap2430_uart2_slaves
[]
=
{
&
omap2_l4_core__uart2
,
};
static
struct
omap_hwmod
omap2430_uart2_hwmod
=
{
.
name
=
"uart2"
,
.
mpu_irqs
=
uart2_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart2_mpu_irqs
),
.
sdma_reqs
=
uart2_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart2_sdma_reqs
),
.
main_clk
=
"uart2_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP24XX_EN_UART2_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP24XX_EN_UART2_SHIFT
,
},
},
.
slaves
=
omap2430_uart2_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap2430_uart2_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2430
),
};
/* UART3 */
static
struct
omap_hwmod_irq_info
uart3_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART3_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart3_sdma_reqs
[]
=
{
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART3_RX
,
},
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART3_TX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap2430_uart3_slaves
[]
=
{
&
omap2_l4_core__uart3
,
};
static
struct
omap_hwmod
omap2430_uart3_hwmod
=
{
.
name
=
"uart3"
,
.
mpu_irqs
=
uart3_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart3_mpu_irqs
),
.
sdma_reqs
=
uart3_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart3_sdma_reqs
),
.
main_clk
=
"uart3_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
2
,
.
module_bit
=
OMAP24XX_EN_UART3_SHIFT
,
.
idlest_reg_id
=
2
,
.
idlest_idle_bit
=
OMAP24XX_EN_UART3_SHIFT
,
},
},
.
slaves
=
omap2430_uart3_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap2430_uart3_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP2430
),
};
static
__initdata
struct
omap_hwmod
*
omap2430_hwmods
[]
=
{
&
omap2430_l3_main_hwmod
,
&
omap2430_l4_core_hwmod
,
...
...
@@ -235,6 +425,9 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = {
&
omap2430_mpu_hwmod
,
&
omap2430_iva_hwmod
,
&
omap2430_wd_timer2_hwmod
,
&
omap2430_uart1_hwmod
,
&
omap2430_uart2_hwmod
,
&
omap2430_uart3_hwmod
,
NULL
,
};
...
...
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
View file @
69758ab7
...
...
@@ -17,6 +17,7 @@
#include <mach/irqs.h>
#include <plat/cpu.h>
#include <plat/dma.h>
#include <plat/serial.h>
#include "omap_hwmod_common_data.h"
...
...
@@ -84,6 +85,10 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod = {
};
static
struct
omap_hwmod
omap3xxx_l4_wkup_hwmod
;
static
struct
omap_hwmod
omap3xxx_uart1_hwmod
;
static
struct
omap_hwmod
omap3xxx_uart2_hwmod
;
static
struct
omap_hwmod
omap3xxx_uart3_hwmod
;
static
struct
omap_hwmod
omap3xxx_uart4_hwmod
;
/* L4_CORE -> L4_WKUP interface */
static
struct
omap_hwmod_ocp_if
omap3xxx_l4_core__l4_wkup
=
{
...
...
@@ -92,6 +97,78 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 CORE -> UART1 interface */
static
struct
omap_hwmod_addr_space
omap3xxx_uart1_addr_space
[]
=
{
{
.
pa_start
=
OMAP3_UART1_BASE
,
.
pa_end
=
OMAP3_UART1_BASE
+
SZ_8K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap3_l4_core__uart1
=
{
.
master
=
&
omap3xxx_l4_core_hwmod
,
.
slave
=
&
omap3xxx_uart1_hwmod
,
.
clk
=
"uart1_ick"
,
.
addr
=
omap3xxx_uart1_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap3xxx_uart1_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 CORE -> UART2 interface */
static
struct
omap_hwmod_addr_space
omap3xxx_uart2_addr_space
[]
=
{
{
.
pa_start
=
OMAP3_UART2_BASE
,
.
pa_end
=
OMAP3_UART2_BASE
+
SZ_1K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap3_l4_core__uart2
=
{
.
master
=
&
omap3xxx_l4_core_hwmod
,
.
slave
=
&
omap3xxx_uart2_hwmod
,
.
clk
=
"uart2_ick"
,
.
addr
=
omap3xxx_uart2_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap3xxx_uart2_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 PER -> UART3 interface */
static
struct
omap_hwmod_addr_space
omap3xxx_uart3_addr_space
[]
=
{
{
.
pa_start
=
OMAP3_UART3_BASE
,
.
pa_end
=
OMAP3_UART3_BASE
+
SZ_1K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap3_l4_per__uart3
=
{
.
master
=
&
omap3xxx_l4_per_hwmod
,
.
slave
=
&
omap3xxx_uart3_hwmod
,
.
clk
=
"uart3_ick"
,
.
addr
=
omap3xxx_uart3_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap3xxx_uart3_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* L4 PER -> UART4 interface */
static
struct
omap_hwmod_addr_space
omap3xxx_uart4_addr_space
[]
=
{
{
.
pa_start
=
OMAP3_UART4_BASE
,
.
pa_end
=
OMAP3_UART4_BASE
+
SZ_1K
-
1
,
.
flags
=
ADDR_MAP_ON_INIT
|
ADDR_TYPE_RT
,
},
};
static
struct
omap_hwmod_ocp_if
omap3_l4_per__uart4
=
{
.
master
=
&
omap3xxx_l4_per_hwmod
,
.
slave
=
&
omap3xxx_uart4_hwmod
,
.
clk
=
"uart4_ick"
,
.
addr
=
omap3xxx_uart4_addr_space
,
.
addr_cnt
=
ARRAY_SIZE
(
omap3xxx_uart4_addr_space
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* Slave interfaces on the L4_CORE interconnect */
static
struct
omap_hwmod_ocp_if
*
omap3xxx_l4_core_slaves
[]
=
{
&
omap3xxx_l3_main__l4_core
,
...
...
@@ -100,6 +177,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
/* Master interfaces on the L4_CORE interconnect */
static
struct
omap_hwmod_ocp_if
*
omap3xxx_l4_core_masters
[]
=
{
&
omap3xxx_l4_core__l4_wkup
,
&
omap3_l4_core__uart1
,
&
omap3_l4_core__uart2
,
};
/* L4 CORE */
...
...
@@ -121,6 +200,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = {
/* Master interfaces on the L4_PER interconnect */
static
struct
omap_hwmod_ocp_if
*
omap3xxx_l4_per_masters
[]
=
{
&
omap3_l4_per__uart3
,
&
omap3_l4_per__uart4
,
};
/* L4 PER */
...
...
@@ -262,6 +343,172 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP3430
),
};
/* UART common */
static
struct
omap_hwmod_class_sysconfig
uart_sysc
=
{
.
rev_offs
=
0x50
,
.
sysc_offs
=
0x54
,
.
syss_offs
=
0x58
,
.
sysc_flags
=
(
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_AUTOIDLE
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
static
struct
omap_hwmod_class
uart_class
=
{
.
name
=
"uart"
,
.
sysc
=
&
uart_sysc
,
};
/* UART1 */
static
struct
omap_hwmod_irq_info
uart1_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART1_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart1_sdma_reqs
[]
=
{
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART1_TX
,
},
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART1_RX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap3xxx_uart1_slaves
[]
=
{
&
omap3_l4_core__uart1
,
};
static
struct
omap_hwmod
omap3xxx_uart1_hwmod
=
{
.
name
=
"uart1"
,
.
mpu_irqs
=
uart1_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart1_mpu_irqs
),
.
sdma_reqs
=
uart1_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart1_sdma_reqs
),
.
main_clk
=
"uart1_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP3430_EN_UART1_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP3430_EN_UART1_SHIFT
,
},
},
.
slaves
=
omap3xxx_uart1_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap3xxx_uart1_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP3430
),
};
/* UART2 */
static
struct
omap_hwmod_irq_info
uart2_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART2_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart2_sdma_reqs
[]
=
{
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART2_TX
,
},
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART2_RX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap3xxx_uart2_slaves
[]
=
{
&
omap3_l4_core__uart2
,
};
static
struct
omap_hwmod
omap3xxx_uart2_hwmod
=
{
.
name
=
"uart2"
,
.
mpu_irqs
=
uart2_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart2_mpu_irqs
),
.
sdma_reqs
=
uart2_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart2_sdma_reqs
),
.
main_clk
=
"uart2_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
CORE_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP3430_EN_UART2_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP3430_EN_UART2_SHIFT
,
},
},
.
slaves
=
omap3xxx_uart2_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap3xxx_uart2_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP3430
),
};
/* UART3 */
static
struct
omap_hwmod_irq_info
uart3_mpu_irqs
[]
=
{
{
.
irq
=
INT_24XX_UART3_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart3_sdma_reqs
[]
=
{
{
.
name
=
"tx"
,
.
dma_req
=
OMAP24XX_DMA_UART3_TX
,
},
{
.
name
=
"rx"
,
.
dma_req
=
OMAP24XX_DMA_UART3_RX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap3xxx_uart3_slaves
[]
=
{
&
omap3_l4_per__uart3
,
};
static
struct
omap_hwmod
omap3xxx_uart3_hwmod
=
{
.
name
=
"uart3"
,
.
mpu_irqs
=
uart3_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart3_mpu_irqs
),
.
sdma_reqs
=
uart3_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart3_sdma_reqs
),
.
main_clk
=
"uart3_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
OMAP3430_PER_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP3430_EN_UART3_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP3430_EN_UART3_SHIFT
,
},
},
.
slaves
=
omap3xxx_uart3_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap3xxx_uart3_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP3430
),
};
/* UART4 */
static
struct
omap_hwmod_irq_info
uart4_mpu_irqs
[]
=
{
{
.
irq
=
INT_36XX_UART4_IRQ
,
},
};
static
struct
omap_hwmod_dma_info
uart4_sdma_reqs
[]
=
{
{
.
name
=
"rx"
,
.
dma_req
=
OMAP36XX_DMA_UART4_RX
,
},
{
.
name
=
"tx"
,
.
dma_req
=
OMAP36XX_DMA_UART4_TX
,
},
};
static
struct
omap_hwmod_ocp_if
*
omap3xxx_uart4_slaves
[]
=
{
&
omap3_l4_per__uart4
,
};
static
struct
omap_hwmod
omap3xxx_uart4_hwmod
=
{
.
name
=
"uart4"
,
.
mpu_irqs
=
uart4_mpu_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
uart4_mpu_irqs
),
.
sdma_reqs
=
uart4_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
uart4_sdma_reqs
),
.
main_clk
=
"uart4_fck"
,
.
prcm
=
{
.
omap2
=
{
.
module_offs
=
OMAP3430_PER_MOD
,
.
prcm_reg_id
=
1
,
.
module_bit
=
OMAP3630_EN_UART4_SHIFT
,
.
idlest_reg_id
=
1
,
.
idlest_idle_bit
=
OMAP3630_EN_UART4_SHIFT
,
},
},
.
slaves
=
omap3xxx_uart4_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap3xxx_uart4_slaves
),
.
class
=
&
uart_class
,
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP3630ES1
),
};
static
__initdata
struct
omap_hwmod
*
omap3xxx_hwmods
[]
=
{
&
omap3xxx_l3_main_hwmod
,
&
omap3xxx_l4_core_hwmod
,
...
...
@@ -270,6 +517,10 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&
omap3xxx_mpu_hwmod
,
&
omap3xxx_iva_hwmod
,
&
omap3xxx_wd_timer2_hwmod
,
&
omap3xxx_uart1_hwmod
,
&
omap3xxx_uart2_hwmod
,
&
omap3xxx_uart3_hwmod
,
&
omap3xxx_uart4_hwmod
,
NULL
,
};
...
...
@@ -277,5 +528,3 @@ int __init omap3xxx_hwmod_init(void)
{
return
omap_hwmod_init
(
omap3xxx_hwmods
);
}
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
View file @
69758ab7
...
...
@@ -468,6 +468,21 @@ static struct omap_hwmod_class_sysconfig omap44xx_wd_timer_sysc = {
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
/*
* 'uart' class
* universal asynchronous receiver/transmitter (uart)
*/
static
struct
omap_hwmod_class_sysconfig
omap44xx_uart_sysc
=
{
.
rev_offs
=
0x0050
,
.
sysc_offs
=
0x0054
,
.
syss_offs
=
0x0058
,
.
sysc_flags
=
(
SYSC_HAS_ENAWAKEUP
|
SYSC_HAS_SIDLEMODE
|
SYSC_HAS_SOFTRESET
|
SYSC_HAS_AUTOIDLE
),
.
idlemodes
=
(
SIDLE_FORCE
|
SIDLE_NO
|
SIDLE_SMART
),
.
sysc_fields
=
&
omap_hwmod_sysc_type1
,
};
static
struct
omap_hwmod_class
omap44xx_wd_timer_hwmod_class
=
{
.
name
=
"wd_timer"
,
.
sysc
=
&
omap44xx_wd_timer_sysc
,
...
...
@@ -487,6 +502,82 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
},
};
static
struct
omap_hwmod_class
omap44xx_uart_hwmod_class
=
{
.
name
=
"uart"
,
.
sysc
=
&
omap44xx_uart_sysc
,
};
/* uart1 */
static
struct
omap_hwmod
omap44xx_uart1_hwmod
;
static
struct
omap_hwmod_irq_info
omap44xx_uart1_irqs
[]
=
{
{
.
irq
=
72
+
OMAP44XX_IRQ_GIC_START
},
};
static
struct
omap_hwmod_dma_info
omap44xx_uart1_sdma_reqs
[]
=
{
{
.
name
=
"tx"
,
.
dma_req
=
48
+
OMAP44XX_DMA_REQ_START
},
{
.
name
=
"rx"
,
.
dma_req
=
49
+
OMAP44XX_DMA_REQ_START
},
};
static
struct
omap_hwmod_addr_space
omap44xx_uart1_addrs
[]
=
{
{
.
pa_start
=
0x4806a000
,
.
pa_end
=
0x4806a0ff
,
.
flags
=
ADDR_TYPE_RT
},
};
/* l4_per -> uart1 */
static
struct
omap_hwmod_ocp_if
omap44xx_l4_per__uart1
=
{
.
master
=
&
omap44xx_l4_per_hwmod
,
.
slave
=
&
omap44xx_uart1_hwmod
,
.
clk
=
"l4_div_ck"
,
.
addr
=
omap44xx_uart1_addrs
,
.
addr_cnt
=
ARRAY_SIZE
(
omap44xx_uart1_addrs
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* uart1 slave ports */
static
struct
omap_hwmod_ocp_if
*
omap44xx_uart1_slaves
[]
=
{
&
omap44xx_l4_per__uart1
,
};
static
struct
omap_hwmod
omap44xx_uart1_hwmod
=
{
.
name
=
"uart1"
,
.
class
=
&
omap44xx_uart_hwmod_class
,
.
mpu_irqs
=
omap44xx_uart1_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart1_irqs
),
.
sdma_reqs
=
omap44xx_uart1_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart1_sdma_reqs
),
.
main_clk
=
"uart1_fck"
,
.
prcm
=
{
.
omap4
=
{
.
clkctrl_reg
=
OMAP4430_CM_L4PER_UART1_CLKCTRL
,
},
},
.
slaves
=
omap44xx_uart1_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap44xx_uart1_slaves
),
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP4430
),
};
/* uart2 */
static
struct
omap_hwmod
omap44xx_uart2_hwmod
;
static
struct
omap_hwmod_irq_info
omap44xx_uart2_irqs
[]
=
{
{
.
irq
=
73
+
OMAP44XX_IRQ_GIC_START
},
};
static
struct
omap_hwmod_dma_info
omap44xx_uart2_sdma_reqs
[]
=
{
{
.
name
=
"tx"
,
.
dma_req
=
50
+
OMAP44XX_DMA_REQ_START
},
{
.
name
=
"rx"
,
.
dma_req
=
51
+
OMAP44XX_DMA_REQ_START
},
};
static
struct
omap_hwmod_addr_space
omap44xx_uart2_addrs
[]
=
{
{
.
pa_start
=
0x4806c000
,
.
pa_end
=
0x4806c0ff
,
.
flags
=
ADDR_TYPE_RT
},
};
/* l4_wkup -> wd_timer2 */
static
struct
omap_hwmod_ocp_if
omap44xx_l4_wkup__wd_timer2
=
{
.
master
=
&
omap44xx_l4_wkup_hwmod
,
...
...
@@ -532,6 +623,58 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
},
};
/* l4_per -> uart2 */
static
struct
omap_hwmod_ocp_if
omap44xx_l4_per__uart2
=
{
.
master
=
&
omap44xx_l4_per_hwmod
,
.
slave
=
&
omap44xx_uart2_hwmod
,
.
clk
=
"l4_div_ck"
,
.
addr
=
omap44xx_uart2_addrs
,
.
addr_cnt
=
ARRAY_SIZE
(
omap44xx_uart2_addrs
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* uart2 slave ports */
static
struct
omap_hwmod_ocp_if
*
omap44xx_uart2_slaves
[]
=
{
&
omap44xx_l4_per__uart2
,
};
static
struct
omap_hwmod
omap44xx_uart2_hwmod
=
{
.
name
=
"uart2"
,
.
class
=
&
omap44xx_uart_hwmod_class
,
.
mpu_irqs
=
omap44xx_uart2_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart2_irqs
),
.
sdma_reqs
=
omap44xx_uart2_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart2_sdma_reqs
),
.
main_clk
=
"uart2_fck"
,
.
prcm
=
{
.
omap4
=
{
.
clkctrl_reg
=
OMAP4430_CM_L4PER_UART2_CLKCTRL
,
},
},
.
slaves
=
omap44xx_uart2_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap44xx_uart2_slaves
),
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP4430
),
};
/* uart3 */
static
struct
omap_hwmod
omap44xx_uart3_hwmod
;
static
struct
omap_hwmod_irq_info
omap44xx_uart3_irqs
[]
=
{
{
.
irq
=
74
+
OMAP44XX_IRQ_GIC_START
},
};
static
struct
omap_hwmod_dma_info
omap44xx_uart3_sdma_reqs
[]
=
{
{
.
name
=
"tx"
,
.
dma_req
=
52
+
OMAP44XX_DMA_REQ_START
},
{
.
name
=
"rx"
,
.
dma_req
=
53
+
OMAP44XX_DMA_REQ_START
},
};
static
struct
omap_hwmod_addr_space
omap44xx_uart3_addrs
[]
=
{
{
.
pa_start
=
0x48020000
,
.
pa_end
=
0x480200ff
,
.
flags
=
ADDR_TYPE_RT
},
};
/* l4_abe -> wd_timer3 */
static
struct
omap_hwmod_ocp_if
omap44xx_l4_abe__wd_timer3
=
{
.
master
=
&
omap44xx_l4_abe_hwmod
,
...
...
@@ -551,6 +694,59 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
},
};
/* l4_per -> uart3 */
static
struct
omap_hwmod_ocp_if
omap44xx_l4_per__uart3
=
{
.
master
=
&
omap44xx_l4_per_hwmod
,
.
slave
=
&
omap44xx_uart3_hwmod
,
.
clk
=
"l4_div_ck"
,
.
addr
=
omap44xx_uart3_addrs
,
.
addr_cnt
=
ARRAY_SIZE
(
omap44xx_uart3_addrs
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* uart3 slave ports */
static
struct
omap_hwmod_ocp_if
*
omap44xx_uart3_slaves
[]
=
{
&
omap44xx_l4_per__uart3
,
};
static
struct
omap_hwmod
omap44xx_uart3_hwmod
=
{
.
name
=
"uart3"
,
.
class
=
&
omap44xx_uart_hwmod_class
,
.
flags
=
(
HWMOD_INIT_NO_IDLE
|
HWMOD_INIT_NO_RESET
),
.
mpu_irqs
=
omap44xx_uart3_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart3_irqs
),
.
sdma_reqs
=
omap44xx_uart3_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart3_sdma_reqs
),
.
main_clk
=
"uart3_fck"
,
.
prcm
=
{
.
omap4
=
{
.
clkctrl_reg
=
OMAP4430_CM_L4PER_UART3_CLKCTRL
,
},
},
.
slaves
=
omap44xx_uart3_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap44xx_uart3_slaves
),
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP4430
),
};
/* uart4 */
static
struct
omap_hwmod
omap44xx_uart4_hwmod
;
static
struct
omap_hwmod_irq_info
omap44xx_uart4_irqs
[]
=
{
{
.
irq
=
70
+
OMAP44XX_IRQ_GIC_START
},
};
static
struct
omap_hwmod_dma_info
omap44xx_uart4_sdma_reqs
[]
=
{
{
.
name
=
"tx"
,
.
dma_req
=
54
+
OMAP44XX_DMA_REQ_START
},
{
.
name
=
"rx"
,
.
dma_req
=
55
+
OMAP44XX_DMA_REQ_START
},
};
static
struct
omap_hwmod_addr_space
omap44xx_uart4_addrs
[]
=
{
{
.
pa_start
=
0x4806e000
,
.
pa_end
=
0x4806e0ff
,
.
flags
=
ADDR_TYPE_RT
},
};
static
struct
omap_hwmod_ocp_if
omap44xx_l4_abe__wd_timer3_dma
=
{
.
master
=
&
omap44xx_l4_abe_hwmod
,
.
slave
=
&
omap44xx_wd_timer3_hwmod
,
...
...
@@ -582,6 +778,39 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP4430
),
};
/* l4_per -> uart4 */
static
struct
omap_hwmod_ocp_if
omap44xx_l4_per__uart4
=
{
.
master
=
&
omap44xx_l4_per_hwmod
,
.
slave
=
&
omap44xx_uart4_hwmod
,
.
clk
=
"l4_div_ck"
,
.
addr
=
omap44xx_uart4_addrs
,
.
addr_cnt
=
ARRAY_SIZE
(
omap44xx_uart4_addrs
),
.
user
=
OCP_USER_MPU
|
OCP_USER_SDMA
,
};
/* uart4 slave ports */
static
struct
omap_hwmod_ocp_if
*
omap44xx_uart4_slaves
[]
=
{
&
omap44xx_l4_per__uart4
,
};
static
struct
omap_hwmod
omap44xx_uart4_hwmod
=
{
.
name
=
"uart4"
,
.
class
=
&
omap44xx_uart_hwmod_class
,
.
mpu_irqs
=
omap44xx_uart4_irqs
,
.
mpu_irqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart4_irqs
),
.
sdma_reqs
=
omap44xx_uart4_sdma_reqs
,
.
sdma_reqs_cnt
=
ARRAY_SIZE
(
omap44xx_uart4_sdma_reqs
),
.
main_clk
=
"uart4_fck"
,
.
prcm
=
{
.
omap4
=
{
.
clkctrl_reg
=
OMAP4430_CM_L4PER_UART4_CLKCTRL
,
},
},
.
slaves
=
omap44xx_uart4_slaves
,
.
slaves_cnt
=
ARRAY_SIZE
(
omap44xx_uart4_slaves
),
.
omap_chip
=
OMAP_CHIP_INIT
(
CHIP_IS_OMAP4430
),
};
static
__initdata
struct
omap_hwmod
*
omap44xx_hwmods
[]
=
{
/* dmm class */
&
omap44xx_dmm_hwmod
,
...
...
@@ -605,6 +834,12 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
/* wd_timer class */
&
omap44xx_wd_timer2_hwmod
,
&
omap44xx_wd_timer3_hwmod
,
/* uart class */
&
omap44xx_uart1_hwmod
,
&
omap44xx_uart2_hwmod
,
&
omap44xx_uart3_hwmod
,
&
omap44xx_uart4_hwmod
,
NULL
,
};
...
...
arch/arm/mach-omap2/pm34xx.c
View file @
69758ab7
...
...
@@ -388,6 +388,7 @@ void omap_sram_idle(void)
/* PER */
if
(
per_next_state
<
PWRDM_POWER_ON
)
{
omap_uart_prepare_idle
(
2
);
omap_uart_prepare_idle
(
3
);
omap2_gpio_prepare_for_idle
(
per_next_state
);
if
(
per_next_state
==
PWRDM_POWER_OFF
)
omap3_per_save_context
();
...
...
@@ -459,6 +460,7 @@ void omap_sram_idle(void)
if
(
per_prev_state
==
PWRDM_POWER_OFF
)
omap3_per_restore_context
();
omap_uart_resume_idle
(
2
);
omap_uart_resume_idle
(
3
);
}
/* Disable IO-PAD and IO-CHAIN wakeup */
...
...
@@ -676,6 +678,14 @@ static void __init omap3_d2d_idle(void)
static
void
__init
prcm_setup_regs
(
void
)
{
u32
omap3630_auto_uart4_mask
=
cpu_is_omap3630
()
?
OMAP3630_AUTO_UART4_MASK
:
0
;
u32
omap3630_en_uart4_mask
=
cpu_is_omap3630
()
?
OMAP3630_EN_UART4_MASK
:
0
;
u32
omap3630_grpsel_uart4_mask
=
cpu_is_omap3630
()
?
OMAP3630_GRPSEL_UART4_MASK
:
0
;
/* XXX Reset all wkdeps. This should be done when initializing
* powerdomains */
prm_write_mod_reg
(
0
,
OMAP3430_IVA2_MOD
,
PM_WKDEP
);
...
...
@@ -762,6 +772,7 @@ static void __init prcm_setup_regs(void)
CM_AUTOIDLE
);
cm_write_mod_reg
(
omap3630_auto_uart4_mask
|
OMAP3430_AUTO_GPIO6_MASK
|
OMAP3430_AUTO_GPIO5_MASK
|
OMAP3430_AUTO_GPIO4_MASK
|
...
...
@@ -838,14 +849,16 @@ static void __init prcm_setup_regs(void)
OMAP3430_DSS_MOD
,
PM_WKEN
);
/* Enable wakeups in PER */
prm_write_mod_reg
(
OMAP3430_EN_GPIO2_MASK
|
OMAP3430_EN_GPIO3_MASK
|
prm_write_mod_reg
(
omap3630_en_uart4_mask
|
OMAP3430_EN_GPIO2_MASK
|
OMAP3430_EN_GPIO3_MASK
|
OMAP3430_EN_GPIO4_MASK
|
OMAP3430_EN_GPIO5_MASK
|
OMAP3430_EN_GPIO6_MASK
|
OMAP3430_EN_UART3_MASK
|
OMAP3430_EN_MCBSP2_MASK
|
OMAP3430_EN_MCBSP3_MASK
|
OMAP3430_EN_MCBSP4_MASK
,
OMAP3430_PER_MOD
,
PM_WKEN
);
/* and allow them to wake up MPU */
prm_write_mod_reg
(
OMAP3430_GRPSEL_GPIO2_MASK
|
prm_write_mod_reg
(
omap3630_grpsel_uart4_mask
|
OMAP3430_GRPSEL_GPIO2_MASK
|
OMAP3430_GRPSEL_GPIO3_MASK
|
OMAP3430_GRPSEL_GPIO4_MASK
|
OMAP3430_GRPSEL_GPIO5_MASK
|
...
...
arch/arm/mach-omap2/prcm-common.h
View file @
69758ab7
...
...
@@ -382,6 +382,9 @@
#define OMAP3430_EN_MPU_SHIFT 1
/* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */
#define OMAP3630_EN_UART4_MASK (1 << 18)
#define OMAP3630_EN_UART4_SHIFT 18
#define OMAP3430_EN_GPIO6_MASK (1 << 17)
#define OMAP3430_EN_GPIO6_SHIFT 17
#define OMAP3430_EN_GPIO5_MASK (1 << 16)
...
...
@@ -422,6 +425,8 @@
#define OMAP3430_EN_MCBSP2_SHIFT 0
/* CM_IDLEST_PER, PM_WKST_PER shared bits */
#define OMAP3630_ST_UART4_SHIFT 18
#define OMAP3630_ST_UART4_MASK (1 << 18)
#define OMAP3430_ST_GPIO6_SHIFT 17
#define OMAP3430_ST_GPIO6_MASK (1 << 17)
#define OMAP3430_ST_GPIO5_SHIFT 16
...
...
arch/arm/mach-omap2/prm-regbits-34xx.h
View file @
69758ab7
...
...
@@ -122,6 +122,7 @@
#define OMAP3430_MEMRETSTATE_MASK (1 << 8)
/* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */
#define OMAP3630_GRPSEL_UART4_MASK (1 << 18)
#define OMAP3430_GRPSEL_GPIO6_MASK (1 << 17)
#define OMAP3430_GRPSEL_GPIO5_MASK (1 << 16)
#define OMAP3430_GRPSEL_GPIO4_MASK (1 << 15)
...
...
arch/arm/mach-omap2/serial.c
View file @
69758ab7
...
...
@@ -19,19 +19,30 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/serial_8250.h>
#include <linux/pm_runtime.h>
#ifdef CONFIG_SERIAL_OMAP
#include <plat/omap-serial.h>
#endif
#include <plat/common.h>
#include <plat/board.h>
#include <plat/clock.h>
#include <plat/control.h>
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
#include "prm.h"
#include "pm.h"
#include "cm.h"
#include "prm-regbits-34xx.h"
#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52
...
...
@@ -48,6 +59,8 @@
*/
#define DEFAULT_TIMEOUT 0
#define MAX_UART_HWMOD_NAME_LEN 16
struct
omap_uart_state
{
int
num
;
int
can_sleep
;
...
...
@@ -58,14 +71,21 @@ struct omap_uart_state {
void
__iomem
*
wk_en
;
u32
wk_mask
;
u32
padconf
;
u32
dma_enabled
;
struct
clk
*
ick
;
struct
clk
*
fck
;
int
clocked
;
struct
plat_serial8250_port
*
p
;
int
irq
;
int
regshift
;
int
irqflags
;
void
__iomem
*
membase
;
resource_size_t
mapbase
;
struct
list_head
node
;
struct
platform_device
pdev
;
struct
omap_hwmod
*
oh
;
struct
platform_device
*
pdev
;
u32
errata
;
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
...
...
@@ -83,75 +103,47 @@ struct omap_uart_state {
};
static
LIST_HEAD
(
uart_list
);
static
u8
num_uarts
;
static
struct
plat_serial8250_port
serial_platform_data0
[]
=
{
{
.
irq
=
72
,
.
flags
=
UPF_BOOT_AUTOCONF
,
.
iotype
=
UPIO_MEM
,
.
regshift
=
2
,
.
uartclk
=
OMAP24XX_BASE_BAUD
*
16
,
},
{
.
flags
=
0
}
};
/*
* Since these idle/enable hooks are used in the idle path itself
* which has interrupts disabled, use the non-locking versions of
* the hwmod enable/disable functions.
*/
static
int
uart_idle_hwmod
(
struct
omap_device
*
od
)
{
_omap_hwmod_idle
(
od
->
hwmods
[
0
]);
static
struct
plat_serial8250_port
serial_platform_data1
[]
=
{
{
.
irq
=
73
,
.
flags
=
UPF_BOOT_AUTOCONF
,
.
iotype
=
UPIO_MEM
,
.
regshift
=
2
,
.
uartclk
=
OMAP24XX_BASE_BAUD
*
16
,
},
{
.
flags
=
0
}
};
return
0
;
}
static
struct
plat_serial8250_port
serial_platform_data2
[]
=
{
{
.
irq
=
74
,
.
flags
=
UPF_BOOT_AUTOCONF
,
.
iotype
=
UPIO_MEM
,
.
regshift
=
2
,
.
uartclk
=
OMAP24XX_BASE_BAUD
*
16
,
},
{
.
flags
=
0
}
};
static
int
uart_enable_hwmod
(
struct
omap_device
*
od
)
{
_omap_hwmod_enable
(
od
->
hwmods
[
0
]);
return
0
;
}
static
struct
plat_serial8250_port
serial_platform_data3
[]
=
{
static
struct
omap_device_pm_latency
omap_uart_latency
[]
=
{
{
.
irq
=
70
,
.
flags
=
UPF_BOOT_AUTOCONF
,
.
iotype
=
UPIO_MEM
,
.
regshift
=
2
,
.
uartclk
=
OMAP24XX_BASE_BAUD
*
16
,
},
{
.
flags
=
0
}
.
deactivate_func
=
uart_idle_hwmod
,
.
activate_func
=
uart_enable_hwmod
,
.
flags
=
OMAP_DEVICE_LATENCY_AUTO_ADJUST
,
},
};
void
__init
omap2_set_globals_uart
(
struct
omap_globals
*
omap2_globals
)
{
serial_platform_data0
[
0
].
mapbase
=
omap2_globals
->
uart1_phys
;
serial_platform_data1
[
0
].
mapbase
=
omap2_globals
->
uart2_phys
;
serial_platform_data2
[
0
].
mapbase
=
omap2_globals
->
uart3_phys
;
serial_platform_data3
[
0
].
mapbase
=
omap2_globals
->
uart4_phys
;
}
static
inline
unsigned
int
__serial_read_reg
(
struct
uart_port
*
up
,
int
offset
)
int
offset
)
{
offset
<<=
up
->
regshift
;
return
(
unsigned
int
)
__raw_readb
(
up
->
membase
+
offset
);
}
static
inline
unsigned
int
serial_read_reg
(
struct
plat_serial8250_port
*
up
,
static
inline
unsigned
int
serial_read_reg
(
struct
omap_uart_state
*
uart
,
int
offset
)
{
offset
<<=
u
p
->
regshift
;
return
(
unsigned
int
)
__raw_readb
(
u
p
->
membase
+
offset
);
offset
<<=
u
art
->
regshift
;
return
(
unsigned
int
)
__raw_readb
(
u
art
->
membase
+
offset
);
}
static
inline
void
__serial_write_reg
(
struct
uart_port
*
up
,
int
offset
,
...
...
@@ -161,11 +153,11 @@ static inline void __serial_write_reg(struct uart_port *up, int offset,
__raw_writeb
(
value
,
up
->
membase
+
offset
);
}
static
inline
void
serial_write_reg
(
struct
plat_serial8250_port
*
p
,
int
offset
,
static
inline
void
serial_write_reg
(
struct
omap_uart_state
*
uart
,
int
offset
,
int
value
)
{
offset
<<=
p
->
regshift
;
__raw_writeb
(
value
,
p
->
membase
+
offset
);
offset
<<=
uart
->
regshift
;
__raw_writeb
(
value
,
uart
->
membase
+
offset
);
}
/*
...
...
@@ -173,14 +165,12 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
* properly. Note that the TX watermark initialization may not be needed
* once the 8250.c watermark handling code is merged.
*/
static
inline
void
__init
omap_uart_reset
(
struct
omap_uart_state
*
uart
)
{
struct
plat_serial8250_port
*
p
=
uart
->
p
;
serial_write_reg
(
p
,
UART_OMAP_MDR1
,
0x07
);
serial_write_reg
(
p
,
UART_OMAP_SCR
,
0x08
);
serial_write_reg
(
p
,
UART_OMAP_MDR1
,
0x00
);
serial_write_reg
(
p
,
UART_OMAP_SYSC
,
(
0x02
<<
3
)
|
(
1
<<
2
)
|
(
1
<<
0
));
serial_write_reg
(
uart
,
UART_OMAP_MDR1
,
0x07
);
serial_write_reg
(
uart
,
UART_OMAP_SCR
,
0x08
);
serial_write_reg
(
uart
,
UART_OMAP_MDR1
,
0x00
);
}
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
...
...
@@ -197,24 +187,23 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart)
static
void
omap_uart_mdr1_errataset
(
struct
omap_uart_state
*
uart
,
u8
mdr1_val
,
u8
fcr_val
)
{
struct
plat_serial8250_port
*
p
=
uart
->
p
;
u8
timeout
=
255
;
serial_write_reg
(
p
,
UART_OMAP_MDR1
,
mdr1_val
);
serial_write_reg
(
uart
,
UART_OMAP_MDR1
,
mdr1_val
);
udelay
(
2
);
serial_write_reg
(
p
,
UART_FCR
,
fcr_val
|
UART_FCR_CLEAR_XMIT
|
serial_write_reg
(
uart
,
UART_FCR
,
fcr_val
|
UART_FCR_CLEAR_XMIT
|
UART_FCR_CLEAR_RCVR
);
/*
* Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
* TX_FIFO_E bit is 1.
*/
while
(
UART_LSR_THRE
!=
(
serial_read_reg
(
p
,
UART_LSR
)
&
while
(
UART_LSR_THRE
!=
(
serial_read_reg
(
uart
,
UART_LSR
)
&
(
UART_LSR_THRE
|
UART_LSR_DR
)))
{
timeout
--
;
if
(
!
timeout
)
{
/* Should *never* happen. we warn and carry on */
dev_crit
(
&
uart
->
pdev
.
dev
,
"Errata i202: timedout %x
\n
"
,
serial_read_reg
(
p
,
UART_LSR
));
dev_crit
(
&
uart
->
pdev
->
dev
,
"Errata i202: timedout %x
\n
"
,
serial_read_reg
(
uart
,
UART_LSR
));
break
;
}
udelay
(
1
);
...
...
@@ -224,23 +213,22 @@ static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
static
void
omap_uart_save_context
(
struct
omap_uart_state
*
uart
)
{
u16
lcr
=
0
;
struct
plat_serial8250_port
*
p
=
uart
->
p
;
if
(
!
enable_off_mode
)
return
;
lcr
=
serial_read_reg
(
p
,
UART_LCR
);
serial_write_reg
(
p
,
UART_LCR
,
0xBF
);
uart
->
dll
=
serial_read_reg
(
p
,
UART_DLL
);
uart
->
dlh
=
serial_read_reg
(
p
,
UART_DLM
);
serial_write_reg
(
p
,
UART_LCR
,
lcr
);
uart
->
ier
=
serial_read_reg
(
p
,
UART_IER
);
uart
->
sysc
=
serial_read_reg
(
p
,
UART_OMAP_SYSC
);
uart
->
scr
=
serial_read_reg
(
p
,
UART_OMAP_SCR
);
uart
->
wer
=
serial_read_reg
(
p
,
UART_OMAP_WER
);
serial_write_reg
(
p
,
UART_LCR
,
0x80
);
uart
->
mcr
=
serial_read_reg
(
p
,
UART_MCR
);
serial_write_reg
(
p
,
UART_LCR
,
lcr
);
lcr
=
serial_read_reg
(
uart
,
UART_LCR
);
serial_write_reg
(
uart
,
UART_LCR
,
0xBF
);
uart
->
dll
=
serial_read_reg
(
uart
,
UART_DLL
);
uart
->
dlh
=
serial_read_reg
(
uart
,
UART_DLM
);
serial_write_reg
(
uart
,
UART_LCR
,
lcr
);
uart
->
ier
=
serial_read_reg
(
uart
,
UART_IER
);
uart
->
sysc
=
serial_read_reg
(
uart
,
UART_OMAP_SYSC
);
uart
->
scr
=
serial_read_reg
(
uart
,
UART_OMAP_SCR
);
uart
->
wer
=
serial_read_reg
(
uart
,
UART_OMAP_WER
);
serial_write_reg
(
uart
,
UART_LCR
,
0x80
);
uart
->
mcr
=
serial_read_reg
(
uart
,
UART_MCR
);
serial_write_reg
(
uart
,
UART_LCR
,
lcr
);
uart
->
context_valid
=
1
;
}
...
...
@@ -248,7 +236,6 @@ static void omap_uart_save_context(struct omap_uart_state *uart)
static
void
omap_uart_restore_context
(
struct
omap_uart_state
*
uart
)
{
u16
efr
=
0
;
struct
plat_serial8250_port
*
p
=
uart
->
p
;
if
(
!
enable_off_mode
)
return
;
...
...
@@ -261,29 +248,30 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
if
(
uart
->
errata
&
UART_ERRATA_i202_MDR1_ACCESS
)
omap_uart_mdr1_errataset
(
uart
,
0x07
,
0xA0
);
else
serial_write_reg
(
p
,
UART_OMAP_MDR1
,
0x7
);
serial_write_reg
(
p
,
UART_LCR
,
0xBF
);
/* Config B mode */
efr
=
serial_read_reg
(
p
,
UART_EFR
);
serial_write_reg
(
p
,
UART_EFR
,
UART_EFR_ECB
);
serial_write_reg
(
p
,
UART_LCR
,
0x0
);
/* Operational mode */
serial_write_reg
(
p
,
UART_IER
,
0x0
);
serial_write_reg
(
p
,
UART_LCR
,
0xBF
);
/* Config B mode */
serial_write_reg
(
p
,
UART_DLL
,
uart
->
dll
);
serial_write_reg
(
p
,
UART_DLM
,
uart
->
dlh
);
serial_write_reg
(
p
,
UART_LCR
,
0x0
);
/* Operational mode */
serial_write_reg
(
p
,
UART_IER
,
uart
->
ier
);
serial_write_reg
(
p
,
UART_LCR
,
0x80
);
serial_write_reg
(
p
,
UART_MCR
,
uart
->
mcr
);
serial_write_reg
(
p
,
UART_LCR
,
0xBF
);
/* Config B mode */
serial_write_reg
(
p
,
UART_EFR
,
efr
);
serial_write_reg
(
p
,
UART_LCR
,
UART_LCR_WLEN8
);
serial_write_reg
(
p
,
UART_OMAP_SCR
,
uart
->
scr
);
serial_write_reg
(
p
,
UART_OMAP_WER
,
uart
->
wer
);
serial_write_reg
(
p
,
UART_OMAP_SYSC
,
uart
->
sysc
);
serial_write_reg
(
uart
,
UART_OMAP_MDR1
,
0x7
);
serial_write_reg
(
uart
,
UART_LCR
,
0xBF
);
/* Config B mode */
efr
=
serial_read_reg
(
uart
,
UART_EFR
);
serial_write_reg
(
uart
,
UART_EFR
,
UART_EFR_ECB
);
serial_write_reg
(
uart
,
UART_LCR
,
0x0
);
/* Operational mode */
serial_write_reg
(
uart
,
UART_IER
,
0x0
);
serial_write_reg
(
uart
,
UART_LCR
,
0xBF
);
/* Config B mode */
serial_write_reg
(
uart
,
UART_DLL
,
uart
->
dll
);
serial_write_reg
(
uart
,
UART_DLM
,
uart
->
dlh
);
serial_write_reg
(
uart
,
UART_LCR
,
0x0
);
/* Operational mode */
serial_write_reg
(
uart
,
UART_IER
,
uart
->
ier
);
serial_write_reg
(
uart
,
UART_LCR
,
0x80
);
serial_write_reg
(
uart
,
UART_MCR
,
uart
->
mcr
);
serial_write_reg
(
uart
,
UART_LCR
,
0xBF
);
/* Config B mode */
serial_write_reg
(
uart
,
UART_EFR
,
efr
);
serial_write_reg
(
uart
,
UART_LCR
,
UART_LCR_WLEN8
);
serial_write_reg
(
uart
,
UART_OMAP_SCR
,
uart
->
scr
);
serial_write_reg
(
uart
,
UART_OMAP_WER
,
uart
->
wer
);
serial_write_reg
(
uart
,
UART_OMAP_SYSC
,
uart
->
sysc
);
if
(
uart
->
errata
&
UART_ERRATA_i202_MDR1_ACCESS
)
omap_uart_mdr1_errataset
(
uart
,
0x00
,
0xA1
);
else
serial_write_reg
(
p
,
UART_OMAP_MDR1
,
0x00
);
/* UART 16x mode */
/* UART 16x mode */
serial_write_reg
(
uart
,
UART_OMAP_MDR1
,
0x00
);
}
#else
static
inline
void
omap_uart_save_context
(
struct
omap_uart_state
*
uart
)
{}
...
...
@@ -295,8 +283,7 @@ static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
if
(
uart
->
clocked
)
return
;
clk_enable
(
uart
->
ick
);
clk_enable
(
uart
->
fck
);
omap_device_enable
(
uart
->
pdev
);
uart
->
clocked
=
1
;
omap_uart_restore_context
(
uart
);
}
...
...
@@ -310,8 +297,7 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
omap_uart_save_context
(
uart
);
uart
->
clocked
=
0
;
clk_disable
(
uart
->
ick
);
clk_disable
(
uart
->
fck
);
omap_device_idle
(
uart
->
pdev
);
}
static
void
omap_uart_enable_wakeup
(
struct
omap_uart_state
*
uart
)
...
...
@@ -349,18 +335,24 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
}
static
void
omap_uart_smart_idle_enable
(
struct
omap_uart_state
*
uart
,
int
enable
)
int
enable
)
{
struct
plat_serial8250_port
*
p
=
uart
->
p
;
u16
sysc
;
u8
idlemode
;
sysc
=
serial_read_reg
(
p
,
UART_OMAP_SYSC
)
&
0x7
;
if
(
enable
)
sysc
|=
0x2
<<
3
;
else
sysc
|=
0x1
<<
3
;
if
(
enable
)
{
/**
* Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
* in Smartidle Mode When Configured for DMA Operations.
*/
if
(
uart
->
dma_enabled
)
idlemode
=
HWMOD_IDLEMODE_FORCE
;
else
idlemode
=
HWMOD_IDLEMODE_SMART
;
}
else
{
idlemode
=
HWMOD_IDLEMODE_NO
;
}
serial_write_reg
(
p
,
UART_OMAP_SYSC
,
sysc
);
omap_hwmod_set_slave_idlemode
(
uart
->
oh
,
idlemode
);
}
static
void
omap_uart_block_sleep
(
struct
omap_uart_state
*
uart
)
...
...
@@ -377,7 +369,7 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
static
void
omap_uart_allow_sleep
(
struct
omap_uart_state
*
uart
)
{
if
(
device_may_wakeup
(
&
uart
->
pdev
.
dev
))
if
(
device_may_wakeup
(
&
uart
->
pdev
->
dev
))
omap_uart_enable_wakeup
(
uart
);
else
omap_uart_disable_wakeup
(
uart
);
...
...
@@ -472,6 +464,7 @@ int omap_uart_can_sleep(void)
* UART will not idle or sleep for its timeout period.
*
**/
/* static int first_interrupt; */
static
irqreturn_t
omap_uart_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
omap_uart_state
*
uart
=
dev_id
;
...
...
@@ -483,7 +476,6 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
static
void
omap_uart_idle_init
(
struct
omap_uart_state
*
uart
)
{
struct
plat_serial8250_port
*
p
=
uart
->
p
;
int
ret
;
uart
->
can_sleep
=
0
;
...
...
@@ -495,7 +487,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
omap_uart_smart_idle_enable
(
uart
,
0
);
if
(
cpu_is_omap34xx
())
{
u32
mod
=
(
uart
->
num
==
2
)
?
OMAP3430_PER_MOD
:
CORE_MOD
;
u32
mod
=
(
uart
->
num
>
1
)
?
OMAP3430_PER_MOD
:
CORE_MOD
;
u32
wk_mask
=
0
;
u32
padconf
=
0
;
...
...
@@ -514,6 +506,10 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
wk_mask
=
OMAP3430_ST_UART3_MASK
;
padconf
=
0x19e
;
break
;
case
3
:
wk_mask
=
OMAP3630_ST_UART4_MASK
;
padconf
=
0x0d2
;
break
;
}
uart
->
wk_mask
=
wk_mask
;
uart
->
padconf
=
padconf
;
...
...
@@ -546,9 +542,9 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
uart
->
padconf
=
0
;
}
p
->
irqflags
|=
IRQF_SHARED
;
ret
=
request_
irq
(
p
->
irq
,
omap_uart_interrupt
,
IRQF_SHARED
,
"serial idle"
,
(
void
*
)
uart
);
uart
->
irqflags
|=
IRQF_SHARED
;
ret
=
request_
threaded_irq
(
uart
->
irq
,
NULL
,
omap_uart_interrupt
,
IRQF_SHARED
,
"serial idle"
,
(
void
*
)
uart
);
WARN_ON
(
ret
);
}
...
...
@@ -558,11 +554,17 @@ void omap_uart_enable_irqs(int enable)
struct
omap_uart_state
*
uart
;
list_for_each_entry
(
uart
,
&
uart_list
,
node
)
{
if
(
enable
)
ret
=
request_irq
(
uart
->
p
->
irq
,
omap_uart_interrupt
,
IRQF_SHARED
,
"serial idle"
,
(
void
*
)
uart
);
else
free_irq
(
uart
->
p
->
irq
,
(
void
*
)
uart
);
if
(
enable
)
{
pm_runtime_put_sync
(
&
uart
->
pdev
->
dev
);
ret
=
request_threaded_irq
(
uart
->
irq
,
NULL
,
omap_uart_interrupt
,
IRQF_SHARED
,
"serial idle"
,
(
void
*
)
uart
);
}
else
{
pm_runtime_get_noresume
(
&
uart
->
pdev
->
dev
);
free_irq
(
uart
->
irq
,
(
void
*
)
uart
);
}
}
}
...
...
@@ -570,10 +572,9 @@ static ssize_t sleep_timeout_show(struct device *dev,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
platform_device
*
pdev
=
container_of
(
dev
,
struct
platform_device
,
dev
);
struct
omap_uart_state
*
uart
=
container_of
(
pdev
,
struct
omap_uart_state
,
pdev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
omap_device
*
odev
=
to_omap_device
(
pdev
);
struct
omap_uart_state
*
uart
=
odev
->
hwmods
[
0
]
->
dev_attr
;
return
sprintf
(
buf
,
"%u
\n
"
,
uart
->
timeout
/
HZ
);
}
...
...
@@ -582,10 +583,9 @@ static ssize_t sleep_timeout_store(struct device *dev,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
n
)
{
struct
platform_device
*
pdev
=
container_of
(
dev
,
struct
platform_device
,
dev
);
struct
omap_uart_state
*
uart
=
container_of
(
pdev
,
struct
omap_uart_state
,
pdev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
omap_device
*
odev
=
to_omap_device
(
pdev
);
struct
omap_uart_state
*
uart
=
odev
->
hwmods
[
0
]
->
dev_attr
;
unsigned
int
value
;
if
(
sscanf
(
buf
,
"%u"
,
&
value
)
!=
1
)
{
...
...
@@ -608,48 +608,11 @@ static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show,
#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
#else
static
inline
void
omap_uart_idle_init
(
struct
omap_uart_state
*
uart
)
{}
static
void
omap_uart_block_sleep
(
struct
omap_uart_state
*
uart
)
{}
#define DEV_CREATE_FILE(dev, attr)
#endif
/* CONFIG_PM */
static
struct
omap_uart_state
omap_uart
[]
=
{
{
.
pdev
=
{
.
name
=
"serial8250"
,
.
id
=
PLAT8250_DEV_PLATFORM
,
.
dev
=
{
.
platform_data
=
serial_platform_data0
,
},
},
},
{
.
pdev
=
{
.
name
=
"serial8250"
,
.
id
=
PLAT8250_DEV_PLATFORM1
,
.
dev
=
{
.
platform_data
=
serial_platform_data1
,
},
},
},
{
.
pdev
=
{
.
name
=
"serial8250"
,
.
id
=
PLAT8250_DEV_PLATFORM2
,
.
dev
=
{
.
platform_data
=
serial_platform_data2
,
},
},
},
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
{
.
pdev
=
{
.
name
=
"serial8250"
,
.
id
=
3
,
.
dev
=
{
.
platform_data
=
serial_platform_data3
,
},
},
},
#endif
};
#ifndef CONFIG_SERIAL_OMAP
/*
* Override the default 8250 read handler: mem_serial_in()
* Empty RX fifo read causes an abort on omap3630 and omap4
...
...
@@ -682,71 +645,44 @@ static void serial_out_override(struct uart_port *up, int offset, int value)
}
__serial_write_reg
(
up
,
offset
,
value
);
}
#endif
void
__init
omap_serial_early_init
(
void
)
{
int
i
,
nr_ports
;
char
name
[
16
];
int
i
=
0
;
if
(
!
(
cpu_is_omap3630
()
||
cpu_is_omap4430
()))
nr_ports
=
3
;
else
nr_ports
=
ARRAY_SIZE
(
omap_uart
)
;
do
{
char
oh_name
[
MAX_UART_HWMOD_NAME_LEN
]
;
struct
omap_hwmod
*
oh
;
struct
omap_uart_state
*
uart
;
/*
* Make sure the serial ports are muxed on at this point.
* You have to mux them off in device drivers later on
* if not needed.
*/
snprintf
(
oh_name
,
MAX_UART_HWMOD_NAME_LEN
,
"uart%d"
,
i
+
1
);
oh
=
omap_hwmod_lookup
(
oh_name
);
if
(
!
oh
)
break
;
for
(
i
=
0
;
i
<
nr_ports
;
i
++
)
{
struct
omap_uart_state
*
uart
=
&
omap_uart
[
i
];
struct
platform_device
*
pdev
=
&
uart
->
pdev
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
plat_serial8250_port
*
p
=
dev
->
platform_data
;
uart
=
kzalloc
(
sizeof
(
struct
omap_uart_state
),
GFP_KERNEL
);
if
(
WARN_ON
(
!
uart
))
return
;
uart
->
oh
=
oh
;
uart
->
num
=
i
++
;
list_add_tail
(
&
uart
->
node
,
&
uart_list
);
num_uarts
++
;
/* Don't map zero-based physical address */
if
(
p
->
mapbase
==
0
)
{
dev_warn
(
dev
,
"no physical address for uart#%d,"
" so skipping early_init...
\n
"
,
i
);
continue
;
}
/*
*
Module 4KB + L4 interconnect 4KB
*
Static mapping, never released
*
NOTE: omap_hwmod_init() has not yet been called,
*
so no hwmod functions will work yet.
*/
p
->
membase
=
ioremap
(
p
->
mapbase
,
SZ_8K
);
if
(
!
p
->
membase
)
{
dev_err
(
dev
,
"ioremap failed for uart%i
\n
"
,
i
+
1
);
continue
;
}
sprintf
(
name
,
"uart%d_ick"
,
i
+
1
);
uart
->
ick
=
clk_get
(
NULL
,
name
);
if
(
IS_ERR
(
uart
->
ick
))
{
dev_err
(
dev
,
"Could not get uart%d_ick
\n
"
,
i
+
1
);
uart
->
ick
=
NULL
;
}
sprintf
(
name
,
"uart%d_fck"
,
i
+
1
);
uart
->
fck
=
clk_get
(
NULL
,
name
);
if
(
IS_ERR
(
uart
->
fck
))
{
dev_err
(
dev
,
"Could not get uart%d_fck
\n
"
,
i
+
1
);
uart
->
fck
=
NULL
;
}
/* FIXME: Remove this once the clkdev is ready */
if
(
!
cpu_is_omap44xx
())
{
if
(
!
uart
->
ick
||
!
uart
->
fck
)
continue
;
}
uart
->
num
=
i
;
p
->
private_data
=
uart
;
uart
->
p
=
p
;
if
(
cpu_is_omap44xx
())
p
->
irq
+=
32
;
}
/*
* During UART early init, device need to be probed
* to determine SoC specific init before omap_device
* is ready. Therefore, don't allow idle here
*/
uart
->
oh
->
flags
|=
HWMOD_INIT_NO_IDLE
|
HWMOD_INIT_NO_RESET
;
}
while
(
1
);
}
/**
...
...
@@ -763,53 +699,135 @@ void __init omap_serial_early_init(void)
void
__init
omap_serial_init_port
(
int
port
)
{
struct
omap_uart_state
*
uart
;
struct
platform_device
*
pdev
;
struct
device
*
dev
;
BUG_ON
(
port
<
0
);
BUG_ON
(
port
>=
ARRAY_SIZE
(
omap_uart
));
uart
=
&
omap_uart
[
port
];
pdev
=
&
uart
->
pdev
;
dev
=
&
pdev
->
dev
;
struct
omap_hwmod
*
oh
;
struct
omap_device
*
od
;
void
*
pdata
=
NULL
;
u32
pdata_size
=
0
;
char
*
name
;
#ifndef CONFIG_SERIAL_OMAP
struct
plat_serial8250_port
ports
[
2
]
=
{
{},
{.
flags
=
0
},
};
struct
plat_serial8250_port
*
p
=
&
ports
[
0
];
#else
struct
omap_uart_port_info
omap_up
;
#endif
/* Don't proceed if there's no clocks available */
if
(
unlikely
(
!
uart
->
ick
||
!
uart
->
fck
))
{
WARN
(
1
,
"%s: can't init uart%d, no clocks available
\n
"
,
kobject_name
(
&
dev
->
kobj
),
port
);
if
(
WARN_ON
(
port
<
0
))
return
;
if
(
WARN_ON
(
port
>=
num_uarts
))
return
;
}
omap_uart_enable_clocks
(
uart
);
omap_uart_reset
(
uart
);
omap_uart_idle_init
(
uart
);
list_add_tail
(
&
uart
->
node
,
&
uart_list
);
list_for_each_entry
(
uart
,
&
uart_list
,
node
)
if
(
port
==
uart
->
num
)
break
;
if
(
WARN_ON
(
platform_device_register
(
pdev
)))
return
;
oh
=
uart
->
oh
;
uart
->
dma_enabled
=
0
;
#ifndef CONFIG_SERIAL_OMAP
name
=
"serial8250"
;
if
((
cpu_is_omap34xx
()
&&
uart
->
padconf
)
||
(
uart
->
wk_en
&&
uart
->
wk_mask
))
{
device_init_wakeup
(
dev
,
true
);
DEV_CREATE_FILE
(
dev
,
&
dev_attr_sleep_timeout
);
}
/*
* !! 8250 driver does not use standard IORESOURCE* It
* has it's own custom pdata that can be taken from
* the hwmod resource data. But, this needs to be
* done after the build.
*
* ?? does it have to be done before the register ??
* YES, because platform_device_data_add() copies
* pdata, it does not use a pointer.
*/
p
->
flags
=
UPF_BOOT_AUTOCONF
;
p
->
iotype
=
UPIO_MEM
;
p
->
regshift
=
2
;
p
->
uartclk
=
OMAP24XX_BASE_BAUD
*
16
;
p
->
irq
=
oh
->
mpu_irqs
[
0
].
irq
;
p
->
mapbase
=
oh
->
slaves
[
0
]
->
addr
->
pa_start
;
p
->
membase
=
omap_hwmod_get_mpu_rt_va
(
oh
);
p
->
irqflags
=
IRQF_SHARED
;
p
->
private_data
=
uart
;
/*
* omap44xx: Never read empty UART fifo
* omap3xxx: Never read empty UART fifo on UARTs
* with IP rev >=0x52
*/
uart
->
regshift
=
p
->
regshift
;
uart
->
membase
=
p
->
membase
;
if
(
cpu_is_omap44xx
())
uart
->
errata
|=
UART_ERRATA_FIFO_FULL_ABORT
;
else
if
((
serial_read_reg
(
uart
->
p
,
UART_OMAP_MVER
)
&
0xFF
)
else
if
((
serial_read_reg
(
uart
,
UART_OMAP_MVER
)
&
0xFF
)
>=
UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV
)
uart
->
errata
|=
UART_ERRATA_FIFO_FULL_ABORT
;
if
(
uart
->
errata
&
UART_ERRATA_FIFO_FULL_ABORT
)
{
uart
->
p
->
serial_in
=
serial_in_override
;
uart
->
p
->
serial_out
=
serial_out_override
;
p
->
serial_in
=
serial_in_override
;
p
->
serial_out
=
serial_out_override
;
}
pdata
=
&
ports
[
0
];
pdata_size
=
2
*
sizeof
(
struct
plat_serial8250_port
);
#else
name
=
DRIVER_NAME
;
omap_up
.
dma_enabled
=
uart
->
dma_enabled
;
omap_up
.
uartclk
=
OMAP24XX_BASE_BAUD
*
16
;
omap_up
.
mapbase
=
oh
->
slaves
[
0
]
->
addr
->
pa_start
;
omap_up
.
membase
=
omap_hwmod_get_mpu_rt_va
(
oh
);
omap_up
.
irqflags
=
IRQF_SHARED
;
omap_up
.
flags
=
UPF_BOOT_AUTOCONF
|
UPF_SHARE_IRQ
;
pdata
=
&
omap_up
;
pdata_size
=
sizeof
(
struct
omap_uart_port_info
);
#endif
if
(
WARN_ON
(
!
oh
))
return
;
od
=
omap_device_build
(
name
,
uart
->
num
,
oh
,
pdata
,
pdata_size
,
omap_uart_latency
,
ARRAY_SIZE
(
omap_uart_latency
),
false
);
WARN
(
IS_ERR
(
od
),
"Could not build omap_device for %s: %s.
\n
"
,
name
,
oh
->
name
);
uart
->
irq
=
oh
->
mpu_irqs
[
0
].
irq
;
uart
->
regshift
=
2
;
uart
->
mapbase
=
oh
->
slaves
[
0
]
->
addr
->
pa_start
;
uart
->
membase
=
omap_hwmod_get_mpu_rt_va
(
oh
);
uart
->
pdev
=
&
od
->
pdev
;
oh
->
dev_attr
=
uart
;
/*
* Because of early UART probing, UART did not get idled
* on init. Now that omap_device is ready, ensure full idle
* before doing omap_device_enable().
*/
omap_hwmod_idle
(
uart
->
oh
);
omap_device_enable
(
uart
->
pdev
);
omap_uart_idle_init
(
uart
);
omap_uart_reset
(
uart
);
omap_hwmod_enable_wakeup
(
uart
->
oh
);
omap_device_idle
(
uart
->
pdev
);
/*
* Need to block sleep long enough for interrupt driven
* driver to start. Console driver is in polling mode
* so device needs to be kept enabled while polling driver
* is in use.
*/
if
(
uart
->
timeout
)
uart
->
timeout
=
(
30
*
HZ
);
omap_uart_block_sleep
(
uart
);
uart
->
timeout
=
DEFAULT_TIMEOUT
;
if
((
cpu_is_omap34xx
()
&&
uart
->
padconf
)
||
(
uart
->
wk_en
&&
uart
->
wk_mask
))
{
device_init_wakeup
(
&
od
->
pdev
.
dev
,
true
);
DEV_CREATE_FILE
(
&
od
->
pdev
.
dev
,
&
dev_attr_sleep_timeout
);
}
/* Enable the MDR1 errata for OMAP3 */
...
...
@@ -826,13 +844,8 @@ void __init omap_serial_init_port(int port)
*/
void
__init
omap_serial_init
(
void
)
{
int
i
,
nr_ports
;
if
(
!
(
cpu_is_omap3630
()
||
cpu_is_omap4430
()))
nr_ports
=
3
;
else
nr_ports
=
ARRAY_SIZE
(
omap_uart
);
struct
omap_uart_state
*
uart
;
for
(
i
=
0
;
i
<
nr_ports
;
i
++
)
omap_serial_init_port
(
i
);
list_for_each_entry
(
uart
,
&
uart_list
,
node
)
omap_serial_init_port
(
uart
->
num
);
}
arch/arm/plat-omap/common.c
View file @
69758ab7
...
...
@@ -257,7 +257,6 @@ static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
omap2_set_globals_sdrc
(
omap2_globals
);
omap2_set_globals_control
(
omap2_globals
);
omap2_set_globals_prcm
(
omap2_globals
);
omap2_set_globals_uart
(
omap2_globals
);
}
#endif
...
...
@@ -272,9 +271,6 @@ static struct omap_globals omap242x_globals = {
.
ctrl
=
OMAP2420_CTRL_BASE
,
.
prm
=
OMAP2420_PRM_BASE
,
.
cm
=
OMAP2420_CM_BASE
,
.
uart1_phys
=
OMAP2_UART1_BASE
,
.
uart2_phys
=
OMAP2_UART2_BASE
,
.
uart3_phys
=
OMAP2_UART3_BASE
,
};
void
__init
omap2_set_globals_242x
(
void
)
...
...
@@ -293,9 +289,6 @@ static struct omap_globals omap243x_globals = {
.
ctrl
=
OMAP243X_CTRL_BASE
,
.
prm
=
OMAP2430_PRM_BASE
,
.
cm
=
OMAP2430_CM_BASE
,
.
uart1_phys
=
OMAP2_UART1_BASE
,
.
uart2_phys
=
OMAP2_UART2_BASE
,
.
uart3_phys
=
OMAP2_UART3_BASE
,
};
void
__init
omap2_set_globals_243x
(
void
)
...
...
@@ -314,10 +307,6 @@ static struct omap_globals omap3_globals = {
.
ctrl
=
OMAP343X_CTRL_BASE
,
.
prm
=
OMAP3430_PRM_BASE
,
.
cm
=
OMAP3430_CM_BASE
,
.
uart1_phys
=
OMAP3_UART1_BASE
,
.
uart2_phys
=
OMAP3_UART2_BASE
,
.
uart3_phys
=
OMAP3_UART3_BASE
,
.
uart4_phys
=
OMAP3_UART4_BASE
,
/* Only on 3630 */
};
void
__init
omap2_set_globals_3xxx
(
void
)
...
...
@@ -341,10 +330,6 @@ static struct omap_globals omap4_globals = {
.
prm
=
OMAP4430_PRM_BASE
,
.
cm
=
OMAP4430_CM_BASE
,
.
cm2
=
OMAP4430_CM2_BASE
,
.
uart1_phys
=
OMAP4_UART1_BASE
,
.
uart2_phys
=
OMAP4_UART2_BASE
,
.
uart3_phys
=
OMAP4_UART3_BASE
,
.
uart4_phys
=
OMAP4_UART4_BASE
,
};
void
__init
omap2_set_globals_443x
(
void
)
...
...
@@ -352,7 +337,6 @@ void __init omap2_set_globals_443x(void)
omap2_set_globals_tap
(
&
omap4_globals
);
omap2_set_globals_control
(
&
omap4_globals
);
omap2_set_globals_prcm
(
&
omap4_globals
);
omap2_set_globals_uart
(
&
omap4_globals
);
}
#endif
arch/arm/plat-omap/include/plat/common.h
View file @
69758ab7
...
...
@@ -67,7 +67,6 @@ void omap2_set_globals_tap(struct omap_globals *);
void
omap2_set_globals_sdrc
(
struct
omap_globals
*
);
void
omap2_set_globals_control
(
struct
omap_globals
*
);
void
omap2_set_globals_prcm
(
struct
omap_globals
*
);
void
omap2_set_globals_uart
(
struct
omap_globals
*
);
void
omap3_map_io
(
void
);
...
...
arch/arm/plat-omap/include/plat/dma.h
View file @
69758ab7
...
...
@@ -319,6 +319,8 @@
#define OMAP34XX_DMA_USIM_TX 79
/* S_DMA_78 */
#define OMAP34XX_DMA_USIM_RX 80
/* S_DMA_79 */
#define OMAP36XX_DMA_UART4_TX 81
/* S_DMA_80 */
#define OMAP36XX_DMA_UART4_RX 82
/* S_DMA_81 */
/*----------------------------------------------------------------------------*/
#define OMAP1_DMA_TOUT_IRQ (1 << 0)
...
...
arch/arm/plat-omap/include/plat/irqs.h
View file @
69758ab7
...
...
@@ -345,6 +345,8 @@
#define INT_34XX_MMC3_IRQ 94
#define INT_34XX_GPT12_IRQ 95
#define INT_36XX_UART4_IRQ 80
#define INT_35XX_HECC0_IRQ 24
#define INT_35XX_HECC1_IRQ 28
#define INT_35XX_EMAC_C0_RXTHRESH_IRQ 67
...
...
arch/arm/plat-omap/include/plat/omap-serial.h
0 → 100644
View file @
69758ab7
/*
* Driver for OMAP-UART controller.
* Based on drivers/serial/8250.c
*
* Copyright (C) 2010 Texas Instruments.
*
* Authors:
* Govindraj R <govindraj.raja@ti.com>
* Thara Gopinath <thara@ti.com>
*
* This program 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 of the License, or
* (at your option) any later version.
*/
#ifndef __OMAP_SERIAL_H__
#define __OMAP_SERIAL_H__
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <plat/control.h>
#include <plat/mux.h>
#define DRIVER_NAME "omap-hsuart"
/*
* Use tty device name as ttyO, [O -> OMAP]
* in bootargs we specify as console=ttyO0 if uart1
* is used as console uart.
*/
#define OMAP_SERIAL_NAME "ttyO"
#define OMAP_MDR1_DISABLE 0x07
#define OMAP_MDR1_MODE13X 0x03
#define OMAP_MDR1_MODE16X 0x00
#define OMAP_MODE13X_SPEED 230400
/*
* LCR = 0XBF: Switch to Configuration Mode B.
* In configuration mode b allow access
* to EFR,DLL,DLH.
* Reference OMAP TRM Chapter 17
* Section: 1.4.3 Mode Selection
*/
#define OMAP_UART_LCR_CONF_MDB 0XBF
/* WER = 0x7F
* Enable module level wakeup in WER reg
*/
#define OMAP_UART_WER_MOD_WKUP 0X7F
/* Enable XON/XOFF flow control on output */
#define OMAP_UART_SW_TX 0x04
/* Enable XON/XOFF flow control on input */
#define OMAP_UART_SW_RX 0x04
#define OMAP_UART_SYSC_RESET 0X07
#define OMAP_UART_TCR_TRIG 0X0F
#define OMAP_UART_SW_CLR 0XF0
#define OMAP_UART_FIFO_CLR 0X06
#define OMAP_UART_DMA_CH_FREE -1
#define RX_TIMEOUT (3 * HZ)
#define OMAP_MAX_HSUART_PORTS 4
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
struct
omap_uart_port_info
{
bool
dma_enabled
;
/* To specify DMA Mode */
unsigned
int
uartclk
;
/* UART clock rate */
void
__iomem
*
membase
;
/* ioremap cookie or NULL */
resource_size_t
mapbase
;
/* resource base */
unsigned
long
irqflags
;
/* request_irq flags */
upf_t
flags
;
/* UPF_* flags */
};
struct
uart_omap_dma
{
u8
uart_dma_tx
;
u8
uart_dma_rx
;
int
rx_dma_channel
;
int
tx_dma_channel
;
dma_addr_t
rx_buf_dma_phys
;
dma_addr_t
tx_buf_dma_phys
;
unsigned
int
uart_base
;
/*
* Buffer for rx dma.It is not required for tx because the buffer
* comes from port structure.
*/
unsigned
char
*
rx_buf
;
unsigned
int
prev_rx_dma_pos
;
int
tx_buf_size
;
int
tx_dma_used
;
int
rx_dma_used
;
spinlock_t
tx_lock
;
spinlock_t
rx_lock
;
/* timer to poll activity on rx dma */
struct
timer_list
rx_timer
;
int
rx_buf_size
;
int
rx_timeout
;
};
struct
uart_omap_port
{
struct
uart_port
port
;
struct
uart_omap_dma
uart_dma
;
struct
platform_device
*
pdev
;
unsigned
char
ier
;
unsigned
char
lcr
;
unsigned
char
mcr
;
unsigned
char
fcr
;
unsigned
char
efr
;
int
use_dma
;
/*
* Some bits in registers are cleared on a read, so they must
* be saved whenever the register is read but the bits will not
* be immediately processed.
*/
unsigned
int
lsr_break_flag
;
unsigned
char
msr_saved_flags
;
char
name
[
20
];
unsigned
long
port_activity
;
};
#endif
/* __OMAP_SERIAL_H__ */
drivers/serial/Kconfig
View file @
69758ab7
...
...
@@ -1416,6 +1416,33 @@ config SERIAL_OF_PLATFORM
Currently, only 8250 compatible ports are supported, but
others can easily be added.
config SERIAL_OMAP
tristate "OMAP serial port support"
depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4
select SERIAL_CORE
help
If you have a machine based on an Texas Instruments OMAP CPU you
can enable its onboard serial ports by enabling this option.
By enabling this option you take advantage of dma feature available
with the omap-serial driver. DMA support can be enabled from platform
data.
config SERIAL_OMAP_CONSOLE
bool "Console on OMAP serial port"
depends on SERIAL_OMAP
select SERIAL_CORE_CONSOLE
help
Select this option if you would like to use omap serial port as
console.
Even if you say Y here, the currently visible virtual console
(/dev/tty0) will still be used as the system console by default, but
you can alter that using a kernel command line option such as
"console=ttyOx". (Try "man bootparam" or see the documentation of
your boot loader about how to pass options to the kernel at
boot time.)
config SERIAL_OF_PLATFORM_NWPSERIAL
tristate "NWP serial port driver"
depends on PPC_OF && PPC_DCR
...
...
drivers/serial/Makefile
View file @
69758ab7
...
...
@@ -88,3 +88,4 @@ obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
obj-$(CONFIG_SERIAL_ALTERA_UART)
+=
altera_uart.o
obj-$(CONFIG_SERIAL_MRST_MAX3110)
+=
mrst_max3110.o
obj-$(CONFIG_SERIAL_MFD_HSU)
+=
mfd.o
obj-$(CONFIG_SERIAL_OMAP)
+=
omap-serial.o
drivers/serial/omap-serial.c
0 → 100644
View file @
69758ab7
/*
* Driver for OMAP-UART controller.
* Based on drivers/serial/8250.c
*
* Copyright (C) 2010 Texas Instruments.
*
* Authors:
* Govindraj R <govindraj.raja@ti.com>
* Thara Gopinath <thara@ti.com>
*
* This program 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 of the License, or
* (at your option) any later version.
*
* Note: This driver is made seperate from 8250 driver as we cannot
* over load 8250 driver with omap platform specific configuration for
* features like DMA, it makes easier to implement features like DMA and
* hardware flow control and software flow control configuration with
* this driver as required for the omap-platform.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/serial_reg.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
#include <plat/dma.h>
#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
static
struct
uart_omap_port
*
ui
[
OMAP_MAX_HSUART_PORTS
];
/* Forward declaration of functions */
static
void
uart_tx_dma_callback
(
int
lch
,
u16
ch_status
,
void
*
data
);
static
void
serial_omap_rx_timeout
(
unsigned
long
uart_no
);
static
int
serial_omap_start_rxdma
(
struct
uart_omap_port
*
up
);
static
inline
unsigned
int
serial_in
(
struct
uart_omap_port
*
up
,
int
offset
)
{
offset
<<=
up
->
port
.
regshift
;
return
readw
(
up
->
port
.
membase
+
offset
);
}
static
inline
void
serial_out
(
struct
uart_omap_port
*
up
,
int
offset
,
int
value
)
{
offset
<<=
up
->
port
.
regshift
;
writew
(
value
,
up
->
port
.
membase
+
offset
);
}
static
inline
void
serial_omap_clear_fifos
(
struct
uart_omap_port
*
up
)
{
serial_out
(
up
,
UART_FCR
,
UART_FCR_ENABLE_FIFO
);
serial_out
(
up
,
UART_FCR
,
UART_FCR_ENABLE_FIFO
|
UART_FCR_CLEAR_RCVR
|
UART_FCR_CLEAR_XMIT
);
serial_out
(
up
,
UART_FCR
,
0
);
}
/*
* serial_omap_get_divisor - calculate divisor value
* @port: uart port info
* @baud: baudrate for which divisor needs to be calculated.
*
* We have written our own function to get the divisor so as to support
* 13x mode. 3Mbps Baudrate as an different divisor.
* Reference OMAP TRM Chapter 17:
* Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
* referring to oversampling - divisor value
* baudrate 460,800 to 3,686,400 all have divisor 13
* except 3,000,000 which has divisor value 16
*/
static
unsigned
int
serial_omap_get_divisor
(
struct
uart_port
*
port
,
unsigned
int
baud
)
{
unsigned
int
divisor
;
if
(
baud
>
OMAP_MODE13X_SPEED
&&
baud
!=
3000000
)
divisor
=
13
;
else
divisor
=
16
;
return
port
->
uartclk
/
(
baud
*
divisor
);
}
static
void
serial_omap_stop_rxdma
(
struct
uart_omap_port
*
up
)
{
if
(
up
->
uart_dma
.
rx_dma_used
)
{
del_timer
(
&
up
->
uart_dma
.
rx_timer
);
omap_stop_dma
(
up
->
uart_dma
.
rx_dma_channel
);
omap_free_dma
(
up
->
uart_dma
.
rx_dma_channel
);
up
->
uart_dma
.
rx_dma_channel
=
OMAP_UART_DMA_CH_FREE
;
up
->
uart_dma
.
rx_dma_used
=
false
;
}
}
static
void
serial_omap_enable_ms
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_enable_ms+%d
\n
"
,
up
->
pdev
->
id
);
up
->
ier
|=
UART_IER_MSI
;
serial_out
(
up
,
UART_IER
,
up
->
ier
);
}
static
void
serial_omap_stop_tx
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
if
(
up
->
use_dma
&&
up
->
uart_dma
.
tx_dma_channel
!=
OMAP_UART_DMA_CH_FREE
)
{
/*
* Check if dma is still active. If yes do nothing,
* return. Else stop dma
*/
if
(
omap_get_dma_active_status
(
up
->
uart_dma
.
tx_dma_channel
))
return
;
omap_stop_dma
(
up
->
uart_dma
.
tx_dma_channel
);
omap_free_dma
(
up
->
uart_dma
.
tx_dma_channel
);
up
->
uart_dma
.
tx_dma_channel
=
OMAP_UART_DMA_CH_FREE
;
}
if
(
up
->
ier
&
UART_IER_THRI
)
{
up
->
ier
&=
~
UART_IER_THRI
;
serial_out
(
up
,
UART_IER
,
up
->
ier
);
}
}
static
void
serial_omap_stop_rx
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
if
(
up
->
use_dma
)
serial_omap_stop_rxdma
(
up
);
up
->
ier
&=
~
UART_IER_RLSI
;
up
->
port
.
read_status_mask
&=
~
UART_LSR_DR
;
serial_out
(
up
,
UART_IER
,
up
->
ier
);
}
static
inline
void
receive_chars
(
struct
uart_omap_port
*
up
,
int
*
status
)
{
struct
tty_struct
*
tty
=
up
->
port
.
state
->
port
.
tty
;
unsigned
int
flag
;
unsigned
char
ch
,
lsr
=
*
status
;
int
max_count
=
256
;
do
{
if
(
likely
(
lsr
&
UART_LSR_DR
))
ch
=
serial_in
(
up
,
UART_RX
);
flag
=
TTY_NORMAL
;
up
->
port
.
icount
.
rx
++
;
if
(
unlikely
(
lsr
&
UART_LSR_BRK_ERROR_BITS
))
{
/*
* For statistics only
*/
if
(
lsr
&
UART_LSR_BI
)
{
lsr
&=
~
(
UART_LSR_FE
|
UART_LSR_PE
);
up
->
port
.
icount
.
brk
++
;
/*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
* or read_status_mask.
*/
if
(
uart_handle_break
(
&
up
->
port
))
goto
ignore_char
;
}
else
if
(
lsr
&
UART_LSR_PE
)
{
up
->
port
.
icount
.
parity
++
;
}
else
if
(
lsr
&
UART_LSR_FE
)
{
up
->
port
.
icount
.
frame
++
;
}
if
(
lsr
&
UART_LSR_OE
)
up
->
port
.
icount
.
overrun
++
;
/*
* Mask off conditions which should be ignored.
*/
lsr
&=
up
->
port
.
read_status_mask
;
#ifdef CONFIG_SERIAL_OMAP_CONSOLE
if
(
up
->
port
.
line
==
up
->
port
.
cons
->
index
)
{
/* Recover the break flag from console xmit */
lsr
|=
up
->
lsr_break_flag
;
up
->
lsr_break_flag
=
0
;
}
#endif
if
(
lsr
&
UART_LSR_BI
)
flag
=
TTY_BREAK
;
else
if
(
lsr
&
UART_LSR_PE
)
flag
=
TTY_PARITY
;
else
if
(
lsr
&
UART_LSR_FE
)
flag
=
TTY_FRAME
;
}
if
(
uart_handle_sysrq_char
(
&
up
->
port
,
ch
))
goto
ignore_char
;
uart_insert_char
(
&
up
->
port
,
lsr
,
UART_LSR_OE
,
ch
,
flag
);
ignore_char:
lsr
=
serial_in
(
up
,
UART_LSR
);
}
while
((
lsr
&
(
UART_LSR_DR
|
UART_LSR_BI
))
&&
(
max_count
--
>
0
));
spin_unlock
(
&
up
->
port
.
lock
);
tty_flip_buffer_push
(
tty
);
spin_lock
(
&
up
->
port
.
lock
);
}
static
void
transmit_chars
(
struct
uart_omap_port
*
up
)
{
struct
circ_buf
*
xmit
=
&
up
->
port
.
state
->
xmit
;
int
count
;
if
(
up
->
port
.
x_char
)
{
serial_out
(
up
,
UART_TX
,
up
->
port
.
x_char
);
up
->
port
.
icount
.
tx
++
;
up
->
port
.
x_char
=
0
;
return
;
}
if
(
uart_circ_empty
(
xmit
)
||
uart_tx_stopped
(
&
up
->
port
))
{
serial_omap_stop_tx
(
&
up
->
port
);
return
;
}
count
=
up
->
port
.
fifosize
/
4
;
do
{
serial_out
(
up
,
UART_TX
,
xmit
->
buf
[
xmit
->
tail
]);
xmit
->
tail
=
(
xmit
->
tail
+
1
)
&
(
UART_XMIT_SIZE
-
1
);
up
->
port
.
icount
.
tx
++
;
if
(
uart_circ_empty
(
xmit
))
break
;
}
while
(
--
count
>
0
);
if
(
uart_circ_chars_pending
(
xmit
)
<
WAKEUP_CHARS
)
uart_write_wakeup
(
&
up
->
port
);
if
(
uart_circ_empty
(
xmit
))
serial_omap_stop_tx
(
&
up
->
port
);
}
static
inline
void
serial_omap_enable_ier_thri
(
struct
uart_omap_port
*
up
)
{
if
(
!
(
up
->
ier
&
UART_IER_THRI
))
{
up
->
ier
|=
UART_IER_THRI
;
serial_out
(
up
,
UART_IER
,
up
->
ier
);
}
}
static
void
serial_omap_start_tx
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
struct
circ_buf
*
xmit
;
unsigned
int
start
;
int
ret
=
0
;
if
(
!
up
->
use_dma
)
{
serial_omap_enable_ier_thri
(
up
);
return
;
}
if
(
up
->
uart_dma
.
tx_dma_used
)
return
;
xmit
=
&
up
->
port
.
state
->
xmit
;
if
(
up
->
uart_dma
.
tx_dma_channel
==
OMAP_UART_DMA_CH_FREE
)
{
ret
=
omap_request_dma
(
up
->
uart_dma
.
uart_dma_tx
,
"UART Tx DMA"
,
(
void
*
)
uart_tx_dma_callback
,
up
,
&
(
up
->
uart_dma
.
tx_dma_channel
));
if
(
ret
<
0
)
{
serial_omap_enable_ier_thri
(
up
);
return
;
}
}
spin_lock
(
&
(
up
->
uart_dma
.
tx_lock
));
up
->
uart_dma
.
tx_dma_used
=
true
;
spin_unlock
(
&
(
up
->
uart_dma
.
tx_lock
));
start
=
up
->
uart_dma
.
tx_buf_dma_phys
+
(
xmit
->
tail
&
(
UART_XMIT_SIZE
-
1
));
up
->
uart_dma
.
tx_buf_size
=
uart_circ_chars_pending
(
xmit
);
/*
* It is a circular buffer. See if the buffer has wounded back.
* If yes it will have to be transferred in two separate dma
* transfers
*/
if
(
start
+
up
->
uart_dma
.
tx_buf_size
>=
up
->
uart_dma
.
tx_buf_dma_phys
+
UART_XMIT_SIZE
)
up
->
uart_dma
.
tx_buf_size
=
(
up
->
uart_dma
.
tx_buf_dma_phys
+
UART_XMIT_SIZE
)
-
start
;
omap_set_dma_dest_params
(
up
->
uart_dma
.
tx_dma_channel
,
0
,
OMAP_DMA_AMODE_CONSTANT
,
up
->
uart_dma
.
uart_base
,
0
,
0
);
omap_set_dma_src_params
(
up
->
uart_dma
.
tx_dma_channel
,
0
,
OMAP_DMA_AMODE_POST_INC
,
start
,
0
,
0
);
omap_set_dma_transfer_params
(
up
->
uart_dma
.
tx_dma_channel
,
OMAP_DMA_DATA_TYPE_S8
,
up
->
uart_dma
.
tx_buf_size
,
1
,
OMAP_DMA_SYNC_ELEMENT
,
up
->
uart_dma
.
uart_dma_tx
,
0
);
/* FIXME: Cache maintenance needed here? */
omap_start_dma
(
up
->
uart_dma
.
tx_dma_channel
);
}
static
unsigned
int
check_modem_status
(
struct
uart_omap_port
*
up
)
{
unsigned
int
status
;
status
=
serial_in
(
up
,
UART_MSR
);
status
|=
up
->
msr_saved_flags
;
up
->
msr_saved_flags
=
0
;
if
((
status
&
UART_MSR_ANY_DELTA
)
==
0
)
return
status
;
if
(
status
&
UART_MSR_ANY_DELTA
&&
up
->
ier
&
UART_IER_MSI
&&
up
->
port
.
state
!=
NULL
)
{
if
(
status
&
UART_MSR_TERI
)
up
->
port
.
icount
.
rng
++
;
if
(
status
&
UART_MSR_DDSR
)
up
->
port
.
icount
.
dsr
++
;
if
(
status
&
UART_MSR_DDCD
)
uart_handle_dcd_change
(
&
up
->
port
,
status
&
UART_MSR_DCD
);
if
(
status
&
UART_MSR_DCTS
)
uart_handle_cts_change
(
&
up
->
port
,
status
&
UART_MSR_CTS
);
wake_up_interruptible
(
&
up
->
port
.
state
->
port
.
delta_msr_wait
);
}
return
status
;
}
/**
* serial_omap_irq() - This handles the interrupt from one port
* @irq: uart port irq number
* @dev_id: uart port info
*/
static
inline
irqreturn_t
serial_omap_irq
(
int
irq
,
void
*
dev_id
)
{
struct
uart_omap_port
*
up
=
dev_id
;
unsigned
int
iir
,
lsr
;
unsigned
long
flags
;
iir
=
serial_in
(
up
,
UART_IIR
);
if
(
iir
&
UART_IIR_NO_INT
)
return
IRQ_NONE
;
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
lsr
=
serial_in
(
up
,
UART_LSR
);
if
(
iir
&
UART_IIR_RLSI
)
{
if
(
!
up
->
use_dma
)
{
if
(
lsr
&
UART_LSR_DR
)
receive_chars
(
up
,
&
lsr
);
}
else
{
up
->
ier
&=
~
(
UART_IER_RDI
|
UART_IER_RLSI
);
serial_out
(
up
,
UART_IER
,
up
->
ier
);
if
((
serial_omap_start_rxdma
(
up
)
!=
0
)
&&
(
lsr
&
UART_LSR_DR
))
receive_chars
(
up
,
&
lsr
);
}
}
check_modem_status
(
up
);
if
((
lsr
&
UART_LSR_THRE
)
&&
(
iir
&
UART_IIR_THRI
))
transmit_chars
(
up
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
up
->
port_activity
=
jiffies
;
return
IRQ_HANDLED
;
}
static
unsigned
int
serial_omap_tx_empty
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
long
flags
=
0
;
unsigned
int
ret
=
0
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_tx_empty+%d
\n
"
,
up
->
pdev
->
id
);
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
ret
=
serial_in
(
up
,
UART_LSR
)
&
UART_LSR_TEMT
?
TIOCSER_TEMT
:
0
;
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
return
ret
;
}
static
unsigned
int
serial_omap_get_mctrl
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
char
status
;
unsigned
int
ret
=
0
;
status
=
check_modem_status
(
up
);
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_get_mctrl+%d
\n
"
,
up
->
pdev
->
id
);
if
(
status
&
UART_MSR_DCD
)
ret
|=
TIOCM_CAR
;
if
(
status
&
UART_MSR_RI
)
ret
|=
TIOCM_RNG
;
if
(
status
&
UART_MSR_DSR
)
ret
|=
TIOCM_DSR
;
if
(
status
&
UART_MSR_CTS
)
ret
|=
TIOCM_CTS
;
return
ret
;
}
static
void
serial_omap_set_mctrl
(
struct
uart_port
*
port
,
unsigned
int
mctrl
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
char
mcr
=
0
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_set_mctrl+%d
\n
"
,
up
->
pdev
->
id
);
if
(
mctrl
&
TIOCM_RTS
)
mcr
|=
UART_MCR_RTS
;
if
(
mctrl
&
TIOCM_DTR
)
mcr
|=
UART_MCR_DTR
;
if
(
mctrl
&
TIOCM_OUT1
)
mcr
|=
UART_MCR_OUT1
;
if
(
mctrl
&
TIOCM_OUT2
)
mcr
|=
UART_MCR_OUT2
;
if
(
mctrl
&
TIOCM_LOOP
)
mcr
|=
UART_MCR_LOOP
;
mcr
|=
up
->
mcr
;
serial_out
(
up
,
UART_MCR
,
mcr
);
}
static
void
serial_omap_break_ctl
(
struct
uart_port
*
port
,
int
break_state
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
long
flags
=
0
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_break_ctl+%d
\n
"
,
up
->
pdev
->
id
);
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
if
(
break_state
==
-
1
)
up
->
lcr
|=
UART_LCR_SBC
;
else
up
->
lcr
&=
~
UART_LCR_SBC
;
serial_out
(
up
,
UART_LCR
,
up
->
lcr
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
}
static
int
serial_omap_startup
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
long
flags
=
0
;
int
retval
;
/*
* Allocate the IRQ
*/
retval
=
request_irq
(
up
->
port
.
irq
,
serial_omap_irq
,
up
->
port
.
irqflags
,
up
->
name
,
up
);
if
(
retval
)
return
retval
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_startup+%d
\n
"
,
up
->
pdev
->
id
);
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
*/
serial_omap_clear_fifos
(
up
);
/* For Hardware flow control */
serial_out
(
up
,
UART_MCR
,
UART_MCR_RTS
);
/*
* Clear the interrupt registers.
*/
(
void
)
serial_in
(
up
,
UART_LSR
);
if
(
serial_in
(
up
,
UART_LSR
)
&
UART_LSR_DR
)
(
void
)
serial_in
(
up
,
UART_RX
);
(
void
)
serial_in
(
up
,
UART_IIR
);
(
void
)
serial_in
(
up
,
UART_MSR
);
/*
* Now, initialize the UART
*/
serial_out
(
up
,
UART_LCR
,
UART_LCR_WLEN8
);
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
/*
* Most PC uarts need OUT2 raised to enable interrupts.
*/
up
->
port
.
mctrl
|=
TIOCM_OUT2
;
serial_omap_set_mctrl
(
&
up
->
port
,
up
->
port
.
mctrl
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
up
->
msr_saved_flags
=
0
;
if
(
up
->
use_dma
)
{
free_page
((
unsigned
long
)
up
->
port
.
state
->
xmit
.
buf
);
up
->
port
.
state
->
xmit
.
buf
=
dma_alloc_coherent
(
NULL
,
UART_XMIT_SIZE
,
(
dma_addr_t
*
)
&
(
up
->
uart_dma
.
tx_buf_dma_phys
),
0
);
init_timer
(
&
(
up
->
uart_dma
.
rx_timer
));
up
->
uart_dma
.
rx_timer
.
function
=
serial_omap_rx_timeout
;
up
->
uart_dma
.
rx_timer
.
data
=
up
->
pdev
->
id
;
/* Currently the buffer size is 4KB. Can increase it */
up
->
uart_dma
.
rx_buf
=
dma_alloc_coherent
(
NULL
,
up
->
uart_dma
.
rx_buf_size
,
(
dma_addr_t
*
)
&
(
up
->
uart_dma
.
rx_buf_dma_phys
),
0
);
}
/*
* Finally, enable interrupts. Note: Modem status interrupts
* are set via set_termios(), which will be occurring imminently
* anyway, so we don't enable them here.
*/
up
->
ier
=
UART_IER_RLSI
|
UART_IER_RDI
;
serial_out
(
up
,
UART_IER
,
up
->
ier
);
up
->
port_activity
=
jiffies
;
return
0
;
}
static
void
serial_omap_shutdown
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
long
flags
=
0
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_shutdown+%d
\n
"
,
up
->
pdev
->
id
);
/*
* Disable interrupts from this port
*/
up
->
ier
=
0
;
serial_out
(
up
,
UART_IER
,
0
);
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
up
->
port
.
mctrl
&=
~
TIOCM_OUT2
;
serial_omap_set_mctrl
(
&
up
->
port
,
up
->
port
.
mctrl
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
/*
* Disable break condition and FIFOs
*/
serial_out
(
up
,
UART_LCR
,
serial_in
(
up
,
UART_LCR
)
&
~
UART_LCR_SBC
);
serial_omap_clear_fifos
(
up
);
/*
* Read data port to reset things, and then free the irq
*/
if
(
serial_in
(
up
,
UART_LSR
)
&
UART_LSR_DR
)
(
void
)
serial_in
(
up
,
UART_RX
);
if
(
up
->
use_dma
)
{
dma_free_coherent
(
up
->
port
.
dev
,
UART_XMIT_SIZE
,
up
->
port
.
state
->
xmit
.
buf
,
up
->
uart_dma
.
tx_buf_dma_phys
);
up
->
port
.
state
->
xmit
.
buf
=
NULL
;
serial_omap_stop_rx
(
port
);
dma_free_coherent
(
up
->
port
.
dev
,
up
->
uart_dma
.
rx_buf_size
,
up
->
uart_dma
.
rx_buf
,
up
->
uart_dma
.
rx_buf_dma_phys
);
up
->
uart_dma
.
rx_buf
=
NULL
;
}
free_irq
(
up
->
port
.
irq
,
up
);
}
static
inline
void
serial_omap_configure_xonxoff
(
struct
uart_omap_port
*
up
,
struct
ktermios
*
termios
)
{
unsigned
char
efr
=
0
;
up
->
lcr
=
serial_in
(
up
,
UART_LCR
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
up
->
efr
=
serial_in
(
up
,
UART_EFR
);
serial_out
(
up
,
UART_EFR
,
up
->
efr
&
~
UART_EFR_ECB
);
serial_out
(
up
,
UART_XON1
,
termios
->
c_cc
[
VSTART
]);
serial_out
(
up
,
UART_XOFF1
,
termios
->
c_cc
[
VSTOP
]);
/* clear SW control mode bits */
efr
=
up
->
efr
;
efr
&=
OMAP_UART_SW_CLR
;
/*
* IXON Flag:
* Enable XON/XOFF flow control on output.
* Transmit XON1, XOFF1
*/
if
(
termios
->
c_iflag
&
IXON
)
efr
|=
OMAP_UART_SW_TX
;
/*
* IXOFF Flag:
* Enable XON/XOFF flow control on input.
* Receiver compares XON1, XOFF1.
*/
if
(
termios
->
c_iflag
&
IXOFF
)
efr
|=
OMAP_UART_SW_RX
;
serial_out
(
up
,
UART_EFR
,
up
->
efr
|
UART_EFR_ECB
);
serial_out
(
up
,
UART_LCR
,
UART_LCR_DLAB
);
up
->
mcr
=
serial_in
(
up
,
UART_MCR
);
/*
* IXANY Flag:
* Enable any character to restart output.
* Operation resumes after receiving any
* character after recognition of the XOFF character
*/
if
(
termios
->
c_iflag
&
IXANY
)
up
->
mcr
|=
UART_MCR_XONANY
;
serial_out
(
up
,
UART_MCR
,
up
->
mcr
|
UART_MCR_TCRTLR
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
serial_out
(
up
,
UART_TI752_TCR
,
OMAP_UART_TCR_TRIG
);
/* Enable special char function UARTi.EFR_REG[5] and
* load the new software flow control mode IXON or IXOFF
* and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
*/
serial_out
(
up
,
UART_EFR
,
efr
|
UART_EFR_SCD
);
serial_out
(
up
,
UART_LCR
,
UART_LCR_DLAB
);
serial_out
(
up
,
UART_MCR
,
up
->
mcr
&
~
UART_MCR_TCRTLR
);
serial_out
(
up
,
UART_LCR
,
up
->
lcr
);
}
static
void
serial_omap_set_termios
(
struct
uart_port
*
port
,
struct
ktermios
*
termios
,
struct
ktermios
*
old
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
char
cval
=
0
;
unsigned
char
efr
=
0
;
unsigned
long
flags
=
0
;
unsigned
int
baud
,
quot
;
switch
(
termios
->
c_cflag
&
CSIZE
)
{
case
CS5
:
cval
=
UART_LCR_WLEN5
;
break
;
case
CS6
:
cval
=
UART_LCR_WLEN6
;
break
;
case
CS7
:
cval
=
UART_LCR_WLEN7
;
break
;
default:
case
CS8
:
cval
=
UART_LCR_WLEN8
;
break
;
}
if
(
termios
->
c_cflag
&
CSTOPB
)
cval
|=
UART_LCR_STOP
;
if
(
termios
->
c_cflag
&
PARENB
)
cval
|=
UART_LCR_PARITY
;
if
(
!
(
termios
->
c_cflag
&
PARODD
))
cval
|=
UART_LCR_EPAR
;
/*
* Ask the core to calculate the divisor for us.
*/
baud
=
uart_get_baud_rate
(
port
,
termios
,
old
,
0
,
port
->
uartclk
/
13
);
quot
=
serial_omap_get_divisor
(
port
,
baud
);
up
->
fcr
=
UART_FCR_R_TRIG_01
|
UART_FCR_T_TRIG_01
|
UART_FCR_ENABLE_FIFO
;
if
(
up
->
use_dma
)
up
->
fcr
|=
UART_FCR_DMA_SELECT
;
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
/*
* Update the per-port timeout.
*/
uart_update_timeout
(
port
,
termios
->
c_cflag
,
baud
);
up
->
port
.
read_status_mask
=
UART_LSR_OE
|
UART_LSR_THRE
|
UART_LSR_DR
;
if
(
termios
->
c_iflag
&
INPCK
)
up
->
port
.
read_status_mask
|=
UART_LSR_FE
|
UART_LSR_PE
;
if
(
termios
->
c_iflag
&
(
BRKINT
|
PARMRK
))
up
->
port
.
read_status_mask
|=
UART_LSR_BI
;
/*
* Characters to ignore
*/
up
->
port
.
ignore_status_mask
=
0
;
if
(
termios
->
c_iflag
&
IGNPAR
)
up
->
port
.
ignore_status_mask
|=
UART_LSR_PE
|
UART_LSR_FE
;
if
(
termios
->
c_iflag
&
IGNBRK
)
{
up
->
port
.
ignore_status_mask
|=
UART_LSR_BI
;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if
(
termios
->
c_iflag
&
IGNPAR
)
up
->
port
.
ignore_status_mask
|=
UART_LSR_OE
;
}
/*
* ignore all characters if CREAD is not set
*/
if
((
termios
->
c_cflag
&
CREAD
)
==
0
)
up
->
port
.
ignore_status_mask
|=
UART_LSR_DR
;
/*
* Modem status interrupts
*/
up
->
ier
&=
~
UART_IER_MSI
;
if
(
UART_ENABLE_MS
(
&
up
->
port
,
termios
->
c_cflag
))
up
->
ier
|=
UART_IER_MSI
;
serial_out
(
up
,
UART_IER
,
up
->
ier
);
serial_out
(
up
,
UART_LCR
,
cval
);
/* reset DLAB */
/* FIFOs and DMA Settings */
/* FCR can be changed only when the
* baud clock is not running
* DLL_REG and DLH_REG set to 0.
*/
serial_out
(
up
,
UART_LCR
,
UART_LCR_DLAB
);
serial_out
(
up
,
UART_DLL
,
0
);
serial_out
(
up
,
UART_DLM
,
0
);
serial_out
(
up
,
UART_LCR
,
0
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
up
->
efr
=
serial_in
(
up
,
UART_EFR
);
serial_out
(
up
,
UART_EFR
,
up
->
efr
|
UART_EFR_ECB
);
serial_out
(
up
,
UART_LCR
,
UART_LCR_DLAB
);
up
->
mcr
=
serial_in
(
up
,
UART_MCR
);
serial_out
(
up
,
UART_MCR
,
up
->
mcr
|
UART_MCR_TCRTLR
);
/* FIFO ENABLE, DMA MODE */
serial_out
(
up
,
UART_FCR
,
up
->
fcr
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
if
(
up
->
use_dma
)
{
serial_out
(
up
,
UART_TI752_TLR
,
0
);
serial_out
(
up
,
UART_OMAP_SCR
,
(
UART_FCR_TRIGGER_4
|
UART_FCR_TRIGGER_8
));
}
serial_out
(
up
,
UART_EFR
,
up
->
efr
);
serial_out
(
up
,
UART_LCR
,
UART_LCR_DLAB
);
serial_out
(
up
,
UART_MCR
,
up
->
mcr
);
/* Protocol, Baud Rate, and Interrupt Settings */
serial_out
(
up
,
UART_OMAP_MDR1
,
OMAP_MDR1_DISABLE
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
up
->
efr
=
serial_in
(
up
,
UART_EFR
);
serial_out
(
up
,
UART_EFR
,
up
->
efr
|
UART_EFR_ECB
);
serial_out
(
up
,
UART_LCR
,
0
);
serial_out
(
up
,
UART_IER
,
0
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
serial_out
(
up
,
UART_DLL
,
quot
&
0xff
);
/* LS of divisor */
serial_out
(
up
,
UART_DLM
,
quot
>>
8
);
/* MS of divisor */
serial_out
(
up
,
UART_LCR
,
0
);
serial_out
(
up
,
UART_IER
,
up
->
ier
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
serial_out
(
up
,
UART_EFR
,
up
->
efr
);
serial_out
(
up
,
UART_LCR
,
cval
);
if
(
baud
>
230400
&&
baud
!=
3000000
)
serial_out
(
up
,
UART_OMAP_MDR1
,
OMAP_MDR1_MODE13X
);
else
serial_out
(
up
,
UART_OMAP_MDR1
,
OMAP_MDR1_MODE16X
);
/* Hardware Flow Control Configuration */
if
(
termios
->
c_cflag
&
CRTSCTS
)
{
efr
|=
(
UART_EFR_CTS
|
UART_EFR_RTS
);
serial_out
(
up
,
UART_LCR
,
UART_LCR_DLAB
);
up
->
mcr
=
serial_in
(
up
,
UART_MCR
);
serial_out
(
up
,
UART_MCR
,
up
->
mcr
|
UART_MCR_TCRTLR
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
up
->
efr
=
serial_in
(
up
,
UART_EFR
);
serial_out
(
up
,
UART_EFR
,
up
->
efr
|
UART_EFR_ECB
);
serial_out
(
up
,
UART_TI752_TCR
,
OMAP_UART_TCR_TRIG
);
serial_out
(
up
,
UART_EFR
,
efr
);
/* Enable AUTORTS and AUTOCTS */
serial_out
(
up
,
UART_LCR
,
UART_LCR_DLAB
);
serial_out
(
up
,
UART_MCR
,
up
->
mcr
|
UART_MCR_RTS
);
serial_out
(
up
,
UART_LCR
,
cval
);
}
serial_omap_set_mctrl
(
&
up
->
port
,
up
->
port
.
mctrl
);
/* Software Flow Control Configuration */
if
(
termios
->
c_iflag
&
(
IXON
|
IXOFF
))
serial_omap_configure_xonxoff
(
up
,
termios
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_set_termios+%d
\n
"
,
up
->
pdev
->
id
);
}
static
void
serial_omap_pm
(
struct
uart_port
*
port
,
unsigned
int
state
,
unsigned
int
oldstate
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
unsigned
char
efr
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_pm+%d
\n
"
,
up
->
pdev
->
id
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
efr
=
serial_in
(
up
,
UART_EFR
);
serial_out
(
up
,
UART_EFR
,
efr
|
UART_EFR_ECB
);
serial_out
(
up
,
UART_LCR
,
0
);
serial_out
(
up
,
UART_IER
,
(
state
!=
0
)
?
UART_IERX_SLEEP
:
0
);
serial_out
(
up
,
UART_LCR
,
OMAP_UART_LCR_CONF_MDB
);
serial_out
(
up
,
UART_EFR
,
efr
);
serial_out
(
up
,
UART_LCR
,
0
);
/* Enable module level wake up */
serial_out
(
up
,
UART_OMAP_WER
,
(
state
!=
0
)
?
OMAP_UART_WER_MOD_WKUP
:
0
);
}
static
void
serial_omap_release_port
(
struct
uart_port
*
port
)
{
dev_dbg
(
port
->
dev
,
"serial_omap_release_port+
\n
"
);
}
static
int
serial_omap_request_port
(
struct
uart_port
*
port
)
{
dev_dbg
(
port
->
dev
,
"serial_omap_request_port+
\n
"
);
return
0
;
}
static
void
serial_omap_config_port
(
struct
uart_port
*
port
,
int
flags
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_config_port+%d
\n
"
,
up
->
pdev
->
id
);
up
->
port
.
type
=
PORT_OMAP
;
}
static
int
serial_omap_verify_port
(
struct
uart_port
*
port
,
struct
serial_struct
*
ser
)
{
/* we don't want the core code to modify any port params */
dev_dbg
(
port
->
dev
,
"serial_omap_verify_port+
\n
"
);
return
-
EINVAL
;
}
static
const
char
*
serial_omap_type
(
struct
uart_port
*
port
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
dev_dbg
(
up
->
port
.
dev
,
"serial_omap_type+%d
\n
"
,
up
->
pdev
->
id
);
return
up
->
name
;
}
#ifdef CONFIG_SERIAL_OMAP_CONSOLE
static
struct
uart_omap_port
*
serial_omap_console_ports
[
4
];
static
struct
uart_driver
serial_omap_reg
;
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
static
inline
void
wait_for_xmitr
(
struct
uart_omap_port
*
up
)
{
unsigned
int
status
,
tmout
=
10000
;
/* Wait up to 10ms for the character(s) to be sent. */
do
{
status
=
serial_in
(
up
,
UART_LSR
);
if
(
status
&
UART_LSR_BI
)
up
->
lsr_break_flag
=
UART_LSR_BI
;
if
(
--
tmout
==
0
)
break
;
udelay
(
1
);
}
while
((
status
&
BOTH_EMPTY
)
!=
BOTH_EMPTY
);
/* Wait up to 1s for flow control if necessary */
if
(
up
->
port
.
flags
&
UPF_CONS_FLOW
)
{
tmout
=
1000000
;
for
(
tmout
=
1000000
;
tmout
;
tmout
--
)
{
unsigned
int
msr
=
serial_in
(
up
,
UART_MSR
);
up
->
msr_saved_flags
|=
msr
&
MSR_SAVE_FLAGS
;
if
(
msr
&
UART_MSR_CTS
)
break
;
udelay
(
1
);
}
}
}
static
void
serial_omap_console_putchar
(
struct
uart_port
*
port
,
int
ch
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
port
;
wait_for_xmitr
(
up
);
serial_out
(
up
,
UART_TX
,
ch
);
}
static
void
serial_omap_console_write
(
struct
console
*
co
,
const
char
*
s
,
unsigned
int
count
)
{
struct
uart_omap_port
*
up
=
serial_omap_console_ports
[
co
->
index
];
unsigned
long
flags
;
unsigned
int
ier
;
int
locked
=
1
;
local_irq_save
(
flags
);
if
(
up
->
port
.
sysrq
)
locked
=
0
;
else
if
(
oops_in_progress
)
locked
=
spin_trylock
(
&
up
->
port
.
lock
);
else
spin_lock
(
&
up
->
port
.
lock
);
/*
* First save the IER then disable the interrupts
*/
ier
=
serial_in
(
up
,
UART_IER
);
serial_out
(
up
,
UART_IER
,
0
);
uart_console_write
(
&
up
->
port
,
s
,
count
,
serial_omap_console_putchar
);
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr
(
up
);
serial_out
(
up
,
UART_IER
,
ier
);
/*
* The receive handling will happen properly because the
* receive ready bit will still be set; it is not cleared
* on read. However, modem control will not, we must
* call it if we have saved something in the saved flags
* while processing with interrupts off.
*/
if
(
up
->
msr_saved_flags
)
check_modem_status
(
up
);
if
(
locked
)
spin_unlock
(
&
up
->
port
.
lock
);
local_irq_restore
(
flags
);
}
static
int
__init
serial_omap_console_setup
(
struct
console
*
co
,
char
*
options
)
{
struct
uart_omap_port
*
up
;
int
baud
=
115200
;
int
bits
=
8
;
int
parity
=
'n'
;
int
flow
=
'n'
;
if
(
serial_omap_console_ports
[
co
->
index
]
==
NULL
)
return
-
ENODEV
;
up
=
serial_omap_console_ports
[
co
->
index
];
if
(
options
)
uart_parse_options
(
options
,
&
baud
,
&
parity
,
&
bits
,
&
flow
);
return
uart_set_options
(
&
up
->
port
,
co
,
baud
,
parity
,
bits
,
flow
);
}
static
struct
console
serial_omap_console
=
{
.
name
=
OMAP_SERIAL_NAME
,
.
write
=
serial_omap_console_write
,
.
device
=
uart_console_device
,
.
setup
=
serial_omap_console_setup
,
.
flags
=
CON_PRINTBUFFER
,
.
index
=
-
1
,
.
data
=
&
serial_omap_reg
,
};
static
void
serial_omap_add_console_port
(
struct
uart_omap_port
*
up
)
{
serial_omap_console_ports
[
up
->
pdev
->
id
]
=
up
;
}
#define OMAP_CONSOLE (&serial_omap_console)
#else
#define OMAP_CONSOLE NULL
static
inline
void
serial_omap_add_console_port
(
struct
uart_omap_port
*
up
)
{}
#endif
static
struct
uart_ops
serial_omap_pops
=
{
.
tx_empty
=
serial_omap_tx_empty
,
.
set_mctrl
=
serial_omap_set_mctrl
,
.
get_mctrl
=
serial_omap_get_mctrl
,
.
stop_tx
=
serial_omap_stop_tx
,
.
start_tx
=
serial_omap_start_tx
,
.
stop_rx
=
serial_omap_stop_rx
,
.
enable_ms
=
serial_omap_enable_ms
,
.
break_ctl
=
serial_omap_break_ctl
,
.
startup
=
serial_omap_startup
,
.
shutdown
=
serial_omap_shutdown
,
.
set_termios
=
serial_omap_set_termios
,
.
pm
=
serial_omap_pm
,
.
type
=
serial_omap_type
,
.
release_port
=
serial_omap_release_port
,
.
request_port
=
serial_omap_request_port
,
.
config_port
=
serial_omap_config_port
,
.
verify_port
=
serial_omap_verify_port
,
};
static
struct
uart_driver
serial_omap_reg
=
{
.
owner
=
THIS_MODULE
,
.
driver_name
=
"OMAP-SERIAL"
,
.
dev_name
=
OMAP_SERIAL_NAME
,
.
nr
=
OMAP_MAX_HSUART_PORTS
,
.
cons
=
OMAP_CONSOLE
,
};
static
int
serial_omap_suspend
(
struct
platform_device
*
pdev
,
pm_message_t
state
)
{
struct
uart_omap_port
*
up
=
platform_get_drvdata
(
pdev
);
if
(
up
)
uart_suspend_port
(
&
serial_omap_reg
,
&
up
->
port
);
return
0
;
}
static
int
serial_omap_resume
(
struct
platform_device
*
dev
)
{
struct
uart_omap_port
*
up
=
platform_get_drvdata
(
dev
);
if
(
up
)
uart_resume_port
(
&
serial_omap_reg
,
&
up
->
port
);
return
0
;
}
static
void
serial_omap_rx_timeout
(
unsigned
long
uart_no
)
{
struct
uart_omap_port
*
up
=
ui
[
uart_no
];
unsigned
int
curr_dma_pos
,
curr_transmitted_size
;
unsigned
int
ret
=
0
;
curr_dma_pos
=
omap_get_dma_dst_pos
(
up
->
uart_dma
.
rx_dma_channel
);
if
((
curr_dma_pos
==
up
->
uart_dma
.
prev_rx_dma_pos
)
||
(
curr_dma_pos
==
0
))
{
if
(
jiffies_to_msecs
(
jiffies
-
up
->
port_activity
)
<
RX_TIMEOUT
)
{
mod_timer
(
&
up
->
uart_dma
.
rx_timer
,
jiffies
+
usecs_to_jiffies
(
up
->
uart_dma
.
rx_timeout
));
}
else
{
serial_omap_stop_rxdma
(
up
);
up
->
ier
|=
(
UART_IER_RDI
|
UART_IER_RLSI
);
serial_out
(
up
,
UART_IER
,
up
->
ier
);
}
return
;
}
curr_transmitted_size
=
curr_dma_pos
-
up
->
uart_dma
.
prev_rx_dma_pos
;
up
->
port
.
icount
.
rx
+=
curr_transmitted_size
;
tty_insert_flip_string
(
up
->
port
.
state
->
port
.
tty
,
up
->
uart_dma
.
rx_buf
+
(
up
->
uart_dma
.
prev_rx_dma_pos
-
up
->
uart_dma
.
rx_buf_dma_phys
),
curr_transmitted_size
);
tty_flip_buffer_push
(
up
->
port
.
state
->
port
.
tty
);
up
->
uart_dma
.
prev_rx_dma_pos
=
curr_dma_pos
;
if
(
up
->
uart_dma
.
rx_buf_size
+
up
->
uart_dma
.
rx_buf_dma_phys
==
curr_dma_pos
)
{
ret
=
serial_omap_start_rxdma
(
up
);
if
(
ret
<
0
)
{
serial_omap_stop_rxdma
(
up
);
up
->
ier
|=
(
UART_IER_RDI
|
UART_IER_RLSI
);
serial_out
(
up
,
UART_IER
,
up
->
ier
);
}
}
else
{
mod_timer
(
&
up
->
uart_dma
.
rx_timer
,
jiffies
+
usecs_to_jiffies
(
up
->
uart_dma
.
rx_timeout
));
}
up
->
port_activity
=
jiffies
;
}
static
void
uart_rx_dma_callback
(
int
lch
,
u16
ch_status
,
void
*
data
)
{
return
;
}
static
int
serial_omap_start_rxdma
(
struct
uart_omap_port
*
up
)
{
int
ret
=
0
;
if
(
up
->
uart_dma
.
rx_dma_channel
==
-
1
)
{
ret
=
omap_request_dma
(
up
->
uart_dma
.
uart_dma_rx
,
"UART Rx DMA"
,
(
void
*
)
uart_rx_dma_callback
,
up
,
&
(
up
->
uart_dma
.
rx_dma_channel
));
if
(
ret
<
0
)
return
ret
;
omap_set_dma_src_params
(
up
->
uart_dma
.
rx_dma_channel
,
0
,
OMAP_DMA_AMODE_CONSTANT
,
up
->
uart_dma
.
uart_base
,
0
,
0
);
omap_set_dma_dest_params
(
up
->
uart_dma
.
rx_dma_channel
,
0
,
OMAP_DMA_AMODE_POST_INC
,
up
->
uart_dma
.
rx_buf_dma_phys
,
0
,
0
);
omap_set_dma_transfer_params
(
up
->
uart_dma
.
rx_dma_channel
,
OMAP_DMA_DATA_TYPE_S8
,
up
->
uart_dma
.
rx_buf_size
,
1
,
OMAP_DMA_SYNC_ELEMENT
,
up
->
uart_dma
.
uart_dma_rx
,
0
);
}
up
->
uart_dma
.
prev_rx_dma_pos
=
up
->
uart_dma
.
rx_buf_dma_phys
;
/* FIXME: Cache maintenance needed here? */
omap_start_dma
(
up
->
uart_dma
.
rx_dma_channel
);
mod_timer
(
&
up
->
uart_dma
.
rx_timer
,
jiffies
+
usecs_to_jiffies
(
up
->
uart_dma
.
rx_timeout
));
up
->
uart_dma
.
rx_dma_used
=
true
;
return
ret
;
}
static
void
serial_omap_continue_tx
(
struct
uart_omap_port
*
up
)
{
struct
circ_buf
*
xmit
=
&
up
->
port
.
state
->
xmit
;
unsigned
int
start
=
up
->
uart_dma
.
tx_buf_dma_phys
+
(
xmit
->
tail
&
(
UART_XMIT_SIZE
-
1
));
if
(
uart_circ_empty
(
xmit
))
return
;
up
->
uart_dma
.
tx_buf_size
=
uart_circ_chars_pending
(
xmit
);
/*
* It is a circular buffer. See if the buffer has wounded back.
* If yes it will have to be transferred in two separate dma
* transfers
*/
if
(
start
+
up
->
uart_dma
.
tx_buf_size
>=
up
->
uart_dma
.
tx_buf_dma_phys
+
UART_XMIT_SIZE
)
up
->
uart_dma
.
tx_buf_size
=
(
up
->
uart_dma
.
tx_buf_dma_phys
+
UART_XMIT_SIZE
)
-
start
;
omap_set_dma_dest_params
(
up
->
uart_dma
.
tx_dma_channel
,
0
,
OMAP_DMA_AMODE_CONSTANT
,
up
->
uart_dma
.
uart_base
,
0
,
0
);
omap_set_dma_src_params
(
up
->
uart_dma
.
tx_dma_channel
,
0
,
OMAP_DMA_AMODE_POST_INC
,
start
,
0
,
0
);
omap_set_dma_transfer_params
(
up
->
uart_dma
.
tx_dma_channel
,
OMAP_DMA_DATA_TYPE_S8
,
up
->
uart_dma
.
tx_buf_size
,
1
,
OMAP_DMA_SYNC_ELEMENT
,
up
->
uart_dma
.
uart_dma_tx
,
0
);
/* FIXME: Cache maintenance needed here? */
omap_start_dma
(
up
->
uart_dma
.
tx_dma_channel
);
}
static
void
uart_tx_dma_callback
(
int
lch
,
u16
ch_status
,
void
*
data
)
{
struct
uart_omap_port
*
up
=
(
struct
uart_omap_port
*
)
data
;
struct
circ_buf
*
xmit
=
&
up
->
port
.
state
->
xmit
;
xmit
->
tail
=
(
xmit
->
tail
+
up
->
uart_dma
.
tx_buf_size
)
&
\
(
UART_XMIT_SIZE
-
1
);
up
->
port
.
icount
.
tx
+=
up
->
uart_dma
.
tx_buf_size
;
if
(
uart_circ_chars_pending
(
xmit
)
<
WAKEUP_CHARS
)
uart_write_wakeup
(
&
up
->
port
);
if
(
uart_circ_empty
(
xmit
))
{
spin_lock
(
&
(
up
->
uart_dma
.
tx_lock
));
serial_omap_stop_tx
(
&
up
->
port
);
up
->
uart_dma
.
tx_dma_used
=
false
;
spin_unlock
(
&
(
up
->
uart_dma
.
tx_lock
));
}
else
{
omap_stop_dma
(
up
->
uart_dma
.
tx_dma_channel
);
serial_omap_continue_tx
(
up
);
}
up
->
port_activity
=
jiffies
;
return
;
}
static
int
serial_omap_probe
(
struct
platform_device
*
pdev
)
{
struct
uart_omap_port
*
up
;
struct
resource
*
mem
,
*
irq
,
*
dma_tx
,
*
dma_rx
;
struct
omap_uart_port_info
*
omap_up_info
=
pdev
->
dev
.
platform_data
;
int
ret
=
-
ENOSPC
;
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
mem
)
{
dev_err
(
&
pdev
->
dev
,
"no mem resource?
\n
"
);
return
-
ENODEV
;
}
irq
=
platform_get_resource
(
pdev
,
IORESOURCE_IRQ
,
0
);
if
(
!
irq
)
{
dev_err
(
&
pdev
->
dev
,
"no irq resource?
\n
"
);
return
-
ENODEV
;
}
if
(
!
request_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
,
pdev
->
dev
.
driver
->
name
))
{
dev_err
(
&
pdev
->
dev
,
"memory region already claimed
\n
"
);
return
-
EBUSY
;
}
dma_rx
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"rx"
);
if
(
!
dma_rx
)
{
ret
=
-
EINVAL
;
goto
err
;
}
dma_tx
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"tx"
);
if
(
!
dma_tx
)
{
ret
=
-
EINVAL
;
goto
err
;
}
up
=
kzalloc
(
sizeof
(
*
up
),
GFP_KERNEL
);
if
(
up
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
do_release_region
;
}
sprintf
(
up
->
name
,
"OMAP UART%d"
,
pdev
->
id
);
up
->
pdev
=
pdev
;
up
->
port
.
dev
=
&
pdev
->
dev
;
up
->
port
.
type
=
PORT_OMAP
;
up
->
port
.
iotype
=
UPIO_MEM
;
up
->
port
.
irq
=
irq
->
start
;
up
->
port
.
regshift
=
2
;
up
->
port
.
fifosize
=
64
;
up
->
port
.
ops
=
&
serial_omap_pops
;
up
->
port
.
line
=
pdev
->
id
;
up
->
port
.
membase
=
omap_up_info
->
membase
;
up
->
port
.
mapbase
=
omap_up_info
->
mapbase
;
up
->
port
.
flags
=
omap_up_info
->
flags
;
up
->
port
.
irqflags
=
omap_up_info
->
irqflags
;
up
->
port
.
uartclk
=
omap_up_info
->
uartclk
;
up
->
uart_dma
.
uart_base
=
mem
->
start
;
if
(
omap_up_info
->
dma_enabled
)
{
up
->
uart_dma
.
uart_dma_tx
=
dma_tx
->
start
;
up
->
uart_dma
.
uart_dma_rx
=
dma_rx
->
start
;
up
->
use_dma
=
1
;
up
->
uart_dma
.
rx_buf_size
=
4096
;
up
->
uart_dma
.
rx_timeout
=
2
;
spin_lock_init
(
&
(
up
->
uart_dma
.
tx_lock
));
spin_lock_init
(
&
(
up
->
uart_dma
.
rx_lock
));
up
->
uart_dma
.
tx_dma_channel
=
OMAP_UART_DMA_CH_FREE
;
up
->
uart_dma
.
rx_dma_channel
=
OMAP_UART_DMA_CH_FREE
;
}
ui
[
pdev
->
id
]
=
up
;
serial_omap_add_console_port
(
up
);
ret
=
uart_add_one_port
(
&
serial_omap_reg
,
&
up
->
port
);
if
(
ret
!=
0
)
goto
do_release_region
;
platform_set_drvdata
(
pdev
,
up
);
return
0
;
err:
dev_err
(
&
pdev
->
dev
,
"[UART%d]: failure [%s]: %d
\n
"
,
pdev
->
id
,
__func__
,
ret
);
do_release_region:
release_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
);
return
ret
;
}
static
int
serial_omap_remove
(
struct
platform_device
*
dev
)
{
struct
uart_omap_port
*
up
=
platform_get_drvdata
(
dev
);
platform_set_drvdata
(
dev
,
NULL
);
if
(
up
)
{
uart_remove_one_port
(
&
serial_omap_reg
,
&
up
->
port
);
kfree
(
up
);
}
return
0
;
}
static
struct
platform_driver
serial_omap_driver
=
{
.
probe
=
serial_omap_probe
,
.
remove
=
serial_omap_remove
,
.
suspend
=
serial_omap_suspend
,
.
resume
=
serial_omap_resume
,
.
driver
=
{
.
name
=
DRIVER_NAME
,
},
};
static
int
__init
serial_omap_init
(
void
)
{
int
ret
;
ret
=
uart_register_driver
(
&
serial_omap_reg
);
if
(
ret
!=
0
)
return
ret
;
ret
=
platform_driver_register
(
&
serial_omap_driver
);
if
(
ret
!=
0
)
uart_unregister_driver
(
&
serial_omap_reg
);
return
ret
;
}
static
void
__exit
serial_omap_exit
(
void
)
{
platform_driver_unregister
(
&
serial_omap_driver
);
uart_unregister_driver
(
&
serial_omap_reg
);
}
module_init
(
serial_omap_init
);
module_exit
(
serial_omap_exit
);
MODULE_DESCRIPTION
(
"OMAP High Speed UART driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Texas Instruments Inc"
);
include/linux/serial_core.h
View file @
69758ab7
...
...
@@ -196,6 +196,9 @@
/* High Speed UART for Medfield */
#define PORT_MFD 95
/* TI OMAP-UART */
#define PORT_OMAP 96
#ifdef __KERNEL__
#include <linux/compiler.h>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment