1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  NEC VR4100 series SIU platform device.
4  *
5  *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@linux-mips.org>
6  */
7 #include <linux/errno.h>
8 #include <linux/init.h>
9 #include <linux/ioport.h>
10 #include <linux/platform_device.h>
11 #include <linux/serial_core.h>
12 #include <linux/irq.h>
13 
14 #include <asm/cpu.h>
15 #include <asm/vr41xx/siu.h>
16 
17 static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = {
18 	PORT_VR41XX_SIU,
19 	PORT_UNKNOWN,
20 };
21 
22 static struct resource siu_type1_resource[] __initdata = {
23 	{
24 		.start	= 0x0c000000,
25 		.end	= 0x0c00000a,
26 		.flags	= IORESOURCE_MEM,
27 	},
28 	{
29 		.start	= SIU_IRQ,
30 		.end	= SIU_IRQ,
31 		.flags	= IORESOURCE_IRQ,
32 	},
33 };
34 
35 static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = {
36 	PORT_VR41XX_SIU,
37 	PORT_VR41XX_DSIU,
38 };
39 
40 static struct resource siu_type2_resource[] __initdata = {
41 	{
42 		.start	= 0x0f000800,
43 		.end	= 0x0f00080a,
44 		.flags	= IORESOURCE_MEM,
45 	},
46 	{
47 		.start	= 0x0f000820,
48 		.end	= 0x0f000829,
49 		.flags	= IORESOURCE_MEM,
50 	},
51 	{
52 		.start	= SIU_IRQ,
53 		.end	= SIU_IRQ,
54 		.flags	= IORESOURCE_IRQ,
55 	},
56 	{
57 		.start	= DSIU_IRQ,
58 		.end	= DSIU_IRQ,
59 		.flags	= IORESOURCE_IRQ,
60 	},
61 };
62 
vr41xx_siu_add(void)63 static int __init vr41xx_siu_add(void)
64 {
65 	struct platform_device *pdev;
66 	struct resource *res;
67 	unsigned int num;
68 	int retval;
69 
70 	pdev = platform_device_alloc("SIU", -1);
71 	if (!pdev)
72 		return -ENOMEM;
73 
74 	switch (current_cpu_type()) {
75 	case CPU_VR4111:
76 	case CPU_VR4121:
77 		pdev->dev.platform_data = siu_type1_ports;
78 		res = siu_type1_resource;
79 		num = ARRAY_SIZE(siu_type1_resource);
80 		break;
81 	case CPU_VR4122:
82 	case CPU_VR4131:
83 	case CPU_VR4133:
84 		pdev->dev.platform_data = siu_type2_ports;
85 		res = siu_type2_resource;
86 		num = ARRAY_SIZE(siu_type2_resource);
87 		break;
88 	default:
89 		retval = -ENODEV;
90 		goto err_free_device;
91 	}
92 
93 	retval = platform_device_add_resources(pdev, res, num);
94 	if (retval)
95 		goto err_free_device;
96 
97 	retval = platform_device_add(pdev);
98 	if (retval)
99 		goto err_free_device;
100 
101 	return 0;
102 
103 err_free_device:
104 	platform_device_put(pdev);
105 
106 	return retval;
107 }
108 device_initcall(vr41xx_siu_add);
109 
vr41xx_siu_setup(void)110 void __init vr41xx_siu_setup(void)
111 {
112 	struct uart_port port;
113 	struct resource *res;
114 	unsigned int *type;
115 	int i;
116 
117 	switch (current_cpu_type()) {
118 	case CPU_VR4111:
119 	case CPU_VR4121:
120 		type = siu_type1_ports;
121 		res = siu_type1_resource;
122 		break;
123 	case CPU_VR4122:
124 	case CPU_VR4131:
125 	case CPU_VR4133:
126 		type = siu_type2_ports;
127 		res = siu_type2_resource;
128 		break;
129 	default:
130 		return;
131 	}
132 
133 	for (i = 0; i < SIU_PORTS_MAX; i++) {
134 		port.line = i;
135 		port.type = type[i];
136 		if (port.type == PORT_UNKNOWN)
137 			break;
138 		port.mapbase = res[i].start;
139 		port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start);
140 		vr41xx_siu_early_setup(&port);
141 	}
142 }
143