1/* 2 * NEC VR4100 series SIU platform device. 3 * 4 * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20#include <linux/errno.h> 21#include <linux/init.h> 22#include <linux/ioport.h> 23#include <linux/platform_device.h> 24#include <linux/serial_core.h> 25 26#include <asm/cpu.h> 27#include <asm/vr41xx/siu.h> 28 29static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = { 30 PORT_VR41XX_SIU, 31 PORT_UNKNOWN, 32}; 33 34static struct resource siu_type1_resource[] __initdata = { 35 { 36 .start = 0x0c000000, 37 .end = 0x0c00000a, 38 .flags = IORESOURCE_MEM, 39 }, 40 { 41 .start = SIU_IRQ, 42 .end = SIU_IRQ, 43 .flags = IORESOURCE_IRQ, 44 }, 45}; 46 47static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = { 48 PORT_VR41XX_SIU, 49 PORT_VR41XX_DSIU, 50}; 51 52static struct resource siu_type2_resource[] __initdata = { 53 { 54 .start = 0x0f000800, 55 .end = 0x0f00080a, 56 .flags = IORESOURCE_MEM, 57 }, 58 { 59 .start = 0x0f000820, 60 .end = 0x0f000829, 61 .flags = IORESOURCE_MEM, 62 }, 63 { 64 .start = SIU_IRQ, 65 .end = SIU_IRQ, 66 .flags = IORESOURCE_IRQ, 67 }, 68 { 69 .start = DSIU_IRQ, 70 .end = DSIU_IRQ, 71 .flags = IORESOURCE_IRQ, 72 }, 73}; 74 75static int __init vr41xx_siu_add(void) 76{ 77 struct platform_device *pdev; 78 struct resource *res; 79 unsigned int num; 80 int retval; 81 82 pdev = platform_device_alloc("SIU", -1); 83 if (!pdev) 84 return -ENOMEM; 85 86 switch (current_cpu_type()) { 87 case CPU_VR4111: 88 case CPU_VR4121: 89 pdev->dev.platform_data = siu_type1_ports; 90 res = siu_type1_resource; 91 num = ARRAY_SIZE(siu_type1_resource); 92 break; 93 case CPU_VR4122: 94 case CPU_VR4131: 95 case CPU_VR4133: 96 pdev->dev.platform_data = siu_type2_ports; 97 res = siu_type2_resource; 98 num = ARRAY_SIZE(siu_type2_resource); 99 break; 100 default: 101 retval = -ENODEV; 102 goto err_free_device; 103 } 104 105 retval = platform_device_add_resources(pdev, res, num); 106 if (retval) 107 goto err_free_device; 108 109 retval = platform_device_add(pdev); 110 if (retval) 111 goto err_free_device; 112 113 return 0; 114 115err_free_device: 116 platform_device_put(pdev); 117 118 return retval; 119} 120device_initcall(vr41xx_siu_add); 121 122void __init vr41xx_siu_setup(void) 123{ 124 struct uart_port port; 125 struct resource *res; 126 unsigned int *type; 127 int i; 128 129 switch (current_cpu_type()) { 130 case CPU_VR4111: 131 case CPU_VR4121: 132 type = siu_type1_ports; 133 res = siu_type1_resource; 134 break; 135 case CPU_VR4122: 136 case CPU_VR4131: 137 case CPU_VR4133: 138 type = siu_type2_ports; 139 res = siu_type2_resource; 140 break; 141 default: 142 return; 143 } 144 145 for (i = 0; i < SIU_PORTS_MAX; i++) { 146 port.line = i; 147 port.type = type[i]; 148 if (port.type == PORT_UNKNOWN) 149 break; 150 port.mapbase = res[i].start; 151 port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start); 152 vr41xx_siu_early_setup(&port); 153 } 154} 155