1/* 2 * board-og.c -- support for the OpenGear KS8695 based boards. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9#include <linux/kernel.h> 10#include <linux/types.h> 11#include <linux/interrupt.h> 12#include <linux/init.h> 13#include <linux/delay.h> 14#include <linux/platform_device.h> 15#include <linux/serial_8250.h> 16#include <linux/gpio.h> 17#include <linux/irq.h> 18#include <asm/mach-types.h> 19#include <asm/mach/arch.h> 20#include <asm/mach/map.h> 21#include <mach/devices.h> 22#include <mach/regs-gpio.h> 23#include <mach/gpio-ks8695.h> 24#include "generic.h" 25 26static int og_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 27{ 28 if (machine_is_im4004() && (slot == 8)) 29 return KS8695_IRQ_EXTERN1; 30 return KS8695_IRQ_EXTERN0; 31} 32 33static struct ks8695_pci_cfg __initdata og_pci = { 34 .mode = KS8695_MODE_PCI, 35 .map_irq = og_pci_map_irq, 36}; 37 38static void __init og_register_pci(void) 39{ 40 /* Initialize the GPIO lines for interrupt mode */ 41 ks8695_gpio_interrupt(KS8695_GPIO_0, IRQ_TYPE_LEVEL_LOW); 42 43 /* Cardbus Slot */ 44 if (machine_is_im4004()) 45 ks8695_gpio_interrupt(KS8695_GPIO_1, IRQ_TYPE_LEVEL_LOW); 46 47 if (IS_ENABLED(CONFIG_PCI)) 48 ks8695_init_pci(&og_pci); 49} 50 51/* 52 * The PCI bus reset is driven by a dedicated GPIO line. Toggle it here 53 * and bring the PCI bus out of reset. 54 */ 55static void __init og_pci_bus_reset(void) 56{ 57 unsigned int rstline = 1; 58 59 /* Some boards use a different GPIO as the PCI reset line */ 60 if (machine_is_im4004()) 61 rstline = 2; 62 else if (machine_is_im42xx()) 63 rstline = 0; 64 65 gpio_request(rstline, "PCI reset"); 66 gpio_direction_output(rstline, 0); 67 68 /* Drive a reset on the PCI reset line */ 69 gpio_set_value(rstline, 1); 70 gpio_set_value(rstline, 0); 71 mdelay(100); 72 gpio_set_value(rstline, 1); 73 mdelay(100); 74} 75 76/* 77 * Direct connect serial ports (non-PCI that is). 78 */ 79#define S8250_PHYS 0x03800000 80#define S8250_VIRT 0xf4000000 81#define S8250_SIZE 0x00100000 82 83static struct __initdata map_desc og_io_desc[] = { 84 { 85 .virtual = S8250_VIRT, 86 .pfn = __phys_to_pfn(S8250_PHYS), 87 .length = S8250_SIZE, 88 .type = MT_DEVICE, 89 } 90}; 91 92static struct resource og_uart_resources[] = { 93 { 94 .start = S8250_VIRT, 95 .end = S8250_VIRT + S8250_SIZE, 96 .flags = IORESOURCE_MEM 97 }, 98}; 99 100static struct plat_serial8250_port og_uart_data[] = { 101 { 102 .mapbase = S8250_VIRT, 103 .membase = (char *) S8250_VIRT, 104 .irq = 3, 105 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, 106 .iotype = UPIO_MEM, 107 .regshift = 2, 108 .uartclk = 115200 * 16, 109 }, 110 { }, 111}; 112 113static struct platform_device og_uart = { 114 .name = "serial8250", 115 .id = 0, 116 .dev.platform_data = og_uart_data, 117 .num_resources = 1, 118 .resource = og_uart_resources 119}; 120 121static struct platform_device *og_devices[] __initdata = { 122 &og_uart 123}; 124 125static void __init og_init(void) 126{ 127 ks8695_register_gpios(); 128 129 if (machine_is_cm4002()) { 130 ks8695_gpio_interrupt(KS8695_GPIO_1, IRQ_TYPE_LEVEL_HIGH); 131 iotable_init(og_io_desc, ARRAY_SIZE(og_io_desc)); 132 platform_add_devices(og_devices, ARRAY_SIZE(og_devices)); 133 } else { 134 og_pci_bus_reset(); 135 og_register_pci(); 136 } 137 138 ks8695_add_device_lan(); 139 ks8695_add_device_wan(); 140} 141 142#ifdef CONFIG_MACH_CM4002 143MACHINE_START(CM4002, "OpenGear/CM4002") 144 /* OpenGear Inc. */ 145 .atag_offset = 0x100, 146 .map_io = ks8695_map_io, 147 .init_irq = ks8695_init_irq, 148 .init_machine = og_init, 149 .init_time = ks8695_timer_init, 150 .restart = ks8695_restart, 151MACHINE_END 152#endif 153 154#ifdef CONFIG_MACH_CM4008 155MACHINE_START(CM4008, "OpenGear/CM4008") 156 /* OpenGear Inc. */ 157 .atag_offset = 0x100, 158 .map_io = ks8695_map_io, 159 .init_irq = ks8695_init_irq, 160 .init_machine = og_init, 161 .init_time = ks8695_timer_init, 162 .restart = ks8695_restart, 163MACHINE_END 164#endif 165 166#ifdef CONFIG_MACH_CM41xx 167MACHINE_START(CM41XX, "OpenGear/CM41xx") 168 /* OpenGear Inc. */ 169 .atag_offset = 0x100, 170 .map_io = ks8695_map_io, 171 .init_irq = ks8695_init_irq, 172 .init_machine = og_init, 173 .init_time = ks8695_timer_init, 174 .restart = ks8695_restart, 175MACHINE_END 176#endif 177 178#ifdef CONFIG_MACH_IM4004 179MACHINE_START(IM4004, "OpenGear/IM4004") 180 /* OpenGear Inc. */ 181 .atag_offset = 0x100, 182 .map_io = ks8695_map_io, 183 .init_irq = ks8695_init_irq, 184 .init_machine = og_init, 185 .init_time = ks8695_timer_init, 186 .restart = ks8695_restart, 187MACHINE_END 188#endif 189 190#ifdef CONFIG_MACH_IM42xx 191MACHINE_START(IM42XX, "OpenGear/IM42xx") 192 /* OpenGear Inc. */ 193 .atag_offset = 0x100, 194 .map_io = ks8695_map_io, 195 .init_irq = ks8695_init_irq, 196 .init_machine = og_init, 197 .init_time = ks8695_timer_init, 198 .restart = ks8695_restart, 199MACHINE_END 200#endif 201