1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * DEC platform devices.
4 *
5 * Copyright (c) 2014 Maciej W. Rozycki
6 */
7
8 #include <linux/ioport.h>
9 #include <linux/kernel.h>
10 #include <linux/mc146818rtc.h>
11 #include <linux/platform_device.h>
12
13 #include <asm/bootinfo.h>
14
15 #include <asm/dec/interrupts.h>
16 #include <asm/dec/ioasic_addrs.h>
17 #include <asm/dec/kn01.h>
18 #include <asm/dec/kn02.h>
19 #include <asm/dec/system.h>
20
21 static struct resource dec_rtc_resources[] = {
22 {
23 .name = "rtc",
24 .flags = IORESOURCE_MEM,
25 },
26 };
27
28 static struct cmos_rtc_board_info dec_rtc_info = {
29 .flags = CMOS_RTC_FLAGS_NOFREQ,
30 .address_space = 64,
31 };
32
33 static struct platform_device dec_rtc_device = {
34 .name = "rtc_cmos",
35 .id = PLATFORM_DEVID_NONE,
36 .dev.platform_data = &dec_rtc_info,
37 .resource = dec_rtc_resources,
38 .num_resources = ARRAY_SIZE(dec_rtc_resources),
39 };
40
41 static struct platform_device *dec_rtc_devices[] __initdata = {
42 &dec_rtc_device,
43 };
44
45 static struct resource dec_dz_resources[] = {
46 { .name = "dz", .flags = IORESOURCE_MEM, },
47 { .name = "dz", .flags = IORESOURCE_IRQ, },
48 };
49
50 static struct platform_device dec_dz_device = {
51 .name = "dz",
52 .id = PLATFORM_DEVID_NONE,
53 .resource = dec_dz_resources,
54 .num_resources = ARRAY_SIZE(dec_dz_resources),
55 };
56
57 static struct platform_device *dec_dz_devices[] __initdata = {
58 &dec_dz_device,
59 };
60
61 static struct resource dec_zs_resources[][2] = {
62 {
63 { .name = "scc0", .flags = IORESOURCE_MEM, },
64 { .name = "scc0", .flags = IORESOURCE_IRQ, },
65 },
66 {
67 { .name = "scc1", .flags = IORESOURCE_MEM, },
68 { .name = "scc1", .flags = IORESOURCE_IRQ, },
69 },
70 };
71
72 static struct platform_device dec_zs_device[] = {
73 {
74 .name = "zs",
75 .id = 0,
76 .resource = dec_zs_resources[0],
77 .num_resources = ARRAY_SIZE(dec_zs_resources[0]),
78 },
79 {
80 .name = "zs",
81 .id = 1,
82 .resource = dec_zs_resources[1],
83 .num_resources = ARRAY_SIZE(dec_zs_resources[1]),
84 },
85 };
86
dec_add_devices(void)87 static int __init dec_add_devices(void)
88 {
89 struct platform_device *dec_zs_devices[ARRAY_SIZE(dec_zs_device)];
90 int ret1, ret2, ret3;
91 int num_dz, num_zs;
92 int irq, i;
93
94 dec_rtc_resources[0].start = RTC_PORT(0);
95 dec_rtc_resources[0].end = RTC_PORT(0) + dec_kn_slot_size - 1;
96
97 i = 0;
98 irq = dec_interrupt[DEC_IRQ_DZ11];
99 if (IS_ENABLED(CONFIG_32BIT) && irq >= 0) {
100 resource_size_t base;
101
102 switch (mips_machtype) {
103 case MACH_DS23100:
104 case MACH_DS5100:
105 base = dec_kn_slot_base + KN01_DZ11;
106 break;
107 default:
108 base = dec_kn_slot_base + KN02_DZ11;
109 break;
110 }
111 dec_dz_device.resource[0].start = base;
112 dec_dz_device.resource[0].end = base + dec_kn_slot_size - 1;
113 dec_dz_device.resource[1].start = irq;
114 dec_dz_device.resource[1].end = irq;
115 i++;
116 }
117 num_dz = i;
118
119 i = 0;
120 irq = dec_interrupt[DEC_IRQ_SCC0];
121 if (irq >= 0) {
122 resource_size_t base = dec_kn_slot_base + IOASIC_SCC0;
123
124 dec_zs_device[i].resource[0].start = base;
125 dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1;
126 dec_zs_device[i].resource[1].start = irq;
127 dec_zs_device[i].resource[1].end = irq;
128 dec_zs_devices[i] = &dec_zs_device[i];
129 i++;
130 }
131 irq = dec_interrupt[DEC_IRQ_SCC1];
132 if (irq >= 0) {
133 resource_size_t base = dec_kn_slot_base + IOASIC_SCC1;
134
135 dec_zs_device[i].resource[0].start = base;
136 dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1;
137 dec_zs_device[i].resource[1].start = irq;
138 dec_zs_device[i].resource[1].end = irq;
139 dec_zs_devices[i] = &dec_zs_device[i];
140 i++;
141 }
142 num_zs = i;
143
144 ret1 = platform_add_devices(dec_rtc_devices, 1);
145 ret2 = IS_ENABLED(CONFIG_32BIT) ?
146 platform_add_devices(dec_dz_devices, num_dz) : 0;
147 ret3 = platform_add_devices(dec_zs_devices, num_zs);
148 return ret1 ? ret1 : ret2 ? ret2 : ret3;
149 }
150
151 device_initcall(dec_add_devices);
152