diff options
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
| -rw-r--r-- | arch/arm/mach-omap2/serial.c | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index d17960a1be25..c64578853a8d 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c | |||
| @@ -40,11 +40,12 @@ | |||
| 40 | #include <plat/omap_hwmod.h> | 40 | #include <plat/omap_hwmod.h> |
| 41 | #include <plat/omap_device.h> | 41 | #include <plat/omap_device.h> |
| 42 | 42 | ||
| 43 | #include "prm.h" | 43 | #include "prm2xxx_3xxx.h" |
| 44 | #include "pm.h" | 44 | #include "pm.h" |
| 45 | #include "cm.h" | 45 | #include "cm2xxx_3xxx.h" |
| 46 | #include "prm-regbits-34xx.h" | 46 | #include "prm-regbits-34xx.h" |
| 47 | #include "control.h" | 47 | #include "control.h" |
| 48 | #include "mux.h" | ||
| 48 | 49 | ||
| 49 | #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 | 50 | #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52 |
| 50 | #define UART_OMAP_WER 0x17 /* Wake-up enable register */ | 51 | #define UART_OMAP_WER 0x17 /* Wake-up enable register */ |
| @@ -106,21 +107,16 @@ struct omap_uart_state { | |||
| 106 | static LIST_HEAD(uart_list); | 107 | static LIST_HEAD(uart_list); |
| 107 | static u8 num_uarts; | 108 | static u8 num_uarts; |
| 108 | 109 | ||
| 109 | /* | ||
| 110 | * Since these idle/enable hooks are used in the idle path itself | ||
| 111 | * which has interrupts disabled, use the non-locking versions of | ||
| 112 | * the hwmod enable/disable functions. | ||
| 113 | */ | ||
| 114 | static int uart_idle_hwmod(struct omap_device *od) | 110 | static int uart_idle_hwmod(struct omap_device *od) |
| 115 | { | 111 | { |
| 116 | _omap_hwmod_idle(od->hwmods[0]); | 112 | omap_hwmod_idle(od->hwmods[0]); |
| 117 | 113 | ||
| 118 | return 0; | 114 | return 0; |
| 119 | } | 115 | } |
| 120 | 116 | ||
| 121 | static int uart_enable_hwmod(struct omap_device *od) | 117 | static int uart_enable_hwmod(struct omap_device *od) |
| 122 | { | 118 | { |
| 123 | _omap_hwmod_enable(od->hwmods[0]); | 119 | omap_hwmod_enable(od->hwmods[0]); |
| 124 | 120 | ||
| 125 | return 0; | 121 | return 0; |
| 126 | } | 122 | } |
| @@ -169,9 +165,9 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset, | |||
| 169 | 165 | ||
| 170 | static inline void __init omap_uart_reset(struct omap_uart_state *uart) | 166 | static inline void __init omap_uart_reset(struct omap_uart_state *uart) |
| 171 | { | 167 | { |
| 172 | serial_write_reg(uart, UART_OMAP_MDR1, 0x07); | 168 | serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); |
| 173 | serial_write_reg(uart, UART_OMAP_SCR, 0x08); | 169 | serial_write_reg(uart, UART_OMAP_SCR, 0x08); |
| 174 | serial_write_reg(uart, UART_OMAP_MDR1, 0x00); | 170 | serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE); |
| 175 | } | 171 | } |
| 176 | 172 | ||
| 177 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) | 173 | #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) |
| @@ -219,7 +215,7 @@ static void omap_uart_save_context(struct omap_uart_state *uart) | |||
| 219 | return; | 215 | return; |
| 220 | 216 | ||
| 221 | lcr = serial_read_reg(uart, UART_LCR); | 217 | lcr = serial_read_reg(uart, UART_LCR); |
| 222 | serial_write_reg(uart, UART_LCR, 0xBF); | 218 | serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); |
| 223 | uart->dll = serial_read_reg(uart, UART_DLL); | 219 | uart->dll = serial_read_reg(uart, UART_DLL); |
| 224 | uart->dlh = serial_read_reg(uart, UART_DLM); | 220 | uart->dlh = serial_read_reg(uart, UART_DLM); |
| 225 | serial_write_reg(uart, UART_LCR, lcr); | 221 | serial_write_reg(uart, UART_LCR, lcr); |
| @@ -227,7 +223,7 @@ static void omap_uart_save_context(struct omap_uart_state *uart) | |||
| 227 | uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC); | 223 | uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC); |
| 228 | uart->scr = serial_read_reg(uart, UART_OMAP_SCR); | 224 | uart->scr = serial_read_reg(uart, UART_OMAP_SCR); |
| 229 | uart->wer = serial_read_reg(uart, UART_OMAP_WER); | 225 | uart->wer = serial_read_reg(uart, UART_OMAP_WER); |
| 230 | serial_write_reg(uart, UART_LCR, 0x80); | 226 | serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A); |
| 231 | uart->mcr = serial_read_reg(uart, UART_MCR); | 227 | uart->mcr = serial_read_reg(uart, UART_MCR); |
| 232 | serial_write_reg(uart, UART_LCR, lcr); | 228 | serial_write_reg(uart, UART_LCR, lcr); |
| 233 | 229 | ||
| @@ -247,32 +243,35 @@ static void omap_uart_restore_context(struct omap_uart_state *uart) | |||
| 247 | uart->context_valid = 0; | 243 | uart->context_valid = 0; |
| 248 | 244 | ||
| 249 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) | 245 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) |
| 250 | omap_uart_mdr1_errataset(uart, 0x07, 0xA0); | 246 | omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0); |
| 251 | else | 247 | else |
| 252 | serial_write_reg(uart, UART_OMAP_MDR1, 0x7); | 248 | serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); |
| 253 | serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ | 249 | |
| 250 | serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); | ||
| 254 | efr = serial_read_reg(uart, UART_EFR); | 251 | efr = serial_read_reg(uart, UART_EFR); |
| 255 | serial_write_reg(uart, UART_EFR, UART_EFR_ECB); | 252 | serial_write_reg(uart, UART_EFR, UART_EFR_ECB); |
| 256 | serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ | 253 | serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ |
| 257 | serial_write_reg(uart, UART_IER, 0x0); | 254 | serial_write_reg(uart, UART_IER, 0x0); |
| 258 | serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ | 255 | serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); |
| 259 | serial_write_reg(uart, UART_DLL, uart->dll); | 256 | serial_write_reg(uart, UART_DLL, uart->dll); |
| 260 | serial_write_reg(uart, UART_DLM, uart->dlh); | 257 | serial_write_reg(uart, UART_DLM, uart->dlh); |
| 261 | serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ | 258 | serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */ |
| 262 | serial_write_reg(uart, UART_IER, uart->ier); | 259 | serial_write_reg(uart, UART_IER, uart->ier); |
| 263 | serial_write_reg(uart, UART_LCR, 0x80); | 260 | serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A); |
| 264 | serial_write_reg(uart, UART_MCR, uart->mcr); | 261 | serial_write_reg(uart, UART_MCR, uart->mcr); |
| 265 | serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */ | 262 | serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B); |
| 266 | serial_write_reg(uart, UART_EFR, efr); | 263 | serial_write_reg(uart, UART_EFR, efr); |
| 267 | serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8); | 264 | serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8); |
| 268 | serial_write_reg(uart, UART_OMAP_SCR, uart->scr); | 265 | serial_write_reg(uart, UART_OMAP_SCR, uart->scr); |
| 269 | serial_write_reg(uart, UART_OMAP_WER, uart->wer); | 266 | serial_write_reg(uart, UART_OMAP_WER, uart->wer); |
| 270 | serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc); | 267 | serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc); |
| 268 | |||
| 271 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) | 269 | if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS) |
| 272 | omap_uart_mdr1_errataset(uart, 0x00, 0xA1); | 270 | omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1); |
| 273 | else | 271 | else |
| 274 | /* UART 16x mode */ | 272 | /* UART 16x mode */ |
| 275 | serial_write_reg(uart, UART_OMAP_MDR1, 0x00); | 273 | serial_write_reg(uart, UART_OMAP_MDR1, |
| 274 | UART_OMAP_MDR1_16X_MODE); | ||
| 276 | } | 275 | } |
| 277 | #else | 276 | #else |
| 278 | static inline void omap_uart_save_context(struct omap_uart_state *uart) {} | 277 | static inline void omap_uart_save_context(struct omap_uart_state *uart) {} |
| @@ -492,6 +491,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) | |||
| 492 | u32 wk_mask = 0; | 491 | u32 wk_mask = 0; |
| 493 | u32 padconf = 0; | 492 | u32 padconf = 0; |
| 494 | 493 | ||
| 494 | /* XXX These PRM accesses do not belong here */ | ||
| 495 | uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1); | 495 | uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1); |
| 496 | uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1); | 496 | uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1); |
| 497 | switch (uart->num) { | 497 | switch (uart->num) { |
| @@ -695,16 +695,16 @@ void __init omap_serial_early_init(void) | |||
| 695 | 695 | ||
| 696 | /** | 696 | /** |
| 697 | * omap_serial_init_port() - initialize single serial port | 697 | * omap_serial_init_port() - initialize single serial port |
| 698 | * @port: serial port number (0-3) | 698 | * @bdata: port specific board data pointer |
| 699 | * | 699 | * |
| 700 | * This function initialies serial driver for given @port only. | 700 | * This function initialies serial driver for given port only. |
| 701 | * Platforms can call this function instead of omap_serial_init() | 701 | * Platforms can call this function instead of omap_serial_init() |
| 702 | * if they don't plan to use all available UARTs as serial ports. | 702 | * if they don't plan to use all available UARTs as serial ports. |
| 703 | * | 703 | * |
| 704 | * Don't mix calls to omap_serial_init_port() and omap_serial_init(), | 704 | * Don't mix calls to omap_serial_init_port() and omap_serial_init(), |
| 705 | * use only one of the two. | 705 | * use only one of the two. |
| 706 | */ | 706 | */ |
| 707 | void __init omap_serial_init_port(int port) | 707 | void __init omap_serial_init_port(struct omap_board_data *bdata) |
| 708 | { | 708 | { |
| 709 | struct omap_uart_state *uart; | 709 | struct omap_uart_state *uart; |
| 710 | struct omap_hwmod *oh; | 710 | struct omap_hwmod *oh; |
| @@ -722,13 +722,15 @@ void __init omap_serial_init_port(int port) | |||
| 722 | struct omap_uart_port_info omap_up; | 722 | struct omap_uart_port_info omap_up; |
| 723 | #endif | 723 | #endif |
| 724 | 724 | ||
| 725 | if (WARN_ON(port < 0)) | 725 | if (WARN_ON(!bdata)) |
| 726 | return; | ||
| 727 | if (WARN_ON(bdata->id < 0)) | ||
| 726 | return; | 728 | return; |
| 727 | if (WARN_ON(port >= num_uarts)) | 729 | if (WARN_ON(bdata->id >= num_uarts)) |
| 728 | return; | 730 | return; |
| 729 | 731 | ||
| 730 | list_for_each_entry(uart, &uart_list, node) | 732 | list_for_each_entry(uart, &uart_list, node) |
| 731 | if (port == uart->num) | 733 | if (bdata->id == uart->num) |
| 732 | break; | 734 | break; |
| 733 | 735 | ||
| 734 | oh = uart->oh; | 736 | oh = uart->oh; |
| @@ -800,6 +802,8 @@ void __init omap_serial_init_port(int port) | |||
| 800 | WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", | 802 | WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", |
| 801 | name, oh->name); | 803 | name, oh->name); |
| 802 | 804 | ||
| 805 | oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); | ||
| 806 | |||
| 803 | uart->irq = oh->mpu_irqs[0].irq; | 807 | uart->irq = oh->mpu_irqs[0].irq; |
| 804 | uart->regshift = 2; | 808 | uart->regshift = 2; |
| 805 | uart->mapbase = oh->slaves[0]->addr->pa_start; | 809 | uart->mapbase = oh->slaves[0]->addr->pa_start; |
| @@ -857,7 +861,14 @@ void __init omap_serial_init_port(int port) | |||
| 857 | void __init omap_serial_init(void) | 861 | void __init omap_serial_init(void) |
| 858 | { | 862 | { |
| 859 | struct omap_uart_state *uart; | 863 | struct omap_uart_state *uart; |
| 864 | struct omap_board_data bdata; | ||
| 860 | 865 | ||
| 861 | list_for_each_entry(uart, &uart_list, node) | 866 | list_for_each_entry(uart, &uart_list, node) { |
| 862 | omap_serial_init_port(uart->num); | 867 | bdata.id = uart->num; |
| 868 | bdata.flags = 0; | ||
| 869 | bdata.pads = NULL; | ||
| 870 | bdata.pads_cnt = 0; | ||
| 871 | omap_serial_init_port(&bdata); | ||
| 872 | |||
| 873 | } | ||
| 863 | } | 874 | } |
