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#include <linux/irq.h> 26 27#include <asm/cpu.h> 28#include <asm/vr41xx/siu.h> 29 30static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = { 31 PORT_VR41XX_SIU, 32 PORT_UNKNOWN, 33}; 34 35static struct resource siu_type1_resource[] __initdata = { 36 { 37 .start = 0x0c000000, 38 .end = 0x0c00000a, 39 .flags = IORESOURCE_MEM, 40 }, 41 { 42 .start = SIU_IRQ, 43 .end = SIU_IRQ, 44 .flags = IORESOURCE_IRQ, 45 }, 46}; 47 48static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = { 49 PORT_VR41XX_SIU, 50 PORT_VR41XX_DSIU, 51}; 52 53static struct resource siu_type2_resource[] __initdata = { 54 { 55 .start = 0x0f000800, 56 .end = 0x0f00080a, 57 .flags = IORESOURCE_MEM, 58 }, 59 { 60 .start = 0x0f000820, 61 .end = 0x0f000829, 62 .flags = IORESOURCE_MEM, 63 }, 64 { 65 .start = SIU_IRQ, 66 .end = SIU_IRQ, 67 .flags = IORESOURCE_IRQ, 68 }, 69 { 70 .start = DSIU_IRQ, 71 .end = DSIU_IRQ, 72 .flags = IORESOURCE_IRQ, 73 }, 74}; 75 76static int __init vr41xx_siu_add(void) 77{ 78 struct platform_device *pdev; 79 struct resource *res; 80 unsigned int num; 81 int retval; 82 83 pdev = platform_device_alloc("SIU", -1); 84 if (!pdev) 85 return -ENOMEM; 86 87 switch (current_cpu_type()) { 88 case CPU_VR4111: 89 case CPU_VR4121: 90 pdev->dev.platform_data = siu_type1_ports; 91 res = siu_type1_resource; 92 num = ARRAY_SIZE(siu_type1_resource); 93 break; 94 case CPU_VR4122: 95 case CPU_VR4131: 96 case CPU_VR4133: 97 pdev->dev.platform_data = siu_type2_ports; 98 res = siu_type2_resource; 99 num = ARRAY_SIZE(siu_type2_resource); 100 break; 101 default: 102 retval = -ENODEV; 103 goto err_free_device; 104 } 105 106 retval = platform_device_add_resources(pdev, res, num); 107 if (retval) 108 goto err_free_device; 109 110 retval = platform_device_add(pdev); 111 if (retval) 112 goto err_free_device; 113 114 return 0; 115 116err_free_device: 117 platform_device_put(pdev); 118 119 return retval; 120} 121device_initcall(vr41xx_siu_add); 122 123void __init vr41xx_siu_setup(void) 124{ 125 struct uart_port port; 126 struct resource *res; 127 unsigned int *type; 128 int i; 129 130 switch (current_cpu_type()) { 131 case CPU_VR4111: 132 case CPU_VR4121: 133 type = siu_type1_ports; 134 res = siu_type1_resource; 135 break; 136 case CPU_VR4122: 137 case CPU_VR4131: 138 case CPU_VR4133: 139 type = siu_type2_ports; 140 res = siu_type2_resource; 141 break; 142 default: 143 return; 144 } 145 146 for (i = 0; i < SIU_PORTS_MAX; i++) { 147 port.line = i; 148 port.type = type[i]; 149 if (port.type == PORT_UNKNOWN) 150 break; 151 port.mapbase = res[i].start; 152 port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start); 153 vr41xx_siu_early_setup(&port); 154 } 155} 156