Commit e19e2303 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-serial

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 54c23d96 38542c88
...@@ -733,3 +733,47 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) ...@@ -733,3 +733,47 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
return 0; return 0;
} }
int __init
efi_uart_console_only(void)
{
efi_status_t status;
char *s, name[] = "ConOut";
efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID;
efi_char16_t *utf16, name_utf16[32];
unsigned char data[1024];
unsigned long size = sizeof(data);
struct efi_generic_dev_path *hdr, *end_addr;
int uart = 0;
/* Convert to UTF-16 */
utf16 = name_utf16;
s = name;
while (*s)
*utf16++ = *s++ & 0x7f;
*utf16 = 0;
status = efi.get_variable(name_utf16, &guid, NULL, &size, data);
if (status != EFI_SUCCESS) {
printk(KERN_ERR "No EFI %s variable?\n", name);
return 0;
}
hdr = (struct efi_generic_dev_path *) data;
end_addr = (struct efi_generic_dev_path *) ((u8 *) data + size);
while (hdr < end_addr) {
if (hdr->type == EFI_DEV_MSG &&
hdr->sub_type == EFI_DEV_MSG_UART)
uart = 1;
else if (hdr->type == EFI_DEV_END_PATH ||
hdr->type == EFI_DEV_END_PATH2) {
if (!uart)
return 0;
if (hdr->sub_type == EFI_DEV_END_ENTIRE)
return 1;
uart = 0;
}
hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length);
}
printk(KERN_ERR "Malformed %s value\n", name);
return 0;
}
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/console.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -44,6 +45,7 @@ setup_serial_hcdp(void *tablep) ...@@ -44,6 +45,7 @@ setup_serial_hcdp(void *tablep)
unsigned long iobase; unsigned long iobase;
hcdp_t hcdp; hcdp_t hcdp;
int gsi, nr; int gsi, nr;
static char options[16];
#if 0 #if 0
static int shift_once = 1; static int shift_once = 1;
#endif #endif
...@@ -147,7 +149,7 @@ setup_serial_hcdp(void *tablep) ...@@ -147,7 +149,7 @@ setup_serial_hcdp(void *tablep)
printk(" gsi = %d, baud rate = %lu, bits = %d, clock = %d\n", printk(" gsi = %d, baud rate = %lu, bits = %d, clock = %d\n",
gsi, (unsigned long) hcdp_dev->baud, hcdp_dev->bits, gsi, (unsigned long) hcdp_dev->baud, hcdp_dev->bits,
hcdp_dev->clock_rate); hcdp_dev->clock_rate);
if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) if (HCDP_PCI_UART(hcdp_dev))
printk(" PCI id: %02x:%02x:%02x, vendor ID=0x%x, " printk(" PCI id: %02x:%02x:%02x, vendor ID=0x%x, "
"dev ID=0x%x\n", hcdp_dev->pci_seg, "dev ID=0x%x\n", hcdp_dev->pci_seg,
hcdp_dev->pci_bus, hcdp_dev->pci_dev, hcdp_dev->pci_bus, hcdp_dev->pci_dev,
...@@ -179,16 +181,26 @@ setup_serial_hcdp(void *tablep) ...@@ -179,16 +181,26 @@ setup_serial_hcdp(void *tablep)
printk(KERN_WARNING"warning: No support for PCI serial console\n"); printk(KERN_WARNING"warning: No support for PCI serial console\n");
return; return;
} }
if (HCDP_IRQ_SUPPORTED(hcdp_dev)) {
#ifdef CONFIG_IA64 #ifdef CONFIG_IA64
port.irq = acpi_register_irq(gsi, ACPI_ACTIVE_HIGH, if (HCDP_PCI_UART(hcdp_dev))
ACPI_EDGE_SENSITIVE); port.irq = acpi_register_irq(gsi,
ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
else
port.irq = acpi_register_irq(gsi,
ACPI_ACTIVE_HIGH, ACPI_EDGE_SENSITIVE);
#else #else
port.irq = gsi; port.irq = gsi;
#endif #endif
port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_RESOURCES;
if (gsi)
port.flags |= UPF_AUTO_IRQ; port.flags |= UPF_AUTO_IRQ;
if (HCDP_PCI_UART(hcdp_dev))
port.flags |= UPF_SHARE_IRQ;
}
port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_RESOURCES;
/* /*
* Note: the above memset() initializes port.line to 0, * Note: the above memset() initializes port.line to 0,
* so we register this port as ttyS0. * so we register this port as ttyS0.
...@@ -197,8 +209,15 @@ setup_serial_hcdp(void *tablep) ...@@ -197,8 +209,15 @@ setup_serial_hcdp(void *tablep)
printk("setup_serial_hcdp(): early_serial_setup() " printk("setup_serial_hcdp(): early_serial_setup() "
"for HCDP serial console port failed. " "for HCDP serial console port failed. "
"Will try any additional consoles in HCDP.\n"); "Will try any additional consoles in HCDP.\n");
memset(&port, 0, sizeof(port));
continue; continue;
} }
if (efi_uart_console_only()) {
snprintf(options, sizeof(options), "%lun%d",
hcdp_dev->baud, hcdp_dev->bits);
add_preferred_console("ttyS", port.line, options);
}
break; break;
} }
......
...@@ -77,3 +77,6 @@ typedef struct { ...@@ -77,3 +77,6 @@ typedef struct {
u32 num_entries; u32 num_entries;
hcdp_dev_t hcdp_dev[MAX_HCDP_DEVICES]; hcdp_dev_t hcdp_dev[MAX_HCDP_DEVICES];
} hcdp_t; } hcdp_t;
#define HCDP_PCI_UART(x) (x->pci_func & 1UL<<7)
#define HCDP_IRQ_SUPPORTED(x) (x->pci_func & 1UL<<6)
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
...@@ -305,6 +306,72 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev) ...@@ -305,6 +306,72 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
} }
} }
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int
sbs_setup(struct pci_dev *dev, struct pci_board *board,
struct serial_struct *req, int idx)
{
unsigned int bar, offset = board->first_offset;
bar = 0;
if (idx < 4) {
/* first four channels map to 0, 0x100, 0x200, 0x300 */
offset += idx * board->uart_offset;
} else if (idx < 8) {
/* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */
offset += idx * board->uart_offset + 0xC00;
} else /* we have only 8 ports on PMC-OCTALPRO */
return 1;
return setup_port(dev, req, bar, offset, board->reg_shift);
}
/*
* This does initialization for PMC OCTALPRO cards:
* maps the device memory, resets the UARTs (needed, bc
* if the module is removed and inserted again, the card
* is in the sleep mode) and enables global interrupt.
*/
/* global control register offset for SBS PMC-OctalPro */
#define OCT_REG_CR_OFF 0x500
static int __devinit sbs_init(struct pci_dev *dev)
{
u8 * p;
p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0));
if (p == NULL)
return -ENOMEM;
/* Set bit-4 Control Register (UART RESET) in to reset the uarts */
writeb(0x10,p + OCT_REG_CR_OFF);
udelay(50);
writeb(0x0,p + OCT_REG_CR_OFF);
/* Set bit-2 (INTENABLE) of Control Register */
writeb(0x4, p + OCT_REG_CR_OFF);
iounmap(p);
return 0;
}
/*
* Disables the global interrupt of PMC-OctalPro
*/
static void __devexit sbs_exit(struct pci_dev *dev)
{
u8 * p;
p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0));
if (p != NULL) {
writeb(0, p + OCT_REG_CR_OFF);
}
iounmap(p);
}
/* /*
* SIIG serial cards have an PCI interface chip which also controls * SIIG serial cards have an PCI interface chip which also controls
* the UART clocking frequency. Each UART can be clocked independently * the UART clocking frequency. Each UART can be clocked independently
...@@ -534,6 +601,15 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board, ...@@ -534,6 +601,15 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
return setup_port(dev, req, bar, offset, board->reg_shift); return setup_port(dev, req, bar, offset, board->reg_shift);
} }
/* This should be in linux/pci_ids.h */
#define PCI_VENDOR_ID_SBSMODULARIO 0x124B
#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
#define PCI_DEVICE_ID_OCTPRO 0x0001
#define PCI_SUBDEVICE_ID_OCTPRO232 0x0108
#define PCI_SUBDEVICE_ID_OCTPRO422 0x0208
#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
/* /*
* Master list of serial port init/setup/exit quirks. * Master list of serial port init/setup/exit quirks.
* This does not describe the general nature of the port. * This does not describe the general nature of the port.
...@@ -618,6 +694,55 @@ static struct pci_serial_quirk pci_serial_quirks[] = { ...@@ -618,6 +694,55 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit), .exit = __devexit_p(pci_plx9050_exit),
}, },
/*
* SBS Technologies, Inc., PMC-OCTALPRO 232
*/
{
.vendor = PCI_VENDOR_ID_SBSMODULARIO,
.device = PCI_DEVICE_ID_OCTPRO,
.subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
.subdevice = PCI_SUBDEVICE_ID_OCTPRO232,
.init = sbs_init,
.setup = sbs_setup,
.exit = sbs_exit
},
/*
* SBS Technologies, Inc., PMC-OCTALPRO 422
*/
{
.vendor = PCI_VENDOR_ID_SBSMODULARIO,
.device = PCI_DEVICE_ID_OCTPRO,
.subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
.subdevice = PCI_SUBDEVICE_ID_OCTPRO422,
.init = sbs_init,
.setup = sbs_setup,
.exit = sbs_exit
},
/*
* SBS Technologies, Inc., P-Octal 232
*/
{
.vendor = PCI_VENDOR_ID_SBSMODULARIO,
.device = PCI_DEVICE_ID_OCTPRO,
.subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
.subdevice = PCI_SUBDEVICE_ID_POCTAL232,
.init = sbs_init,
.setup = sbs_setup,
.exit = sbs_exit
},
/*
* SBS Technologies, Inc., P-Octal 422
*/
{
.vendor = PCI_VENDOR_ID_SBSMODULARIO,
.device = PCI_DEVICE_ID_OCTPRO,
.subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO,
.subdevice = PCI_SUBDEVICE_ID_POCTAL422,
.init = sbs_init,
.setup = sbs_setup,
.exit = sbs_exit
},
/* /*
* SIIG cards. * SIIG cards.
* It is not clear whether these could be collapsed. * It is not clear whether these could be collapsed.
...@@ -944,8 +1069,19 @@ enum pci_board_num_t { ...@@ -944,8 +1069,19 @@ enum pci_board_num_t {
pbn_computone_4, pbn_computone_4,
pbn_computone_6, pbn_computone_6,
pbn_computone_8, pbn_computone_8,
pbn_sbsxrsio,
}; };
/*
* uart_offset - the space between channels
* reg_shift - describes how the UART registers are mapped
* to PCI memory by the card.
* For example IER register on SBS, Inc. PMC-OctPro is located at
* offset 0x10 from the UART base, while UART_IER is defined as 1
* in include/linux/serial_reg.h,
* see first lines of serial_in() and serial_out() in 8250.c
*/
static struct pci_board pci_boards[] __devinitdata = { static struct pci_board pci_boards[] __devinitdata = {
[pbn_default] = { [pbn_default] = {
.flags = FL_BASE0, .flags = FL_BASE0,
...@@ -1348,6 +1484,13 @@ static struct pci_board pci_boards[] __devinitdata = { ...@@ -1348,6 +1484,13 @@ static struct pci_board pci_boards[] __devinitdata = {
.reg_shift = 2, .reg_shift = 2,
.first_offset = 0x200, .first_offset = 0x200,
}, },
[pbn_sbsxrsio] = {
.flags = FL_BASE0,
.num_ports = 8,
.base_baud = 460800,
.uart_offset = 256,
.reg_shift = 4,
}
}; };
/* /*
...@@ -1755,27 +1898,44 @@ static struct pci_device_id serial_pci_tbl[] = { ...@@ -1755,27 +1898,44 @@ static struct pci_device_id serial_pci_tbl[] = {
0x10b5, 0x106a, 0, 0, 0x10b5, 0x106a, 0, 0,
pbn_plx_romulus }, pbn_plx_romulus },
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_4_115200 }, pbn_b1_4_115200 },
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_2_115200 }, pbn_b1_2_115200 },
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_8_115200 }, pbn_b1_8_115200 },
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b1_8_115200 }, pbn_b1_8_115200 },
{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0, PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0,
pbn_b0_4_921600 }, pbn_b0_4_921600 },
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_4_115200 }, pbn_b0_4_115200 },
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_2_921600 }, pbn_b0_bt_2_921600 },
/*
* SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
* from skokodyn@yahoo.com
*/
{ PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO232, 0, 0,
pbn_sbsxrsio },
{ PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO422, 0, 0,
pbn_sbsxrsio },
{ PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL232, 0, 0,
pbn_sbsxrsio },
{ PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO,
PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL422, 0, 0,
pbn_sbsxrsio },
/* /*
* Digitan DS560-558, from jimd@esoft.com * Digitan DS560-558, from jimd@esoft.com
*/ */
......
...@@ -212,6 +212,9 @@ typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_siz ...@@ -212,6 +212,9 @@ typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_siz
#define UGA_IO_PROTOCOL_GUID \ #define UGA_IO_PROTOCOL_GUID \
EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 ) EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 )
#define EFI_GLOBAL_VARIABLE_GUID \
EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c )
typedef struct { typedef struct {
efi_guid_t guid; efi_guid_t guid;
unsigned long table; unsigned long table;
...@@ -294,6 +297,7 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos ...@@ -294,6 +297,7 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos
extern u64 efi_get_iobase (void); extern u64 efi_get_iobase (void);
extern u32 efi_mem_type (unsigned long phys_addr); extern u32 efi_mem_type (unsigned long phys_addr);
extern u64 efi_mem_attributes (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr);
extern int __init efi_uart_console_only (void);
extern void efi_initialize_iomem_resources(struct resource *code_resource, extern void efi_initialize_iomem_resources(struct resource *code_resource,
struct resource *data_resource); struct resource *data_resource);
extern efi_status_t phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc); extern efi_status_t phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc);
...@@ -322,6 +326,49 @@ extern struct efi_memory_map memmap; ...@@ -322,6 +326,49 @@ extern struct efi_memory_map memmap;
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 #define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
/*
* EFI Device Path information
*/
#define EFI_DEV_HW 0x01
#define EFI_DEV_PCI 1
#define EFI_DEV_PCCARD 2
#define EFI_DEV_MEM_MAPPED 3
#define EFI_DEV_VENDOR 4
#define EFI_DEV_CONTROLLER 5
#define EFI_DEV_ACPI 0x02
#define EFI_DEV_BASIC_ACPI 1
#define EFI_DEV_EXPANDED_ACPI 2
#define EFI_DEV_MSG 0x03
#define EFI_DEV_MSG_ATAPI 1
#define EFI_DEV_MSG_SCSI 2
#define EFI_DEV_MSG_FC 3
#define EFI_DEV_MSG_1394 4
#define EFI_DEV_MSG_USB 5
#define EFI_DEV_MSG_USB_CLASS 15
#define EFI_DEV_MSG_I20 6
#define EFI_DEV_MSG_MAC 11
#define EFI_DEV_MSG_IPV4 12
#define EFI_DEV_MSG_IPV6 13
#define EFI_DEV_MSG_INFINIBAND 9
#define EFI_DEV_MSG_UART 14
#define EFI_DEV_MSG_VENDOR 10
#define EFI_DEV_MEDIA 0x04
#define EFI_DEV_MEDIA_HARD_DRIVE 1
#define EFI_DEV_MEDIA_CDROM 2
#define EFI_DEV_MEDIA_VENDOR 3
#define EFI_DEV_MEDIA_FILE 4
#define EFI_DEV_MEDIA_PROTOCOL 5
#define EFI_DEV_BIOS_BOOT 0x05
#define EFI_DEV_END_PATH 0x7F
#define EFI_DEV_END_PATH2 0xFF
#define EFI_DEV_END_INSTANCE 0x01
#define EFI_DEV_END_ENTIRE 0xFF
struct efi_generic_dev_path {
u8 type;
u8 sub_type;
u16 length;
} __attribute ((packed));
/* /*
* efi_dir is allocated in arch/ia64/kernel/efi.c. * efi_dir is allocated in arch/ia64/kernel/efi.c.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment