root/arch/x86/platform/ce4100/ce4100.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ce4100_power_off
  2. mem_serial_in
  3. ce4100_mem_serial_in
  4. ce4100_mem_serial_out
  5. ce4100_serial_fixup
  6. sdv_serial_fixup
  7. sdv_serial_fixup
  8. sdv_arch_setup
  9. sdv_pci_init
  10. x86_ce4100_early_setup

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Intel CE4100  platform specific setup code
   4  *
   5  * (C) Copyright 2010 Intel Corporation
   6  */
   7 #include <linux/init.h>
   8 #include <linux/kernel.h>
   9 #include <linux/irq.h>
  10 #include <linux/reboot.h>
  11 #include <linux/serial_reg.h>
  12 #include <linux/serial_8250.h>
  13 
  14 #include <asm/ce4100.h>
  15 #include <asm/prom.h>
  16 #include <asm/setup.h>
  17 #include <asm/i8259.h>
  18 #include <asm/io.h>
  19 #include <asm/io_apic.h>
  20 #include <asm/emergency-restart.h>
  21 
  22 /*
  23  * The CE4100 platform has an internal 8051 Microcontroller which is
  24  * responsible for signaling to the external Power Management Unit the
  25  * intention to reset, reboot or power off the system. This 8051 device has
  26  * its command register mapped at I/O port 0xcf9 and the value 0x4 is used
  27  * to power off the system.
  28  */
  29 static void ce4100_power_off(void)
  30 {
  31         outb(0x4, 0xcf9);
  32 }
  33 
  34 #ifdef CONFIG_SERIAL_8250
  35 
  36 static unsigned int mem_serial_in(struct uart_port *p, int offset)
  37 {
  38         offset = offset << p->regshift;
  39         return readl(p->membase + offset);
  40 }
  41 
  42 /*
  43  * The UART Tx interrupts are not set under some conditions and therefore serial
  44  * transmission hangs. This is a silicon issue and has not been root caused. The
  45  * workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT
  46  * bit of LSR register in interrupt handler to see whether at least one of these
  47  * two bits is set, if so then process the transmit request. If this workaround
  48  * is not applied, then the serial transmission may hang. This workaround is for
  49  * errata number 9 in Errata - B step.
  50 */
  51 
  52 static unsigned int ce4100_mem_serial_in(struct uart_port *p, int offset)
  53 {
  54         unsigned int ret, ier, lsr;
  55 
  56         if (offset == UART_IIR) {
  57                 offset = offset << p->regshift;
  58                 ret = readl(p->membase + offset);
  59                 if (ret & UART_IIR_NO_INT) {
  60                         /* see if the TX interrupt should have really set */
  61                         ier = mem_serial_in(p, UART_IER);
  62                         /* see if the UART's XMIT interrupt is enabled */
  63                         if (ier & UART_IER_THRI) {
  64                                 lsr = mem_serial_in(p, UART_LSR);
  65                                 /* now check to see if the UART should be
  66                                    generating an interrupt (but isn't) */
  67                                 if (lsr & (UART_LSR_THRE | UART_LSR_TEMT))
  68                                         ret &= ~UART_IIR_NO_INT;
  69                         }
  70                 }
  71         } else
  72                 ret =  mem_serial_in(p, offset);
  73         return ret;
  74 }
  75 
  76 static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value)
  77 {
  78         offset = offset << p->regshift;
  79         writel(value, p->membase + offset);
  80 }
  81 
  82 static void ce4100_serial_fixup(int port, struct uart_port *up,
  83         u32 *capabilities)
  84 {
  85 #ifdef CONFIG_EARLY_PRINTK
  86         /*
  87          * Over ride the legacy port configuration that comes from
  88          * asm/serial.h. Using the ioport driver then switching to the
  89          * PCI memmaped driver hangs the IOAPIC
  90          */
  91         if (up->iotype !=  UPIO_MEM32) {
  92                 up->uartclk  = 14745600;
  93                 up->mapbase = 0xdffe0200;
  94                 set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
  95                                 up->mapbase & PAGE_MASK);
  96                 up->membase =
  97                         (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
  98                 up->membase += up->mapbase & ~PAGE_MASK;
  99                 up->mapbase += port * 0x100;
 100                 up->membase += port * 0x100;
 101                 up->iotype   = UPIO_MEM32;
 102                 up->regshift = 2;
 103                 up->irq = 4;
 104         }
 105 #endif
 106         up->iobase = 0;
 107         up->serial_in = ce4100_mem_serial_in;
 108         up->serial_out = ce4100_mem_serial_out;
 109 
 110         *capabilities |= (1 << 12);
 111 }
 112 
 113 static __init void sdv_serial_fixup(void)
 114 {
 115         serial8250_set_isa_configurator(ce4100_serial_fixup);
 116 }
 117 
 118 #else
 119 static inline void sdv_serial_fixup(void) {};
 120 #endif
 121 
 122 static void __init sdv_arch_setup(void)
 123 {
 124         sdv_serial_fixup();
 125 }
 126 
 127 static void sdv_pci_init(void)
 128 {
 129         x86_of_pci_init();
 130 }
 131 
 132 /*
 133  * CE4100 specific x86_init function overrides and early setup
 134  * calls.
 135  */
 136 void __init x86_ce4100_early_setup(void)
 137 {
 138         x86_init.oem.arch_setup = sdv_arch_setup;
 139         x86_init.resources.probe_roms = x86_init_noop;
 140         x86_init.mpparse.get_smp_config = x86_init_uint_noop;
 141         x86_init.mpparse.find_smp_config = x86_init_noop;
 142         x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
 143         x86_init.pci.init = ce4100_pci_init;
 144         x86_init.pci.init_irq = sdv_pci_init;
 145 
 146         /*
 147          * By default, the reboot method is ACPI which is supported by the
 148          * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue
 149          * the bootloader will however issue a system power off instead of
 150          * reboot. By using BOOT_KBD we ensure proper system reboot as
 151          * expected.
 152          */
 153         reboot_type = BOOT_KBD;
 154 
 155         pm_power_off = ce4100_power_off;
 156 }

/* [<][>][^][v][top][bottom][index][help] */