0001
0002
0003
0004
0005
0006
0007 #include <linux/gpio.h>
0008 #include <linux/module.h>
0009 #include <linux/kernel.h>
0010 #include <linux/init.h>
0011 #include <linux/irq.h>
0012 #include <linux/delay.h>
0013 #include <linux/serial.h>
0014 #include <linux/tty.h>
0015 #include <linux/serial_8250.h>
0016 #include <linux/serial_reg.h>
0017 #include <linux/clk.h>
0018 #include <linux/io.h>
0019
0020 #include <asm/mach-types.h>
0021
0022 #include "serial.h"
0023 #include "mux.h"
0024 #include "pm.h"
0025 #include "soc.h"
0026
0027 static struct clk * uart1_ck;
0028 static struct clk * uart2_ck;
0029 static struct clk * uart3_ck;
0030
0031 static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
0032 int offset)
0033 {
0034 offset <<= up->regshift;
0035 return (unsigned int)__raw_readb(up->membase + offset);
0036 }
0037
0038 static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
0039 int value)
0040 {
0041 offset <<= p->regshift;
0042 __raw_writeb(value, p->membase + offset);
0043 }
0044
0045
0046
0047
0048
0049
0050 static void __init omap_serial_reset(struct plat_serial8250_port *p)
0051 {
0052 omap_serial_outp(p, UART_OMAP_MDR1,
0053 UART_OMAP_MDR1_DISABLE);
0054 omap_serial_outp(p, UART_OMAP_SCR, 0x08);
0055 omap_serial_outp(p, UART_OMAP_MDR1,
0056 UART_OMAP_MDR1_16X_MODE);
0057
0058 if (!cpu_is_omap15xx()) {
0059 omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
0060 while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
0061 }
0062 }
0063
0064 static struct plat_serial8250_port serial_platform_data[] = {
0065 {
0066 .mapbase = OMAP1_UART1_BASE,
0067 .irq = INT_UART1,
0068 .flags = UPF_BOOT_AUTOCONF,
0069 .iotype = UPIO_MEM,
0070 .regshift = 2,
0071 .uartclk = OMAP16XX_BASE_BAUD * 16,
0072 },
0073 {
0074 .mapbase = OMAP1_UART2_BASE,
0075 .irq = INT_UART2,
0076 .flags = UPF_BOOT_AUTOCONF,
0077 .iotype = UPIO_MEM,
0078 .regshift = 2,
0079 .uartclk = OMAP16XX_BASE_BAUD * 16,
0080 },
0081 {
0082 .mapbase = OMAP1_UART3_BASE,
0083 .irq = INT_UART3,
0084 .flags = UPF_BOOT_AUTOCONF,
0085 .iotype = UPIO_MEM,
0086 .regshift = 2,
0087 .uartclk = OMAP16XX_BASE_BAUD * 16,
0088 },
0089 { },
0090 };
0091
0092 static struct platform_device serial_device = {
0093 .name = "serial8250",
0094 .id = PLAT8250_DEV_PLATFORM,
0095 .dev = {
0096 .platform_data = serial_platform_data,
0097 },
0098 };
0099
0100
0101
0102
0103
0104
0105 void __init omap_serial_init(void)
0106 {
0107 int i;
0108
0109 if (cpu_is_omap7xx()) {
0110 serial_platform_data[0].regshift = 0;
0111 serial_platform_data[1].regshift = 0;
0112 serial_platform_data[0].irq = INT_7XX_UART_MODEM_1;
0113 serial_platform_data[1].irq = INT_7XX_UART_MODEM_IRDA_2;
0114 }
0115
0116 if (cpu_is_omap15xx()) {
0117 serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
0118 serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
0119 serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
0120 }
0121
0122 for (i = 0; i < ARRAY_SIZE(serial_platform_data) - 1; i++) {
0123
0124
0125 if (cpu_is_omap7xx() && i > 1) {
0126 serial_platform_data[i].membase = NULL;
0127 serial_platform_data[i].mapbase = 0;
0128 continue;
0129 }
0130
0131
0132 serial_platform_data[i].membase =
0133 ioremap(serial_platform_data[i].mapbase, SZ_2K);
0134 if (!serial_platform_data[i].membase) {
0135 printk(KERN_ERR "Could not ioremap uart%i\n", i);
0136 continue;
0137 }
0138 switch (i) {
0139 case 0:
0140 uart1_ck = clk_get(NULL, "uart1_ck");
0141 if (IS_ERR(uart1_ck))
0142 printk("Could not get uart1_ck\n");
0143 else {
0144 clk_prepare_enable(uart1_ck);
0145 if (cpu_is_omap15xx())
0146 clk_set_rate(uart1_ck, 12000000);
0147 }
0148 break;
0149 case 1:
0150 uart2_ck = clk_get(NULL, "uart2_ck");
0151 if (IS_ERR(uart2_ck))
0152 printk("Could not get uart2_ck\n");
0153 else {
0154 clk_prepare_enable(uart2_ck);
0155 if (cpu_is_omap15xx())
0156 clk_set_rate(uart2_ck, 12000000);
0157 else
0158 clk_set_rate(uart2_ck, 48000000);
0159 }
0160 break;
0161 case 2:
0162 uart3_ck = clk_get(NULL, "uart3_ck");
0163 if (IS_ERR(uart3_ck))
0164 printk("Could not get uart3_ck\n");
0165 else {
0166 clk_prepare_enable(uart3_ck);
0167 if (cpu_is_omap15xx())
0168 clk_set_rate(uart3_ck, 12000000);
0169 }
0170 break;
0171 }
0172 omap_serial_reset(&serial_platform_data[i]);
0173 }
0174 }
0175
0176 #ifdef CONFIG_OMAP_SERIAL_WAKE
0177
0178 static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id)
0179 {
0180
0181 return IRQ_HANDLED;
0182 }
0183
0184
0185
0186
0187
0188
0189 void omap_serial_wake_trigger(int enable)
0190 {
0191 if (!cpu_is_omap16xx())
0192 return;
0193
0194 if (uart1_ck != NULL) {
0195 if (enable)
0196 omap_cfg_reg(V14_16XX_GPIO37);
0197 else
0198 omap_cfg_reg(V14_16XX_UART1_RX);
0199 }
0200 if (uart2_ck != NULL) {
0201 if (enable)
0202 omap_cfg_reg(R9_16XX_GPIO18);
0203 else
0204 omap_cfg_reg(R9_16XX_UART2_RX);
0205 }
0206 if (uart3_ck != NULL) {
0207 if (enable)
0208 omap_cfg_reg(L14_16XX_GPIO49);
0209 else
0210 omap_cfg_reg(L14_16XX_UART3_RX);
0211 }
0212 }
0213
0214 static void __init omap_serial_set_port_wakeup(int gpio_nr)
0215 {
0216 int ret;
0217
0218 ret = gpio_request(gpio_nr, "UART wake");
0219 if (ret < 0) {
0220 printk(KERN_ERR "Could not request UART wake GPIO: %i\n",
0221 gpio_nr);
0222 return;
0223 }
0224 gpio_direction_input(gpio_nr);
0225 ret = request_irq(gpio_to_irq(gpio_nr), &omap_serial_wake_interrupt,
0226 IRQF_TRIGGER_RISING, "serial wakeup", NULL);
0227 if (ret) {
0228 gpio_free(gpio_nr);
0229 printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n",
0230 gpio_nr);
0231 return;
0232 }
0233 enable_irq_wake(gpio_to_irq(gpio_nr));
0234 }
0235
0236 int __init omap_serial_wakeup_init(void)
0237 {
0238 if (!cpu_is_omap16xx())
0239 return 0;
0240
0241 if (uart1_ck != NULL)
0242 omap_serial_set_port_wakeup(37);
0243 if (uart2_ck != NULL)
0244 omap_serial_set_port_wakeup(18);
0245 if (uart3_ck != NULL)
0246 omap_serial_set_port_wakeup(49);
0247
0248 return 0;
0249 }
0250
0251 #endif
0252
0253 static int __init omap_init(void)
0254 {
0255 if (!cpu_class_is_omap1())
0256 return -ENODEV;
0257
0258 return platform_device_register(&serial_device);
0259 }
0260 arch_initcall(omap_init);