1/* 2 * linux/arch/arm/mach-omap1/board-voiceblue.c 3 * 4 * Modified from board-generic.c 5 * 6 * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz> 7 * 8 * Code for OMAP5910 based VoiceBlue board (VoIP to GSM gateway). 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/delay.h> 16#include <linux/gpio.h> 17#include <linux/platform_device.h> 18#include <linux/interrupt.h> 19#include <linux/irq.h> 20#include <linux/init.h> 21#include <linux/kernel.h> 22#include <linux/mtd/physmap.h> 23#include <linux/notifier.h> 24#include <linux/reboot.h> 25#include <linux/serial_8250.h> 26#include <linux/serial_reg.h> 27#include <linux/smc91x.h> 28#include <linux/export.h> 29#include <linux/reboot.h> 30 31#include <asm/mach-types.h> 32#include <asm/mach/arch.h> 33#include <asm/mach/map.h> 34 35#include <mach/board-voiceblue.h> 36#include <mach/flash.h> 37#include <mach/mux.h> 38#include <mach/tc.h> 39 40#include <mach/hardware.h> 41#include <mach/usb.h> 42 43#include "common.h" 44 45static struct plat_serial8250_port voiceblue_ports[] = { 46 { 47 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x40000), 48 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 49 .iotype = UPIO_MEM, 50 .regshift = 1, 51 .uartclk = 3686400, 52 }, 53 { 54 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x50000), 55 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 56 .iotype = UPIO_MEM, 57 .regshift = 1, 58 .uartclk = 3686400, 59 }, 60 { 61 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x60000), 62 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 63 .iotype = UPIO_MEM, 64 .regshift = 1, 65 .uartclk = 3686400, 66 }, 67 { 68 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x70000), 69 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 70 .iotype = UPIO_MEM, 71 .regshift = 1, 72 .uartclk = 3686400, 73 }, 74 { }, 75}; 76 77static struct platform_device serial_device = { 78 .name = "serial8250", 79 .id = PLAT8250_DEV_PLATFORM1, 80}; 81 82static int __init ext_uart_init(void) 83{ 84 if (!machine_is_voiceblue()) 85 return -ENODEV; 86 87 voiceblue_ports[0].irq = gpio_to_irq(12); 88 voiceblue_ports[1].irq = gpio_to_irq(13); 89 voiceblue_ports[2].irq = gpio_to_irq(14); 90 voiceblue_ports[3].irq = gpio_to_irq(15); 91 serial_device.dev.platform_data = voiceblue_ports; 92 return platform_device_register(&serial_device); 93} 94arch_initcall(ext_uart_init); 95 96static struct physmap_flash_data voiceblue_flash_data = { 97 .width = 2, 98 .set_vpp = omap1_set_vpp, 99}; 100 101static struct resource voiceblue_flash_resource = { 102 .start = OMAP_CS0_PHYS, 103 .end = OMAP_CS0_PHYS + SZ_32M - 1, 104 .flags = IORESOURCE_MEM, 105}; 106 107static struct platform_device voiceblue_flash_device = { 108 .name = "physmap-flash", 109 .id = 0, 110 .dev = { 111 .platform_data = &voiceblue_flash_data, 112 }, 113 .num_resources = 1, 114 .resource = &voiceblue_flash_resource, 115}; 116 117static struct smc91x_platdata voiceblue_smc91x_info = { 118 .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, 119 .leda = RPC_LED_100_10, 120 .ledb = RPC_LED_TX_RX, 121}; 122 123static struct resource voiceblue_smc91x_resources[] = { 124 [0] = { 125 .start = OMAP_CS2_PHYS + 0x300, 126 .end = OMAP_CS2_PHYS + 0x300 + 16, 127 .flags = IORESOURCE_MEM, 128 }, 129 [1] = { 130 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 131 }, 132}; 133 134static struct platform_device voiceblue_smc91x_device = { 135 .name = "smc91x", 136 .id = 0, 137 .dev = { 138 .platform_data = &voiceblue_smc91x_info, 139 }, 140 .num_resources = ARRAY_SIZE(voiceblue_smc91x_resources), 141 .resource = voiceblue_smc91x_resources, 142}; 143 144static struct platform_device *voiceblue_devices[] __initdata = { 145 &voiceblue_flash_device, 146 &voiceblue_smc91x_device, 147}; 148 149static struct omap_usb_config voiceblue_usb_config __initdata = { 150 .hmc_mode = 3, 151 .register_host = 1, 152 .register_dev = 1, 153 .pins[0] = 2, 154 .pins[1] = 6, 155 .pins[2] = 6, 156}; 157 158#define MACHINE_PANICED 1 159#define MACHINE_REBOOTING 2 160#define MACHINE_REBOOT 4 161static unsigned long machine_state; 162 163static int panic_event(struct notifier_block *this, unsigned long event, 164 void *ptr) 165{ 166 if (test_and_set_bit(MACHINE_PANICED, &machine_state)) 167 return NOTIFY_DONE; 168 169 /* Flash power LED */ 170 omap_writeb(0x78, OMAP_LPG1_LCR); 171 omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */ 172 173 return NOTIFY_DONE; 174} 175 176static struct notifier_block panic_block = { 177 .notifier_call = panic_event, 178}; 179 180static int __init voiceblue_setup(void) 181{ 182 if (!machine_is_voiceblue()) 183 return -ENODEV; 184 185 /* Setup panic notifier */ 186 atomic_notifier_chain_register(&panic_notifier_list, &panic_block); 187 188 return 0; 189} 190postcore_initcall(voiceblue_setup); 191 192static int wdt_gpio_state; 193 194void voiceblue_wdt_enable(void) 195{ 196 gpio_direction_output(0, 0); 197 gpio_set_value(0, 1); 198 gpio_set_value(0, 0); 199 wdt_gpio_state = 0; 200} 201 202void voiceblue_wdt_disable(void) 203{ 204 gpio_set_value(0, 0); 205 gpio_set_value(0, 1); 206 gpio_set_value(0, 0); 207 gpio_direction_input(0); 208} 209 210void voiceblue_wdt_ping(void) 211{ 212 if (test_bit(MACHINE_REBOOT, &machine_state)) 213 return; 214 215 wdt_gpio_state = !wdt_gpio_state; 216 gpio_set_value(0, wdt_gpio_state); 217} 218 219static void voiceblue_restart(enum reboot_mode mode, const char *cmd) 220{ 221 /* 222 * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28 223 * "Global Software Reset Affects Traffic Controller Frequency". 224 */ 225 if (cpu_is_omap5912()) { 226 omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4), DPLL_CTL); 227 omap_writew(0x8, ARM_RSTCT1); 228 } 229 230 set_bit(MACHINE_REBOOT, &machine_state); 231 voiceblue_wdt_enable(); 232 while (1) ; 233} 234 235EXPORT_SYMBOL(voiceblue_wdt_enable); 236EXPORT_SYMBOL(voiceblue_wdt_disable); 237EXPORT_SYMBOL(voiceblue_wdt_ping); 238 239static void __init voiceblue_init(void) 240{ 241 /* mux pins for uarts */ 242 omap_cfg_reg(UART1_TX); 243 omap_cfg_reg(UART1_RTS); 244 omap_cfg_reg(UART2_TX); 245 omap_cfg_reg(UART2_RTS); 246 omap_cfg_reg(UART3_TX); 247 omap_cfg_reg(UART3_RX); 248 249 /* Watchdog */ 250 gpio_request(0, "Watchdog"); 251 /* smc91x reset */ 252 gpio_request(7, "SMC91x reset"); 253 gpio_direction_output(7, 1); 254 udelay(2); /* wait at least 100ns */ 255 gpio_set_value(7, 0); 256 mdelay(50); /* 50ms until PHY ready */ 257 /* smc91x interrupt pin */ 258 gpio_request(8, "SMC91x irq"); 259 /* 16C554 reset*/ 260 gpio_request(6, "16C554 reset"); 261 gpio_direction_output(6, 0); 262 /* 16C554 interrupt pins */ 263 gpio_request(12, "16C554 irq"); 264 gpio_request(13, "16C554 irq"); 265 gpio_request(14, "16C554 irq"); 266 gpio_request(15, "16C554 irq"); 267 irq_set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING); 268 irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING); 269 irq_set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING); 270 irq_set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING); 271 272 voiceblue_smc91x_resources[1].start = gpio_to_irq(8); 273 voiceblue_smc91x_resources[1].end = gpio_to_irq(8); 274 platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices)); 275 omap_serial_init(); 276 omap1_usb_init(&voiceblue_usb_config); 277 omap_register_i2c_bus(1, 100, NULL, 0); 278 279 /* There is a good chance board is going up, so enable power LED 280 * (it is connected through invertor) */ 281 omap_writeb(0x00, OMAP_LPG1_LCR); 282 omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ 283} 284 285MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910") 286 /* Maintainer: Ladislav Michl <michl@2n.cz> */ 287 .atag_offset = 0x100, 288 .map_io = omap15xx_map_io, 289 .init_early = omap1_init_early, 290 .init_irq = omap1_init_irq, 291 .init_machine = voiceblue_init, 292 .init_late = omap1_init_late, 293 .init_time = omap1_timer_init, 294 .restart = voiceblue_restart, 295MACHINE_END 296