From 232f7e29c95654932f3ad291dcb7194c27a45be4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Feb 2010 22:39:59 +0100 Subject: [PATCH 01/45] SMBus on CS5536 support --- bus/cs5536.c | 213 +++++++++++++++++++++++++++++++++ commands/mips/yeeloong/lsspd.c | 92 ++++++++++++++ conf/mips-yeeloong.rmk | 11 ++ disk/ata.c | 3 +- include/grub/cs5536.h | 62 ++++++++++ include/grub/smbus.h | 39 ++++++ 6 files changed, 419 insertions(+), 1 deletion(-) create mode 100644 bus/cs5536.c create mode 100644 commands/mips/yeeloong/lsspd.c create mode 100644 include/grub/cs5536.h create mode 100644 include/grub/smbus.h diff --git a/bus/cs5536.c b/bus/cs5536.c new file mode 100644 index 000000000..3a7ac2bb1 --- /dev/null +++ b/bus/cs5536.c @@ -0,0 +1,213 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +int +grub_cs5536_find (grub_pci_device_t *devp) +{ + int found = 0; + auto int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, + grub_pci_id_t pciid); + + int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, + grub_pci_id_t pciid) + { + if (pciid == GRUB_CS5536_PCIID) + { + *devp = dev; + found = 1; + return 1; + } + return 0; + } + + grub_pci_iterate (hook); + + return found; +} + +grub_uint64_t +grub_cs5536_read_msr (grub_pci_device_t dev, grub_uint32_t addr) +{ + grub_uint64_t ret = 0; + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_ADDR), + addr); + ret = (grub_uint64_t) + grub_pci_read (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA0)); + ret |= (((grub_uint64_t) + grub_pci_read (grub_pci_make_address (dev, + GRUB_CS5536_MSR_MAILBOX_DATA1))) + << 32); + return ret; +} + +void +grub_cs5536_write_msr (grub_pci_device_t dev, grub_uint32_t addr, + grub_uint64_t val) +{ + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_ADDR), + addr); + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA0), + val & 0xffffffff); + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA1), + val >> 32); +} + +grub_err_t +grub_cs5536_smbus_wait (grub_port_t smbbase) +{ + grub_uint64_t start = grub_get_time_ms (); + while (1) + { + grub_uint8_t status; + status = grub_inb (smbbase + GRUB_CS5536_SMB_REG_STATUS); + if (status & (1 << 6)) + return GRUB_ERR_NONE; + if (status & (1 << 5)) + return grub_error (GRUB_ERR_IO, "SM bus error"); + if (status & (1 << 4)) + return grub_error (GRUB_ERR_IO, "NACK received"); + if (grub_get_time_ms () > start + 40) + return grub_error (GRUB_ERR_IO, "SM stalled"); + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, + grub_uint8_t addr, grub_uint8_t *res) +{ + grub_err_t err; + + /* Send START. */ + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_START, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Send device address. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (dev << 1, smbbase + GRUB_CS5536_SMB_REG_DATA); + + /* Send ACK. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_ACK, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Send byte address. */ + grub_outb (addr, smbbase + GRUB_CS5536_SMB_REG_DATA); + + /* Send START. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_START, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Send device address. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb ((dev << 1) | 1, smbbase + GRUB_CS5536_SMB_REG_DATA); + + /* Send STOP. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_STOP, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + *res = grub_inb (smbbase + GRUB_CS5536_SMB_REG_DATA); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_cs5536_init_smbus (grub_pci_device_t dev, grub_uint16_t divisor, + grub_port_t *smbbase) +{ + grub_uint64_t smbbar; + + smbbar = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_SMB_BAR); + + /* FIXME */ + if (!(smbbar & GRUB_CS5536_LBAR_ENABLE)) + return grub_error(GRUB_ERR_IO, "SMB controller not enabled\n"); + *smbbase = (smbbar & GRUB_CS5536_LBAR_ADDR_MASK) + GRUB_MACHINE_PCI_IO_BASE; + + if (divisor < 8) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid divisor"); + + /* Disable SMB. */ + grub_outb (0, *smbbase + GRUB_CS5536_SMB_REG_CTRL2); + + /* Disable interrupts. */ + grub_outb (0, *smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Set as master. */ + grub_outb (GRUB_CS5536_SMB_REG_ADDR_MASTER, + *smbbase + GRUB_CS5536_SMB_REG_ADDR); + + /* Launch. */ + grub_outb (((divisor >> 7) & 0xff), *smbbase + GRUB_CS5536_SMB_REG_CTRL3); + grub_outb (((divisor << 1) & 0xfe) | GRUB_CS5536_SMB_REG_CTRL2_ENABLE, + *smbbase + GRUB_CS5536_SMB_REG_CTRL2); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev, + struct grub_smbus_spd *res) +{ + grub_err_t err; + grub_size_t size; + grub_uint8_t b; + grub_size_t ptr; + + err = grub_cs5536_read_spd_byte (smbbase, dev, 0, &b); + if (err) + return err; + if (b == 0) + return grub_error (GRUB_ERR_IO, "no SPD found"); + size = b; + + ((grub_uint8_t *) res)[0] = b; + for (ptr = 1; ptr < size; ptr++) + { + err = grub_cs5536_read_spd_byte (smbbase, dev, ptr, + &((grub_uint8_t *) res)[ptr]); + if (err) + return err; + } + return GRUB_ERR_NONE; +} diff --git a/commands/mips/yeeloong/lsspd.c b/commands/mips/yeeloong/lsspd.c new file mode 100644 index 000000000..539cda34c --- /dev/null +++ b/commands/mips/yeeloong/lsspd.c @@ -0,0 +1,92 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static grub_err_t +grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_pci_device_t dev; + grub_port_t smbbase; + int i; + grub_err_t err; + + if (!grub_cs5536_find (&dev)) + { + grub_printf ("No CS5536 found\n"); + return GRUB_ERR_NONE; + } + grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev), + grub_pci_get_device (dev), grub_pci_get_function (dev)); + + err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase); + if (err) + return err; + + grub_printf ("SMB base = 0x%x\n", smbbase); + + for (i = GRUB_SMB_RAM_START_ADDR; + i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++) + { + struct grub_smbus_spd spd; + grub_memset (&spd, 0, sizeof (spd)); + grub_printf ("Device %d\n", i); + err = grub_cs5536_read_spd (smbbase, i, &spd); + if (err) + { + grub_print_error (); + continue; + } + grub_printf ("Written SPD bytes: %d B.\n", spd.written_size); + grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size); + if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2) + { + char str[sizeof (spd.ddr2.part_number) + 1]; + grub_printf ("Memory type: DDR2.\n"); + grub_memcpy (str, spd.ddr2.part_number, + sizeof (spd.ddr2.part_number)); + str[sizeof (spd.ddr2.part_number)] = 0; + grub_printf ("Part no: %s.\n", str); + } + else + grub_printf ("Memory type: Unknown.\n"); + } + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsspd) +{ + cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0, + "Print Memory information."); +} + +GRUB_MOD_FINI(lsspd) +{ + grub_unregister_command (cmd); +} diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk index eb0dc9676..901a63dd0 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -73,6 +73,17 @@ datehook_mod_SOURCES = hook/datehook.c datehook_mod_CFLAGS = $(COMMON_CFLAGS) datehook_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For lsspd.mod +pkglib_MODULES += lsspd.mod +lsspd_mod_SOURCES = commands/mips/yeeloong/lsspd.c +lsspd_mod_CFLAGS = $(COMMON_CFLAGS) +lsspd_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For cs5536.mod +pkglib_MODULES += cs5536.mod +cs5536_mod_SOURCES = bus/cs5536.c +cs5536_mod_CFLAGS = $(COMMON_CFLAGS) +cs5536_mod_LDFLAGS = $(COMMON_LDFLAGS) sbin_SCRIPTS += grub-install grub_install_SOURCES = util/grub-install.in diff --git a/disk/ata.c b/disk/ata.c index 687ed9378..662fe71a7 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -24,6 +24,7 @@ #include #include #include +#include /* At the moment, only two IDE ports are supported. */ static const grub_port_t grub_ata_ioaddress[] = { 0x1f0, 0x170 }; @@ -408,7 +409,7 @@ grub_ata_pciinit (grub_pci_device_t dev, class = grub_pci_read (addr); /* AMD CS5536 Southbridge. */ - if (pciid == 0x208f1022) + if (pciid == GRUB_CS5536_PCIID) { cs5536 = 1; nports = 1; diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h new file mode 100644 index 000000000..233362160 --- /dev/null +++ b/include/grub/cs5536.h @@ -0,0 +1,62 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_CS5536_HEADER +#define GRUB_CS5536_HEADER 1 + +#include +#include +#include + +#define GRUB_CS5536_PCIID 0x208f1022 +#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4 +#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8 +#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc +#define GRUB_CS5536_MSR_SMB_BAR 0x8000000b +#define GRUB_CS5536_SMB_REG_DATA 0x0 +#define GRUB_CS5536_SMB_REG_STATUS 0x1 +#define GRUB_CS5536_SMB_REG_CTRL1 0x3 +#define GRUB_CS5536_SMB_REG_CTRL1_START 0x01 +#define GRUB_CS5536_SMB_REG_CTRL1_STOP 0x02 +#define GRUB_CS5536_SMB_REG_CTRL1_ACK 0x10 +#define GRUB_CS5536_SMB_REG_ADDR 0x4 +#define GRUB_CS5536_SMB_REG_ADDR_MASTER 0x0 +#define GRUB_CS5536_SMB_REG_CTRL2 0x5 +#define GRUB_CS5536_SMB_REG_CTRL2_ENABLE 0x1 +#define GRUB_CS5536_SMB_REG_CTRL3 0x6 + +#define GRUB_CS5536_LBAR_ADDR_MASK 0x000000000000fff8ULL +#define GRUB_CS5536_LBAR_ADDR_OFF 3 +#define GRUB_CS5536_LBAR_ENABLE 0x0000000100000000ULL +#define GRUB_SMB_RAM_START_ADDR 0x50 +#define GRUB_SMB_RAM_NUM_MAX 0x08 + +int grub_cs5536_find (grub_pci_device_t *devp); + +grub_uint64_t grub_cs5536_read_msr (grub_pci_device_t dev, grub_uint32_t addr); +void grub_cs5536_write_msr (grub_pci_device_t dev, grub_uint32_t addr, + grub_uint64_t val); +grub_err_t grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, + grub_uint8_t addr, grub_uint8_t *res); +grub_err_t grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev, + struct grub_smbus_spd *res); +grub_err_t grub_cs5536_smbus_wait (grub_port_t smbbase); +grub_err_t grub_cs5536_init_smbus (grub_pci_device_t dev, grub_uint16_t divisor, + grub_port_t *smbbase); + +#endif diff --git a/include/grub/smbus.h b/include/grub/smbus.h new file mode 100644 index 000000000..6e9b5005c --- /dev/null +++ b/include/grub/smbus.h @@ -0,0 +1,39 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_SMBUS_HEADER +#define GRUB_SMBUS_HEADER 1 + +struct grub_smbus_spd +{ + grub_uint8_t written_size; + grub_uint8_t log_total_flash_size; +#define GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 8 + grub_uint8_t memory_type; + union + { + grub_uint8_t unknown[253]; + struct { + grub_uint8_t unused1[70]; + grub_uint8_t part_number[18]; + grub_uint8_t unused2[165]; + } ddr2; + }; +}; + +#endif From 1eb746f2749f09ab7e1f8e83bc5cda7fb24bafbc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Feb 2010 22:40:53 +0100 Subject: [PATCH 02/45] Initialise remaining UART registers on Yeeloong --- include/grub/serial.h | 10 ++++++++-- term/serial.c | 11 +++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/grub/serial.h b/include/grub/serial.h index 1c35b4093..758b6fb3e 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -59,9 +59,15 @@ #define UART_DLAB 0x80 /* Enable the FIFO. */ -#define UART_ENABLE_FIFO 0xC7 +#define UART_ENABLE_FIFO_TRIGGER14 0xC7 + +/* Enable the FIFO. */ +#define UART_ENABLE_FIFO_TRIGGER1 0x07 /* Turn on DTR, RTS, and OUT2. */ -#define UART_ENABLE_MODEM 0x0B +#define UART_ENABLE_DTRRTS 0x03 + +/* Turn on DTR, RTS, and OUT2. */ +#define UART_ENABLE_OUT2 0x08 #endif /* ! GRUB_SERIAL_MACHINE_HEADER */ diff --git a/term/serial.c b/term/serial.c index 05497ce40..2dbebc2f1 100644 --- a/term/serial.c +++ b/term/serial.c @@ -300,10 +300,17 @@ serial_hw_init (void) /* In Yeeloong serial port has only 3 wires. */ #ifndef GRUB_MACHINE_MIPS_YEELOONG /* Enable the FIFO. */ - grub_outb (UART_ENABLE_FIFO, serial_settings.port + UART_FCR); + grub_outb (UART_ENABLE_FIFO_TRIGGER1, serial_settings.port + UART_FCR); + + /* Turn on DTR and RTS. */ + grub_outb (UART_ENABLE_DTRRTS, serial_settings.port + UART_MCR); +#else + /* Enable the FIFO. */ + grub_outb (UART_ENABLE_FIFO_TRIGGER14, serial_settings.port + UART_FCR); /* Turn on DTR, RTS, and OUT2. */ - grub_outb (UART_ENABLE_MODEM, serial_settings.port + UART_MCR); + grub_outb (UART_ENABLE_DTRRTS | UART_ENABLE_OUT2, + serial_settings.port + UART_MCR); #endif /* Drain the input buffer. */ From a1efcc79d346648871c976543d43ed1e9ad38f7a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Feb 2010 22:41:29 +0100 Subject: [PATCH 03/45] Firmware startup block (for now just output a string on console) --- include/grub/mips/yeeloong/serial.h | 5 ++ kern/mips/yeeloong/fwstart.S | 81 +++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 kern/mips/yeeloong/fwstart.S diff --git a/include/grub/mips/yeeloong/serial.h b/include/grub/mips/yeeloong/serial.h index 9390ea18a..bced102b6 100644 --- a/include/grub/mips/yeeloong/serial.h +++ b/include/grub/mips/yeeloong/serial.h @@ -19,6 +19,11 @@ #ifndef GRUB_MACHINE_SERIAL_HEADER #define GRUB_MACHINE_SERIAL_HEADER 1 +#ifndef ASM_FILE #define GRUB_MACHINE_SERIAL_PORTS { 0xbff003f8 } +#else +#define GRUB_MACHINE_SERIAL_PORT_HI 0xbff0 +#define GRUB_MACHINE_SERIAL_PORT_LO 0x03f8 +#endif #endif diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S new file mode 100644 index 000000000..5132d7584 --- /dev/null +++ b/kern/mips/yeeloong/fwstart.S @@ -0,0 +1,81 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + + .set noreorder + .set noat + .set nomacro + + bal serial_hw_init + nop +self: + b self + nop + + /* Same as similarly named C function but in asm since + we need it early. */ + /* In: none. Out: none. Clobbered: $t0, $t1, $a0. */ +serial_hw_init: + lui $t0, GRUB_MACHINE_SERIAL_PORT_HI + + /* Turn off the interrupt. */ + sb $zero, (GRUB_MACHINE_SERIAL_PORT_LO + UART_IER)($t0) + + /* Set DLAB. */ + ori $t1, $zero, UART_DLAB + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LCR)($t0) + + /* Set the baud rate 115200. */ + ori $t1, $zero, 2 + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_DLL)($t0) + sb $zero, (GRUB_MACHINE_SERIAL_PORT_LO + UART_DLH)($t0) + + /* Set the line status. */ + ori $t1, $zero, (UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT) + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LCR)($t0) + + /* Enable the FIFO. */ + ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1 + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_FCR)($t0) + + /* Turn on DTR and RTS. */ + ori $t1, $zero, UART_ENABLE_DTRRTS + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_MCR)($t0) + + lui $t0, 0xbff0 + addiu $t0, $t0, 0x03f8 + + /* Let message return to original caller. */ + lui $a0, %hi(notification_string) + addiu $a0, $a0, %lo(notification_string) + + /* Print message on serial console. */ + /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */ +message: + lui $t0, GRUB_MACHINE_SERIAL_PORT_HI +1: + lb $t1, 0($a0) + addiu $a0, $a0, 1 + bne $t1, $zero, 1b + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_TX)($t0) + jr $ra + nop + +notification_string: .asciz "GRUB " From 7517048135ddc577be71751bca56dedfe37f00e6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 17 Feb 2010 21:10:58 +0100 Subject: [PATCH 04/45] Working SPD reading in fwstart.img --- bus/cs5536.c | 6 +- conf/mips-yeeloong.rmk | 8 + include/grub/cs5536.h | 21 ++- include/grub/mips/yeeloong/boot.h | 27 ++++ include/grub/mips/yeeloong/pci.h | 10 ++ include/grub/pci.h | 4 + include/grub/smbus.h | 3 + kern/mips/yeeloong/fwstart.S | 254 +++++++++++++++++++++++++++++- 8 files changed, 321 insertions(+), 12 deletions(-) diff --git a/bus/cs5536.c b/bus/cs5536.c index 3a7ac2bb1..f481397b7 100644 --- a/bus/cs5536.c +++ b/bus/cs5536.c @@ -80,11 +80,11 @@ grub_cs5536_smbus_wait (grub_port_t smbbase) { grub_uint8_t status; status = grub_inb (smbbase + GRUB_CS5536_SMB_REG_STATUS); - if (status & (1 << 6)) + if (status & GRUB_CS5536_SMB_REG_STATUS_SDAST) return GRUB_ERR_NONE; - if (status & (1 << 5)) + if (status & GRUB_CS5536_SMB_REG_STATUS_BER) return grub_error (GRUB_ERR_IO, "SM bus error"); - if (status & (1 << 4)) + if (status & GRUB_CS5536_SMB_REG_STATUS_NACK) return grub_error (GRUB_ERR_IO, "NACK received"); if (grub_get_time_ms () > start + 40) return grub_error (GRUB_ERR_IO, "SM stalled"); diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk index 901a63dd0..aa3e96fa0 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -30,6 +30,14 @@ kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \ -Wl,-N,-S,-Ttext,$(LINK_BASE),-Bstatic kernel_img_FORMAT = binary +pkglib_IMAGES += fwstart.img +fwstart_img_SOURCES = kern/$(target_cpu)/$(target_machine)/fwstart.S +fwstart_img_CFLAGS = $(COMMON_CFLAGS) +fwstart_img_ASFLAGS = $(COMMON_ASFLAGS) +fwstart_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \ + -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic +fwstart_img_FORMAT = binary + # For ata.mod. pkglib_MODULES += ata.mod ata_mod_SOURCES = disk/ata.c diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index 233362160..51a21eb6e 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -19,17 +19,23 @@ #ifndef GRUB_CS5536_HEADER #define GRUB_CS5536_HEADER 1 +#ifndef ASM_FILE #include #include #include +#endif #define GRUB_CS5536_PCIID 0x208f1022 #define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4 #define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8 #define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc #define GRUB_CS5536_MSR_SMB_BAR 0x8000000b +#define GRUB_CS5536_MSR_GPIO_BAR 0x8000000c #define GRUB_CS5536_SMB_REG_DATA 0x0 #define GRUB_CS5536_SMB_REG_STATUS 0x1 +#define GRUB_CS5536_SMB_REG_STATUS_SDAST (1 << 6) +#define GRUB_CS5536_SMB_REG_STATUS_BER (1 << 5) +#define GRUB_CS5536_SMB_REG_STATUS_NACK (1 << 4) #define GRUB_CS5536_SMB_REG_CTRL1 0x3 #define GRUB_CS5536_SMB_REG_CTRL1_START 0x01 #define GRUB_CS5536_SMB_REG_CTRL1_STOP 0x02 @@ -41,11 +47,19 @@ #define GRUB_CS5536_SMB_REG_CTRL3 0x6 #define GRUB_CS5536_LBAR_ADDR_MASK 0x000000000000fff8ULL -#define GRUB_CS5536_LBAR_ADDR_OFF 3 #define GRUB_CS5536_LBAR_ENABLE 0x0000000100000000ULL -#define GRUB_SMB_RAM_START_ADDR 0x50 -#define GRUB_SMB_RAM_NUM_MAX 0x08 +/* PMON-compatible LBARs. */ +#define GRUB_CS5536_LBAR_GPIO 0x0b000 +#define GRUB_CS5536_LBAR_SMBUS 0x0b390 + +#define GRUB_GPIO_SMBUS_PINS ((1 << 14) | (1 << 15)) +#define GRUB_GPIO_REG_OUT_EN 0x4 +#define GRUB_GPIO_REG_OUT_AUX1 0x10 +#define GRUB_GPIO_REG_IN_EN 0x20 +#define GRUB_GPIO_REG_IN_AUX1 0x34 + +#ifndef ASM_FILE int grub_cs5536_find (grub_pci_device_t *devp); grub_uint64_t grub_cs5536_read_msr (grub_pci_device_t dev, grub_uint32_t addr); @@ -58,5 +72,6 @@ grub_err_t grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev, grub_err_t grub_cs5536_smbus_wait (grub_port_t smbbase); grub_err_t grub_cs5536_init_smbus (grub_pci_device_t dev, grub_uint16_t divisor, grub_port_t *smbbase); +#endif #endif diff --git a/include/grub/mips/yeeloong/boot.h b/include/grub/mips/yeeloong/boot.h index e69de29bb..205c557fe 100644 --- a/include/grub/mips/yeeloong/boot.h +++ b/include/grub/mips/yeeloong/boot.h @@ -0,0 +1,27 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_BOOT_MACHINE_HEADER +#define GRUB_BOOT_MACHINE_HEADER 1 + +#define GRUB_MACHINE_FLASH_START 0xbfc00000 +#define GRUB_MACHINE_FLASH_TLB_REFILL 0xbfc00200 +#define GRUB_MACHINE_FLASH_CACHE_ERROR 0xbfc00300 +#define GRUB_MACHINE_FLASH_OTHER_EXCEPTION 0xbfc00380 + +#endif diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h index c7bd31d4f..f50cdcb35 100644 --- a/include/grub/mips/yeeloong/pci.h +++ b/include/grub/mips/yeeloong/pci.h @@ -19,16 +19,24 @@ #ifndef GRUB_MACHINE_PCI_H #define GRUB_MACHINE_PCI_H 1 +#ifndef ASM_FILE #include #include +#endif #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 + +#ifndef ASM_FILE #define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00118) #define GRUB_MACHINE_PCI_IO_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110) +#else +#define GRUB_MACHINE_PCI_CONF_CTRL_REG_HI 0xbfe0 +#define GRUB_MACHINE_PCI_CONF_CTRL_REG_LO 0x0118 +#endif #define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6 #define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1) @@ -46,6 +54,7 @@ #define GRUB_MACHINE_PCI_WIN2_ADDR 0xb4000000 #define GRUB_MACHINE_PCI_WIN3_ADDR 0xb8000000 +#ifndef ASM_FILE static inline grub_uint32_t grub_pci_read (grub_pci_address_t addr) { @@ -101,5 +110,6 @@ void grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), volatile void *mem, grub_size_t size __attribute__ ((unused))); +#endif #endif /* GRUB_MACHINE_PCI_H */ diff --git a/include/grub/pci.h b/include/grub/pci.h index 1f3ac7fc7..17f769f4c 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -19,8 +19,10 @@ #ifndef GRUB_PCI_H #define GRUB_PCI_H 1 +#ifndef ASM_FILE #include #include +#endif #define GRUB_PCI_ADDR_SPACE_MASK 0x01 #define GRUB_PCI_ADDR_SPACE_MEMORY 0x00 @@ -66,6 +68,7 @@ #define GRUB_PCI_REG_MIN_GNT 0x3e #define GRUB_PCI_REG_MAX_LAT 0x3f +#ifndef ASM_FILE typedef grub_uint32_t grub_pci_id_t; #ifdef GRUB_UTIL @@ -106,5 +109,6 @@ grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev, int reg); void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook); +#endif #endif /* GRUB_PCI_H */ diff --git a/include/grub/smbus.h b/include/grub/smbus.h index 6e9b5005c..b9cc6ab9e 100644 --- a/include/grub/smbus.h +++ b/include/grub/smbus.h @@ -19,6 +19,9 @@ #ifndef GRUB_SMBUS_HEADER #define GRUB_SMBUS_HEADER 1 +#define GRUB_SMB_RAM_START_ADDR 0x50 +#define GRUB_SMB_RAM_NUM_MAX 0x08 + struct grub_smbus_spd { grub_uint8_t written_size; diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index 5132d7584..59fe4d3e6 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -17,17 +17,107 @@ */ #include +#include +#include +#include #include +#include .set noreorder .set noat .set nomacro + .global start,_start,__start +start: +_start: +__start: bal serial_hw_init nop -self: - b self - nop + /* Find CS5536 controller. */ + /* $t4 chooses device in priority encoding. */ + /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG. + This way we don't need to sacrifice a register for it. */ + /* We have only one bus (0). Function is 0. */ + lui $t0, GRUB_MACHINE_PCI_CONF_CTRL_REG_HI + lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) + lui $t3, %hi(GRUB_CS5536_PCIID) + addiu $t3, $t3, %lo(GRUB_CS5536_PCIID) + ori $t4, $zero, 1 + lui $a0, %hi(no_cs5536) +1: + andi $t4, $t4, 0xffff + beql $t4, $zero, fatal + addiu $a0, $a0, %lo(no_cs5536) + sw $t4, GRUB_MACHINE_PCI_CONF_CTRL_REG_LO($t0) + lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1) + bnel $t2, $t3, 1b + sll $t4, $t4, 1 + + bal message + addiu $a0, $a0, %lo(cs5536_found) + bal printhex + move $a0, $t4 + + /* Initialise SMBus controller. */ + /* Set GPIO LBAR. */ + lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR) + addiu $a0, $a0, %lo(GRUB_CS5536_MSR_GPIO_BAR) + ori $a1, $zero, GRUB_CS5536_LBAR_GPIO + /* Set mask to 0xf and enabled bit to 1. */ + bal wrmsr + ori $a2, $zero, 0xf001 + + /* Set SMBUS LBAR. */ + lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR) + addiu $a0, $a0, %lo(GRUB_CS5536_MSR_SMB_BAR) + ori $a1, $zero, GRUB_CS5536_LBAR_SMBUS + /* Set mask to 0xf and enabled bit to 1. */ + bal wrmsr + ori $a2, $zero, 0xf001 + + lui $a0, %hi(smbus_enabled) + bal message + addiu $a0, $a0, %lo(smbus_enabled) + + /* Enable SMBus controller pins. */ + lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO) + ori $t1, $zero, GRUB_GPIO_SMBUS_PINS + sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_EN) ($t0) + sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_AUX1) ($t0) + sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_EN) ($t0) + sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_AUX1) ($t0) + + lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS) + + /* Disable SMB. */ + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) + + /* Disable interrupts. */ + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0) + + /* Set as master. */ + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0) + + /* Launch SMBus controller at slowest speed possible. */ + ori $t1, $zero, 0xff + sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0) + sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) + + ori $a0, $zero, 0x50 + bal read_spd + move $a1, $zero + bal printhex + move $a0, $v0 + + ori $a0, $zero, 0x50 + bal read_spd + ori $a1, $zero, 2 + bal printhex + move $a0, $v0 + + lui $a0, %hi(not_implemented) + b fatal + addiu $a0, $a0, %lo(not_implemented) /* Same as similarly named C function but in asm since we need it early. */ @@ -70,12 +160,164 @@ serial_hw_init: /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */ message: lui $t0, GRUB_MACHINE_SERIAL_PORT_HI -1: +1: + lb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LSR)($t0) + andi $t1, $t1, UART_EMPTY_TRANSMITTER + beq $t1, $zero, 1b + nop lb $t1, 0($a0) - addiu $a0, $a0, 1 + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_TX)($t0) bne $t1, $zero, 1b - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_TX)($t0) + addiu $a0, $a0, 1 jr $ra nop + /* Print 32-bit hexadecimal on serial. + In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2 + */ +printhex: + lui $t0, GRUB_MACHINE_SERIAL_PORT_HI + ori $t2, $zero, 8 +1: + lb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LSR)($t0) + andi $t1, $t1, UART_EMPTY_TRANSMITTER + beq $t1, $zero, 1b + nop + srl $t1, $a0, 28 + addiu $t1, $t1, -10 + blt $t1, $zero, 2f + sll $a0, $a0, 4 + addiu $t1, $t1, 'A'-10-'0' +2: addiu $t1, $t1, '0'+10 + sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_TX)($t0) + addiu $t2, $t2, -1 + bne $t2, $zero, 1b + nop + jr $ra + nop + +fatal: + bal message + nop +self: + b self + nop + + . = start + GRUB_MACHINE_FLASH_TLB_REFILL - GRUB_MACHINE_FLASH_START +tlb_refill: + lui $a0, %hi(unhandled_tlb_refill) + b fatal + addiu $a0, $a0, %lo(unhandled_tlb_refill) + + . = start + GRUB_MACHINE_FLASH_CACHE_ERROR - GRUB_MACHINE_FLASH_START +cache_error: + lui $a0, %hi(unhandled_cache_error) + b fatal + addiu $a0, $a0, %lo(unhandled_cache_error) + + . = start + GRUB_MACHINE_FLASH_OTHER_EXCEPTION - GRUB_MACHINE_FLASH_START +other_exception: + lui $a0, %hi(unhandled_exception) + b fatal + addiu $a0, $a0, %lo(unhandled_exception) + + /* Write CS5536 MSR. + In: $a0 address, $a1 lower word, $a2 upper word. + Out: None + Clobbered: $t0 + */ +wrmsr: + lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE) + sw $a0, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_ADDR) ($t0) + sw $a1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA0) ($t0) + jr $ra + sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0) + + /* Wait for SMBus data or empty transmitter. */ + /* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1 */ +smbus_wait: +1: + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) + lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) ($t0) + andi $t1, $t0, GRUB_CS5536_SMB_REG_STATUS_SDAST + bne $t1, $zero, return + nop + andi $t1, $t0, (GRUB_CS5536_SMB_REG_STATUS_BER | GRUB_CS5536_SMB_REG_STATUS_NACK) + beq $t1, $zero, 1b + nop + jr $a0 + nop +return: + jr $ra + nop + + /* Read SPD byte. In: $a0 device, $a1 byte. Out: $v0 read byte (0x100 on failure). + Clobbered: $t0, $t1, $t2, $t3, $a0. */ +read_spd: + move $t2, $a0 + move $t3, $ra + lui $a0, %hi(read_spd_fail) + addiu $a0, $a0, %hi(read_spd_fail) + + /* Send START. */ + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START + bal smbus_wait + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + + /* Send device address. */ + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) + sll $t1, $t2, 1 + bal smbus_wait + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + + /* Send ACK. */ + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_ACK + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + + /* Send byte address. */ + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) + bal smbus_wait + sb $a1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + + /* Send START. */ + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START + bal smbus_wait + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + + /* Send device address. */ + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) + sll $t1, $t2, 1 + ori $t1, $t1, 1 + bal smbus_wait + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + + /* Send STOP. */ + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_STOP + bal smbus_wait + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) + lb $v0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + jr $t3 + andi $v0, $v0, 0xff +read_spd_fail: + jr $t3 + ori $v0, $v0, 0x100 + notification_string: .asciz "GRUB " +no_cs5536: .asciz "No CS5536 found.\n\r" +cs5536_found: .asciz "CS5536 at " +sm_failed: .asciz "SM transaction failed.\n\r" +not_implemented: .asciz "Nothing more is implemented. Bye.\n\r" +unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r" +unhandled_cache_error: .asciz "Unhandled cache error.\n\r" +unhandled_exception: .asciz "Unhandled exception.\n\r" +smbus_enabled: .asciz "SMBus controller enabled.\n\r" From 813a5f2d33cd81da080daba410543f68aa7382e0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 1 Mar 2010 18:53:34 +0100 Subject: [PATCH 05/45] Init DDR2 controller --- include/grub/mips/yeeloong/boot.h | 3 + include/grub/smbus.h | 34 +++- kern/mips/yeeloong/fwstart.S | 279 ++++++++++++++++++++++++++---- util/grub-mkrawimage.c | 26 ++- 4 files changed, 307 insertions(+), 35 deletions(-) diff --git a/include/grub/mips/yeeloong/boot.h b/include/grub/mips/yeeloong/boot.h index 205c557fe..6a4189ede 100644 --- a/include/grub/mips/yeeloong/boot.h +++ b/include/grub/mips/yeeloong/boot.h @@ -24,4 +24,7 @@ #define GRUB_MACHINE_FLASH_CACHE_ERROR 0xbfc00300 #define GRUB_MACHINE_FLASH_OTHER_EXCEPTION 0xbfc00380 +#define GRUB_MACHINE_DDR2_BASE 0xaffffe00 +#define GRUB_MACHINE_DDR2_REG1_HI_8BANKS 0x00000001 + #endif diff --git a/include/grub/smbus.h b/include/grub/smbus.h index b9cc6ab9e..0b8e6718f 100644 --- a/include/grub/smbus.h +++ b/include/grub/smbus.h @@ -22,21 +22,49 @@ #define GRUB_SMB_RAM_START_ADDR 0x50 #define GRUB_SMB_RAM_NUM_MAX 0x08 +#define GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR 2 +#define GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 8 +#define GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR 17 +#define GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR 3 +#define GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR 4 +#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_ADDR 5 +#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK 0x7 +#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR 18 +#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE 5 +#define GRUB_SMBUS_SPD_MEMORY_TRAS_ADDR 30 +#define GRUB_SMBUS_SPD_MEMORY_TRTP_ADDR 38 + +#ifndef ASM_FILE + struct grub_smbus_spd { grub_uint8_t written_size; grub_uint8_t log_total_flash_size; -#define GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 8 grub_uint8_t memory_type; union { grub_uint8_t unknown[253]; struct { - grub_uint8_t unused1[70]; + grub_uint8_t num_rows; + grub_uint8_t num_columns; + grub_uint8_t num_of_ranks; + grub_uint8_t unused1[12]; + grub_uint8_t num_of_banks; + grub_uint8_t unused2[2]; + grub_uint8_t cas_latency; + grub_uint8_t unused3[9]; + grub_uint8_t rank_capacity; + grub_uint8_t unused4[1]; + grub_uint8_t tras; + grub_uint8_t unused5[7]; + grub_uint8_t trtp; + grub_uint8_t unused6[31]; grub_uint8_t part_number[18]; - grub_uint8_t unused2[165]; + grub_uint8_t unused7[165]; } ddr2; }; }; #endif + +#endif diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index 59fe4d3e6..3dccb65fd 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -22,6 +22,7 @@ #include #include #include +#include .set noreorder .set noat @@ -103,21 +104,102 @@ __start: sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0) sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) - ori $a0, $zero, 0x50 + /* Yeeloong has only one memory slot. */ + /* Output first byte on serial for debugging. */ + ori $a1, $zero, GRUB_SMB_RAM_START_ADDR bal read_spd - move $a1, $zero + move $a0, $zero bal printhex move $a0, $v0 - ori $a0, $zero, 0x50 bal read_spd - ori $a1, $zero, 2 + ori $a0, $zero, 2 + ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 + lui $a0, %hi(unimplemented_memory_type) + bne $t0, $v0, fatal + addiu $a0, $a0, %hi(unimplemented_memory_type) + + /* And here is our goal: DDR2 controller initialisation. */ + lui $t0, 0xbfe0 + ld $t1, 0x0180($t0) + andi $t1, $t1, 0x4ff + sd $t1, 0x0180($t0) + + b continue + + . = start + GRUB_MACHINE_FLASH_TLB_REFILL - GRUB_MACHINE_FLASH_START +tlb_refill: + mfc0 $s1, $14 + mfc0 $s2, $8 + move $s3, $ra + lui $a0, %hi(epc) + bal message + addiu $a0, $a0, %lo(epc) + bal printhex - move $a0, $v0 + move $a0, $s1 + + lui $a0, %hi(badvaddr) + bal message + addiu $a0, $a0, %lo(badvaddr) + + bal printhex + move $a0, $s2 + + lui $a0, %hi(return_msg) + bal message + addiu $a0, $a0, %lo(return_msg) + + bal printhex + move $a0, $s3 - lui $a0, %hi(not_implemented) + lui $a0, %hi(newline) + bal message + addiu $a0, $a0, %lo(newline) + + lui $a0, %hi(unhandled_tlb_refill) b fatal - addiu $a0, $a0, %lo(not_implemented) + addiu $a0, $a0, %lo(unhandled_tlb_refill) + + . = start + GRUB_MACHINE_FLASH_CACHE_ERROR - GRUB_MACHINE_FLASH_START +cache_error: + lui $a0, %hi(unhandled_cache_error) + b fatal + addiu $a0, $a0, %lo(unhandled_cache_error) + + . = start + GRUB_MACHINE_FLASH_OTHER_EXCEPTION - GRUB_MACHINE_FLASH_START +other_exception: + mfc0 $s0, $13 + mfc0 $s1, $14 + mfc0 $s2, $8 + lui $a0, %hi(cause) + bal message + addiu $a0, $a0, %lo(cause) + + bal printhex + move $a0, $s0 + + lui $a0, %hi(epc) + bal message + addiu $a0, $a0, %lo(epc) + + bal printhex + move $a0, $s1 + + lui $a0, %hi(badvaddr) + bal message + addiu $a0, $a0, %lo(badvaddr) + + bal printhex + move $a0, $s2 + + lui $a0, %hi(newline) + bal message + addiu $a0, $a0, %lo(newline) + + lui $a0, %hi(unhandled_exception) + b fatal + addiu $a0, $a0, %lo(unhandled_exception) /* Same as similarly named C function but in asm since we need it early. */ @@ -171,7 +253,7 @@ message: addiu $a0, $a0, 1 jr $ra nop - + /* Print 32-bit hexadecimal on serial. In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2 */ @@ -202,25 +284,7 @@ fatal: self: b self nop - - . = start + GRUB_MACHINE_FLASH_TLB_REFILL - GRUB_MACHINE_FLASH_START -tlb_refill: - lui $a0, %hi(unhandled_tlb_refill) - b fatal - addiu $a0, $a0, %lo(unhandled_tlb_refill) - - . = start + GRUB_MACHINE_FLASH_CACHE_ERROR - GRUB_MACHINE_FLASH_START -cache_error: - lui $a0, %hi(unhandled_cache_error) - b fatal - addiu $a0, $a0, %lo(unhandled_cache_error) - - . = start + GRUB_MACHINE_FLASH_OTHER_EXCEPTION - GRUB_MACHINE_FLASH_START -other_exception: - lui $a0, %hi(unhandled_exception) - b fatal - addiu $a0, $a0, %lo(unhandled_exception) - + /* Write CS5536 MSR. In: $a0 address, $a1 lower word, $a2 upper word. Out: None @@ -251,7 +315,7 @@ return: jr $ra nop - /* Read SPD byte. In: $a0 device, $a1 byte. Out: $v0 read byte (0x100 on failure). + /* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure). Clobbered: $t0, $t1, $t2, $t3, $a0. */ read_spd: move $t2, $a0 @@ -268,7 +332,7 @@ read_spd: /* Send device address. */ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) - sll $t1, $t2, 1 + sll $t1, $a1, 1 bal smbus_wait sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) @@ -281,7 +345,7 @@ read_spd: /* Send byte address. */ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) bal smbus_wait - sb $a1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) /* Send START. */ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) @@ -292,7 +356,7 @@ read_spd: /* Send device address. */ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) - sll $t1, $t2, 1 + sll $t1, $a1, 1 ori $t1, $t1, 1 bal smbus_wait sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) @@ -321,3 +385,156 @@ unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r" unhandled_cache_error: .asciz "Unhandled cache error.\n\r" unhandled_exception: .asciz "Unhandled exception.\n\r" smbus_enabled: .asciz "SMBus controller enabled.\n\r" +unimplemented_memory_type: .asciz "non-DDR2 memory isn't supported.\n\r" +no_cas_latency: .asciz "Couldn't determine CAS latency.\n\r" +cause: .asciz "Cause: " +epc: .asciz "\n\rEPC: " +badvaddr: .asciz "\n\rBadVaddr: " +newline: .asciz "\n\r" +return_msg: .asciz "\n\rReturn address: " + + .p2align 3 + +regdump: + .quad 0x0100010000000101 /* 0 */ + .quad 0x0100010100000000 /* 2 */ + .quad 0x0101000001000000 /* 3 */ + .quad 0x0100020200010101 /* 4 */ + .quad 0x0a04030603050203 /* 6 */ + .quad 0x0f0e040000010a0b /* 7 */ + .quad 0x0000010200000102 /* 8 */ + .quad 0x0000060c00000000 /* 9 */ + .quad 0x2323233f3f1f0200 /* a */ + .quad 0x5f7f232323232323 /* b */ + .quad 0x002a3c0615000000 /* c */ + .quad 0x002a002a002a002a /* d */ + .quad 0x002a002a002a002a /* e */ + .quad 0x00b40020006d0004 /* f */ + .quad 0x070007ff00000087 /* 10 */ + .quad 0x000000000016101f /* 11 */ + .quad 0x001c000000000000 /* 12 */ + .quad 0x28e1000200c8006b /* 13 */ + .quad 0x0000204200c8002f /* 14 */ + .quad 0x0000000000030d40 /* 15 */ + .quad 0 /* 16 */ + .quad 0 /* 17 */ + .quad 0 /* 18 */ + .quad 0 /* 19 */ + .quad 0 /* 1a */ + .quad 0 /* 1b */ + .quad 0 /* 1c */ + + .p2align + +write_dumpreg: + ld $t2, 0($t6) + sd $t2, 0($t4) + addiu $t4, $t4, 0x10 + jr $ra + addiu $t6, $t6, 0x8 + +continue: + lui $t4, %hi(GRUB_MACHINE_DDR2_BASE) + addiu $t4, $t4, %lo(GRUB_MACHINE_DDR2_BASE) + lui $t6, %hi(regdump) + + /* 0 */ + bal write_dumpreg + addiu $t6, $t6, %lo(regdump) + + /* 1 */ + ori $a1, $a1, 0x50 + move $t8, $zero + lui $t5, 0x0001 + bal read_spd + ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR + ori $t7, $zero, 8 + bne $v0, $t7, 1f + ori $t5, $t5, 0x0001 + ori $t8, $t8, GRUB_MACHINE_DDR2_REG1_HI_8BANKS +1: + dsll $t8, $t8, 32 + or $t5, $t5, $t8 + sd $t5, 0 ($t4) + addiu $t4, $t4, 0x10 + + /* 2 */ + bal write_dumpreg + nop + + /* 3 */ + bal write_dumpreg + nop + + /* 4 */ + bal write_dumpreg + nop + + /* 5 */ + /* FIXME: figure termination resistance. */ + ori $t5, $zero, 0x2 + bal read_spd + ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR + /* $v0 = 15 - $v0. */ + xori $v0, $v0, 0xf + andi $v0, $v0, 0x7 + sll $v0, $v0, 8 + or $t5, $t5, $v0 + + /* Find the fastest supported CAS latency. */ + bal read_spd + ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR + ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE + ori $t1, $zero, (1 << GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE) +2: + and $t2, $t1, $v0 + bne $t2, $zero, 1f + ori $t3, $zero, 8 + lui $a0, %hi(no_cas_latency) + beq $t0, $t3, fatal + addiu $a0, $a0, %lo(no_cas_latency) + addiu $t0, $t0, 1 + b 2b + sll $t1, $t1, 1 +1: + sll $t0, $t0, 16 + or $t5, $t5, $t0 + + bal read_spd + ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR + /* $v0 = 15 - ($v0 + 1) = 14 - $v0. */ + addiu $v0, $v0, 1 + xori $v0, $v0, 0xf + andi $v0, $v0, 0x7 + sll $v0, 24 + or $t5, $t5, $v0 + sd $t5, 0 ($t4) + + addiu $t4, $t4, 0x10 + + ori $t7, $zero, 0x16 + +1: + ld $t2, 0($t6) + sd $t2, 0($t4) + addiu $t4, $t4, 0x10 + addiu $t7, $t7, -1 + bne $t7, $zero, 1b + addiu $t6, $t6, 0x8 + + lui $t4, %hi(GRUB_MACHINE_DDR2_BASE) + ld $t5, (%lo(GRUB_MACHINE_DDR2_BASE) + 0x30) ($t4) + ori $t0, $zero, 1 + dsll $t0, $t0, 40 + or $t5, $t5, $t0 + sd $t5, (%lo(GRUB_MACHINE_DDR2_BASE) + 0x30) ($t4) + + /* Desactivate DDR2 registers. */ + lui $t0, 0xbfe0 + ld $t1, 0x0180($t0) + ori $t1, $t1, 0x100 + sd $t1, 0x0180($t0) + + addiu $a0, $zero, -1 + addiu $a1, $zero, -1 + addiu $a2, $zero, -1 diff --git a/util/grub-mkrawimage.c b/util/grub-mkrawimage.c index 83bb51c02..2f721f6ed 100644 --- a/util/grub-mkrawimage.c +++ b/util/grub-mkrawimage.c @@ -391,7 +391,31 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], free (core_img); core_img = elf_img; core_size = program_size + sizeof (*ehdr) + sizeof (*phdr); - } + } + else + { + char *rom_img; + size_t rom_size; + char *boot_path, *boot_img; + size_t boot_size; + + boot_path = grub_util_get_path (dir, "fwstart.img"); + boot_size = grub_util_get_image_size (boot_path); + boot_img = grub_util_read_image (boot_path); + + rom_size = core_size + boot_size; + + rom_img = xmalloc (rom_size); + memset (rom_img, 0, rom_size); + + memcpy (rom_img, boot_img, boot_size); + + memcpy (rom_img + boot_size, core_img, core_size); + + free (core_img); + core_img = rom_img; + core_size = rom_size; + } #endif grub_util_write_image (core_img, core_size, out); From 5dd8753cc0351adbeb5eb271e2a34d2d0ba73329 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 1 Mar 2010 18:57:31 +0100 Subject: [PATCH 06/45] Properly init even without pmon parameters --- kern/mips/startup.S | 9 ++++++- kern/mips/yeeloong/init.c | 56 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/kern/mips/startup.S b/kern/mips/startup.S index 5e3fb7ad5..e3ba131aa 100644 --- a/kern/mips/startup.S +++ b/kern/mips/startup.S @@ -48,8 +48,15 @@ codestart: /* Parse arguments. Has to be done before relocation. So need to do it in asm. */ #ifdef GRUB_MACHINE_MIPS_YEELOONG + move $s2, $zero + move $s3, $zero + move $s4, $zero + move $s5, $zero + /* $a2 has the environment. */ - move $t0, $a2 + addiu $t0, $a2, 1 + beq $t0, $zero, argdone + move $t0, $a2 argcont: lw $t1, 0($t0) beq $t1, $zero, argdone diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 14e8a39a2..f35605f63 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -27,6 +27,7 @@ #include #include #include +#include extern void grub_video_sm712_init (void); extern void grub_video_video_init (void); @@ -89,16 +90,67 @@ void grub_machine_init (void) { void *modend; + + /* FIXME: measure this. */ + if (grub_arch_busclock == 0) + { + grub_arch_busclock = 66000000; + grub_arch_cpuclock = 797000000; + } + + grub_install_get_time_ms (grub_rtc_get_time_ms); + + if (grub_arch_memsize == 0) + { + grub_port_t smbbase; + grub_err_t err; + grub_pci_device_t dev; + struct grub_smbus_spd spd; + unsigned totalmem; + int i; + + if (!grub_cs5536_find (&dev)) + grub_fatal ("No CS5536 found\n"); + + err = grub_cs5536_init_smbus (dev, 0x7ff, &smbbase); + if (err) + grub_fatal ("Couldn't init SMBus: %s\n", grub_errmsg); + + /* Yeeloong has only one memory slot. */ + err = grub_cs5536_read_spd (smbbase, GRUB_SMB_RAM_START_ADDR, &spd); + if (err) + grub_fatal ("Couldn't read SPD: %s\n", grub_errmsg); + for (i = 5; i < 13; i++) + if (spd.ddr2.rank_capacity & (1 << (i & 7))) + break; + /* Something is wrong. */ + if (i == 13) + totalmem = 256; + else + totalmem = ((spd.ddr2.num_of_ranks + & GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK) + 1) << (i + 2); + + if (totalmem >= 256) + { + grub_arch_memsize = 256; + grub_arch_highmemsize = totalmem - 256; + } + else + { + grub_arch_memsize = (totalmem >> 20); + grub_arch_highmemsize = 0; + } + } + modend = get_modules_end (); grub_mm_init_region (modend, (grub_arch_memsize << 20) - (((grub_addr_t) modend) - GRUB_ARCH_LOWMEMVSTART)); /* FIXME: use upper memory as well. */ - grub_install_get_time_ms (grub_rtc_get_time_ms); /* Initialize output terminal (can't be done earlier, as gfxterm relies on a working heap. */ - grub_video_sm712_init (); grub_video_video_init (); + grub_video_sm712_init (); grub_video_bitmap_init (); grub_font_manager_init (); grub_term_gfxterm_init (); From 32f86589a6c13fe3e90d100bf7625970f1e1dfb8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 10 Mar 2010 22:09:06 +0100 Subject: [PATCH 07/45] Video support in firmware --- video/sm712.c | 70 +++++- video/sm712_init.c | 546 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 607 insertions(+), 9 deletions(-) create mode 100644 video/sm712_init.c diff --git a/video/sm712.c b/video/sm712.c index a86470b7d..f0d0f29c4 100644 --- a/video/sm712.c +++ b/video/sm712.c @@ -27,6 +27,10 @@ #include #include +#include "sm712_init.c" + +#define GRUB_SM712_TOTAL_MEMORY_SPACE 0x700400 + static struct { struct grub_video_mode_info mode_info; @@ -55,7 +59,7 @@ grub_video_sm712_video_fini (void) { if (framebuffer.mapped) grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, - 1024 * 600 * 2); + GRUB_SM712_TOTAL_MEMORY_SPACE); return grub_video_fb_fini (); } @@ -67,6 +71,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, int depth; grub_err_t err; int found = 0; + unsigned i; auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) @@ -102,11 +107,6 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); - if (found && framebuffer.base == 0) - { - /* FIXME: change framebuffer base */ - } - /* Fill mode info details. */ framebuffer.mode_info.width = 1024; framebuffer.mode_info.height = 600; @@ -124,12 +124,64 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, framebuffer.mode_info.reserved_mask_size = 0; framebuffer.mode_info.reserved_field_pos = 0; framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + + if (found && framebuffer.base == 0) + { + grub_pci_address_t addr; + /* FIXME: choose address dynamically if needed. */ + framebuffer.base = 0x04000000; + + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, framebuffer.base); + + /* Set latency. */ + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_CACHELINE); + grub_pci_write (addr, 0x8); + + /* Enable address spaces. */ + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, 0x7); + } + /* We can safely discard volatile attribute. */ - framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, - framebuffer.base, - 1024 * 600 * 2); + framebuffer.ptr + = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + GRUB_SM712_TOTAL_MEMORY_SPACE); framebuffer.mapped = 1; + /* Initialise SM712. */ + grub_outb (0x18, GRUB_MACHINE_PCI_IO_BASE + 0x3c4); + grub_outb (0x11, GRUB_MACHINE_PCI_IO_BASE + 0x3c5); + + /* Prevent garbage from appearing on the screen. */ + grub_memset (framebuffer.ptr, 0, + framebuffer.mode_info.height * framebuffer.mode_info.pitch); + + for (i = 0; i < ARRAY_SIZE (sm712_init); i++) + switch (sm712_init[i].directive) + { + case 1: + *(volatile grub_uint8_t *) ((char *) framebuffer.ptr + + sm712_init[i].addr) = sm712_init[i].val; + break; + case -1: + { + grub_uint8_t val = *(volatile grub_uint8_t *) + ((char *) framebuffer.ptr + sm712_init[i].addr); + (void) val; + } + break; + case 2: + *(volatile grub_uint16_t *) ((char *) framebuffer.ptr + + sm712_init[i].addr) = sm712_init[i].val; + break; + case 4: + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + + sm712_init[i].addr) = sm712_init[i].val; + break; + } + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); if (err) diff --git a/video/sm712_init.c b/video/sm712_init.c new file mode 100644 index 000000000..02c64c453 --- /dev/null +++ b/video/sm712_init.c @@ -0,0 +1,546 @@ +/* Following sequence is a capture of sm712 initialisation sequence. */ +static struct +{ + int directive; + grub_uint32_t addr; + grub_uint32_t val; +} sm712_init[] = +{ + {1, 0x7003c4, 0x21}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x62}, + {1, 0x7003c5, 0x7a}, + {1, 0x7003c4, 0x6a}, + {1, 0x7003c5, 0x16}, + {1, 0x7003c4, 0x6b}, + {1, 0x7003c5, 0x2}, + {1, 0x7003c6, 0x0}, + {1, 0x7003c4, 0x0}, + {1, 0x7003c5, 0x1}, + {1, 0x7003c2, 0xeb}, + {1, 0x7003c4, 0x0}, + {1, 0x7003c5, 0x3}, + {1, 0x7003c4, 0x1}, + {1, 0x7003c5, 0x1}, + {1, 0x7003c4, 0x2}, + {1, 0x7003c5, 0xf}, + {1, 0x7003c4, 0x3}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x4}, + {1, 0x7003c5, 0xe}, + {1, 0x7003c4, 0x10}, + {1, 0x7003c5, 0xc8}, + {1, 0x7003c4, 0x11}, + {1, 0x7003c5, 0x40}, + {1, 0x7003c4, 0x12}, + {1, 0x7003c5, 0x14}, + {1, 0x7003c4, 0x13}, + {1, 0x7003c5, 0x60}, + {1, 0x7003c4, 0x14}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x15}, + {1, 0x7003c5, 0xa}, + {1, 0x7003c4, 0x16}, + {1, 0x7003c5, 0x92}, + {1, 0x7003c4, 0x17}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x18}, + {1, 0x7003c5, 0x51}, + {1, 0x7003c4, 0x19}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x1a}, + {1, 0x7003c5, 0x1}, + {1, 0x7003c4, 0x1b}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x1c}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x1d}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x1e}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x1f}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x20}, + {1, 0x7003c5, 0xc4}, + {1, 0x7003c4, 0x21}, + {1, 0x7003c5, 0x30}, + {1, 0x7003c4, 0x22}, + {1, 0x7003c5, 0x2}, + {1, 0x7003c4, 0x23}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x24}, + {1, 0x7003c5, 0x1}, + {1, 0x7003c4, 0x30}, + {1, 0x7003c5, 0x28}, + {1, 0x7003c4, 0x31}, + {1, 0x7003c5, 0x3}, + {1, 0x7003c4, 0x32}, + {1, 0x7003c5, 0x24}, + {1, 0x7003c4, 0x33}, + {1, 0x7003c5, 0x9}, + {1, 0x7003c4, 0x34}, + {1, 0x7003c5, 0xc0}, + {1, 0x7003c4, 0x35}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x36}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x37}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x38}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x39}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x3a}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x3b}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x3c}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x3d}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x3e}, + {1, 0x7003c5, 0x3}, + {1, 0x7003c4, 0x3f}, + {1, 0x7003c5, 0xff}, + {1, 0x7003c4, 0x40}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x41}, + {1, 0x7003c5, 0xfc}, + {1, 0x7003c4, 0x42}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x43}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x44}, + {1, 0x7003c5, 0x20}, + {1, 0x7003c4, 0x45}, + {1, 0x7003c5, 0x18}, + {1, 0x7003c4, 0x46}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x47}, + {1, 0x7003c5, 0xfc}, + {1, 0x7003c4, 0x48}, + {1, 0x7003c5, 0x20}, + {1, 0x7003c4, 0x49}, + {1, 0x7003c5, 0xc}, + {1, 0x7003c4, 0x4a}, + {1, 0x7003c5, 0x44}, + {1, 0x7003c4, 0x4b}, + {1, 0x7003c5, 0x20}, + {1, 0x7003c4, 0x4c}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x4d}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x4e}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x4f}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x50}, + {1, 0x7003c5, 0x6}, + {1, 0x7003c4, 0x51}, + {1, 0x7003c5, 0x68}, + {1, 0x7003c4, 0x52}, + {1, 0x7003c5, 0xa7}, + {1, 0x7003c4, 0x53}, + {1, 0x7003c5, 0x7f}, + {1, 0x7003c4, 0x54}, + {1, 0x7003c5, 0x83}, + {1, 0x7003c4, 0x55}, + {1, 0x7003c5, 0x24}, + {1, 0x7003c4, 0x56}, + {1, 0x7003c5, 0xff}, + {1, 0x7003c4, 0x57}, + {1, 0x7003c5, 0x3}, + {1, 0x7003c4, 0x58}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x59}, + {1, 0x7003c5, 0x60}, + {1, 0x7003c4, 0x5a}, + {1, 0x7003c5, 0x59}, + {1, 0x7003c4, 0x5b}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x5c}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x5d}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x5e}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x5f}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x60}, + {1, 0x7003c5, 0x1}, + {1, 0x7003c4, 0x61}, + {1, 0x7003c5, 0x80}, + {1, 0x7003c4, 0x63}, + {1, 0x7003c5, 0x1a}, + {1, 0x7003c4, 0x64}, + {1, 0x7003c5, 0x1a}, + {1, 0x7003c4, 0x65}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x66}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x67}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x68}, + {1, 0x7003c5, 0x50}, + {1, 0x7003c4, 0x69}, + {1, 0x7003c5, 0x3}, + {1, 0x7003c4, 0x6c}, + {1, 0x7003c5, 0x52}, + {1, 0x7003c4, 0x6d}, + {1, 0x7003c5, 0x89}, + {1, 0x7003c4, 0x6e}, + {1, 0x7003c5, 0x9}, + {1, 0x7003c4, 0x6f}, + {1, 0x7003c5, 0x2}, + {1, 0x7003c4, 0x70}, + {1, 0x7003c5, 0x4}, + {1, 0x7003c4, 0x71}, + {1, 0x7003c5, 0x45}, + {1, 0x7003c4, 0x72}, + {1, 0x7003c5, 0x30}, + {1, 0x7003c4, 0x73}, + {1, 0x7003c5, 0x30}, + {1, 0x7003c4, 0x74}, + {1, 0x7003c5, 0x40}, + {1, 0x7003c4, 0x75}, + {1, 0x7003c5, 0x20}, + {1, 0x7003c4, 0x80}, + {1, 0x7003c5, 0xff}, + {1, 0x7003c4, 0x81}, + {1, 0x7003c5, 0x7}, + {1, 0x7003c4, 0x82}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x83}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x84}, + {1, 0x7003c5, 0x8}, + {1, 0x7003c4, 0x85}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x86}, + {1, 0x7003c5, 0x42}, + {1, 0x7003c4, 0x87}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x88}, + {1, 0x7003c5, 0x59}, + {1, 0x7003c4, 0x89}, + {1, 0x7003c5, 0x2}, + {1, 0x7003c4, 0x8a}, + {1, 0x7003c5, 0x44}, + {1, 0x7003c4, 0x8b}, + {1, 0x7003c5, 0x2}, + {1, 0x7003c4, 0x8c}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x8d}, + {1, 0x7003c5, 0xff}, + {1, 0x7003c4, 0x8e}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x8f}, + {1, 0x7003c5, 0x3a}, + {1, 0x7003c4, 0x90}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x91}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x92}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0x93}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0xa0}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0xa1}, + {1, 0x7003c5, 0x10}, + {1, 0x7003c4, 0xa2}, + {1, 0x7003c5, 0x8}, + {1, 0x7003c4, 0xa3}, + {1, 0x7003c5, 0x0}, + {1, 0x7003c4, 0xa4}, + {1, 0x7003c5, 0x2}, + {1, 0x7003c4, 0xa5}, + {1, 0x7003c5, 0xed}, + {1, 0x7003c4, 0xa6}, + {1, 0x7003c5, 0xed}, + {1, 0x7003c4, 0xa7}, + {1, 0x7003c5, 0xed}, + {1, 0x7003c4, 0xa8}, + {1, 0x7003c5, 0x7b}, + {1, 0x7003c4, 0xa9}, + {1, 0x7003c5, 0xfb}, + {1, 0x7003c4, 0xaa}, + {1, 0x7003c5, 0xff}, + {1, 0x7003c4, 0xab}, + {1, 0x7003c5, 0xff}, + {1, 0x7003c4, 0xac}, + {1, 0x7003c5, 0x97}, + {1, 0x7003c4, 0xad}, + {1, 0x7003c5, 0xef}, + {1, 0x7003c4, 0xae}, + {1, 0x7003c5, 0xbf}, + {1, 0x7003c4, 0xaf}, + {1, 0x7003c5, 0xdf}, + {1, 0x7003ce, 0x0}, + {1, 0x7003cf, 0x0}, + {1, 0x7003ce, 0x1}, + {1, 0x7003cf, 0x0}, + {1, 0x7003ce, 0x2}, + {1, 0x7003cf, 0x0}, + {1, 0x7003ce, 0x3}, + {1, 0x7003cf, 0x0}, + {1, 0x7003ce, 0x4}, + {1, 0x7003cf, 0x0}, + {1, 0x7003ce, 0x5}, + {1, 0x7003cf, 0x40}, + {1, 0x7003ce, 0x6}, + {1, 0x7003cf, 0x5}, + {1, 0x7003ce, 0x7}, + {1, 0x7003cf, 0xf}, + {1, 0x7003ce, 0x8}, + {1, 0x7003cf, 0xff}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x0}, + {-1, 0x7003c1, 0x3e}, + {1, 0x7003c0, 0x0}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x1}, + {-1, 0x7003c1, 0x3b}, + {1, 0x7003c0, 0x1}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x2}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0x2}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x3}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0x3}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x4}, + {-1, 0x7003c1, 0x3b}, + {1, 0x7003c0, 0x4}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x5}, + {-1, 0x7003c1, 0x2f}, + {1, 0x7003c0, 0x5}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x6}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0x6}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x7}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0x7}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x8}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0x8}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x9}, + {-1, 0x7003c1, 0x3d}, + {1, 0x7003c0, 0x9}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0xa}, + {-1, 0x7003c1, 0x1f}, + {1, 0x7003c0, 0xa}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0xb}, + {-1, 0x7003c1, 0x1f}, + {1, 0x7003c0, 0xb}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0xc}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0xc}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0xd}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0xd}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0xe}, + {-1, 0x7003c1, 0x3f}, + {1, 0x7003c0, 0xe}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0xf}, + {-1, 0x7003c1, 0x2e}, + {1, 0x7003c0, 0xf}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x10}, + {-1, 0x7003c1, 0x0}, + {1, 0x7003c0, 0x41}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x11}, + {-1, 0x7003c1, 0x0}, + {1, 0x7003c0, 0x0}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x12}, + {-1, 0x7003c1, 0x0}, + {1, 0x7003c0, 0xf}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x13}, + {-1, 0x7003c1, 0x0}, + {1, 0x7003c0, 0x0}, + {-1, 0x7003da, 0x5}, + {1, 0x7003c0, 0x14}, + {-1, 0x7003c1, 0x0}, + {1, 0x7003c0, 0x0}, + {1, 0x7003d4, 0x0}, + {1, 0x7003d5, 0xa3}, + {1, 0x7003d4, 0x1}, + {1, 0x7003d5, 0x7f}, + {1, 0x7003d4, 0x2}, + {1, 0x7003d5, 0x7f}, + {1, 0x7003d4, 0x3}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x4}, + {1, 0x7003d5, 0x85}, + {1, 0x7003d4, 0x5}, + {1, 0x7003d5, 0x16}, + {1, 0x7003d4, 0x6}, + {1, 0x7003d5, 0x24}, + {1, 0x7003d4, 0x7}, + {1, 0x7003d5, 0xf5}, + {1, 0x7003d4, 0x8}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x9}, + {1, 0x7003d5, 0x60}, + {1, 0x7003d4, 0xa}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0xb}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0xc}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0xd}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0xe}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0xf}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x10}, + {1, 0x7003d5, 0x3}, + {1, 0x7003d4, 0x11}, + {1, 0x7003d5, 0x9}, + {1, 0x7003d4, 0x12}, + {1, 0x7003d5, 0xff}, + {1, 0x7003d4, 0x13}, + {1, 0x7003d5, 0x80}, + {1, 0x7003d4, 0x14}, + {1, 0x7003d5, 0x40}, + {1, 0x7003d4, 0x15}, + {1, 0x7003d5, 0xff}, + {1, 0x7003d4, 0x16}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x17}, + {1, 0x7003d5, 0xe3}, + {1, 0x7003d4, 0x18}, + {1, 0x7003d5, 0xff}, + {1, 0x7003d4, 0x30}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x31}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x32}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x33}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x34}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x35}, + {1, 0x7003d5, 0x80}, + {1, 0x7003d4, 0x36}, + {1, 0x7003d5, 0x2}, + {1, 0x7003d4, 0x37}, + {1, 0x7003d5, 0x20}, + {1, 0x7003d4, 0x38}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x39}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x3a}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x3b}, + {1, 0x7003d5, 0x40}, + {1, 0x7003d4, 0x3c}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x3d}, + {1, 0x7003d5, 0xff}, + {1, 0x7003d4, 0x3e}, + {1, 0x7003d5, 0x46}, + {1, 0x7003d4, 0x3f}, + {1, 0x7003d5, 0x91}, + {1, 0x7003d4, 0x40}, + {1, 0x7003d5, 0xa3}, + {1, 0x7003d4, 0x41}, + {1, 0x7003d5, 0x7f}, + {1, 0x7003d4, 0x42}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x43}, + {1, 0x7003d5, 0x86}, + {1, 0x7003d4, 0x44}, + {1, 0x7003d5, 0x15}, + {1, 0x7003d4, 0x45}, + {1, 0x7003d5, 0x24}, + {1, 0x7003d4, 0x46}, + {1, 0x7003d5, 0xff}, + {1, 0x7003d4, 0x47}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x48}, + {1, 0x7003d5, 0x1}, + {1, 0x7003d4, 0x49}, + {1, 0x7003d5, 0x7}, + {1, 0x7003d4, 0x4a}, + {1, 0x7003d5, 0xe5}, + {1, 0x7003d4, 0x4b}, + {1, 0x7003d5, 0x20}, + {1, 0x7003d4, 0x4c}, + {1, 0x7003d5, 0x7f}, + {1, 0x7003d4, 0x4d}, + {1, 0x7003d5, 0x57}, + {1, 0x7003d4, 0x90}, + {1, 0x7003d5, 0x55}, + {1, 0x7003d4, 0x91}, + {1, 0x7003d5, 0xd5}, + {1, 0x7003d4, 0x92}, + {1, 0x7003d5, 0x5d}, + {1, 0x7003d4, 0x93}, + {1, 0x7003d5, 0xdd}, + {1, 0x7003d4, 0x94}, + {1, 0x7003d5, 0x86}, + {1, 0x7003d4, 0x95}, + {1, 0x7003d5, 0x17}, + {1, 0x7003d4, 0x96}, + {1, 0x7003d5, 0x8e}, + {1, 0x7003d4, 0x97}, + {1, 0x7003d5, 0xaa}, + {1, 0x7003d4, 0x98}, + {1, 0x7003d5, 0x8a}, + {1, 0x7003d4, 0x99}, + {1, 0x7003d5, 0xa3}, + {1, 0x7003d4, 0x9a}, + {1, 0x7003d5, 0xde}, + {1, 0x7003d4, 0x9b}, + {1, 0x7003d5, 0xab}, + {1, 0x7003d4, 0x9c}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x9d}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x9e}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0x9f}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0xa0}, + {1, 0x7003d5, 0x2}, + {1, 0x7003d4, 0xa1}, + {1, 0x7003d5, 0x2}, + {1, 0x7003d4, 0xa2}, + {1, 0x7003d5, 0x2}, + {1, 0x7003d4, 0xa3}, + {1, 0x7003d5, 0x15}, + {1, 0x7003d4, 0xa4}, + {1, 0x7003d5, 0x2}, + {1, 0x7003d4, 0xa5}, + {1, 0x7003d5, 0x6}, + {1, 0x7003d4, 0xa6}, + {1, 0x7003d5, 0x0}, + {1, 0x7003d4, 0xa7}, + {1, 0x7003d5, 0x0}, + {1, 0x7003c2, 0x67}, + {4, 0x40c00c, 0x0}, + {4, 0x40c040, 0x0}, + {4, 0x40c000, 0x20000}, + {4, 0x40c010, 0x1020100}, + {1, 0x7003c4, 0x16}, + {-1, 0x7003c5, 0x17} +}; From bf8b8ab72558b490130666f1cc1f119607ff9f6f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 11 Mar 2010 02:47:08 +0100 Subject: [PATCH 08/45] Enable caches on yeeloong --- include/grub/mips/loongson.h | 57 +++++++++++++++++++++++++++ kern/mips/yeeloong/fwstart.S | 75 ++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 include/grub/mips/loongson.h diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h new file mode 100644 index 000000000..9c1ba6da9 --- /dev/null +++ b/include/grub/mips/loongson.h @@ -0,0 +1,57 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_LOONGSON_CPU_HEADER +#define GRUB_LOONGSON_CPU_HEADER 1 + +#define GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG $16 +#define GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE 0x10 +#define GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE 0x8 +#define GRUB_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT 6 +#define GRUB_CPU_LOONGSON_COP0_CACHE_ISIZE_SHIFT 9 +#define GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK 0x7 +#define GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET 12 + +#define GRUB_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE 0 +#define GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE 9 +#define GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE 11 + +#define GRUB_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET 5 +#define GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET 5 +#define GRUB_CPU_LOONGSON_COP0_S_INDEX_BIT_OFFSET 5 + +#define GRUB_CPU_LOONGSON_CACHE_ACCELERATED 7 +#define GRUB_CPU_LOONGSON_CACHE_UNCACHED 2 +#define GRUB_CPU_LOONGSON_CACHE_CACHED 3 +#define GRUB_CPU_LOONGSON_CACHE_TYPE_MASK 7 +#define GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_SMALL 4 +#define GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG 5 +#define GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_SMALL 16 +#define GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_BIG 32 + +#define GRUB_CPU_LOONGSON_I_CACHE_LOG_WAYS 2 +#define GRUB_CPU_LOONGSON_D_CACHE_LOG_WAYS 2 +#define GRUB_CPU_LOONGSON_S_CACHE_LOG_WAYS 2 + +/* Fixme: determine dynamically. */ +#define GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE 19 + +#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO $28 +#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI $29 + +#endif diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index 3dccb65fd..dc5dabc6c 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -392,6 +393,7 @@ epc: .asciz "\n\rEPC: " badvaddr: .asciz "\n\rBadVaddr: " newline: .asciz "\n\r" return_msg: .asciz "\n\rReturn address: " +caches_enabled: .asciz "Caches enabled\n\r" .p2align 3 @@ -535,6 +537,79 @@ continue: ori $t1, $t1, 0x100 sd $t1, 0x0180($t0) + /* Enable cache. */ + mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG + addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK + and $t0, $t1, $t1 + /* Set line size to 32 bytes and disabled cache. */ + ori $t0, $t0, (GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE \ + | GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE \ + | GRUB_CPU_LOONGSON_CACHE_ACCELERATED) + mtc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG + + /* Invalidate all I-cache entries. */ + srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_ISIZE_SHIFT + andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK + ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \ + - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \ + - GRUB_CPU_LOONGSON_I_CACHE_LOG_WAYS)) + sll $t1, $t2, $t1 + lui $t2, 0x8000 + +1: + cache GRUB_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE, 0($t2) + addiu $t1, $t1, -1 + bne $t1, $zero, 1b + addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET) + + /* Invalidate all D-cache entries. */ + srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT + andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK + ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \ + - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \ + - GRUB_CPU_LOONGSON_D_CACHE_LOG_WAYS)) + sll $t1, $t2, $t1 + lui $t2, 0x8000 + mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO + mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI +1: + /* All four ways. */ + cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 0($t2) + cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 1($t2) + cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 2($t2) + cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 3($t2) + addiu $t1, $t1, -1 + bne $t1, $zero, 1b + addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET) + + /* Invalidate all S-cache entries. */ + ori $t1, $zero, (1 << (GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE \ + - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \ + - GRUB_CPU_LOONGSON_S_CACHE_LOG_WAYS)) + lui $t2, 0x8000 + mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO + mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI +1: + /* All four ways. */ + cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 0($t2) + cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 1($t2) + cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 2($t2) + cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 3($t2) + addiu $t1, $t1, -1 + bne $t1, $zero, 1b + addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET) + + /* Finally enable cache. */ + mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG + addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK + and $t0, $t1, $t1 + ori $t0, $t0, GRUB_CPU_LOONGSON_CACHE_CACHED + mtc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG + + lui $a0, %hi(caches_enabled) + bal message + addiu $a0, $a0, %lo(caches_enabled) + addiu $a0, $zero, -1 addiu $a1, $zero, -1 addiu $a2, $zero, -1 From 21eecb8e83fd5bca74b1c5a694e1f89f11b4d4d6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 11 Mar 2010 03:21:10 +0100 Subject: [PATCH 09/45] Set ROM delay to 1 --- include/grub/mips/loongson.h | 4 ++++ kern/mips/yeeloong/fwstart.S | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index 9c1ba6da9..8441b6c0f 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -54,4 +54,8 @@ #define GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO $28 #define GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI $29 +#define GRUB_CPU_LOONGSON_LIOCFG 0xbfe00108 +#define GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET 2 +#define GRUB_CPU_LOONGSON_ROM_DELAY_MASK 0x1f + #endif diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index dc5dabc6c..d48acabc8 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -609,6 +609,15 @@ continue: lui $a0, %hi(caches_enabled) bal message addiu $a0, $a0, %lo(caches_enabled) + + /* Set ROM delay cycles to 1. */ + lui $t0, %hi(GRUB_CPU_LOONGSON_LIOCFG) + lw $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0) + addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_ROM_DELAY_MASK \ + << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET) + and $t1, $t1, $t2 + ori $t1, $t1, (1 << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET) + sw $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0) addiu $a0, $zero, -1 addiu $a1, $zero, -1 From edf717f5cb173c215c48dce454264637b048de3e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 11 Mar 2010 13:59:56 +0100 Subject: [PATCH 10/45] Macroify CP0 registers --- include/grub/mips/loongson.h | 16 +++++++++++++--- kern/mips/yeeloong/fwstart.S | 10 +++++----- kern/mips/yeeloong/init.c | 3 ++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index 8441b6c0f..2c69e6c3d 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -19,7 +19,13 @@ #ifndef GRUB_LOONGSON_CPU_HEADER #define GRUB_LOONGSON_CPU_HEADER 1 -#define GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG $16 +#ifdef ASM_FILE +#define GRUB_CPU_REGISTER_WRAP(x) x +#else +#define GRUB_CPU_REGISTER_WRAP(x) #x +#endif + +#define GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG GRUB_CPU_REGISTER_WRAP($16) #define GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE 0x10 #define GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE 0x8 #define GRUB_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT 6 @@ -51,8 +57,12 @@ /* Fixme: determine dynamically. */ #define GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE 19 -#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO $28 -#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI $29 +#define GRUB_CPU_LOONGSON_COP0_BADVADDR GRUB_CPU_REGISTER_WRAP($8) +#define GRUB_CPU_LOONGSON_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP($9) +#define GRUB_CPU_LOONGSON_COP0_CAUSE GRUB_CPU_REGISTER_WRAP($13) +#define GRUB_CPU_LOONGSON_COP0_EPC GRUB_CPU_REGISTER_WRAP($14) +#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO GRUB_CPU_REGISTER_WRAP($28) +#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI GRUB_CPU_REGISTER_WRAP($29) #define GRUB_CPU_LOONGSON_LIOCFG 0xbfe00108 #define GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET 2 diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index d48acabc8..e00da8933 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -130,8 +130,8 @@ __start: . = start + GRUB_MACHINE_FLASH_TLB_REFILL - GRUB_MACHINE_FLASH_START tlb_refill: - mfc0 $s1, $14 - mfc0 $s2, $8 + mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC + mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR move $s3, $ra lui $a0, %hi(epc) bal message @@ -170,9 +170,9 @@ cache_error: . = start + GRUB_MACHINE_FLASH_OTHER_EXCEPTION - GRUB_MACHINE_FLASH_START other_exception: - mfc0 $s0, $13 - mfc0 $s1, $14 - mfc0 $s2, $8 + mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE + mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC + mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR lui $a0, %hi(cause) bal message addiu $a0, $a0, %lo(cause) diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index f35605f63..f931cdb57 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,7 @@ grub_get_rtc (void) static grub_uint32_t last = 0; grub_uint32_t low; - asm volatile ("mfc0 %0, $9": "=r" (low)); + asm volatile ("mfc0 %0, " GRUB_CPU_LOONGSON_COP0_TIMER_COUNT : "=r" (low)); if (low < last) high++; last = low; From d0c7485824f6052c9f425bdb821f30de892edd54 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 11 Mar 2010 15:21:06 +0100 Subject: [PATCH 11/45] Macroify serial and PCI constants --- include/grub/mips/yeeloong/serial.h | 6 ++--- kern/mips/yeeloong/fwstart.S | 34 ++++++++++++++--------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/grub/mips/yeeloong/serial.h b/include/grub/mips/yeeloong/serial.h index bced102b6..b22352f5a 100644 --- a/include/grub/mips/yeeloong/serial.h +++ b/include/grub/mips/yeeloong/serial.h @@ -19,11 +19,11 @@ #ifndef GRUB_MACHINE_SERIAL_HEADER #define GRUB_MACHINE_SERIAL_HEADER 1 +#define GRUB_MACHINE_SERIAL_PORT 0xbff003f8 + #ifndef ASM_FILE -#define GRUB_MACHINE_SERIAL_PORTS { 0xbff003f8 } +#define GRUB_MACHINE_SERIAL_PORTS { GRUB_MACHINE_SERIAL_PORT } #else -#define GRUB_MACHINE_SERIAL_PORT_HI 0xbff0 -#define GRUB_MACHINE_SERIAL_PORT_LO 0x03f8 #endif #endif diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index e00da8933..838becb1b 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -47,7 +47,7 @@ __start: ori $t4, $zero, 1 lui $a0, %hi(no_cs5536) 1: - andi $t4, $t4, 0xffff + andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1) beql $t4, $zero, fatal addiu $a0, $a0, %lo(no_cs5536) sw $t4, GRUB_MACHINE_PCI_CONF_CTRL_REG_LO($t0) @@ -206,34 +206,34 @@ other_exception: we need it early. */ /* In: none. Out: none. Clobbered: $t0, $t1, $a0. */ serial_hw_init: - lui $t0, GRUB_MACHINE_SERIAL_PORT_HI + lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT) /* Turn off the interrupt. */ - sb $zero, (GRUB_MACHINE_SERIAL_PORT_LO + UART_IER)($t0) + sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_IER)($t0) /* Set DLAB. */ ori $t1, $zero, UART_DLAB - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LCR)($t0) + sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0) /* Set the baud rate 115200. */ ori $t1, $zero, 2 - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_DLL)($t0) - sb $zero, (GRUB_MACHINE_SERIAL_PORT_LO + UART_DLH)($t0) + sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLL)($t0) + sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLH)($t0) /* Set the line status. */ ori $t1, $zero, (UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT) - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LCR)($t0) + sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0) /* Enable the FIFO. */ ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1 - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_FCR)($t0) + sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_FCR)($t0) /* Turn on DTR and RTS. */ ori $t1, $zero, UART_ENABLE_DTRRTS - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_MCR)($t0) + sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_MCR)($t0) - lui $t0, 0xbff0 - addiu $t0, $t0, 0x03f8 + lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT) + addiu $t0, $t0, %lo (GRUB_MACHINE_SERIAL_PORT) /* Let message return to original caller. */ lui $a0, %hi(notification_string) @@ -242,14 +242,14 @@ serial_hw_init: /* Print message on serial console. */ /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */ message: - lui $t0, GRUB_MACHINE_SERIAL_PORT_HI + lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT) 1: - lb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LSR)($t0) + lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0) andi $t1, $t1, UART_EMPTY_TRANSMITTER beq $t1, $zero, 1b nop lb $t1, 0($a0) - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_TX)($t0) + sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0) bne $t1, $zero, 1b addiu $a0, $a0, 1 jr $ra @@ -259,10 +259,10 @@ message: In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2 */ printhex: - lui $t0, GRUB_MACHINE_SERIAL_PORT_HI + lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT) ori $t2, $zero, 8 1: - lb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_LSR)($t0) + lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0) andi $t1, $t1, UART_EMPTY_TRANSMITTER beq $t1, $zero, 1b nop @@ -272,7 +272,7 @@ printhex: sll $a0, $a0, 4 addiu $t1, $t1, 'A'-10-'0' 2: addiu $t1, $t1, '0'+10 - sb $t1, (GRUB_MACHINE_SERIAL_PORT_LO + UART_TX)($t0) + sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0) addiu $t2, $t2, -1 bne $t2, $zero, 1b nop From 144d0913f3d60c59517f0f6005ec61f816775c48 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 11 Mar 2010 15:22:04 +0100 Subject: [PATCH 12/45] Remove leftover --- kern/mips/yeeloong/fwstart.S | 3 --- 1 file changed, 3 deletions(-) diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index 838becb1b..17fe78f40 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -232,9 +232,6 @@ serial_hw_init: ori $t1, $zero, UART_ENABLE_DTRRTS sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_MCR)($t0) - lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT) - addiu $t0, $t0, %lo (GRUB_MACHINE_SERIAL_PORT) - /* Let message return to original caller. */ lui $a0, %hi(notification_string) addiu $a0, $a0, %lo(notification_string) From 8d15b3f817ab60a994df97063c96121e9c9478e7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 11 Mar 2010 20:47:22 +0100 Subject: [PATCH 13/45] Use cached address when running from ROM --- kern/mips/yeeloong/fwstart.S | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index 17fe78f40..c7ed420a4 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -618,4 +618,11 @@ continue: addiu $a0, $zero, -1 addiu $a1, $zero, -1 - addiu $a2, $zero, -1 + + /* Take advantage of cache. */ + lui $t0, %hi(cached_continue - 0x20000000) + addiu $t0, $t0, %lo(cached_continue - 0x20000000) + jr $t0 + addiu $a2, $zero, -1 + +cached_continue: \ No newline at end of file From f9ef05770a365f5ba498329eafc5bb186a64e5ca Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 12 Mar 2010 14:07:33 +0100 Subject: [PATCH 14/45] Shutdown and reboot on yeeloong --- conf/mips-yeeloong.rmk | 12 ++++++++++ include/grub/mips/loongson.h | 3 +++ include/grub/mips/yeeloong/ec.h | 41 +++++++++++++++++++++++++++++++++ include/grub/misc.h | 4 ++-- kern/mips/yeeloong/init.c | 17 +++++++++++--- 5 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 include/grub/mips/yeeloong/ec.h diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk index 91a2283e8..001bae966 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -98,6 +98,18 @@ linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_ASFLAGS = $(COMMON_ASFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For halt.mod. +pkglib_MODULES += halt.mod +halt_mod_SOURCES = commands/halt.c +halt_mod_CFLAGS = $(COMMON_CFLAGS) +halt_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For reboot.mod. +pkglib_MODULES += reboot.mod +reboot_mod_SOURCES = commands/reboot.c +reboot_mod_CFLAGS = $(COMMON_CFLAGS) +reboot_mod_LDFLAGS = $(COMMON_LDFLAGS) + sbin_SCRIPTS += grub-install grub_install_SOURCES = util/grub-install.in diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index 2c69e6c3d..c2aa276a2 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -68,4 +68,7 @@ #define GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET 2 #define GRUB_CPU_LOONGSON_ROM_DELAY_MASK 0x1f +#define GRUB_CPU_LOONGSON_GPIOCFG 0xbfe00120 +#define GRUB_CPU_LOONGSON_SHUTDOWN_GPIO 1 + #endif diff --git a/include/grub/mips/yeeloong/ec.h b/include/grub/mips/yeeloong/ec.h new file mode 100644 index 000000000..62d1d33d9 --- /dev/null +++ b/include/grub/mips/yeeloong/ec.h @@ -0,0 +1,41 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_EC_MACHINE_HEADER +#define GRUB_EC_MACHINE_HEADER 1 + +#define GRUB_MACHINE_EC_MAGIC_PORT1 0x381 +#define GRUB_MACHINE_EC_MAGIC_PORT2 0x382 +#define GRUB_MACHINE_EC_DATA_PORT 0x383 + +#define GRUB_MACHINE_EC_MAGIC_VAL1 0xf4 +#define GRUB_MACHINE_EC_MAGIC_VAL2 0xec + +#define GRUB_MACHINE_EC_COMMAND_REBOOT 1 + +static inline void +grub_write_ec (grub_uint8_t value) +{ + grub_outb (GRUB_MACHINE_EC_MAGIC_VAL1, + GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_MAGIC_PORT1); + grub_outb (GRUB_MACHINE_EC_MAGIC_VAL2, + GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_MAGIC_PORT2); + grub_outb (value, GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_DATA_PORT); +} + +#endif diff --git a/include/grub/misc.h b/include/grub/misc.h index dcbafba87..1a2105549 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -298,9 +298,9 @@ void EXPORT_FUNC (grub_reboot) (void); #ifdef GRUB_MACHINE_PCBIOS /* Halt the system, using APM if possible. If NO_APM is true, don't * use APM even if it is available. */ -void EXPORT_FUNC (grub_halt) (int no_apm); +void EXPORT_FUNC (grub_halt) (int no_apm) __attribute__ ((noreturn)); #else -void EXPORT_FUNC (grub_halt) (void); +void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); #endif #endif /* ! GRUB_MISC_HEADER */ diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index f931cdb57..8a29be8eb 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include extern void grub_video_sm712_init (void); extern void grub_video_video_init (void); @@ -165,20 +167,29 @@ grub_machine_fini (void) } void -grub_exit (void) +grub_halt (void) { + grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG) + & ~GRUB_CPU_LOONGSON_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG); + + grub_printf ("Shutdown failed\n"); + grub_refresh (); while (1); } void -grub_halt (void) +grub_exit (void) { - while (1); + grub_halt (); } void grub_reboot (void) { + grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT); + + grub_printf ("Reboot failed\n"); + grub_refresh (); while (1); } From 5dbb0fc055bddb0083ad9b5ede4265a4c4d1629f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 12 Mar 2010 14:08:26 +0100 Subject: [PATCH 15/45] Another round of macrofication --- include/grub/cs5536.h | 11 +++++++++-- include/grub/mips/yeeloong/boot.h | 2 ++ include/grub/mips/yeeloong/pci.h | 8 ++++---- kern/mips/yeeloong/fwstart.S | 22 ++++++++++++---------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index 3f06bdb68..ec554f002 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -46,8 +46,15 @@ #define GRUB_CS5536_SMB_REG_CTRL2_ENABLE 0x1 #define GRUB_CS5536_SMB_REG_CTRL3 0x6 -#define GRUB_CS5536_LBAR_ADDR_MASK 0x000000000000fff8ULL -#define GRUB_CS5536_LBAR_ENABLE 0x0000000100000000ULL +#ifdef ASM_FILE +#define GRUB_ULL(x) x +#else +#define GRUB_ULL(x) x ## ULL +#endif + +#define GRUB_CS5536_LBAR_ADDR_MASK GRUB_ULL (0x000000000000fff8) +#define GRUB_CS5536_LBAR_ENABLE GRUB_ULL (0x0000000100000000) +#define GRUB_CS5536_LBAR_MASK_MASK GRUB_ULL (0x0000f00000000000) /* PMON-compatible LBARs. */ #define GRUB_CS5536_LBAR_GPIO 0x0b000 diff --git a/include/grub/mips/yeeloong/boot.h b/include/grub/mips/yeeloong/boot.h index 6a4189ede..eda9c6ad5 100644 --- a/include/grub/mips/yeeloong/boot.h +++ b/include/grub/mips/yeeloong/boot.h @@ -26,5 +26,7 @@ #define GRUB_MACHINE_DDR2_BASE 0xaffffe00 #define GRUB_MACHINE_DDR2_REG1_HI_8BANKS 0x00000001 +#define GRUB_MACHINE_DDR2_REG_SIZE 0x8 +#define GRUB_MACHINE_DDR2_REG_STEP 0x10 #endif diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h index f50cdcb35..aa5e0bbea 100644 --- a/include/grub/mips/yeeloong/pci.h +++ b/include/grub/mips/yeeloong/pci.h @@ -30,12 +30,12 @@ #define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000 #define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000 +#define GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR 0xbfe00118 + #ifndef ASM_FILE -#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00118) +#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) \ + GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) #define GRUB_MACHINE_PCI_IO_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110) -#else -#define GRUB_MACHINE_PCI_CONF_CTRL_REG_HI 0xbfe0 -#define GRUB_MACHINE_PCI_CONF_CTRL_REG_LO 0x0118 #endif #define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6 #define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1) diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index c7ed420a4..4a9a749f7 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -40,7 +40,7 @@ __start: /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG. This way we don't need to sacrifice a register for it. */ /* We have only one bus (0). Function is 0. */ - lui $t0, GRUB_MACHINE_PCI_CONF_CTRL_REG_HI + lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) lui $t3, %hi(GRUB_CS5536_PCIID) addiu $t3, $t3, %lo(GRUB_CS5536_PCIID) @@ -50,7 +50,7 @@ __start: andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1) beql $t4, $zero, fatal addiu $a0, $a0, %lo(no_cs5536) - sw $t4, GRUB_MACHINE_PCI_CONF_CTRL_REG_LO($t0) + sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1) bnel $t2, $t3, 1b sll $t4, $t4, 1 @@ -67,7 +67,8 @@ __start: ori $a1, $zero, GRUB_CS5536_LBAR_GPIO /* Set mask to 0xf and enabled bit to 1. */ bal wrmsr - ori $a2, $zero, 0xf001 + ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \ + | GRUB_CS5536_LBAR_ENABLE) >> 32) /* Set SMBUS LBAR. */ lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR) @@ -75,7 +76,8 @@ __start: ori $a1, $zero, GRUB_CS5536_LBAR_SMBUS /* Set mask to 0xf and enabled bit to 1. */ bal wrmsr - ori $a2, $zero, 0xf001 + ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \ + | GRUB_CS5536_LBAR_ENABLE) >> 32) lui $a0, %hi(smbus_enabled) bal message @@ -430,7 +432,7 @@ write_dumpreg: sd $t2, 0($t4) addiu $t4, $t4, 0x10 jr $ra - addiu $t6, $t6, 0x8 + addiu $t6, $t6, GRUB_MACHINE_DDR2_REG_SIZE continue: lui $t4, %hi(GRUB_MACHINE_DDR2_BASE) @@ -442,7 +444,7 @@ continue: addiu $t6, $t6, %lo(regdump) /* 1 */ - ori $a1, $a1, 0x50 + ori $a1, $a1, GRUB_SMB_RAM_START_ADDR move $t8, $zero lui $t5, 0x0001 bal read_spd @@ -455,7 +457,7 @@ continue: dsll $t8, $t8, 32 or $t5, $t5, $t8 sd $t5, 0 ($t4) - addiu $t4, $t4, 0x10 + addiu $t4, $t4, GRUB_MACHINE_DDR2_REG_STEP /* 2 */ bal write_dumpreg @@ -509,17 +511,17 @@ continue: or $t5, $t5, $v0 sd $t5, 0 ($t4) - addiu $t4, $t4, 0x10 + addiu $t4, $t4, GRUB_MACHINE_DDR2_REG_STEP ori $t7, $zero, 0x16 1: ld $t2, 0($t6) sd $t2, 0($t4) - addiu $t4, $t4, 0x10 + addiu $t4, $t4, GRUB_MACHINE_DDR2_REG_STEP addiu $t7, $t7, -1 bne $t7, $zero, 1b - addiu $t6, $t6, 0x8 + addiu $t6, $t6, GRUB_MACHINE_DDR2_REG_SIZE lui $t4, %hi(GRUB_MACHINE_DDR2_BASE) ld $t5, (%lo(GRUB_MACHINE_DDR2_BASE) + 0x30) ($t4) From 9b6e10bbbfc52a2a5f121e3b999e836114fa5417 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 14 Mar 2010 23:18:13 +0100 Subject: [PATCH 16/45] Handle defered device registration --- disk/ata.c | 92 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/disk/ata.c b/disk/ata.c index 662fe71a7..b2291cd53 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -332,11 +332,38 @@ grub_ata_identify (struct grub_ata_device *dev) return 0; } +static grub_err_t +check_device (struct grub_ata_device *dev) +{ + grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); + grub_ata_wait (); + + /* Try to detect if the port is in use by writing to it, + waiting for a while and reading it again. If the value + was preserved, there is a device connected. */ + grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A); + grub_ata_wait (); + grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS); + grub_dprintf ("ata", "sectors=0x%x\n", sec); + if (sec != 0x5A) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected"); + + /* The above test may detect a second (slave) device + connected to a SATA controller which supports only one + (master) device. It is not safe to use the status register + READY bit to check for controller channel existence. Some + ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */ + + /* Use the IDENTIFY DEVICE command to query the device. */ + return grub_ata_identify (dev); +} + static grub_err_t grub_ata_device_initialize (int port, int device, int addr, int addr2) { struct grub_ata_device *dev; struct grub_ata_device **devp; + grub_err_t err; grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n", port, device, addr, addr2); @@ -352,39 +379,14 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2) dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; dev->next = NULL; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); - grub_ata_wait (); - - /* Try to detect if the port is in use by writing to it, - waiting for a while and reading it again. If the value - was preserved, there is a device connected. */ - grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A); - grub_ata_wait (); - grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS); - grub_dprintf ("ata", "sectors=0x%x\n", sec); - if (sec != 0x5A) - { - grub_free(dev); - return 0; - } - - /* The above test may detect a second (slave) device - connected to a SATA controller which supports only one - (master) device. It is not safe to use the status register - READY bit to check for controller channel existence. Some - ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */ - - /* Use the IDENTIFY DEVICE command to query the device. */ - if (grub_ata_identify (dev)) - { - grub_free (dev); - return 0; - } - /* Register the device. */ for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next); *devp = dev; + err = check_device (dev); + if (err) + grub_print_error (); + return 0; } @@ -667,6 +669,14 @@ grub_ata_iterate (int (*hook) (const char *name)) for (dev = grub_ata_devices; dev; dev = dev->next) { char devname[10]; + grub_err_t err; + + err = check_device (dev); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } if (dev->atapi) continue; @@ -685,6 +695,7 @@ static grub_err_t grub_ata_open (const char *name, grub_disk_t disk) { struct grub_ata_device *dev; + grub_err_t err; for (dev = grub_ata_devices; dev; dev = dev->next) { @@ -701,6 +712,11 @@ grub_ata_open (const char *name, grub_disk_t disk) if (dev->atapi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); + err = check_device (dev); + + if (err) + return err; + disk->total_sectors = dev->size; disk->id = (unsigned long) dev; @@ -757,6 +773,16 @@ grub_atapi_iterate (int (*hook) (const char *name, int luns)) for (dev = grub_ata_devices; dev; dev = dev->next) { char devname[10]; + + grub_err_t err; + + err = check_device (dev); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + grub_snprintf (devname, sizeof (devname), "ata%d", dev->port * 2 + dev->device); @@ -827,6 +853,7 @@ grub_atapi_open (const char *name, struct grub_scsi *scsi) { struct grub_ata_device *dev; struct grub_ata_device *devfnd = 0; + grub_err_t err; for (dev = grub_ata_devices; dev; dev = dev->next) { @@ -846,6 +873,13 @@ grub_atapi_open (const char *name, struct grub_scsi *scsi) if (! devfnd) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); + err = check_device (devfnd); + if (err) + return err; + + if (! devfnd->atapi) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); + scsi->data = devfnd; return GRUB_ERR_NONE; From 04a3792f87113f34b7fe3bfce3bdf347cb19ff84 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 5 Apr 2010 22:39:58 +0200 Subject: [PATCH 17/45] Macroify fwstart.S more --- include/grub/mips/loongson.h | 3 +++ include/grub/mips/yeeloong/serial.h | 1 + kern/mips/yeeloong/fwstart.S | 24 +++++++++++++----------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index c2aa276a2..7dcc15cd4 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -67,6 +67,9 @@ #define GRUB_CPU_LOONGSON_LIOCFG 0xbfe00108 #define GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET 2 #define GRUB_CPU_LOONGSON_ROM_DELAY_MASK 0x1f +#define GRUB_CPU_LOONGSON_CORECFG 0xbfe00180 +#define GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE 0x100 +#define GRUB_CPU_LOONGSON_CORECFG_BUFFER_CPU 0x200 #define GRUB_CPU_LOONGSON_GPIOCFG 0xbfe00120 #define GRUB_CPU_LOONGSON_SHUTDOWN_GPIO 1 diff --git a/include/grub/mips/yeeloong/serial.h b/include/grub/mips/yeeloong/serial.h index b22352f5a..ebe3638a1 100644 --- a/include/grub/mips/yeeloong/serial.h +++ b/include/grub/mips/yeeloong/serial.h @@ -19,6 +19,7 @@ #ifndef GRUB_MACHINE_SERIAL_HEADER #define GRUB_MACHINE_SERIAL_HEADER 1 +#define GRUB_MACHINE_SERIAL_DIVISOR_115200 2 #define GRUB_MACHINE_SERIAL_PORT 0xbff003f8 #ifndef ASM_FILE diff --git a/kern/mips/yeeloong/fwstart.S b/kern/mips/yeeloong/fwstart.S index 4a9a749f7..f541a535f 100644 --- a/kern/mips/yeeloong/fwstart.S +++ b/kern/mips/yeeloong/fwstart.S @@ -116,17 +116,19 @@ __start: move $a0, $v0 bal read_spd - ori $a0, $zero, 2 + ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 lui $a0, %hi(unimplemented_memory_type) bne $t0, $v0, fatal addiu $a0, $a0, %hi(unimplemented_memory_type) /* And here is our goal: DDR2 controller initialisation. */ - lui $t0, 0xbfe0 - ld $t1, 0x0180($t0) - andi $t1, $t1, 0x4ff - sd $t1, 0x0180($t0) + lui $t0, %hi(GRUB_CPU_LOONGSON_CORECFG) + ld $t1, %lo(GRUB_CPU_LOONGSON_CORECFG) ($t0) + /* Use addiu for sign-extension. */ + addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE|GRUB_CPU_LOONGSON_CORECFG_BUFFER_CPU) + and $t1, $t1, $t2 + sd $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0) b continue @@ -218,7 +220,7 @@ serial_hw_init: sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0) /* Set the baud rate 115200. */ - ori $t1, $zero, 2 + ori $t1, $zero, GRUB_MACHINE_SERIAL_DIVISOR_115200 sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLL)($t0) sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLH)($t0) @@ -430,7 +432,7 @@ regdump: write_dumpreg: ld $t2, 0($t6) sd $t2, 0($t4) - addiu $t4, $t4, 0x10 + addiu $t4, $t4, GRUB_MACHINE_DDR2_REG_STEP jr $ra addiu $t6, $t6, GRUB_MACHINE_DDR2_REG_SIZE @@ -531,10 +533,10 @@ continue: sd $t5, (%lo(GRUB_MACHINE_DDR2_BASE) + 0x30) ($t4) /* Desactivate DDR2 registers. */ - lui $t0, 0xbfe0 - ld $t1, 0x0180($t0) - ori $t1, $t1, 0x100 - sd $t1, 0x0180($t0) + lui $t0, %hi (GRUB_CPU_LOONGSON_CORECFG) + ld $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0) + ori $t1, $t1, GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE + sd $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0) /* Enable cache. */ mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG From f9e7780cfff7fad076c23c73a930f3bb5b33fcee Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 6 Apr 2010 02:40:44 +0200 Subject: [PATCH 18/45] Fix an early timer-related hang --- include/grub/cs5536.h | 9 +++++++++ kern/mips/yeeloong/init.c | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index ec554f002..21d6d55fc 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -29,8 +29,12 @@ #define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4 #define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8 #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_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_SMB_REG_DATA 0x0 #define GRUB_CS5536_SMB_REG_STATUS 0x1 #define GRUB_CS5536_SMB_REG_STATUS_SDAST (1 << 6) @@ -55,10 +59,15 @@ #define GRUB_CS5536_LBAR_ADDR_MASK GRUB_ULL (0x000000000000fff8) #define GRUB_CS5536_LBAR_ENABLE GRUB_ULL (0x0000000100000000) #define GRUB_CS5536_LBAR_MASK_MASK GRUB_ULL (0x0000f00000000000) +#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_GPIO_SMBUS_PINS ((1 << 14) | (1 << 15)) #define GRUB_GPIO_REG_OUT_EN 0x4 diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 127cf870e..9cadd64b2 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -67,6 +67,26 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, return GRUB_ERR_NONE; } +/* Dump of GPIO connections. FIXME: Remove useless and macroify. */ +static grub_uint32_t gpiodump[] = { + 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000, + 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000, + 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000, + 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000, + 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, + 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000, + 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000, + 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000, + 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x50000000, 0x00000000, 0x00000000, +}; + void grub_machine_init (void) { @@ -121,6 +141,27 @@ grub_machine_init (void) grub_arch_memsize = (totalmem >> 20); grub_arch_highmemsize = 0; } + + /* Make sure GPIO is where we expect it to be. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GPIO_BAR, + GRUB_CS5536_LBAR_TURN_ON + | GRUB_CS5536_LBAR_GPIO); + + for (i = 0; i < (int) ARRAY_SIZE (gpiodump); i++) + ((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_IO_BASE + + GRUB_CS5536_LBAR_GPIO)) [i] + = gpiodump[i]; + + /* Enable more BARs. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IRQ_MAP_BAR, + GRUB_CS5536_LBAR_TURN_ON + | GRUB_CS5536_LBAR_IRQ_MAP); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_MFGPT_BAR, + GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_MFGPT); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_ACPI_BAR, + 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); } modend = grub_modules_get_end (); From 781d7798bb2fa0f04c455fe5df1f72b4255b589b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 6 Apr 2010 22:12:04 +0200 Subject: [PATCH 19/45] 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 (); From 3bf09c9ea83350ee0be9c970ddbb8a57606f3eb5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 6 Apr 2010 22:23:02 +0200 Subject: [PATCH 20/45] rename format from raw to yeeloong_flash --- include/grub/mips/kernel.h | 13 ------------- include/grub/mips/qemu-mips/kernel.h | 15 +++++++++++++++ include/grub/mips/yeeloong/kernel.h | 13 +++++++++++++ util/grub-mkrawimage.c | 5 +++++ 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h index 8b68f7b6b..ee759f10b 100644 --- a/include/grub/mips/kernel.h +++ b/include/grub/mips/kernel.h @@ -41,21 +41,8 @@ #define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_KERNEL_CPU_TOTAL_MODULE_SIZE #define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_KERNEL_CPU_COMPRESSED_SIZE -#define GRUB_PLATFORM_IMAGE_FORMATS "raw, elf" -#define GRUB_PLATFORM_IMAGE_DEFAULT_FORMAT "raw" - -#define GRUB_PLATFORM_IMAGE_DEFAULT GRUB_PLATFORM_IMAGE_RAW - #ifndef ASM_FILE -typedef enum { - GRUB_PLATFORM_IMAGE_RAW, - GRUB_PLATFORM_IMAGE_ELF -} - grub_platform_image_format_t; -#define GRUB_PLATFORM_IMAGE_RAW GRUB_PLATFORM_IMAGE_RAW -#define GRUB_PLATFORM_IMAGE_ELF GRUB_PLATFORM_IMAGE_ELF - /* The prefix which points to the directory where GRUB modules and its configuration file are located. */ extern char grub_prefix[]; diff --git a/include/grub/mips/qemu-mips/kernel.h b/include/grub/mips/qemu-mips/kernel.h index dbf74c1b2..cc6169d5f 100644 --- a/include/grub/mips/qemu-mips/kernel.h +++ b/include/grub/mips/qemu-mips/kernel.h @@ -31,6 +31,21 @@ void EXPORT_FUNC (grub_halt) (void); configuration file are located. */ extern char grub_prefix[]; +#define GRUB_PLATFORM_IMAGE_FORMATS "raw, elf" +#define GRUB_PLATFORM_IMAGE_DEFAULT_FORMAT "raw" + +#define GRUB_PLATFORM_IMAGE_DEFAULT GRUB_PLATFORM_IMAGE_RAW + +#ifndef ASM_FILE + +typedef enum { + GRUB_PLATFORM_IMAGE_RAW, + GRUB_PLATFORM_IMAGE_ELF +} + grub_platform_image_format_t; +#define GRUB_PLATFORM_IMAGE_RAW GRUB_PLATFORM_IMAGE_RAW +#define GRUB_PLATFORM_IMAGE_ELF GRUB_PLATFORM_IMAGE_ELF + #endif #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/mips/yeeloong/kernel.h b/include/grub/mips/yeeloong/kernel.h index 230455dbf..05fe0eb55 100644 --- a/include/grub/mips/yeeloong/kernel.h +++ b/include/grub/mips/yeeloong/kernel.h @@ -27,6 +27,19 @@ void EXPORT_FUNC (grub_reboot) (void); void EXPORT_FUNC (grub_halt) (void); +#define GRUB_PLATFORM_IMAGE_FORMATS "yeeloong_flash, elf" +#define GRUB_PLATFORM_IMAGE_DEFAULT_FORMAT "yeeloong_flash" + +#define GRUB_PLATFORM_IMAGE_DEFAULT GRUB_PLATFORM_IMAGE_YEELOONG_FLASH + +typedef enum { + GRUB_PLATFORM_IMAGE_YEELOONG_FLASH, + GRUB_PLATFORM_IMAGE_ELF +} + grub_platform_image_format_t; +#define GRUB_PLATFORM_IMAGE_YEELOONG_FLASH GRUB_PLATFORM_IMAGE_YEELOONG_FLASH +#define GRUB_PLATFORM_IMAGE_ELF GRUB_PLATFORM_IMAGE_ELF + #endif #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/util/grub-mkrawimage.c b/util/grub-mkrawimage.c index 7babbef6a..67bd64a1b 100644 --- a/util/grub-mkrawimage.c +++ b/util/grub-mkrawimage.c @@ -569,6 +569,11 @@ main (int argc, char *argv[]) #ifdef GRUB_PLATFORM_IMAGE_DEFAULT case 'O': +#ifdef GRUB_PLATFORM_IMAGE_YEELOONG_FLASH + if (strcmp (optarg, "yeeloong_flash") == 0) + format = GRUB_PLATFORM_IMAGE_YEELOONG_FLASH; + else +#endif #ifdef GRUB_PLATFORM_IMAGE_RAW if (strcmp (optarg, "raw") == 0) format = GRUB_PLATFORM_IMAGE_RAW; From 1c9d6bb81b49ef776dde560ac13cb3222f14c25e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Apr 2010 19:43:52 +0200 Subject: [PATCH 21/45] Initialise USB option controller --- include/grub/cs5536.h | 13 ++++++++++--- kern/mips/yeeloong/init.c | 13 +++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index c2323fe9b..218e17d1a 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -39,6 +39,11 @@ #define GRUB_CS5536_PM_REGS_SIZE 128 #define GRUB_CS5536_ACPI_REGS_SIZE 32 +#define GRUB_CS5536_USB_OPTION_REGS_SIZE 0x1c +#define GRUB_CS5536_USB_OPTION_REG_UOCMUX 1 +#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK 0x03 +#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC 0x02 + #define GRUB_CS5536_DESTINATION_GLIU 0 #define GRUB_CS5536_DESTINATION_GLPCI_SB 1 #define GRUB_CS5536_DESTINATION_USB 2 @@ -78,9 +83,11 @@ #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_BASE_ADDR_MASK 0x00ffffff00ULL +#define GRUB_CS5536_MSR_USB_BASE_BUS_MASTER 0x0400000000ULL +#define GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE 0x0200000000ULL +#define GRUB_CS5536_MSR_USB_BASE_PME_ENABLED 0x0800000000ULL +#define GRUB_CS5536_MSR_USB_BASE_PME_STATUS 0x1000000000ULL #define GRUB_CS5536_MSR_USB_EHCI_BASE_FLDJ_SHIFT 40 #define GRUB_CS5536_MSR_IDE_IO_BAR 0x60000008 diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index cf241ea96..5c3340f39 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -239,6 +239,19 @@ grub_machine_init (void) set_p2d (dev, 5, GRUB_CS5536_DESTINATION_USB, 0x05024000); set_p2d (dev, 6, GRUB_CS5536_DESTINATION_USB, 0x05023000); + { + volatile grub_uint32_t *oc; + oc = grub_pci_device_map_range (dev, 0x05022000, + GRUB_CS5536_USB_OPTION_REGS_SIZE); + + oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] = + (oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] + & ~GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK) + | GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC; + grub_pci_device_unmap_range (dev, oc, GRUB_CS5536_USB_OPTION_REGS_SIZE); + } + + /* Setup IDE controller. */ grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IDE_IO_BAR, GRUB_CS5536_LBAR_IDE From 913043335344de534fa70205f6c823090b707a0a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Apr 2010 19:46:22 +0200 Subject: [PATCH 22/45] Enable USB compilation on Yeeloong --- conf/mips-yeeloong.rmk | 34 ++++++++++++++++++++++++++++++-- include/grub/cs5536.h | 8 +++++--- include/grub/mips/yeeloong/pci.h | 10 +++++----- term/usb_keyboard.c | 1 - 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk index 288b36ea5..233d8dae6 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -5,7 +5,7 @@ COMMON_CFLAGS += -march=mips3 COMMON_ASFLAGS += -march=mips3 kernel_img_HEADERS += pci.h bitmap.h video.h gfxterm.h font.h \ - bitmap_scale.h bufio.h cs5536.h + bitmap_scale.h bufio.h cs5536.h machine/pci.h include $(srcdir)/conf/mips.mk @@ -27,7 +27,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ video/fb/fbfill.c video/fb/fbutil.c video/bitmap.c \ video/bitmap_scale.c video/sm712.c bus/pci.c bus/bonito.c \ term/gfxterm.c commands/extcmd.c lib/arg.c \ - bus/cs5536.c \ + bus/cs5536.c term/serial.c term/terminfo.c term/tparm.c \ symlist.c kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK kernel_img_ASFLAGS = $(COMMON_ASFLAGS) @@ -92,5 +92,35 @@ halt_mod_SOURCES = commands/halt.c halt_mod_CFLAGS = $(COMMON_CFLAGS) halt_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For usb.mod +pkglib_MODULES += usb.mod +usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c +usb_mod_CFLAGS = $(COMMON_CFLAGS) +usb_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For usbtest.mod +pkglib_MODULES += usbtest.mod +usbtest_mod_SOURCES = commands/usbtest.c +usbtest_mod_CFLAGS = $(COMMON_CFLAGS) +usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For ohci.mod +pkglib_MODULES += ohci.mod +ohci_mod_SOURCES = bus/usb/ohci.c +ohci_mod_CFLAGS = $(COMMON_CFLAGS) +ohci_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For usbms.mod +pkglib_MODULES += usbms.mod +usbms_mod_SOURCES = disk/usbms.c +usbms_mod_CFLAGS = $(COMMON_CFLAGS) +usbms_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For usb_keyboard.mod +pkglib_MODULES += usb_keyboard.mod +usb_keyboard_mod_SOURCES = term/usb_keyboard.c +usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS) +usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS) + sbin_SCRIPTS += grub-install grub_install_SOURCES = util/grub-install.in diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index 218e17d1a..a16fb7a09 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -169,9 +169,11 @@ #ifndef ASM_FILE int EXPORT_FUNC (grub_cs5536_find) (grub_pci_device_t *devp); -grub_uint64_t grub_cs5536_read_msr (grub_pci_device_t dev, grub_uint32_t addr); -void grub_cs5536_write_msr (grub_pci_device_t dev, grub_uint32_t addr, - grub_uint64_t val); +grub_uint64_t EXPORT_FUNC (grub_cs5536_read_msr) (grub_pci_device_t dev, + grub_uint32_t addr); +void EXPORT_FUNC (grub_cs5536_write_msr) (grub_pci_device_t dev, + grub_uint32_t addr, + grub_uint64_t val); grub_err_t grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, grub_uint8_t addr, grub_uint8_t *res); grub_err_t EXPORT_FUNC (grub_cs5536_read_spd) (grub_port_t smbbase, diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h index 8f3a29d5c..7c816ac8e 100644 --- a/include/grub/mips/yeeloong/pci.h +++ b/include/grub/mips/yeeloong/pci.h @@ -105,12 +105,12 @@ grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data) } volatile void * -grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), - grub_addr_t base, grub_size_t size); +EXPORT_FUNC (grub_pci_device_map_range) (grub_pci_device_t dev, + grub_addr_t base, grub_size_t size); void -grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), - volatile void *mem, - grub_size_t size __attribute__ ((unused))); +EXPORT_FUNC (grub_pci_device_unmap_range) (grub_pci_device_t dev, + volatile void *mem, + grub_size_t size); #endif #endif /* GRUB_MACHINE_PCI_H */ diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 5d76c5e02..69d5709b6 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include From f78e34d87c779d71e957cc8a0d3ed0505f44b0f7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Apr 2010 19:59:51 +0200 Subject: [PATCH 23/45] Initialize power and timing of OHCI. --- bus/usb/ohci.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 6d185bc7f..b385a699a 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include struct grub_ohci_hcca @@ -91,10 +91,18 @@ typedef enum GRUB_OHCI_REG_BULKCURR, GRUB_OHCI_REG_DONEHEAD, GRUB_OHCI_REG_FRAME_INTERVAL, + GRUB_OHCI_REG_PERIODIC_START = 16, GRUB_OHCI_REG_RHUBA = 18, GRUB_OHCI_REG_RHUBPORT = 21 } grub_ohci_reg_t; +#define GRUB_OHCI_RHUB_PORT_POWER_MASK 0x300 +#define GRUB_OHCI_RHUB_PORT_ALL_POWERED 0x200 + +/* XXX: Is this choice of timings sane? */ +#define GRUB_OHCI_FSMPS 0x2778 +#define GRUB_OHCI_PERIODIC_START 0x257f + static grub_uint32_t grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg) { @@ -166,6 +174,11 @@ grub_ohci_pci_iter (grub_pci_device_t dev, if ((revision & 0xFF) != 0x10) goto fail; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBA, + (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) + & ~GRUB_OHCI_RHUB_PORT_POWER_MASK) + | GRUB_OHCI_RHUB_PORT_ALL_POWERED); + /* Backup the frame interval register. */ frame_interval = grub_ohci_readreg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL); @@ -175,8 +188,17 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_dprintf ("ohci", "OHCI reset\n"); /* Restore the frame interval register. */ +#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK 0x8fff0000 +#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT 16 + + frame_interval = (frame_interval & ~GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK) + | (GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT + << GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT); grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, frame_interval); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_PERIODIC_START, + GRUB_OHCI_PERIODIC_START); + /* Setup the HCCA. */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, (grub_uint32_t) o->hcca); grub_dprintf ("ohci", "OHCI HCCA\n"); From 481695bce082577ca2d56f476be6727b3d543394 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Apr 2010 20:04:44 +0200 Subject: [PATCH 24/45] Adjust OHCI init routines for MIPS and CS5535 --- bus/usb/ohci.c | 90 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index b385a699a..efa2b74e9 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -26,6 +26,7 @@ #include #include #include +#include struct grub_ohci_hcca { @@ -70,6 +71,7 @@ struct grub_ohci { volatile grub_uint32_t *iobase; volatile struct grub_ohci_hcca *hcca; + grub_uint32_t hcca_addr; struct grub_ohci *next; }; @@ -122,51 +124,85 @@ grub_ohci_writereg32 (struct grub_ohci *o, controller. If this is the case, initialize it. */ static int NESTED_FUNC_ATTR grub_ohci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__((unused))) + grub_pci_id_t pciid) { - grub_uint32_t class_code; - grub_uint32_t class; - grub_uint32_t subclass; grub_uint32_t interf; grub_uint32_t base; grub_pci_address_t addr; struct grub_ohci *o; grub_uint32_t revision; grub_uint32_t frame_interval; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class_code = grub_pci_read (addr) >> 8; - - interf = class_code & 0xFF; - subclass = (class_code >> 8) & 0xFF; - class = class_code >> 16; - - /* If this is not an OHCI controller, just return. */ - if (class != 0x0c || subclass != 0x03 || interf != 0x10) - return 0; + int cs5536; + grub_uint32_t hcca_addr; /* Determine IO base address. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - base = grub_pci_read (addr); + grub_dprintf ("ohci", "pciid = %x\n", pciid); + if (pciid == GRUB_CS5536_PCIID) + { + grub_uint64_t basereg; + + cs5536 = 1; + basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE); + if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE)) + { + /* Shouldn't happen. */ + grub_dprintf ("ohci", "No OHCI address is assigned\n"); + return 0; + } + base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK); + basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS; + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, basereg); + + } + else + { + grub_uint32_t class_code; + grub_uint32_t class; + grub_uint32_t subclass; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class_code = grub_pci_read (addr) >> 8; + + interf = class_code & 0xFF; + subclass = (class_code >> 8) & 0xFF; + class = class_code >> 16; + + /* If this is not an OHCI controller, just return. */ + if (class != 0x0c || subclass != 0x03 || interf != 0x10) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + base = grub_pci_read (addr); #if 0 - /* Stop if there is no IO space base address defined. */ - if (! (base & 1)) - return 0; + /* Stop if there is no IO space base address defined. */ + if (! (base & 1)) + return 0; #endif + grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x\n", + class, subclass, interf); + } + /* Allocate memory for the controller and register it. */ o = grub_malloc (sizeof (*o)); if (! o) return 1; - o->iobase = (grub_uint32_t *) base; + o->iobase = grub_pci_device_map_range (dev, base, 0x100); + grub_dprintf ("ohci", "base=%p\n", o->iobase); + + /* FIXME: create proper abstraction for this. */ +#ifdef GRUB_MACHINE_MIPS_YEELOONG + hcca_addr = 0x05000100; +#else /* Reserve memory for the HCCA. */ - o->hcca = (struct grub_ohci_hcca *) grub_memalign (256, 256); - - grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x base=%p\n", - class, subclass, interf, o->iobase); + hcca_addr = (grub_uint32_t) grub_memalign (256, 256); +#endif + o->hcca = grub_pci_device_map_range (dev, hcca_addr, 256); /* Check if the OHCI revision is actually 1.0 as supported. */ revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION); @@ -200,7 +236,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, GRUB_OHCI_PERIODIC_START); /* Setup the HCCA. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, (grub_uint32_t) o->hcca); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, hcca_addr); grub_dprintf ("ohci", "OHCI HCCA\n"); /* Enable the OHCI. */ @@ -216,8 +252,10 @@ grub_ohci_pci_iter (grub_pci_device_t dev, return 0; fail: +#ifndef GRUB_MACHINE_MIPS_YEELOONG if (o) grub_free ((void *) o->hcca); +#endif grub_free (o); return 1; From 7e3a6f3b23ab021e66752c278d49dad863bae4b4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Apr 2010 20:05:35 +0200 Subject: [PATCH 25/45] Move few defines to appropriate place --- bus/usb/ohci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index efa2b74e9..69efda435 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -101,6 +101,9 @@ typedef enum #define GRUB_OHCI_RHUB_PORT_POWER_MASK 0x300 #define GRUB_OHCI_RHUB_PORT_ALL_POWERED 0x200 +#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK 0x8fff0000 +#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT 16 + /* XXX: Is this choice of timings sane? */ #define GRUB_OHCI_FSMPS 0x2778 #define GRUB_OHCI_PERIODIC_START 0x257f @@ -224,9 +227,6 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_dprintf ("ohci", "OHCI reset\n"); /* Restore the frame interval register. */ -#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK 0x8fff0000 -#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT 16 - frame_interval = (frame_interval & ~GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK) | (GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT << GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT); From fa2bef48160d1d397e48ed5552ddcd215675865f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Apr 2010 20:41:54 +0200 Subject: [PATCH 26/45] Skip unfunctional controllers --- bus/usb/ohci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 69efda435..de20a1491 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -258,7 +258,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, #endif grub_free (o); - return 1; + return 0; } From 04d050152fc2069b1a57208e6510af555c7fe732 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 4 May 2010 00:05:23 +0200 Subject: [PATCH 27/45] Move geode init to bus/cs5536.c --- bus/cs5536.c | 167 ++++++++++++++++++++++++++++++++++++ include/grub/cs5536.h | 2 + kern/mips/yeeloong/init.c | 174 +------------------------------------- 3 files changed, 170 insertions(+), 173 deletions(-) diff --git a/bus/cs5536.c b/bus/cs5536.c index f481397b7..088f4dfc1 100644 --- a/bus/cs5536.c +++ b/bus/cs5536.c @@ -20,6 +20,7 @@ #include #include #include +#include int grub_cs5536_find (grub_pci_device_t *devp) @@ -211,3 +212,169 @@ grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev, } return GRUB_ERR_NONE; } + +/* Dump of GPIO connections. FIXME: Remove useless and macroify. */ +static grub_uint32_t gpiodump[] = { + 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000, + 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000, + 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000, + 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000, + 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, + 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000, + 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000, + 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000, + 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 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_cs5536_init_geode (grub_pci_device_t dev) +{ + int i; + + /* Make sure GPIO is where we expect it to be. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GPIO_BAR, + 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] = gpiodump[i]; + + /* Enable more BARs. */ + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IRQ_MAP_BAR, + GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_IRQ_MAP); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_MFGPT_BAR, + GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_MFGPT); + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_ACPI_BAR, + 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); + + { + volatile grub_uint32_t *oc; + oc = grub_pci_device_map_range (dev, 0x05022000, + GRUB_CS5536_USB_OPTION_REGS_SIZE); + + oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] = + (oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] + & ~GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK) + | GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC; + grub_pci_device_unmap_range (dev, oc, GRUB_CS5536_USB_OPTION_REGS_SIZE); + } + + /* 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); +} diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index a16fb7a09..cd17e11fc 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -183,6 +183,8 @@ grub_err_t grub_cs5536_smbus_wait (grub_port_t smbbase); grub_err_t EXPORT_FUNC (grub_cs5536_init_smbus) (grub_pci_device_t dev, grub_uint16_t divisor, grub_port_t *smbbase); + +void grub_cs5536_init_geode (grub_pci_device_t dev); #endif #endif diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 5c3340f39..fa02df601 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -31,7 +31,6 @@ #include #include #include -#include extern void grub_video_sm712_init (void); extern void grub_video_init (void); @@ -68,63 +67,6 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, return GRUB_ERR_NONE; } -/* Dump of GPIO connections. FIXME: Remove useless and macroify. */ -static grub_uint32_t gpiodump[] = { - 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000, - 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000, - 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000, - 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000, - 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, - 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000, - 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000, - 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000, - 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 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) { @@ -180,121 +122,7 @@ grub_machine_init (void) grub_arch_highmemsize = 0; } - /* Make sure GPIO is where we expect it to be. */ - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GPIO_BAR, - 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] - = gpiodump[i]; - - /* Enable more BARs. */ - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IRQ_MAP_BAR, - GRUB_CS5536_LBAR_TURN_ON - | GRUB_CS5536_LBAR_IRQ_MAP); - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_MFGPT_BAR, - GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_MFGPT); - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_ACPI_BAR, - 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); - - { - volatile grub_uint32_t *oc; - oc = grub_pci_device_map_range (dev, 0x05022000, - GRUB_CS5536_USB_OPTION_REGS_SIZE); - - oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] = - (oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] - & ~GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK) - | GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC; - grub_pci_device_unmap_range (dev, oc, GRUB_CS5536_USB_OPTION_REGS_SIZE); - } - - - /* 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); + grub_cs5536_init_geode (dev); /* Setup PCI controller. */ *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER From 0a58eb2e3ac748bf613cb0270b22fe36f6c75bb6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 4 May 2010 10:56:52 +0200 Subject: [PATCH 28/45] move fwstart.S to boot/ --- {kern => boot}/mips/yeeloong/fwstart.S | 0 conf/mips-yeeloong.rmk | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {kern => boot}/mips/yeeloong/fwstart.S (100%) diff --git a/kern/mips/yeeloong/fwstart.S b/boot/mips/yeeloong/fwstart.S similarity index 100% rename from kern/mips/yeeloong/fwstart.S rename to boot/mips/yeeloong/fwstart.S diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk index 233d8dae6..fbc23db7b 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -36,7 +36,7 @@ kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \ kernel_img_FORMAT = binary pkglib_IMAGES += fwstart.img -fwstart_img_SOURCES = kern/$(target_cpu)/$(target_machine)/fwstart.S +fwstart_img_SOURCES = boot/$(target_cpu)/$(target_machine)/fwstart.S fwstart_img_CFLAGS = $(COMMON_CFLAGS) fwstart_img_ASFLAGS = $(COMMON_ASFLAGS) fwstart_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \ From 469ed9410b4a1e7c20948a4ced73e8f3343379be Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 May 2010 09:58:02 +0200 Subject: [PATCH 29/45] Fix i386-pc compilation --- conf/i386.rmk | 6 ++++++ include/grub/i386/pci.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/conf/i386.rmk b/conf/i386.rmk index 3d7f42804..bf2b80821 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -56,6 +56,12 @@ pci_mod_SOURCES = bus/pci.c pci_mod_CFLAGS = $(COMMON_CFLAGS) pci_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For cs5536.mod +pkglib_MODULES += cs5536.mod +cs5536_mod_SOURCES = bus/cs5536.c +cs5536_mod_CFLAGS = $(COMMON_CFLAGS) +cs5536_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For lspci.mod pkglib_MODULES += lspci.mod lspci_mod_SOURCES = commands/lspci.c diff --git a/include/grub/i386/pci.h b/include/grub/i386/pci.h index bab42adb6..795dec58b 100644 --- a/include/grub/i386/pci.h +++ b/include/grub/i386/pci.h @@ -80,7 +80,7 @@ grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), static inline void grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), - void *mem __attribute__ ((unused)), + volatile void *mem __attribute__ ((unused)), grub_size_t size __attribute__ ((unused))) { } From 839ced08f5cbc496087e21a51784d568eda96f7b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 May 2010 10:40:48 +0200 Subject: [PATCH 30/45] separate function to allocate DMA memory --- bus/pci.c | 43 +++++++++++++++++++ bus/usb/ohci.c | 62 ++++++++++++++++------------ bus/usb/uhci.c | 6 +-- bus/usb/usbtrans.c | 91 +++++++++++++++++++++++++++++++++-------- include/grub/pci.h | 9 ++++ include/grub/usbtrans.h | 2 +- kern/misc.c | 3 +- 7 files changed, 167 insertions(+), 49 deletions(-) diff --git a/bus/pci.c b/bus/pci.c index a08e53446..2fe9d764e 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -19,6 +19,49 @@ #include #include +#include + +#if GRUB_TARGET_SIZEOF_VOID_P == 4 +struct grub_pci_dma_chunk * +grub_memalign_dma32 (grub_size_t align, grub_size_t size) +{ + return grub_memalign (align, size); +} + +void +grub_dma_free (struct grub_pci_dma_chunk *ch) +{ + grub_free (ch); +} +#endif + +#ifdef GRUB_MACHINE_MIPS_YEELOONG +void * +grub_dma_get_virt (struct grub_pci_dma_chunk *ch) +{ + return (void *) ((((grub_uint32_t) ch) & 0x1fffffff) | 0xa0000000); +} + +grub_uint32_t +grub_dma_get_phys (struct grub_pci_dma_chunk *ch) +{ + return ((grub_uint32_t) ch) & 0x1fffffff; +} +#else + +void * +grub_dma_get_virt (struct grub_pci_dma_chunk *ch) +{ + return (void *) ch; +} + +grub_uint32_t +grub_dma_get_phys (struct grub_pci_dma_chunk *ch) +{ + return (grub_uint32_t) ch; +} + +#endif grub_pci_address_t grub_pci_make_address (grub_pci_device_t dev, int reg) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index de20a1491..81ce3294d 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -72,6 +72,7 @@ struct grub_ohci volatile grub_uint32_t *iobase; volatile struct grub_ohci_hcca *hcca; grub_uint32_t hcca_addr; + struct grub_pci_dma_chunk *hcca_chunk; struct grub_ohci *next; }; @@ -136,7 +137,6 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_uint32_t revision; grub_uint32_t frame_interval; int cs5536; - grub_uint32_t hcca_addr; /* Determine IO base address. */ grub_dprintf ("ohci", "pciid = %x\n", pciid); @@ -157,7 +157,6 @@ grub_ohci_pci_iter (grub_pci_device_t dev, basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED; basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS; grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, basereg); - } else { @@ -198,14 +197,12 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_dprintf ("ohci", "base=%p\n", o->iobase); - /* FIXME: create proper abstraction for this. */ -#ifdef GRUB_MACHINE_MIPS_YEELOONG - hcca_addr = 0x05000100; -#else /* Reserve memory for the HCCA. */ - hcca_addr = (grub_uint32_t) grub_memalign (256, 256); -#endif - o->hcca = grub_pci_device_map_range (dev, hcca_addr, 256); + o->hcca_chunk = grub_memalign_dma32 (256, 256); + if (! o->hcca_chunk) + return 1; + o->hcca = grub_dma_get_virt (o->hcca_chunk); + o->hcca_addr = grub_dma_get_phys (o->hcca_chunk); /* Check if the OHCI revision is actually 1.0 as supported. */ revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION); @@ -236,7 +233,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, GRUB_OHCI_PERIODIC_START); /* Setup the HCCA. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, hcca_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, o->hcca_addr); grub_dprintf ("ohci", "OHCI HCCA\n"); /* Enable the OHCI. */ @@ -289,7 +286,7 @@ grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev)) static void grub_ohci_transaction (grub_ohci_td_t td, grub_transfer_type_t type, unsigned int toggle, - grub_size_t size, char *data) + grub_size_t size, grub_uint32_t data) { grub_uint32_t token; grub_uint32_t buffer; @@ -321,7 +318,7 @@ grub_ohci_transaction (grub_ohci_td_t td, token |= toggle << 24; token |= 1 << 25; - buffer = (grub_uint32_t) data; + buffer = data; buffer_end = buffer + size - 1; td->token = grub_cpu_to_le32 (token); @@ -336,7 +333,10 @@ grub_ohci_transfer (grub_usb_controller_t dev, { struct grub_ohci *o = (struct grub_ohci *) dev->data; grub_ohci_ed_t ed; + grub_uint32_t ed_addr; + struct grub_pci_dma_chunk *ed_chunk, *td_list_chunk; grub_ohci_td_t td_list; + grub_uint32_t td_list_addr; grub_uint32_t target; grub_uint32_t td_tail; grub_uint32_t td_head; @@ -346,18 +346,23 @@ grub_ohci_transfer (grub_usb_controller_t dev, int i; /* Allocate an Endpoint Descriptor. */ - ed = grub_memalign (16, sizeof (*ed)); - if (! ed) + ed_chunk = grub_memalign_dma32 (256, sizeof (*ed)); + if (! ed_chunk) return GRUB_USB_ERR_INTERNAL; + ed = grub_dma_get_virt (ed_chunk); + ed_addr = grub_dma_get_phys (ed_chunk); - td_list = grub_memalign (16, sizeof (*td_list) * (transfer->transcnt + 1)); - if (! td_list) + td_list_chunk = grub_memalign_dma32 (256, sizeof (*td_list) + * (transfer->transcnt + 1)); + if (! td_list_chunk) { - grub_free ((void *) ed); + grub_dma_free (ed_chunk); return GRUB_USB_ERR_INTERNAL; } + td_list = grub_dma_get_virt (td_list_chunk); + td_list_addr = grub_dma_get_phys (td_list_chunk); - grub_dprintf ("ohci", "alloc=%p\n", td_list); + grub_dprintf ("ohci", "alloc=%p/0x%x\n", td_list, td_list_addr); /* Setup all Transfer Descriptors. */ for (i = 0; i < transfer->transcnt; i++) @@ -367,7 +372,8 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_ohci_transaction (&td_list[i], tr->pid, tr->toggle, tr->size, tr->data); - td_list[i].next_td = grub_cpu_to_le32 (&td_list[i + 1]); + td_list[i].next_td = grub_cpu_to_le32 (td_list_addr + + (i + 1) * sizeof (td_list[0])); } /* Setup the Endpoint Descriptor. */ @@ -384,9 +390,9 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Set the maximum packet size. */ target |= transfer->max << 16; - td_head = (grub_uint32_t) td_list; + td_head = td_list_addr; - td_tail = (grub_uint32_t) &td_list[transfer->transcnt]; + td_tail = td_list_addr + transfer->transcnt * sizeof (*td_list); ed->target = grub_cpu_to_le32 (target); ed->td_head = grub_cpu_to_le32 (td_head); @@ -413,7 +419,7 @@ grub_ohci_transfer (grub_usb_controller_t dev, status &= ~(1 << 2); grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, (grub_uint32_t) ed); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, ed_addr); /* Enable the Bulk list. */ control |= 1 << 5; @@ -440,10 +446,9 @@ grub_ohci_transfer (grub_usb_controller_t dev, status &= ~(1 << 1); grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, - (grub_uint32_t) ed); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, ed_addr); grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD+1, - (grub_uint32_t) ed); + ed_addr); /* Enable the Control list. */ control |= 1 << 4; @@ -484,9 +489,12 @@ grub_ohci_transfer (grub_usb_controller_t dev, { grub_uint8_t errcode; grub_ohci_td_t tderr; + grub_uint32_t td_err_addr; - tderr = (grub_ohci_td_t) grub_ohci_readreg32 (o, - GRUB_OHCI_REG_DONEHEAD); + td_err_addr = grub_ohci_readreg32 (o, GRUB_OHCI_REG_DONEHEAD); + + tderr = (grub_ohci_td_t) ((char *) td_list + + (td_err_addr - td_list_addr)); errcode = tderr->token >> 28; switch (errcode) diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index 947f2367b..6e47c38ef 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -380,7 +380,7 @@ static grub_uhci_td_t grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, grub_transfer_type_t type, unsigned int addr, unsigned int toggle, grub_size_t size, - char *data) + grub_uint32_t data) { grub_uhci_td_t td; static const unsigned int tf[] = { 0x69, 0xE1, 0x2D }; @@ -398,7 +398,7 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, } grub_dprintf ("uhci", - "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=%p td=%p\n", + "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=0x%x td=%p\n", endp, type, addr, toggle, size, data, td); /* Don't point to any TD, just terminate. */ @@ -418,7 +418,7 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, td->token = ((size << 21) | (toggle << 19) | (endp << 15) | (addr << 8) | tf[type]); - td->buffer = (grub_uint32_t) data; + td->buffer = data; return td; } diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index 09e7af83e..f59d5ec77 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -29,30 +30,59 @@ grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t request, grub_uint16_t value, grub_uint16_t index, - grub_size_t size, char *data) + grub_size_t size0, char *data_in) { int i; grub_usb_transfer_t transfer; int datablocks; - struct grub_usb_packet_setup setupdata; + struct grub_usb_packet_setup *setupdata; + grub_uint32_t setupdata_addr; grub_usb_err_t err; unsigned int max; + struct grub_pci_dma_chunk *data_chunk, *setupdata_chunk; + char *data; + grub_uint32_t data_addr; + grub_size_t size = size0; + + /* FIXME: avoid allocation any kind of buffer in a first place. */ + data_chunk = grub_memalign_dma32 (128, size ? : 16); + if (!data_chunk) + return GRUB_USB_ERR_INTERNAL; + data = grub_dma_get_virt (data_chunk); + data_addr = grub_dma_get_phys (data_chunk); + grub_memcpy (data, data_in, size); grub_dprintf ("usb", "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n", reqtype, request, value, index, size); /* Create a transfer. */ - transfer = grub_malloc (sizeof (struct grub_usb_transfer)); + transfer = grub_malloc (sizeof (*transfer)); if (! transfer) - return grub_errno; + { + grub_dma_free (data_chunk); + return grub_errno; + } + + setupdata_chunk = grub_memalign_dma32 (32, sizeof (*setupdata)); + if (! setupdata_chunk) + { + grub_free (transfer); + grub_dma_free (data_chunk); + return grub_errno; + } + + setupdata = grub_dma_get_virt (setupdata_chunk); + setupdata_addr = grub_dma_get_phys (setupdata_chunk); /* Determine the maximum packet size. */ - if (dev->initialized) + if (dev->initialized && dev->descdev.maxsize0) max = dev->descdev.maxsize0; else max = 64; + grub_dprintf ("usb", "transfer = %p, dev = %p\n", transfer, dev); + datablocks = (size + max - 1) / max; /* XXX: Discriminate between different types of control @@ -71,18 +101,20 @@ grub_usb_control_msg (grub_usb_device_t dev, if (! transfer->transactions) { grub_free (transfer); + grub_dma_free (setupdata_chunk); + grub_dma_free (data_chunk); return grub_errno; } /* Build a Setup packet. XXX: Endianness. */ - setupdata.reqtype = reqtype; - setupdata.request = request; - setupdata.value = value; - setupdata.index = index; - setupdata.length = size; - transfer->transactions[0].size = sizeof (setupdata); + setupdata->reqtype = reqtype; + setupdata->request = request; + setupdata->value = value; + setupdata->index = index; + setupdata->length = size; + transfer->transactions[0].size = sizeof (*setupdata); transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP; - transfer->transactions[0].data = (char *) &setupdata; + transfer->transactions[0].data = setupdata_addr; transfer->transactions[0].toggle = 0; /* Now the data... XXX: Is this the right way to transfer control @@ -99,13 +131,13 @@ grub_usb_control_msg (grub_usb_device_t dev, tr->pid = GRUB_USB_TRANSFER_TYPE_IN; else tr->pid = GRUB_USB_TRANSFER_TYPE_OUT; - tr->data = &data[i * max]; + tr->data = data_addr + i * max; size -= max; } /* End with an empty OUT transaction. */ transfer->transactions[datablocks + 1].size = 0; - transfer->transactions[datablocks + 1].data = NULL; + transfer->transactions[datablocks + 1].data = 0; if (reqtype & 128) transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_OUT; else @@ -117,13 +149,17 @@ grub_usb_control_msg (grub_usb_device_t dev, grub_free (transfer->transactions); grub_free (transfer); + grub_dma_free (data_chunk); + grub_dma_free (setupdata_chunk); + + grub_memcpy (data_in, data, size0); return err; } static grub_usb_err_t grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data, + int endpoint, grub_size_t size0, char *data_in, grub_transfer_type_t type) { int i; @@ -132,6 +168,19 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, unsigned int max; grub_usb_err_t err; int toggle = dev->toggle[endpoint]; + char *data; + grub_uint32_t data_addr; + struct grub_pci_dma_chunk *data_chunk; + grub_size_t size = size0; + + /* FIXME: avoid allocation any kind of buffer in a first place. */ + data_chunk = grub_memalign_dma32 (128, size); + if (!data_chunk) + return GRUB_USB_ERR_INTERNAL; + data = grub_dma_get_virt (data_chunk); + data_addr = grub_dma_get_phys (data_chunk); + if (type == GRUB_USB_TRANSFER_TYPE_OUT) + grub_memcpy (data, data_in, size); /* Use the maximum packet size given in the endpoint descriptor. */ if (dev->initialized) @@ -150,7 +199,10 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, /* Create a transfer. */ transfer = grub_malloc (sizeof (struct grub_usb_transfer)); if (! transfer) - return grub_errno; + { + grub_dma_free (data_chunk); + return grub_errno; + } datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; @@ -167,6 +219,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, if (! transfer->transactions) { grub_free (transfer); + grub_dma_free (data_chunk); return grub_errno; } @@ -181,7 +234,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, tr->toggle = toggle; toggle = toggle ? 0 : 1; tr->pid = type; - tr->data = &data[i * max]; + tr->data = data_addr + i * max; size -= tr->size; } @@ -191,6 +244,10 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, grub_free (transfer->transactions); grub_free (transfer); + grub_dma_free (data_chunk); + + if (type == GRUB_USB_TRANSFER_TYPE_IN) + grub_memcpy (data_in, data, size0); return err; } diff --git a/include/grub/pci.h b/include/grub/pci.h index 8a653c43e..fff4d3e3a 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -109,6 +109,15 @@ grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev, int reg); void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook); + +struct grub_pci_dma_chunk; + +struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align, + grub_size_t size); +void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch); +void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch); +grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch); + #endif #endif /* GRUB_PCI_H */ diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index 7e4a9d7ee..8c739684e 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -37,7 +37,7 @@ struct grub_usb_transaction int size; int toggle; grub_transfer_type_t pid; - char *data; + grub_uint32_t data; }; typedef struct grub_usb_transaction *grub_usb_transaction_t; diff --git a/kern/misc.c b/kern/misc.c index 9d8fc70da..e86043c15 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -189,7 +189,7 @@ grub_real_dprintf (const char *file, const int line, const char *condition, const char *debug = grub_env_get ("debug"); if (! debug) - return; + debug = "usb,ohci"; if (grub_strword (debug, "all") || grub_strword (debug, condition)) { @@ -197,6 +197,7 @@ grub_real_dprintf (const char *file, const int line, const char *condition, va_start (args, fmt); grub_vprintf (fmt, args); va_end (args); + grub_refresh (); } } From dcf937195ca499ce0b672e98e81c92891ea3abd2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 May 2010 10:49:03 +0200 Subject: [PATCH 31/45] revert accidental debugging commit --- kern/misc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kern/misc.c b/kern/misc.c index e86043c15..9d8fc70da 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -189,7 +189,7 @@ grub_real_dprintf (const char *file, const int line, const char *condition, const char *debug = grub_env_get ("debug"); if (! debug) - debug = "usb,ohci"; + return; if (grub_strword (debug, "all") || grub_strword (debug, condition)) { @@ -197,7 +197,6 @@ grub_real_dprintf (const char *file, const int line, const char *condition, va_start (args, fmt); grub_vprintf (fmt, args); va_end (args); - grub_refresh (); } } From a7208779c3f5260f2cb353b047bdece889906600 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 22 May 2010 23:06:47 +0200 Subject: [PATCH 32/45] init PCI DMA and USB controllers --- kern/mips/yeeloong/init.c | 54 +++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 697e9733c..826659968 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -66,6 +66,49 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, return GRUB_ERR_NONE; } +static void +init_pci (void) +{ + auto int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid); + int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid) + { + grub_pci_address_t addr; + /* FIXME: autoscan for BARs and devices. */ + switch (pciid) + { + case 0x00351033: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5025000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, 0x2100146); + break; + case 0x00e01033: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5026000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, 0x2100146); + break; + } + return 0; + } + + *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) = 0x8000000c; + *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) = 0xffffffff; + + /* 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; + + grub_pci_iterate (set_card); +} + void grub_machine_init (void) { @@ -123,16 +166,7 @@ grub_machine_init (void) grub_cs5536_init_geode (dev); - /* 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; + init_pci (); } modend = grub_modules_get_end (); From 6e198650e987488632ff81c2bc538bf5ea299fcf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 22 May 2010 23:36:44 +0200 Subject: [PATCH 33/45] Enable serial in simulcast with local terminal on yeeloong --- conf/mips-qemu-mips.rmk | 6 ++++++ conf/mips.rmk | 6 ------ kern/mips/yeeloong/init.c | 5 +++++ term/serial.c | 15 +++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/conf/mips-qemu-mips.rmk b/conf/mips-qemu-mips.rmk index 2f80ab2e3..0d81bbe8b 100644 --- a/conf/mips-qemu-mips.rmk +++ b/conf/mips-qemu-mips.rmk @@ -20,3 +20,9 @@ kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(LINK_BASE),-Bstatic kernel_img_FORMAT = binary + +# For serial.mod. +pkglib_MODULES += serial.mod +serial_mod_SOURCES = term/serial.c +serial_mod_CFLAGS = $(COMMON_CFLAGS) +serial_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/mips.rmk b/conf/mips.rmk index 7d30f55f1..26c516fc4 100644 --- a/conf/mips.rmk +++ b/conf/mips.rmk @@ -10,12 +10,6 @@ kernel_img_HEADERS += cpu/cache.h sbin_SCRIPTS = bin_SCRIPTS = -# For serial.mod. -pkglib_MODULES += serial.mod -serial_mod_SOURCES = term/serial.c -serial_mod_CFLAGS = $(COMMON_CFLAGS) -serial_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For relocator.mod. pkglib_MODULES += relocator.mod relocator_mod_SOURCES = lib/$(target_cpu)/relocator.c lib/$(target_cpu)/relocator_asm.S diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 826659968..78586dbd4 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -37,6 +37,8 @@ extern void grub_bitmap_init (void); extern void grub_font_init (void); extern void grub_gfxterm_init (void); extern void grub_at_keyboard_init (void); +extern void grub_serial_init (void); +extern void grub_terminfo_init (void); /* FIXME: use interrupt to count high. */ grub_uint64_t @@ -183,6 +185,9 @@ grub_machine_init (void) grub_gfxterm_init (); grub_at_keyboard_init (); + + grub_terminfo_init (); + grub_serial_init (); } void diff --git a/term/serial.c b/term/serial.c index b16b608f1..ef9efac2e 100644 --- a/term/serial.c +++ b/term/serial.c @@ -636,6 +636,21 @@ GRUB_MOD_INIT(serial) serial_settings.word_len = UART_8BITS_WORD; serial_settings.parity = UART_NO_PARITY; serial_settings.stop_bits = UART_1_STOP_BIT; + +#ifdef GRUB_MACHINE_MIPS_YEELOONG + { + grub_err_t hwiniterr; + hwiniterr = serial_hw_init (); + + if (hwiniterr == GRUB_ERR_NONE) + { + grub_term_register_input_active ("serial", &grub_serial_term_input); + grub_term_register_output_active ("serial", &grub_serial_term_output); + + registered = 1; + } + } +#endif } GRUB_MOD_FINI(serial) From 4b9fa9d70f80349aa97c76a5cedb402395787d8a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:08:52 +0200 Subject: [PATCH 34/45] Addmissing definitions --- include/grub/mips/loongson.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index 09b788db2..6cb1178d5 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -64,7 +64,7 @@ #define GRUB_CPU_LOONGSON_D_CACHE_LOG_WAYS 2 #define GRUB_CPU_LOONGSON_S_CACHE_LOG_WAYS 2 -/* Fixme: determine dynamically. */ +/* FIXME: determine dynamically. */ #define GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE 19 #define GRUB_CPU_LOONGSON_COP0_BADVADDR GRUB_CPU_REGISTER_WRAP($8) @@ -81,6 +81,9 @@ #define GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE 0x100 #define GRUB_CPU_LOONGSON_CORECFG_BUFFER_CPU 0x200 +#define GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO 0xbfe00150 +#define GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI 0xbfe00154 + #define GRUB_CPU_LOONGSON_GPIOCFG 0xbfe00120 #define GRUB_CPU_LOONGSON_SHUTDOWN_GPIO 1 From 5667f2656d69cfeac04146a92d072b41710fceec Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:09:39 +0200 Subject: [PATCH 35/45] Add missing part of serial commit --- include/grub/term.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/grub/term.h b/include/grub/term.h index 143aabe1e..9500e1c99 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -213,6 +213,14 @@ grub_term_register_input (const char *name __attribute__ ((unused)), } } +static inline void +grub_term_register_input_active (const char *name __attribute__ ((unused)), + grub_term_input_t term) +{ + if (! term->init || term->init () == GRUB_ERR_NONE) + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); +} + static inline void grub_term_register_output (const char *name __attribute__ ((unused)), grub_term_output_t term) @@ -229,6 +237,15 @@ grub_term_register_output (const char *name __attribute__ ((unused)), } } +static inline void +grub_term_register_output_active (const char *name __attribute__ ((unused)), + grub_term_output_t term) +{ + if (! term->init || term->init () == GRUB_ERR_NONE) + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), + GRUB_AS_LIST (term)); +} + static inline void grub_term_unregister_input (grub_term_input_t term) { From ae87524ea6e268013a315b230cd23716ef6dd705 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:11:47 +0200 Subject: [PATCH 36/45] Fix getvirt function on yeeloong --- bus/pci.c | 4 ++-- include/grub/pci.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bus/pci.c b/bus/pci.c index 2fe9d764e..3fec44fc2 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -36,7 +36,7 @@ grub_dma_free (struct grub_pci_dma_chunk *ch) #endif #ifdef GRUB_MACHINE_MIPS_YEELOONG -void * +volatile void * grub_dma_get_virt (struct grub_pci_dma_chunk *ch) { return (void *) ((((grub_uint32_t) ch) & 0x1fffffff) | 0xa0000000); @@ -45,7 +45,7 @@ grub_dma_get_virt (struct grub_pci_dma_chunk *ch) grub_uint32_t grub_dma_get_phys (struct grub_pci_dma_chunk *ch) { - return ((grub_uint32_t) ch) & 0x1fffffff; + return (((grub_uint32_t) ch) & 0x1fffffff) | 0x80000000; } #else diff --git a/include/grub/pci.h b/include/grub/pci.h index fff4d3e3a..51adf9377 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -115,7 +115,7 @@ struct grub_pci_dma_chunk; struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align, grub_size_t size); void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch); -void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch); +volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch); grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch); #endif From 980d936688f2308a8db23639201320ccb7d09493 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:12:33 +0200 Subject: [PATCH 37/45] Skip ghost USB controllers --- bus/pci.c | 8 ++++++++ include/grub/mips/yeeloong/pci.h | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/bus/pci.c b/bus/pci.c index 3fec44fc2..d8698ba33 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -91,6 +91,14 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) if (id >> 16 == 0xFFFF) continue; + /* Skip ghosts. */ + if (id == GRUB_YEELOONG_OHCI_PCIID + && dev.function == GRUB_YEELOONG_OHCI_GHOST_FUNCTION) + continue; + if (id == GRUB_YEELOONG_EHCI_PCIID + && dev.function == GRUB_YEELOONG_EHCI_GHOST_FUNCTION) + continue; + if (hook (dev, id)) return; diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h index 7c816ac8e..199bac048 100644 --- a/include/grub/mips/yeeloong/pci.h +++ b/include/grub/mips/yeeloong/pci.h @@ -24,6 +24,11 @@ #include #endif +#define GRUB_YEELOONG_OHCI_PCIID 0x00351033 +#define GRUB_YEELOONG_EHCI_PCIID 0x00e01033 +#define GRUB_YEELOONG_OHCI_GHOST_FUNCTION 4 +#define GRUB_YEELOONG_EHCI_GHOST_FUNCTION 5 + #define GRUB_PCI_NUM_BUS 1 #define GRUB_PCI_NUM_DEVICES 16 From 60c33f8c0fadde0cd6d266d612fa4050bd390db4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:13:37 +0200 Subject: [PATCH 38/45] Use DMA memory in usbtrans.c --- bus/usb/usbtrans.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index f59d5ec77..f6d3d30f9 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -35,12 +35,12 @@ grub_usb_control_msg (grub_usb_device_t dev, int i; grub_usb_transfer_t transfer; int datablocks; - struct grub_usb_packet_setup *setupdata; + volatile struct grub_usb_packet_setup *setupdata; grub_uint32_t setupdata_addr; grub_usb_err_t err; unsigned int max; struct grub_pci_dma_chunk *data_chunk, *setupdata_chunk; - char *data; + volatile char *data; grub_uint32_t data_addr; grub_size_t size = size0; @@ -50,7 +50,7 @@ grub_usb_control_msg (grub_usb_device_t dev, return GRUB_USB_ERR_INTERNAL; data = grub_dma_get_virt (data_chunk); data_addr = grub_dma_get_phys (data_chunk); - grub_memcpy (data, data_in, size); + grub_memcpy ((char *) data, data_in, size); grub_dprintf ("usb", "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n", @@ -152,7 +152,7 @@ grub_usb_control_msg (grub_usb_device_t dev, grub_dma_free (data_chunk); grub_dma_free (setupdata_chunk); - grub_memcpy (data_in, data, size0); + grub_memcpy (data_in, (char *) data, size0); return err; } @@ -168,7 +168,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, unsigned int max; grub_usb_err_t err; int toggle = dev->toggle[endpoint]; - char *data; + volatile char *data; grub_uint32_t data_addr; struct grub_pci_dma_chunk *data_chunk; grub_size_t size = size0; @@ -180,7 +180,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, data = grub_dma_get_virt (data_chunk); data_addr = grub_dma_get_phys (data_chunk); if (type == GRUB_USB_TRANSFER_TYPE_OUT) - grub_memcpy (data, data_in, size); + grub_memcpy ((char *) data, data_in, size); /* Use the maximum packet size given in the endpoint descriptor. */ if (dev->initialized) @@ -247,7 +247,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, grub_dma_free (data_chunk); if (type == GRUB_USB_TRANSFER_TYPE_IN) - grub_memcpy (data_in, data, size0); + grub_memcpy (data_in, (char *) data, size0); return err; } From 20ad3a81dc8c9d5c186ecf4361d1c70515008540 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:14:23 +0200 Subject: [PATCH 39/45] Macroify USB controllers ID --- kern/mips/yeeloong/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 78586dbd4..46b3af2e1 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -78,13 +78,13 @@ init_pci (void) /* FIXME: autoscan for BARs and devices. */ switch (pciid) { - case 0x00351033: + case GRUB_YEELOONG_OHCI_PCIID: addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); grub_pci_write (addr, 0x5025000); addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); grub_pci_write (addr, 0x2100146); break; - case 0x00e01033: + case GRUB_YEELOONG_EHCI_PCIID: addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); grub_pci_write (addr, 0x5026000); addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); From c710f8cc096a84178931e6a9b867e10f0ae75fa3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:17:16 +0200 Subject: [PATCH 40/45] Always write the whole of frame interval register --- bus/usb/ohci.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 81ce3294d..b86e78ef2 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -104,10 +104,12 @@ typedef enum #define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK 0x8fff0000 #define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT 16 +#define GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT 0 /* XXX: Is this choice of timings sane? */ #define GRUB_OHCI_FSMPS 0x2778 #define GRUB_OHCI_PERIODIC_START 0x257f +#define GRUB_OHCI_FRAME_INTERVAL 0x2edf static grub_uint32_t grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg) @@ -135,11 +137,11 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_address_t addr; struct grub_ohci *o; grub_uint32_t revision; - grub_uint32_t frame_interval; int cs5536; /* Determine IO base address. */ grub_dprintf ("ohci", "pciid = %x\n", pciid); + if (pciid == GRUB_CS5536_PCIID) { grub_uint64_t basereg; @@ -215,19 +217,16 @@ grub_ohci_pci_iter (grub_pci_device_t dev, & ~GRUB_OHCI_RHUB_PORT_POWER_MASK) | GRUB_OHCI_RHUB_PORT_ALL_POWERED); - /* Backup the frame interval register. */ - frame_interval = grub_ohci_readreg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL); - /* Suspend the OHCI by issuing a reset. */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ grub_millisleep (1); grub_dprintf ("ohci", "OHCI reset\n"); - /* Restore the frame interval register. */ - frame_interval = (frame_interval & ~GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK) - | (GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT - << GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, frame_interval); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, + (GRUB_OHCI_FSMPS + << GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT) + | (GRUB_OHCI_FRAME_INTERVAL + << GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT)); grub_ohci_writereg32 (o, GRUB_OHCI_REG_PERIODIC_START, GRUB_OHCI_PERIODIC_START); From e51a665432fafb4016613be732f45f24ffa4eb23 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 00:17:51 +0200 Subject: [PATCH 41/45] Add missing volatile attribute --- bus/usb/ohci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index b86e78ef2..9515423fa 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -64,8 +64,8 @@ struct grub_ohci_td grub_uint32_t buffer_end; } __attribute__((packed)); -typedef struct grub_ohci_td *grub_ohci_td_t; -typedef struct grub_ohci_ed *grub_ohci_ed_t; +typedef volatile struct grub_ohci_td *grub_ohci_td_t; +typedef volatile struct grub_ohci_ed *grub_ohci_ed_t; struct grub_ohci { From 27cd973df6fc3cc528a43f1f4d078ab296c5ef5f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 May 2010 02:41:16 +0200 Subject: [PATCH 42/45] Macroify command and status registers --- include/grub/pci.h | 13 +++++++++++++ kern/mips/yeeloong/init.c | 29 +++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/grub/pci.h b/include/grub/pci.h index 51adf9377..e6d6488f0 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -68,6 +68,19 @@ #define GRUB_PCI_REG_MIN_GNT 0x3e #define GRUB_PCI_REG_MAX_LAT 0x3f +#define GRUB_PCI_COMMAND_IO_ENABLED 0x0001 +#define GRUB_PCI_COMMAND_MEM_ENABLED 0x0002 +#define GRUB_PCI_COMMAND_BUS_MASTER 0x0004 +#define GRUB_PCI_COMMAND_PARITY_ERROR 0x0040 +#define GRUB_PCI_COMMAND_SERR_ENABLE 0x0100 + +#define GRUB_PCI_STATUS_CAPABILITIES 0x0010 +#define GRUB_PCI_STATUS_66MHZ_CAPABLE 0x0020 +#define GRUB_PCI_STATUS_FAST_B2B_CAPABLE 0x0080 + +#define GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9 +#define GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600 + #ifndef ASM_FILE typedef grub_uint32_t grub_pci_id_t; diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 46b3af2e1..523f90282 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -82,13 +82,26 @@ init_pci (void) addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); grub_pci_write (addr, 0x5025000); addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write (addr, 0x2100146); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); break; case GRUB_YEELOONG_EHCI_PCIID: addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); grub_pci_write (addr, 0x5026000); addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write (addr, 0x2100146); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) + | GRUB_PCI_STATUS_CAPABILITIES); break; } return 0; @@ -98,8 +111,16 @@ init_pci (void) *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) = 0xffffffff; /* Setup PCI controller. */ - *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER - + GRUB_PCI_REG_COMMAND)) = 0x22b00046; + *((volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + + GRUB_PCI_REG_COMMAND)) + = GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED; + *((volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + + GRUB_PCI_REG_STATUS)) + = (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) + | GRUB_PCI_STATUS_FAST_B2B_CAPABLE | GRUB_PCI_STATUS_66MHZ_CAPABLE + | GRUB_PCI_STATUS_CAPABILITIES; + *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + GRUB_PCI_REG_CACHELINE)) = 0xff; *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER From 7eaef0ed512fb3547b318c571681c7a649865387 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 May 2010 20:43:43 +0200 Subject: [PATCH 43/45] fix compilation on not-yeeloong --- bus/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bus/pci.c b/bus/pci.c index d8698ba33..3e2126962 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -49,7 +49,7 @@ grub_dma_get_phys (struct grub_pci_dma_chunk *ch) } #else -void * +volatile void * grub_dma_get_virt (struct grub_pci_dma_chunk *ch) { return (void *) ch; @@ -91,6 +91,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) if (id >> 16 == 0xFFFF) continue; +#ifdef GRUB_MACHINE_MIPS_YEELOONG /* Skip ghosts. */ if (id == GRUB_YEELOONG_OHCI_PCIID && dev.function == GRUB_YEELOONG_OHCI_GHOST_FUNCTION) @@ -98,6 +99,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) if (id == GRUB_YEELOONG_EHCI_PCIID && dev.function == GRUB_YEELOONG_EHCI_GHOST_FUNCTION) continue; +#endif if (hook (dev, id)) return; From 8148171e96f291ad36b1d58e2332d41552f73992 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 31 May 2010 08:24:33 +0200 Subject: [PATCH 44/45] Pad image to 512K for flashrom --- util/grub-mkimage.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index bb4a9b2eb..dc9dcc208 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1015,14 +1015,17 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], boot_size = grub_util_get_image_size (boot_path); boot_img = grub_util_read_image (boot_path); - rom_size = core_size + boot_size; + rom_size = ALIGN_UP (core_size + boot_size, 512 * 1024); rom_img = xmalloc (rom_size); memset (rom_img, 0, rom_size); memcpy (rom_img, boot_img, boot_size); - memcpy (rom_img + boot_size, core_img, core_size); + memcpy (rom_img + boot_size, core_img, core_size); + + memset (rom_img + boot_size + core_size, 0, + rom_size - (boot_size + core_size)); free (core_img); core_img = rom_img; From 4fa54f9209d3c71f7e33dd37df0a0c87892524eb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 31 May 2010 08:25:20 +0200 Subject: [PATCH 45/45] Remove leftover message --- boot/mips/yeeloong/fwstart.S | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/mips/yeeloong/fwstart.S b/boot/mips/yeeloong/fwstart.S index 239305939..7fe5d7ac2 100644 --- a/boot/mips/yeeloong/fwstart.S +++ b/boot/mips/yeeloong/fwstart.S @@ -381,7 +381,6 @@ notification_string: .asciz "GRUB " no_cs5536: .asciz "No CS5536 found.\n\r" cs5536_found: .asciz "CS5536 at " sm_failed: .asciz "SM transaction failed.\n\r" -not_implemented: .asciz "Nothing more is implemented. Bye.\n\r" unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r" unhandled_cache_error: .asciz "Unhandled cache error.\n\r" unhandled_exception: .asciz "Unhandled exception.\n\r"