^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * arch/arm/mach-iop32x/n2100.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Board support code for the Thecus N2100 platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Rory Bolt <rorybolt@pacbell.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2002 Rory Bolt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2003 (c) MontaVista, Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2004 Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/f75375s.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/leds-pca9532.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/serial_8250.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mtd/physmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/gpio/machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/mach/arch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/mach/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/mach/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/mach/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/mach-types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "hardware.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "irqs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include "gpio-iop32x.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * N2100 timer tick configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static void __init n2100_timer_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* 33.000 MHz crystal. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) iop_init_time(198000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * N2100 I/O.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static struct map_desc n2100_io_desc[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { /* on-board devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .virtual = N2100_UART,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .pfn = __phys_to_pfn(N2100_UART),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .length = 0x00100000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .type = MT_DEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) void __init n2100_map_io(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) iop3xx_map_io();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) iotable_init(n2100_io_desc, ARRAY_SIZE(n2100_io_desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * N2100 PCI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (PCI_SLOT(dev->devfn) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* RTL8110SB #1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) irq = IRQ_IOP32X_XINT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) } else if (PCI_SLOT(dev->devfn) == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* RTL8110SB #2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) irq = IRQ_IOP32X_XINT3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) } else if (PCI_SLOT(dev->devfn) == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Sil3512 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) irq = IRQ_IOP32X_XINT2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) } else if (PCI_SLOT(dev->devfn) == 4 && pin == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* VT6212 INTA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) irq = IRQ_IOP32X_XINT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) } else if (PCI_SLOT(dev->devfn) == 4 && pin == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* VT6212 INTB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) irq = IRQ_IOP32X_XINT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) } else if (PCI_SLOT(dev->devfn) == 4 && pin == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* VT6212 INTC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) irq = IRQ_IOP32X_XINT2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) } else if (PCI_SLOT(dev->devfn) == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* Mini-PCI slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) irq = IRQ_IOP32X_XINT3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) printk(KERN_ERR "n2100_pci_map_irq() called for unknown "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "device PCI:%d:%d:%d\n", dev->bus->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static struct hw_pci n2100_pci __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .nr_controllers = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .ops = &iop3xx_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .setup = iop3xx_pci_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .preinit = iop3xx_pci_preinit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .map_irq = n2100_pci_map_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Both r8169 chips on the n2100 exhibit PCI parity problems. Set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * the ->broken_parity_status flag for both ports so that the r8169
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * driver knows it should ignore error interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static void n2100_fixup_r8169(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (dev->bus->number == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) (dev->devfn == PCI_DEVFN(1, 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) dev->devfn == PCI_DEVFN(2, 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dev->broken_parity_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int __init n2100_pci_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (machine_is_n2100())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pci_common_init(&n2100_pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) subsys_initcall(n2100_pci_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * N2100 machine initialisation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static struct physmap_flash_data n2100_flash_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .width = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static struct resource n2100_flash_resource = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .start = 0xf0000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .end = 0xf0ffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static struct platform_device n2100_flash_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .name = "physmap-flash",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .platform_data = &n2100_flash_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .num_resources = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .resource = &n2100_flash_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static struct plat_serial8250_port n2100_serial_port[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .mapbase = N2100_UART,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .membase = (char *)N2100_UART,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .irq = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .flags = UPF_SKIP_TEST | UPF_AUTO_IRQ | UPF_SHARE_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .iotype = UPIO_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .regshift = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .uartclk = 1843200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static struct resource n2100_uart_resource = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .start = N2100_UART,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .end = N2100_UART + 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static struct platform_device n2100_serial_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .name = "serial8250",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .id = PLAT8250_DEV_PLATFORM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .platform_data = n2100_serial_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .num_resources = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .resource = &n2100_uart_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static struct f75375s_platform_data n2100_f75375s = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .pwm = { 255, 255 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .pwm_enable = { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static struct pca9532_platform_data n2100_leds = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .leds = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { .name = "n2100:red:satafail0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .state = PCA9532_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .type = PCA9532_TYPE_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { .name = "n2100:red:satafail1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .state = PCA9532_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .type = PCA9532_TYPE_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { .name = "n2100:blue:usb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .state = PCA9532_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .type = PCA9532_TYPE_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) { .type = PCA9532_TYPE_NONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { .type = PCA9532_TYPE_NONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) { .type = PCA9532_TYPE_NONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) { .type = PCA9532_TYPE_NONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) { .name = "n2100:red:usb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .state = PCA9532_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .type = PCA9532_TYPE_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { .type = PCA9532_TYPE_NONE }, /* power OFF gpio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { .type = PCA9532_TYPE_NONE }, /* reset gpio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { .type = PCA9532_TYPE_NONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { .type = PCA9532_TYPE_NONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) { .type = PCA9532_TYPE_NONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) { .name = "n2100:orange:system",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .state = PCA9532_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .type = PCA9532_TYPE_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) { .name = "n2100:red:system",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .state = PCA9532_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .type = PCA9532_TYPE_LED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) { .name = "N2100 beeper" ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .state = PCA9532_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .type = PCA9532_TYPE_N2100_BEEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .psc = { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .pwm = { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static struct i2c_board_info __initdata n2100_i2c_devices[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) I2C_BOARD_INFO("rs5c372b", 0x32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) I2C_BOARD_INFO("f75375", 0x2e),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .platform_data = &n2100_f75375s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) I2C_BOARD_INFO("pca9532", 0x60),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .platform_data = &n2100_leds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * Pull PCA9532 GPIO #8 low to power off the machine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static void n2100_power_off(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Start condition, I2C address of PCA9532, write transaction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) *IOP3XX_IDBR0 = 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) *IOP3XX_ICR0 = 0xe9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Write address 0x08. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) *IOP3XX_IDBR0 = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *IOP3XX_ICR0 = 0xe8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Write data 0x01, stop condition. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *IOP3XX_IDBR0 = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) *IOP3XX_ICR0 = 0xea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) while (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static void n2100_restart(enum reboot_mode mode, const char *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ret = gpio_direction_output(N2100_HARDWARE_RESET, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pr_crit("could not drive reset GPIO low\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* Wait for reset to happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) while (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static struct timer_list power_button_poll_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void power_button_poll(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (gpio_get_value(N2100_POWER_BUTTON) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ctrl_alt_del();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) power_button_poll_timer.expires = jiffies + (HZ / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) add_timer(&power_button_poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int __init n2100_request_gpios(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (!machine_is_n2100())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ret = gpio_request(N2100_HARDWARE_RESET, "reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pr_err("could not request reset GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ret = gpio_request(N2100_POWER_BUTTON, "power");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) pr_err("could not request power GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret = gpio_direction_input(N2100_POWER_BUTTON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) pr_err("could not set power GPIO as input\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* Set up power button poll timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) timer_setup(&power_button_poll_timer, power_button_poll, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) power_button_poll_timer.expires = jiffies + (HZ / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) add_timer(&power_button_poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) device_initcall(n2100_request_gpios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static void __init n2100_init_machine(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) register_iop32x_gpio();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) gpiod_add_lookup_table(&iop3xx_i2c0_gpio_lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) platform_device_register(&iop3xx_i2c0_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) platform_device_register(&n2100_flash_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) platform_device_register(&n2100_serial_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) platform_device_register(&iop3xx_dma_0_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) platform_device_register(&iop3xx_dma_1_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) i2c_register_board_info(0, n2100_i2c_devices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ARRAY_SIZE(n2100_i2c_devices));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) pm_power_off = n2100_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) MACHINE_START(N2100, "Thecus N2100")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) .atag_offset = 0x100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) .map_io = n2100_map_io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) .init_irq = iop32x_init_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) .init_time = n2100_timer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) .init_machine = n2100_init_machine,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) .restart = n2100_restart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) MACHINE_END