| // SPDX-License-Identifier: GPL-2.0-or-later |
| /* |
| * DEC platform devices. |
| * |
| * Copyright (c) 2014 Maciej W. Rozycki |
| */ |
| |
| #include <linux/ioport.h> |
| #include <linux/kernel.h> |
| #include <linux/mc146818rtc.h> |
| #include <linux/platform_device.h> |
| |
| #include <asm/bootinfo.h> |
| |
| #include <asm/dec/interrupts.h> |
| #include <asm/dec/ioasic_addrs.h> |
| #include <asm/dec/kn01.h> |
| #include <asm/dec/kn02.h> |
| #include <asm/dec/system.h> |
| |
| static struct resource dec_rtc_resources[] = { |
| { |
| .name = "rtc", |
| .flags = IORESOURCE_MEM, |
| }, |
| }; |
| |
| static struct cmos_rtc_board_info dec_rtc_info = { |
| .flags = CMOS_RTC_FLAGS_NOFREQ, |
| .address_space = 64, |
| }; |
| |
| static struct platform_device dec_rtc_device = { |
| .name = "rtc_cmos", |
| .id = PLATFORM_DEVID_NONE, |
| .dev.platform_data = &dec_rtc_info, |
| .resource = dec_rtc_resources, |
| .num_resources = ARRAY_SIZE(dec_rtc_resources), |
| }; |
| |
| static struct resource dec_dz_resources[] = { |
| { .name = "dz", .flags = IORESOURCE_MEM, }, |
| { .name = "dz", .flags = IORESOURCE_IRQ, }, |
| }; |
| |
| static struct platform_device dec_dz_device = { |
| .name = "dz", |
| .id = PLATFORM_DEVID_NONE, |
| .resource = dec_dz_resources, |
| .num_resources = ARRAY_SIZE(dec_dz_resources), |
| }; |
| |
| static struct platform_device *dec_dz_devices[] __initdata = { |
| &dec_dz_device, |
| }; |
| |
| static struct resource dec_zs_resources[][2] = { |
| { |
| { .name = "scc0", .flags = IORESOURCE_MEM, }, |
| { .name = "scc0", .flags = IORESOURCE_IRQ, }, |
| }, |
| { |
| { .name = "scc1", .flags = IORESOURCE_MEM, }, |
| { .name = "scc1", .flags = IORESOURCE_IRQ, }, |
| }, |
| }; |
| |
| static struct platform_device dec_zs_device[] = { |
| { |
| .name = "zs", |
| .id = 0, |
| .resource = dec_zs_resources[0], |
| .num_resources = ARRAY_SIZE(dec_zs_resources[0]), |
| }, |
| { |
| .name = "zs", |
| .id = 1, |
| .resource = dec_zs_resources[1], |
| .num_resources = ARRAY_SIZE(dec_zs_resources[1]), |
| }, |
| }; |
| |
| static int __init dec_add_devices(void) |
| { |
| struct platform_device *dec_zs_devices[ARRAY_SIZE(dec_zs_device)]; |
| int ret1, ret2, ret3; |
| int num_dz, num_zs; |
| int irq, i; |
| |
| dec_rtc_resources[0].start = RTC_PORT(0); |
| dec_rtc_resources[0].end = RTC_PORT(0) + dec_kn_slot_size - 1; |
| |
| i = 0; |
| irq = dec_interrupt[DEC_IRQ_DZ11]; |
| if (IS_ENABLED(CONFIG_32BIT) && irq >= 0) { |
| resource_size_t base; |
| |
| switch (mips_machtype) { |
| case MACH_DS23100: |
| case MACH_DS5100: |
| base = dec_kn_slot_base + KN01_DZ11; |
| break; |
| default: |
| base = dec_kn_slot_base + KN02_DZ11; |
| break; |
| } |
| dec_dz_device.resource[0].start = base; |
| dec_dz_device.resource[0].end = base + dec_kn_slot_size - 1; |
| dec_dz_device.resource[1].start = irq; |
| dec_dz_device.resource[1].end = irq; |
| i++; |
| } |
| num_dz = i; |
| |
| i = 0; |
| irq = dec_interrupt[DEC_IRQ_SCC0]; |
| if (irq >= 0) { |
| resource_size_t base = dec_kn_slot_base + IOASIC_SCC0; |
| |
| dec_zs_device[i].resource[0].start = base; |
| dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1; |
| dec_zs_device[i].resource[1].start = irq; |
| dec_zs_device[i].resource[1].end = irq; |
| dec_zs_devices[i] = &dec_zs_device[i]; |
| i++; |
| } |
| irq = dec_interrupt[DEC_IRQ_SCC1]; |
| if (irq >= 0) { |
| resource_size_t base = dec_kn_slot_base + IOASIC_SCC1; |
| |
| dec_zs_device[i].resource[0].start = base; |
| dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1; |
| dec_zs_device[i].resource[1].start = irq; |
| dec_zs_device[i].resource[1].end = irq; |
| dec_zs_devices[i] = &dec_zs_device[i]; |
| i++; |
| } |
| num_zs = i; |
| |
| ret1 = platform_device_register(&dec_rtc_device); |
| ret2 = IS_ENABLED(CONFIG_32BIT) ? |
| platform_add_devices(dec_dz_devices, num_dz) : 0; |
| ret3 = platform_add_devices(dec_zs_devices, num_zs); |
| return ret1 ? ret1 : ret2 ? ret2 : ret3; |
| } |
| |
| device_initcall(dec_add_devices); |