From 781d7798bb2fa0f04c455fe5df1f72b4255b589b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 6 Apr 2010 22:12:04 +0200 Subject: [PATCH] Fix interrupt and windows problems --- disk/ata.c | 6 +- include/grub/ata.h | 6 ++ include/grub/cs5536.h | 96 ++++++++++++++++++++-- include/grub/mips/yeeloong/pci.h | 5 +- kern/mips/yeeloong/init.c | 131 +++++++++++++++++++++++++++++++ 5 files changed, 234 insertions(+), 10 deletions(-) diff --git a/disk/ata.c b/disk/ata.c index b2291cd53..1b55ee680 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -27,8 +27,10 @@ #include /* At the moment, only two IDE ports are supported. */ -static const grub_port_t grub_ata_ioaddress[] = { 0x1f0, 0x170 }; -static const grub_port_t grub_ata_ioaddress2[] = { 0x3f6, 0x376 }; +static const grub_port_t grub_ata_ioaddress[] = { GRUB_ATA_CH0_PORT1, + GRUB_ATA_CH1_PORT1 }; +static const grub_port_t grub_ata_ioaddress2[] = { GRUB_ATA_CH0_PORT2, + GRUB_ATA_CH1_PORT2 }; static struct grub_ata_device *grub_ata_devices; diff --git a/include/grub/ata.h b/include/grub/ata.h index 940e67102..9e3aaf0e6 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -32,6 +32,12 @@ typedef enum GRUB_ATA_LBA48 } grub_ata_addressing_t; +#define GRUB_ATA_CH0_PORT1 0x1f0 +#define GRUB_ATA_CH1_PORT1 0x170 + +#define GRUB_ATA_CH0_PORT2 0x3f6 +#define GRUB_ATA_CH1_PORT2 0x376 + #define GRUB_ATA_REG_DATA 0 #define GRUB_ATA_REG_ERROR 1 #define GRUB_ATA_REG_FEATURES 1 diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index 21d6d55fc..c2323fe9b 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -31,10 +31,92 @@ #define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc #define GRUB_CS5536_MSR_IRQ_MAP_BAR 0x80000008 #define GRUB_CS5536_MSR_SMB_BAR 0x8000000b + +#define GRUB_CS5536_SMBUS_REGS_SIZE 8 +#define GRUB_CS5536_GPIO_REGS_SIZE 256 +#define GRUB_CS5536_MFGPT_REGS_SIZE 64 +#define GRUB_CS5536_IRQ_MAP_REGS_SIZE 32 +#define GRUB_CS5536_PM_REGS_SIZE 128 +#define GRUB_CS5536_ACPI_REGS_SIZE 32 + +#define GRUB_CS5536_DESTINATION_GLIU 0 +#define GRUB_CS5536_DESTINATION_GLPCI_SB 1 +#define GRUB_CS5536_DESTINATION_USB 2 +#define GRUB_CS5536_DESTINATION_IDE 3 +#define GRUB_CS5536_DESTINATION_DD 4 +#define GRUB_CS5536_DESTINATION_ACC 5 +#define GRUB_CS5536_DESTINATION_GLCP 7 + +#define GRUB_CS5536_P2D_DEST_SHIFT 61 +#define GRUB_CS5536_P2D_LOG_ALIGN 12 +#define GRUB_CS5536_P2D_ALIGN (1 << GRUB_CS5536_P2D_LOG_ALIGN) +#define GRUB_CS5536_P2D_BASE_SHIFT 20 +#define GRUB_CS5536_P2D_MASK_SHIFT 0 + +#define GRUB_CS5536_MSR_GL_IOD_START 0x000100e0 +#define GRUB_CS5536_IOD_DEST_SHIFT 61 +#define GRUB_CS5536_IOD_BASE_SHIFT 20 +#define GRUB_CS5536_IOD_MASK_SHIFT 0 +#define GRUB_CS5536_IOD_ADDR_MASK 0xfffff + #define GRUB_CS5536_MSR_GPIO_BAR 0x8000000c #define GRUB_CS5536_MSR_MFGPT_BAR 0x8000000d #define GRUB_CS5536_MSR_ACPI_BAR 0x8000000e #define GRUB_CS5536_MSR_PM_BAR 0x8000000f +#define GRUB_CS5536_MSR_DIVIL_LEG_IO 0x80000014 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 0x00000001 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1 0x00000002 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 0x10000000 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP 0x04000000 +#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK 0x80000024 +#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK 0x80000025 +#define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002 +#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL 0x8000004e +#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE 0x80 + +#define GRUB_CS5536_MSR_USB_OHCI_BASE 0x40000008 +#define GRUB_CS5536_MSR_USB_EHCI_BASE 0x40000009 +#define GRUB_CS5536_MSR_USB_CONTROLLER_BASE 0x4000000a +#define GRUB_CS5536_MSR_USB_OPTION_CONTROLLER_BASE 0x4000000b +#define GRUB_CS5536_MSR_USB_BASE_ADDR_MASK 0xffffff00 +#define GRUB_CS5536_MSR_USB_BASE_BUS_MASTER 0x400000000ULL +#define GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE 0x200000000ULL +#define GRUB_CS5536_MSR_USB_EHCI_BASE_FLDJ_SHIFT 40 + +#define GRUB_CS5536_MSR_IDE_IO_BAR 0x60000008 +#define GRUB_CS5536_MSR_IDE_IO_BAR_UNITS 1 +#define GRUB_CS5536_MSR_IDE_IO_BAR_ADDR_MASK 0xfffffff0 +#define GRUB_CS5536_MSR_IDE_CFG 0x60000010 +#define GRUB_CS5536_MSR_IDE_CFG_CHANNEL_ENABLE 2 +#define GRUB_CS5536_MSR_IDE_TIMING 0x60000012 +#define GRUB_CS5536_MSR_IDE_TIMING_PIO0 0x98 +#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE0_SHIFT 24 +#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE1_SHIFT 16 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING 0x60000013 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_PIO0 0x99 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_SHIFT 24 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE0_SHIFT 6 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE1_SHIFT 4 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_PIO0 2 + +#define GRUB_CS5536_MSR_GL_PCI_CTRL 0x00000010 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_MEMORY_ENABLE 1 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_IO_ENABLE 2 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_LATENCY_SHIFT 35 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_OUT_THR_SHIFT 60 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_IN_THR_SHIFT 56 + +#define GRUB_CS5536_MSR_GL_REGIONS_START 0x00000020 +#define GRUB_CS5536_MSR_GL_REGIONS_NUM 16 +#define GRUB_CS5536_MSR_GL_REGION_ENABLE 1 +#define GRUB_CS5536_MSR_GL_REGION_IO 0x100000000ULL +#define GRUB_CS5536_MSR_GL_REGION_BASE_MASK 0xfffff000ULL +#define GRUB_CS5536_MSR_GL_REGION_IO_BASE_SHIFT 12 +#define GRUB_CS5536_MSR_GL_REGION_TOP_MASK 0xfffff00000000000ULL +#define GRUB_CS5536_MSR_GL_REGION_IO_TOP_SHIFT 44 + +#define GRUB_CS5536_MSR_GL_P2D_START 0x00010020 + #define GRUB_CS5536_SMB_REG_DATA 0x0 #define GRUB_CS5536_SMB_REG_STATUS 0x1 #define GRUB_CS5536_SMB_REG_STATUS_SDAST (1 << 6) @@ -62,12 +144,14 @@ #define GRUB_CS5536_LBAR_TURN_ON (GRUB_CS5536_LBAR_ENABLE | GRUB_CS5536_LBAR_MASK_MASK) /* PMON-compatible LBARs. */ -#define GRUB_CS5536_LBAR_IRQ_MAP 0x0b360 -#define GRUB_CS5536_LBAR_GPIO 0x0b000 -#define GRUB_CS5536_LBAR_MFGPT 0x0b300 -#define GRUB_CS5536_LBAR_SMBUS 0x0b390 -#define GRUB_CS5536_LBAR_ACPI 0x0b340 -#define GRUB_CS5536_LBAR_PM 0x0b280 +#define GRUB_CS5536_LBAR_GPIO 0xb000 +#define GRUB_CS5536_LBAR_ACC 0xb200 +#define GRUB_CS5536_LBAR_PM 0xb280 +#define GRUB_CS5536_LBAR_MFGPT 0xb300 +#define GRUB_CS5536_LBAR_ACPI 0xb340 +#define GRUB_CS5536_LBAR_IRQ_MAP 0xb360 +#define GRUB_CS5536_LBAR_IDE 0xb380 +#define GRUB_CS5536_LBAR_SMBUS 0xb390 #define GRUB_GPIO_SMBUS_PINS ((1 << 14) | (1 << 15)) #define GRUB_GPIO_REG_OUT_EN 0x4 diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h index aa5e0bbea..8f3a29d5c 100644 --- a/include/grub/mips/yeeloong/pci.h +++ b/include/grub/mips/yeeloong/pci.h @@ -27,8 +27,9 @@ #define GRUB_PCI_NUM_BUS 1 #define GRUB_PCI_NUM_DEVICES 16 -#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000 -#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000 +#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000 +#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000 +#define GRUB_MACHINE_PCI_CONTROLLER_HEADER 0xbfe00000 #define GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR 0xbfe00118 diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 9cadd64b2..cf241ea96 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -31,6 +31,7 @@ #include #include #include +#include extern void grub_video_sm712_init (void); extern void grub_video_init (void); @@ -87,6 +88,43 @@ static grub_uint32_t gpiodump[] = { 0x00000000, 0x50000000, 0x00000000, 0x00000000, }; +static inline void +set_io_space (grub_pci_device_t dev, int num, grub_uint16_t start, + grub_uint16_t len) +{ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GL_REGIONS_START + num, + ((((grub_uint64_t) start + len - 4) + << GRUB_CS5536_MSR_GL_REGION_IO_TOP_SHIFT) + & GRUB_CS5536_MSR_GL_REGION_TOP_MASK) + | (((grub_uint64_t) start + << GRUB_CS5536_MSR_GL_REGION_IO_BASE_SHIFT) + & GRUB_CS5536_MSR_GL_REGION_BASE_MASK) + | GRUB_CS5536_MSR_GL_REGION_IO + | GRUB_CS5536_MSR_GL_REGION_ENABLE); +} + +static inline void +set_iod (grub_pci_device_t dev, int num, int dest, int start, int mask) +{ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GL_IOD_START + num, + ((grub_uint64_t) dest << GRUB_CS5536_IOD_DEST_SHIFT) + | (((grub_uint64_t) start & GRUB_CS5536_IOD_ADDR_MASK) + << GRUB_CS5536_IOD_BASE_SHIFT) + | ((mask & GRUB_CS5536_IOD_ADDR_MASK) + << GRUB_CS5536_IOD_MASK_SHIFT)); +} + +static inline void +set_p2d (grub_pci_device_t dev, int num, int dest, grub_uint32_t start) +{ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GL_P2D_START + num, + (((grub_uint64_t) dest) << GRUB_CS5536_P2D_DEST_SHIFT) + | ((grub_uint64_t) (start >> GRUB_CS5536_P2D_LOG_ALIGN) + << GRUB_CS5536_P2D_BASE_SHIFT) + | (((1 << (32 - GRUB_CS5536_P2D_LOG_ALIGN)) - 1) + << GRUB_CS5536_P2D_MASK_SHIFT)); +} + void grub_machine_init (void) { @@ -147,6 +185,7 @@ grub_machine_init (void) GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_GPIO); + /* Setup GPIO. */ for (i = 0; i < (int) ARRAY_SIZE (gpiodump); i++) ((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)) [i] @@ -162,6 +201,98 @@ grub_machine_init (void) GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_ACPI); grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_PM_BAR, GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_PM); + + /* Setup DIVIL. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO, + GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK, + (~GRUB_CS5536_DIVIL_LPC_INTERRUPTS) & 0xffff); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK, + GRUB_CS5536_DIVIL_LPC_INTERRUPTS); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL, + GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE); + + /* Initialise USB controller. */ + /* FIXME: assign adresses dynamically. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, + GRUB_CS5536_MSR_USB_BASE_BUS_MASTER + | GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE + | 0x05024000); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, + GRUB_CS5536_MSR_USB_BASE_BUS_MASTER + | GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE + | (0x20ULL + << GRUB_CS5536_MSR_USB_EHCI_BASE_FLDJ_SHIFT) + | 0x05023000); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_CONTROLLER_BASE, + GRUB_CS5536_MSR_USB_BASE_BUS_MASTER + | GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE + | 0x05020000); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OPTION_CONTROLLER_BASE, + GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE + | 0x05022000); + set_p2d (dev, 0, GRUB_CS5536_DESTINATION_USB, 0x05020000); + set_p2d (dev, 1, GRUB_CS5536_DESTINATION_USB, 0x05022000); + set_p2d (dev, 5, GRUB_CS5536_DESTINATION_USB, 0x05024000); + set_p2d (dev, 6, GRUB_CS5536_DESTINATION_USB, 0x05023000); + + /* Setup IDE controller. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IDE_IO_BAR, + GRUB_CS5536_LBAR_IDE + | GRUB_CS5536_MSR_IDE_IO_BAR_UNITS); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IDE_CFG, + GRUB_CS5536_MSR_IDE_CFG_CHANNEL_ENABLE); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IDE_TIMING, + (GRUB_CS5536_MSR_IDE_TIMING_PIO0 + << GRUB_CS5536_MSR_IDE_TIMING_DRIVE0_SHIFT) + | (GRUB_CS5536_MSR_IDE_TIMING_PIO0 + << GRUB_CS5536_MSR_IDE_TIMING_DRIVE1_SHIFT)); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IDE_CAS_TIMING, + (GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_PIO0 + << GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_SHIFT) + | (GRUB_CS5536_MSR_IDE_CAS_TIMING_PIO0 + << GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE0_SHIFT) + | (GRUB_CS5536_MSR_IDE_CAS_TIMING_PIO0 + << GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE1_SHIFT)); + + /* Setup Geodelink PCI. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GL_PCI_CTRL, + (4ULL << GRUB_CS5536_MSR_GL_PCI_CTRL_OUT_THR_SHIFT) + | (4ULL << GRUB_CS5536_MSR_GL_PCI_CTRL_IN_THR_SHIFT) + | (8ULL << GRUB_CS5536_MSR_GL_PCI_CTRL_LATENCY_SHIFT) + | GRUB_CS5536_MSR_GL_PCI_CTRL_IO_ENABLE + | GRUB_CS5536_MSR_GL_PCI_CTRL_MEMORY_ENABLE); + + /* Setup windows. */ + set_io_space (dev, 0, GRUB_CS5536_LBAR_SMBUS, + GRUB_CS5536_SMBUS_REGS_SIZE); + set_io_space (dev, 1, GRUB_CS5536_LBAR_GPIO, GRUB_CS5536_GPIO_REGS_SIZE); + set_io_space (dev, 2, GRUB_CS5536_LBAR_MFGPT, + GRUB_CS5536_MFGPT_REGS_SIZE); + set_io_space (dev, 3, GRUB_CS5536_LBAR_IRQ_MAP, + GRUB_CS5536_IRQ_MAP_REGS_SIZE); + set_io_space (dev, 4, GRUB_CS5536_LBAR_PM, GRUB_CS5536_PM_REGS_SIZE); + set_io_space (dev, 5, GRUB_CS5536_LBAR_ACPI, GRUB_CS5536_ACPI_REGS_SIZE); + set_iod (dev, 0, GRUB_CS5536_DESTINATION_IDE, GRUB_ATA_CH0_PORT1, + 0xffff8); + set_iod (dev, 1, GRUB_CS5536_DESTINATION_ACC, GRUB_CS5536_LBAR_ACC, + 0xfff80); + set_iod (dev, 2, GRUB_CS5536_DESTINATION_IDE, GRUB_CS5536_LBAR_IDE, + 0xffff0); + + /* Setup PCI controller. */ + *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + + GRUB_PCI_REG_COMMAND)) = 0x22b00046; + *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + + GRUB_PCI_REG_CACHELINE)) = 0xff; + *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + + GRUB_PCI_REG_ADDRESS_REG0)) + = 0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 | GRUB_PCI_ADDR_MEM_PREFETCH; + *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + + GRUB_PCI_REG_ADDRESS_REG1)) = 0; } modend = grub_modules_get_end ();