diff options
Diffstat (limited to 'drivers')
70 files changed, 2207 insertions, 397 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 7683c61..5ef58c0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -16,6 +16,7 @@ obj-y += twserial/ obj-y += video/ obj-y += watchdog/ obj-$(CONFIG_QE) += qe/ +obj-$(CONFIG_U_QE) += qe/ obj-y += memory/ obj-y += pwm/ obj-y += input/ diff --git a/drivers/bios_emulator/Makefile b/drivers/bios_emulator/Makefile index e56356e..2ba43ac 100644 --- a/drivers/bios_emulator/Makefile +++ b/drivers/bios_emulator/Makefile @@ -9,4 +9,4 @@ obj-y = atibios.o biosemu.o besys.o bios.o \ $(X86DIR)/debug.o ccflags-y := -I$(srctree)/$(src) -I$(srctree)/$(src)/include \ - -D__PPC__ -D__BIG_ENDIAN__ + $(if $(CONFIG_PPC),-D__PPC__ -D__BIG_ENDIAN__) diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c index 3b2ed6e..93b815c 100644 --- a/drivers/bios_emulator/atibios.c +++ b/drivers/bios_emulator/atibios.c @@ -46,8 +46,11 @@ * BIOS in u-boot. ****************************************************************************/ #include <common.h> -#include "biosemui.h" +#include <bios_emul.h> +#include <errno.h> #include <malloc.h> +#include <vbe.h> +#include "biosemui.h" /* Length of the BIOS image */ #define MAX_BIOSLEN (128 * 1024L) @@ -59,17 +62,54 @@ static u32 saveBaseAddress14; static u32 saveBaseAddress18; static u32 saveBaseAddress20; +static void atibios_set_vesa_mode(RMREGS *regs, int vesa_mode, + struct vbe_mode_info *mode_info) +{ + debug("VBE: Setting VESA mode %#04x\n", vesa_mode); + /* request linear framebuffer mode */ + vesa_mode |= (1 << 14); + /* request clearing of framebuffer */ + vesa_mode &= ~(1 << 15); + regs->e.eax = VESA_SET_MODE; + regs->e.ebx = vesa_mode; + BE_int86(0x10, regs, regs); + + int offset = 0x2000; + void *buffer = (void *)(M.mem_base + offset); + + u16 buffer_seg = (((unsigned long)offset) >> 4) & 0xff00; + u16 buffer_adr = ((unsigned long)offset) & 0xffff; + regs->e.eax = VESA_GET_MODE_INFO; + regs->e.ebx = 0; + regs->e.ecx = vesa_mode; + regs->e.edx = 0; + regs->e.esi = buffer_seg; + regs->e.edi = buffer_adr; + BE_int86(0x10, regs, regs); + memcpy(mode_info->mode_info_block, buffer, + sizeof(struct vbe_mode_info)); + mode_info->valid = true; + + vesa_mode |= (1 << 14); + /* request clearing of framebuffer */ + vesa_mode &= ~(1 << 15); + regs->e.eax = VESA_SET_MODE; + regs->e.ebx = vesa_mode; + BE_int86(0x10, regs, regs); +} + /**************************************************************************** PARAMETERS: pcidev - PCI device info for the video card on the bus to boot -VGAInfo - BIOS emulator VGA info structure +vga_info - BIOS emulator VGA info structure REMARKS: This function executes the BIOS POST code on the controller. We assume that at this stage the controller has its I/O and memory space enabled and that all other controllers are in a disabled state. ****************************************************************************/ -static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo * VGAInfo) +static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo *vga_info, + int vesa_mode, struct vbe_mode_info *mode_info) { RMREGS regs; RMSREGS sregs; @@ -84,13 +124,16 @@ static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo * VGAInfo) ((int)PCI_DEV(pcidev) << 3) | (int)PCI_FUNC(pcidev); /*Setup the X86 emulator for the VGA BIOS*/ - BE_setVGA(VGAInfo); + BE_setVGA(vga_info); /*Execute the BIOS POST code*/ BE_callRealMode(0xC000, 0x0003, ®s, &sregs); /*Cleanup and exit*/ - BE_getVGA(VGAInfo); + BE_getVGA(vga_info); + + if (vesa_mode != -1) + atibios_set_vesa_mode(®s, vesa_mode, mode_info); } /**************************************************************************** @@ -244,60 +287,61 @@ REMARKS: Loads and POST's the display controllers BIOS, directly from the BIOS image we can extract over the PCI bus. ****************************************************************************/ -static int PCI_postController(pci_dev_t pcidev, BE_VGAInfo * VGAInfo) +static int PCI_postController(pci_dev_t pcidev, uchar *bios_rom, int bios_len, + BE_VGAInfo *vga_info, int vesa_mode, + struct vbe_mode_info *mode_info) { - u32 BIOSImageLen; - uchar *mappedBIOS; - uchar *copyOfBIOS; - - /*Allocate memory to store copy of BIOS from display controller*/ - if ((mappedBIOS = PCI_mapBIOSImage(pcidev)) == NULL) { - printf("videoboot: Video ROM failed to map!\n"); - return false; - } + u32 bios_image_len; + uchar *mapped_bios; + uchar *copy_of_bios; + + if (bios_rom) { + copy_of_bios = bios_rom; + bios_image_len = bios_len; + } else { + /* + * Allocate memory to store copy of BIOS from display + * controller + */ + mapped_bios = PCI_mapBIOSImage(pcidev); + if (mapped_bios == NULL) { + printf("videoboot: Video ROM failed to map!\n"); + return false; + } - BIOSImageLen = mappedBIOS[2] * 512; + bios_image_len = mapped_bios[2] * 512; - if ((copyOfBIOS = malloc(BIOSImageLen)) == NULL) { - printf("videoboot: Out of memory!\n"); - return false; + copy_of_bios = malloc(bios_image_len); + if (copy_of_bios == NULL) { + printf("videoboot: Out of memory!\n"); + return false; + } + memcpy(copy_of_bios, mapped_bios, bios_image_len); + PCI_unmapBIOSImage(pcidev, mapped_bios); } - memcpy(copyOfBIOS, mappedBIOS, BIOSImageLen); - PCI_unmapBIOSImage(pcidev, mappedBIOS); - - /*Save information in VGAInfo structure*/ - VGAInfo->function = PCI_FUNC(pcidev); - VGAInfo->device = PCI_DEV(pcidev); - VGAInfo->bus = PCI_BUS(pcidev); - VGAInfo->pcidev = pcidev; - VGAInfo->BIOSImage = copyOfBIOS; - VGAInfo->BIOSImageLen = BIOSImageLen; + /*Save information in vga_info structure*/ + vga_info->function = PCI_FUNC(pcidev); + vga_info->device = PCI_DEV(pcidev); + vga_info->bus = PCI_BUS(pcidev); + vga_info->pcidev = pcidev; + vga_info->BIOSImage = copy_of_bios; + vga_info->BIOSImageLen = bios_image_len; /*Now execute the BIOS POST for the device*/ - if (copyOfBIOS[0] != 0x55 || copyOfBIOS[1] != 0xAA) { + if (copy_of_bios[0] != 0x55 || copy_of_bios[1] != 0xAA) { printf("videoboot: Video ROM image is invalid!\n"); return false; } - PCI_doBIOSPOST(pcidev, VGAInfo); + PCI_doBIOSPOST(pcidev, vga_info, vesa_mode, mode_info); /*Reset the size of the BIOS image to the final size*/ - VGAInfo->BIOSImageLen = copyOfBIOS[2] * 512; + vga_info->BIOSImageLen = copy_of_bios[2] * 512; return true; } -/**************************************************************************** -PARAMETERS: -pcidev - PCI device info for the video card on the bus to boot -pVGAInfo - Place to return VGA info structure is requested -cleanUp - true to clean up on exit, false to leave emulator active - -REMARKS: -Boots the PCI/AGP video card on the bus using the Video ROM BIOS image -and the X86 BIOS emulator module. -****************************************************************************/ -int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp) +int biosemu_setup(pci_dev_t pcidev, BE_VGAInfo **vga_infop) { BE_VGAInfo *VGAInfo; @@ -307,28 +351,70 @@ int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp) /*Initialise the x86 BIOS emulator*/ if ((VGAInfo = malloc(sizeof(*VGAInfo))) == NULL) { printf("videoboot: Out of memory!\n"); - return false; + return -ENOMEM; } memset(VGAInfo, 0, sizeof(*VGAInfo)); BE_init(0, 65536, VGAInfo, 0); + *vga_infop = VGAInfo; - /*Post all the display controller BIOS'es*/ - if (!PCI_postController(pcidev, VGAInfo)) - return false; + return 0; +} - /*Cleanup and exit the emulator if requested. If the BIOS emulator - is needed after booting the card, we will not call BE_exit and - leave it enabled for further use (ie: VESA driver etc). +void biosemu_set_interrupt_handler(int intnum, int (*int_func)(void)) +{ + X86EMU_setupIntrFunc(intnum, (X86EMU_intrFuncs)int_func); +} + +int biosemu_run(pci_dev_t pcidev, uchar *bios_rom, int bios_len, + BE_VGAInfo *vga_info, int clean_up, int vesa_mode, + struct vbe_mode_info *mode_info) +{ + /*Post all the display controller BIOS'es*/ + if (!PCI_postController(pcidev, bios_rom, bios_len, vga_info, + vesa_mode, mode_info)) + return -EINVAL; + + /* + * Cleanup and exit the emulator if requested. If the BIOS emulator + * is needed after booting the card, we will not call BE_exit and + * leave it enabled for further use (ie: VESA driver etc). */ - if (cleanUp) { + if (clean_up) { BE_exit(); - if (VGAInfo->BIOSImage) - free(VGAInfo->BIOSImage); - free(VGAInfo); - VGAInfo = NULL; + if (vga_info->BIOSImage) + free(vga_info->BIOSImage); + free(vga_info); + vga_info = NULL; } - /*Return VGA info pointer if the caller requested it*/ + + return 0; +} + +/**************************************************************************** +PARAMETERS: +pcidev - PCI device info for the video card on the bus to boot +pVGAInfo - Place to return VGA info structure is requested +cleanUp - true to clean up on exit, false to leave emulator active + +REMARKS: +Boots the PCI/AGP video card on the bus using the Video ROM BIOS image +and the X86 BIOS emulator module. +****************************************************************************/ +int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo **pVGAInfo, int clean_up) +{ + BE_VGAInfo *VGAInfo; + int ret; + + ret = biosemu_setup(pcidev, &VGAInfo); + if (ret) + return false; + ret = biosemu_run(pcidev, NULL, 0, VGAInfo, clean_up, -1, NULL); + if (ret) + return false; + + /* Return VGA info pointer if the caller requested it*/ if (pVGAInfo) *pVGAInfo = VGAInfo; + return true; } diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c index ad88a53..752a928 100644 --- a/drivers/bios_emulator/besys.c +++ b/drivers/bios_emulator/besys.c @@ -54,12 +54,20 @@ /*------------------------- Global Variables ------------------------------*/ -#ifndef __i386__ +#ifndef CONFIG_X86EMU_RAW_IO static char *BE_biosDate = "08/14/99"; static u8 BE_model = 0xFC; static u8 BE_submodel = 0x00; #endif +#undef DEBUG_IO_ACCESS + +#ifdef DEBUG_IO_ACCESS +#define debug_io(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define debug_io(x, b...) +#endif + /*----------------------------- Implementation ----------------------------*/ /**************************************************************************** @@ -80,38 +88,40 @@ static u8 *BE_memaddr(u32 addr) if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { return (u8*)(_BE_env.biosmem_base + addr - 0xC0000); } else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) { - DB(printf("BE_memaddr: address %#lx may be invalid!\n", addr);) - return M.mem_base; + DB(printf("BE_memaddr: address %#lx may be invalid!\n", + (ulong)addr);) + return (u8 *)M.mem_base; } else if (addr >= 0xA0000 && addr <= 0xBFFFF) { return (u8*)(_BE_env.busmem_base + addr - 0xA0000); } -#ifdef __i386__ +#ifdef CONFIG_X86EMU_RAW_IO else if (addr >= 0xD0000 && addr <= 0xFFFFF) { /* We map the real System BIOS directly on real PC's */ - DB(printf("BE_memaddr: System BIOS address %#lx\n", addr);) - return _BE_env.busmem_base + addr - 0xA0000; + DB(printf("BE_memaddr: System BIOS address %#lx\n", + (ulong)addr);) + return (u8 *)_BE_env.busmem_base + addr - 0xA0000; } #else else if (addr >= 0xFFFF5 && addr < 0xFFFFE) { /* Return a faked BIOS date string for non-x86 machines */ - DB(printf("BE_memaddr - Returning BIOS date\n");) + debug_io("BE_memaddr - Returning BIOS date\n"); return (u8 *)(BE_biosDate + addr - 0xFFFF5); } else if (addr == 0xFFFFE) { /* Return system model identifier for non-x86 machines */ - DB(printf("BE_memaddr - Returning model\n");) + debug_io("BE_memaddr - Returning model\n"); return &BE_model; } else if (addr == 0xFFFFF) { /* Return system submodel identifier for non-x86 machines */ - DB(printf("BE_memaddr - Returning submodel\n");) + debug_io("BE_memaddr - Returning submodel\n"); return &BE_submodel; } #endif else if (addr > M.mem_size - 1) { HALT_SYS(); - return M.mem_base; + return (u8 *)M.mem_base; } - return M.mem_base + addr; + return (u8 *)(M.mem_base + addr); } /**************************************************************************** @@ -230,7 +240,7 @@ void X86API BE_wrl(u32 addr, u32 val) } } -#if defined(DEBUG) || !defined(__i386__) +#if !defined(CONFIG_X86EMU_RAW_IO) /* For Non-Intel machines we may need to emulate some I/O port accesses that * the BIOS may try to access, such as the PCI config registers. @@ -258,6 +268,7 @@ static u8 VGA_inpb (const int port) { u8 val = 0xff; + debug_io("vga_inb.%04X -> ", (u16) port); switch (port) { case 0x3C0: /* 3C0 has funky characteristics because it can act as either @@ -560,7 +571,7 @@ u8 X86API BE_inb(X86EMU_pioAddr port) { u8 val = 0; -#if defined(DEBUG) || !defined(__i386__) +#if !defined(CONFIG_X86EMU_RAW_IO) if (IS_VGA_PORT(port)){ /*seems reading port 0x3c3 return the high 16 bit of io port*/ if(port == 0x3c3) @@ -581,7 +592,12 @@ u8 X86API BE_inb(X86EMU_pioAddr port) val = LOG_inpb(port); } else #endif + { + debug_io("inb.%04X -> ", (u16) port); val = LOG_inpb(port); + debug_io("%02X\n", val); + } + return val; } @@ -601,7 +617,7 @@ u16 X86API BE_inw(X86EMU_pioAddr port) { u16 val = 0; -#if defined(DEBUG) || !defined(__i386__) +#if !defined(CONFIG_X86EMU_RAW_IO) if (IS_PCI_PORT(port)) val = PCI_inp(port, REG_READ_WORD); else if (port < 0x100) { @@ -609,7 +625,12 @@ u16 X86API BE_inw(X86EMU_pioAddr port) val = LOG_inpw(port); } else #endif + { + debug_io("inw.%04X -> ", (u16) port); val = LOG_inpw(port); + debug_io("%04X\n", val); + } + return val; } @@ -629,14 +650,19 @@ u32 X86API BE_inl(X86EMU_pioAddr port) { u32 val = 0; -#if defined(DEBUG) || !defined(__i386__) +#if !defined(CONFIG_X86EMU_RAW_IO) if (IS_PCI_PORT(port)) val = PCI_inp(port, REG_READ_DWORD); else if (port < 0x100) { val = LOG_inpd(port); } else #endif + { + debug_io("inl.%04X -> ", (u16) port); val = LOG_inpd(port); + debug_io("%08X\n", val); + } + return val; } @@ -652,7 +678,7 @@ through to the real hardware if we don't need to special case it. ****************************************************************************/ void X86API BE_outb(X86EMU_pioAddr port, u8 val) { -#if defined(DEBUG) || !defined(__i386__) +#if !defined(CONFIG_X86EMU_RAW_IO) if (IS_VGA_PORT(port)) VGA_outpb(port, val); else if (IS_TIMER_PORT(port)) @@ -668,7 +694,11 @@ void X86API BE_outb(X86EMU_pioAddr port, u8 val) LOG_outpb(port, val); } else #endif + { + debug_io("outb.%04X <- %02X", (u16) port, val); LOG_outpb(port, val); + debug_io("\n"); + } } /**************************************************************************** @@ -683,19 +713,23 @@ through to the real hardware if we don't need to special case it. ****************************************************************************/ void X86API BE_outw(X86EMU_pioAddr port, u16 val) { -#if defined(DEBUG) || !defined(__i386__) - if (IS_VGA_PORT(port)) { - VGA_outpb(port, val); - VGA_outpb(port + 1, val >> 8); - } else if (IS_PCI_PORT(port)) - PCI_outp(port, val, REG_WRITE_WORD); - else if (port < 0x100) { - DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16) port, - val);) - LOG_outpw(port, val); - } else +#if !defined(CONFIG_X86EMU_RAW_IO) + if (IS_VGA_PORT(port)) { + VGA_outpb(port, val); + VGA_outpb(port + 1, val >> 8); + } else if (IS_PCI_PORT(port)) { + PCI_outp(port, val, REG_WRITE_WORD); + } else if (port < 0x100) { + DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16)port, + val);) + LOG_outpw(port, val); + } else #endif - LOG_outpw(port, val); + { + debug_io("outw.%04X <- %04X", (u16) port, val); + LOG_outpw(port, val); + debug_io("\n"); + } } /**************************************************************************** @@ -710,13 +744,17 @@ through to the real hardware if we don't need to special case it. ****************************************************************************/ void X86API BE_outl(X86EMU_pioAddr port, u32 val) { -#if defined(DEBUG) || !defined(__i386__) - if (IS_PCI_PORT(port)) +#if !defined(CONFIG_X86EMU_RAW_IO) + if (IS_PCI_PORT(port)) { PCI_outp(port, val, REG_WRITE_DWORD); - else if (port < 0x100) { + } else if (port < 0x100) { DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);) LOG_outpd(port, val); } else #endif + { + debug_io("outl.%04X <- %08X", (u16) port, val); LOG_outpd(port, val); + debug_io("\n"); + } } diff --git a/drivers/bios_emulator/bios.c b/drivers/bios_emulator/bios.c index bcc192f..152d70a 100644 --- a/drivers/bios_emulator/bios.c +++ b/drivers/bios_emulator/bios.c @@ -84,14 +84,14 @@ static void X86API int42(int intno) PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8) ~ 0x02); return; } -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG else { printf("int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n", M.x86.R_AL); } #endif } -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG else { printf("int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n", M.x86.R_AH, M.x86.R_AL, M.x86.R_BL); diff --git a/drivers/bios_emulator/biosemui.h b/drivers/bios_emulator/biosemui.h index 8c1f111..7853015 100644 --- a/drivers/bios_emulator/biosemui.h +++ b/drivers/bios_emulator/biosemui.h @@ -48,7 +48,7 @@ #include <asm/io.h> /*---------------------- Macros and type definitions ----------------------*/ -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG #define DB(x) x #else #define DB(x) do{}while(0); diff --git a/drivers/bios_emulator/include/biosemu.h b/drivers/bios_emulator/include/biosemu.h index e92e96e..124d79d 100644 --- a/drivers/bios_emulator/include/biosemu.h +++ b/drivers/bios_emulator/include/biosemu.h @@ -43,6 +43,8 @@ #ifndef __BIOSEMU_H #define __BIOSEMU_H +#include <bios_emul.h> + #ifdef __KERNEL__ #include "x86emu.h" #else @@ -55,57 +57,6 @@ #pragma pack(1) -#ifndef __KERNEL__ -/**************************************************************************** -REMARKS: -Data structure used to describe the details specific to a particular VGA -controller. This information is used to allow the VGA controller to be -swapped on the fly within the BIOS emulator. - -HEADER: -biosemu.h - -MEMBERS: -pciInfo - PCI device information block for the controller -BIOSImage - Pointer to a read/write copy of the BIOS image -BIOSImageLen - Length of the BIOS image -LowMem - Copy of key low memory areas -****************************************************************************/ -typedef struct { - PCIDeviceInfo *pciInfo; - void *BIOSImage; - ulong BIOSImageLen; - uchar LowMem[1536]; -} BE_VGAInfo; -#else -/**************************************************************************** -REMARKS: -Data structure used to describe the details for the BIOS emulator system -environment as used by the X86 emulator library. - -HEADER: -biosemu.h - -MEMBERS: -vgaInfo - VGA BIOS information structure -biosmem_base - Base of the BIOS image -biosmem_limit - Limit of the BIOS image -busmem_base - Base of the VGA bus memory -****************************************************************************/ -typedef struct { - int function; - int device; - int bus; - u32 VendorID; - u32 DeviceID; - pci_dev_t pcidev; - void *BIOSImage; - u32 BIOSImageLen; - u8 LowMem[1536]; -} BE_VGAInfo; - -#endif /* __KERNEL__ */ - #define CRT_C 24 /* 24 CRT Controller Registers */ #define ATT_C 21 /* 21 Attribute Controller Registers */ #define GRA_C 9 /* 9 Graphics Controller Registers */ diff --git a/drivers/bios_emulator/include/x86emu.h b/drivers/bios_emulator/include/x86emu.h index a70a768..b28cdc6 100644 --- a/drivers/bios_emulator/include/x86emu.h +++ b/drivers/bios_emulator/include/x86emu.h @@ -53,9 +53,9 @@ typedef u16 X86EMU_pioAddr; /*---------------------- Macros and type definitions ----------------------*/ -#if defined (CONFIG_ARM) +#if defined(CONFIG_ARM) #define GAS_LINE_COMMENT "@" -#elif defined(CONFIG_MIPS) || defined(CONFIG_PPC) +#elif defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_X86) #define GAS_LINE_COMMENT "#" #elif defined (CONFIG_SH) #define GAS_LINE_COMMENT "!" @@ -153,6 +153,7 @@ extern "C" { /* Use "C" linkage when in C++ mode */ void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs); void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs); void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]); + void X86EMU_setupIntrFunc(int intnum, X86EMU_intrFuncs func); void X86EMU_prepareForInt(int num); /* decode.c */ @@ -160,7 +161,7 @@ extern "C" { /* Use "C" linkage when in C++ mode */ void X86EMU_exec(void); void X86EMU_halt_sys(void); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG #define HALT_SYS() \ printf("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \ X86EMU_halt_sys() diff --git a/drivers/bios_emulator/include/x86emu/debug.h b/drivers/bios_emulator/include/x86emu/debug.h index 268c9d3..304b2bf 100644 --- a/drivers/bios_emulator/include/x86emu/debug.h +++ b/drivers/bios_emulator/include/x86emu/debug.h @@ -48,7 +48,7 @@ #define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */ #define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset */ -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG # define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F) # define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F) # define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F) @@ -60,7 +60,7 @@ # define CHECK_DATA_ACCESS() #endif -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG # define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F) # define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F) # define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F) @@ -99,7 +99,11 @@ # define DEBUG_DECODE_NOPRINT() 0 #endif -#ifdef DEBUG +# define ERR_PRINTF(x) printf(x) +# define ERR_PRINTF2(x, y) printf(x, y) + +#ifdef CONFIG_X86EMU_DEBUG103 + # define DECODE_PRINTF(x) if (DEBUG_DECODE()) \ x86emu_decode_printf(x) @@ -129,7 +133,7 @@ # define SAVE_IP_CS(x,y) #endif -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG #define TRACE_REGS() \ if (DEBUG_DISASSEMBLE()) { \ x86emu_just_disassemble(); \ @@ -140,7 +144,7 @@ # define TRACE_REGS() #endif -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG # define SINGLE_STEP() if (DEBUG_STEP()) x86emu_single_step() #else # define SINGLE_STEP() @@ -150,7 +154,7 @@ TRACE_REGS(); \ SINGLE_STEP() -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG # define START_OF_INSTR() # define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr(); # define END_OF_INSTR_NO_TRACE() x86emu_end_instr(); @@ -160,7 +164,7 @@ # define END_OF_INSTR_NO_TRACE() #endif -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG # define CALL_TRACE(u,v,w,x,s) \ if (DEBUG_TRACECALLREGS()) \ x86emu_dump_regs(); \ @@ -176,7 +180,7 @@ # define RETURN_TRACE(n,u,v) #endif -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG #define DB(x) x #else #define DB(x) diff --git a/drivers/bios_emulator/include/x86emu/regs.h b/drivers/bios_emulator/include/x86emu/regs.h index a7fedd2..2934129 100644 --- a/drivers/bios_emulator/include/x86emu/regs.h +++ b/drivers/bios_emulator/include/x86emu/regs.h @@ -282,7 +282,7 @@ typedef struct { u8 intno; volatile int intr; /* mask of pending interrupts */ int debug; -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG int check; u16 saved_ip; u16 saved_cs; diff --git a/drivers/bios_emulator/x86emu/debug.c b/drivers/bios_emulator/x86emu/debug.c index 2fa8050..27e90e4 100644 --- a/drivers/bios_emulator/x86emu/debug.c +++ b/drivers/bios_emulator/x86emu/debug.c @@ -44,7 +44,7 @@ /*----------------------------- Implementation ----------------------------*/ -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG static void print_encoded_bytes(u16 s, u16 o); static void print_decoded_instruction(void); @@ -211,9 +211,7 @@ void X86EMU_dump_memory(u16 seg, u16 off, u32 amt) u32 start = off & 0xfffffff0; u32 end = (off + 16) & 0xfffffff0; u32 i; - u32 current; - current = start; while (end <= off + amt) { printk("%04x:%04x ", seg, start); for (i = start; i < off; i++) @@ -229,7 +227,7 @@ void X86EMU_dump_memory(u16 seg, u16 off, u32 amt) void x86emu_single_step(void) { char s[1024]; - int ps[10]; + int ps[10]; int ntok; int cmd; int done; @@ -238,8 +236,6 @@ void x86emu_single_step(void) static int breakpoint; static int noDecode = 1; - char *p; - if (DEBUG_BREAK()) { if (M.x86.saved_ip != breakpoint) { return; @@ -255,6 +251,8 @@ void x86emu_single_step(void) offset = M.x86.saved_ip; while (!done) { printk("-"); + ps[1] = 0; /* Avoid dodgy compiler warnings */ + ps[2] = 0; cmd = x86emu_parse_line(s, ps, &ntok); switch (cmd) { case 'u': diff --git a/drivers/bios_emulator/x86emu/decode.c b/drivers/bios_emulator/x86emu/decode.c index a782b81..da44c3d 100644 --- a/drivers/bios_emulator/x86emu/decode.c +++ b/drivers/bios_emulator/x86emu/decode.c @@ -303,7 +303,7 @@ NOTE: Do not inline this function as (*sys_rdX) is already inline! u8 fetch_data_byte( uint offset) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif @@ -322,7 +322,7 @@ NOTE: Do not inline this function as (*sys_rdX) is already inline! u16 fetch_data_word( uint offset) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif @@ -341,7 +341,7 @@ NOTE: Do not inline this function as (*sys_rdX) is already inline! u32 fetch_data_long( uint offset) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif @@ -362,7 +362,7 @@ u8 fetch_data_byte_abs( uint segment, uint offset) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif @@ -383,7 +383,7 @@ u16 fetch_data_word_abs( uint segment, uint offset) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif @@ -404,7 +404,7 @@ u32 fetch_data_long_abs( uint segment, uint offset) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif @@ -426,7 +426,7 @@ void store_data_byte( uint offset, u8 val) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif @@ -448,7 +448,7 @@ void store_data_word( uint offset, u16 val) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif @@ -470,7 +470,7 @@ void store_data_long( uint offset, u32 val) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset); #endif @@ -493,7 +493,7 @@ void store_data_byte_abs( uint offset, u8 val) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif @@ -516,7 +516,7 @@ void store_data_word_abs( uint offset, u16 val) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif @@ -539,7 +539,7 @@ void store_data_long_abs( uint offset, u32 val) { -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset); #endif diff --git a/drivers/bios_emulator/x86emu/ops.c b/drivers/bios_emulator/x86emu/ops.c index f8e093d..2bb5e2d 100644 --- a/drivers/bios_emulator/x86emu/ops.c +++ b/drivers/bios_emulator/x86emu/ops.c @@ -79,7 +79,7 @@ /* constant arrays to do several instructions in just one function */ -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG static char *x86emu_GenOpName[8] = { "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"}; #endif @@ -160,7 +160,7 @@ static u32 (*opcD1_long_operation[])(u32 s, u8 d) = sar_long, }; -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG static char *opF6_names[8] = { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" }; @@ -179,7 +179,7 @@ void x86emuOp_illegal_op( { START_OF_INSTR(); if (M.x86.R_SP != 0) { - DECODE_PRINTF("ILLEGAL X86 OPCODE\n"); + ERR_PRINTF("ILLEGAL X86 OPCODE\n"); TRACE_REGS(); DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n", M.x86.R_CS, M.x86.R_IP-1,op1)); @@ -1281,7 +1281,7 @@ void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -1359,7 +1359,7 @@ void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -1475,7 +1475,7 @@ void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -1551,7 +1551,7 @@ void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -2148,7 +2148,7 @@ void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1)) DECODE_PRINTF("POP\t"); FETCH_DECODE_MODRM(mod, rh, rl); if (rh != 0) { - DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); + ERR_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); HALT_SYS(); } if (mod < 3) { @@ -3083,7 +3083,7 @@ void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -3158,7 +3158,7 @@ void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -3347,7 +3347,7 @@ void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); if (rh != 0) { - DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n"); + ERR_PRINTF("ILLEGAL DECODE OF OPCODE c6\n"); HALT_SYS(); } if (mod < 3) { @@ -3381,7 +3381,7 @@ void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1)) DECODE_PRINTF("MOV\t"); FETCH_DECODE_MODRM(mod, rh, rl); if (rh != 0) { - DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); + ERR_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); HALT_SYS(); } if (mod < 3) { @@ -3630,7 +3630,7 @@ void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -3701,7 +3701,7 @@ void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -3803,7 +3803,7 @@ void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -3876,7 +3876,7 @@ void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1)) */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -3968,7 +3968,7 @@ void x86emuOp_aam(u8 X86EMU_UNUSED(op1)) DECODE_PRINTF("AAM\n"); a = fetch_byte_imm(); /* this is a stupid encoding. */ if (a != 10) { - DECODE_PRINTF("ERROR DECODING AAM\n"); + ERR_PRINTF("ERROR DECODING AAM\n"); TRACE_REGS(); HALT_SYS(); } @@ -4443,7 +4443,7 @@ void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1)) test_byte(destval, srcval); break; case 1: - DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); + ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: @@ -4490,7 +4490,7 @@ void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1)) test_byte(*destreg, srcval); break; case 1: - DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); + ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: @@ -4559,7 +4559,7 @@ void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) test_long(destval, srcval); break; case 1: - DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); + ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); HALT_SYS(); break; case 2: @@ -4611,7 +4611,7 @@ void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) test_word(destval, srcval); break; case 1: - DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); + ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); HALT_SYS(); break; case 2: @@ -4666,7 +4666,7 @@ void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) test_long(*destreg, srcval); break; case 1: - DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); + ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: @@ -4715,7 +4715,7 @@ void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) test_word(*destreg, srcval); break; case 1: - DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); + ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); HALT_SYS(); break; case 2: @@ -4859,7 +4859,7 @@ void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1)) /* Yet another special case instruction. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -4879,7 +4879,7 @@ void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1)) case 5: case 6: case 7: - DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod); + ERR_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x\n", mod); HALT_SYS(); break; } @@ -4923,7 +4923,7 @@ void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) /* Yet another special case instruction. */ START_OF_INSTR(); FETCH_DECODE_MODRM(mod, rh, rl); -#ifdef DEBUG +#ifdef CONFIG_X86EMU_DEBUG if (DEBUG_DECODE()) { /* XXX DECODE_PRINTF may be changed to something more general, so that it is important to leave the strings @@ -4961,7 +4961,7 @@ void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) DECODE_PRINTF("PUSH\t"); break; case 7: - DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t"); + ERR_PRINTF("ILLEGAL DECODING OF OPCODE FF\t"); HALT_SYS(); break; } @@ -5092,7 +5092,7 @@ void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) M.x86.R_IP = *destreg; break; case 3: /* jmp far ptr ... */ - DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); + ERR_PRINTF("OPERATION UNDEFINED 0XFF\n"); TRACE_AND_STEP(); HALT_SYS(); break; @@ -5104,7 +5104,7 @@ void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) M.x86.R_IP = (u16) (*destreg); break; case 5: /* jmp far ptr ... */ - DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); + ERR_PRINTF("OPERATION UNDEFINED 0XFF\n"); TRACE_AND_STEP(); HALT_SYS(); break; diff --git a/drivers/bios_emulator/x86emu/ops2.c b/drivers/bios_emulator/x86emu/ops2.c index 59dbb42..be4ef36 100644 --- a/drivers/bios_emulator/x86emu/ops2.c +++ b/drivers/bios_emulator/x86emu/ops2.c @@ -58,7 +58,7 @@ void x86emuOp2_illegal_op( u8 op2) { START_OF_INSTR(); - DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); + ERR_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); TRACE_REGS(); printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n", M.x86.R_CS, M.x86.R_IP-2,op2); @@ -1089,7 +1089,7 @@ void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2)) DECODE_PRINTF("BTC\t"); break; default: - DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); + ERR_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); TRACE_REGS(); printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n", M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl); diff --git a/drivers/bios_emulator/x86emu/sys.c b/drivers/bios_emulator/x86emu/sys.c index 21f9730..0ba9c0c 100644 --- a/drivers/bios_emulator/x86emu/sys.c +++ b/drivers/bios_emulator/x86emu/sys.c @@ -273,6 +273,11 @@ void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs) sys_outl = funcs->outl; } +void X86EMU_setupIntrFunc(int intnum, X86EMU_intrFuncs func) +{ + _X86EMU_intrTab[intnum] = func; +} + /**************************************************************************** PARAMETERS: funcs - New interrupt vector table to make active diff --git a/drivers/block/pata_bfin.h b/drivers/block/pata_bfin.h index 2093cf0..b678f60 100644 --- a/drivers/block/pata_bfin.h +++ b/drivers/block/pata_bfin.h @@ -43,7 +43,6 @@ struct ata_port { #define DRV_NAME "pata-bfin" #define DRV_VERSION "0.9" -#define __iomem #define ATA_REG_CTRL 0x0E #define ATA_REG_ALTSTATUS ATA_REG_CTRL diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 9e2a4d2..fe8aa98 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -253,22 +253,30 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr) /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */ #if !defined(CONFIG_SYS_FSL_DDR1) +/* + * Check DIMM configuration, return 2 if quad-rank or two dual-rank + * Return 1 if other two slots configuration. Return 0 if single slot. + */ static inline int avoid_odt_overlap(const dimm_params_t *dimm_params) { #if CONFIG_DIMM_SLOTS_PER_CTLR == 1 if (dimm_params[0].n_ranks == 4) - return 1; + return 2; #endif #if CONFIG_DIMM_SLOTS_PER_CTLR == 2 if ((dimm_params[0].n_ranks == 2) && (dimm_params[1].n_ranks == 2)) - return 1; + return 2; #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE if (dimm_params[0].n_ranks == 4) - return 1; + return 2; #endif + + if ((dimm_params[0].n_ranks != 0) && + (dimm_params[2].n_ranks != 0)) + return 1; #endif return 0; } @@ -316,6 +324,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, #elif defined(CONFIG_SYS_FSL_DDR3) unsigned int data_rate = get_ddr_freq(0); int txp; + int odt_overlap; /* * (tXARD and tXARDS). Empirical? * The DDR3 spec has not tXARD, @@ -331,13 +340,23 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, /* set the turnaround time */ /* - * for single quad-rank DIMM and two dual-rank DIMMs + * for single quad-rank DIMM and two-slot DIMMs * to avoid ODT overlap */ - if (avoid_odt_overlap(dimm_params)) { + odt_overlap = avoid_odt_overlap(dimm_params); + switch (odt_overlap) { + case 2: twwt_mclk = 2; trrt_mclk = 1; + break; + case 1: + twwt_mclk = 1; + trrt_mclk = 0; + break; + default: + break; } + /* for faster clock, need more time for data setup */ trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1; @@ -383,7 +402,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, ); debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0); } -#endif /* defined(CONFIG_SYS_FSL_DDR2) */ +#endif /* !defined(CONFIG_SYS_FSL_DDR1) */ /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 2418dca..aaddc8f 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -126,6 +126,12 @@ ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd, { unsigned int retval; int i; + const u8 udimm_rc_e_dq[18] = { + 0x0c, 0x2c, 0x15, 0x35, 0x15, 0x35, 0x0b, 0x2c, 0x15, + 0x35, 0x0b, 0x35, 0x0b, 0x2c, 0x0b, 0x35, 0x15, 0x36 + }; + int spd_error = 0; + u8 *ptr; if (spd->mem_type) { if (spd->mem_type != SPD_MEMTYPE_DDR4) { @@ -179,6 +185,22 @@ ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd, /* Unbuffered DIMMs */ if (spd->mod_section.unbuffered.addr_mapping & 0x1) pdimm->mirrored_dimm = 1; + if ((spd->mod_section.unbuffered.mod_height & 0xe0) == 0 && + (spd->mod_section.unbuffered.ref_raw_card == 0x04)) { + /* Fix SPD error found on DIMMs with raw card E0 */ + for (i = 0; i < 18; i++) { + if (spd->mapping[i] == udimm_rc_e_dq[i]) + continue; + spd_error = 1; + debug("SPD byte %d: 0x%x, should be 0x%x\n", + 60 + i, spd->mapping[i], + udimm_rc_e_dq[i]); + ptr = (u8 *)&spd->mapping[i]; + *ptr = udimm_rc_e_dq[i]; + } + if (spd_error) + puts("SPD DQ mapping error fixed\n"); + } break; default: diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c index d34b749..41cc3b8 100644 --- a/drivers/i2c/i2c_core.c +++ b/drivers/i2c/i2c_core.c @@ -174,11 +174,11 @@ static int i2c_mux_set_all(void) return 0; } -static int i2c_mux_disconnet_all(void) +static int i2c_mux_disconnect_all(void) { struct i2c_bus_hose *i2c_bus_tmp = &i2c_bus[I2C_BUS]; int i; - uint8_t buf; + uint8_t buf = 0; if (I2C_ADAP->init_done == 0) return 0; @@ -197,7 +197,7 @@ static int i2c_mux_disconnet_all(void) ret = I2C_ADAP->write(I2C_ADAP, chip, 0, 0, &buf, 1); if (ret != 0) { - printf("i2c: mux diconnect error\n"); + printf("i2c: mux disconnect error\n"); return ret; } } while (i > 0); @@ -293,7 +293,7 @@ int i2c_set_bus_num(unsigned int bus) } #ifndef CONFIG_SYS_I2C_DIRECT_BUS - i2c_mux_disconnet_all(); + i2c_mux_disconnect_all(); #endif gd->cur_i2c_bus = bus; diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index cb46b13..c55eb28 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -618,7 +618,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) #endif cfg->cfg.f_min = 400000; - cfg->cfg.f_max = min(gd->arch.sdhc_clk, (u32)52000000); + cfg->cfg.f_max = min(cfg->sdhc_clk, (u32)52000000); cfg->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 44a4feb..8436bc7 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1277,6 +1277,11 @@ block_dev_desc_t *mmc_get_dev(int dev) } #endif +/* board-specific MMC power initializations. */ +__weak void board_mmc_power_init(void) +{ +} + int mmc_start_init(struct mmc *mmc) { int err; @@ -1293,6 +1298,8 @@ int mmc_start_init(struct mmc *mmc) if (mmc->has_init) return 0; + board_mmc_power_init(); + /* made sure it's not NULL earlier */ err = mmc->cfg->ops->init(mmc); diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index ffb5284..c880ced 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -135,12 +135,7 @@ static unsigned char mmc_board_init(struct mmc *mmc) pbias_lite = readl(&t2_base->pbias_lite); pbias_lite &= ~(PBIASLITEPWRDNZ1 | PBIASLITEPWRDNZ0); writel(pbias_lite, &t2_base->pbias_lite); -#endif -#if defined(CONFIG_TWL4030_POWER) - twl4030_power_mmc_init(); - mdelay(100); /* ramp-up delay from Linux code */ -#endif -#if defined(CONFIG_OMAP34XX) + writel(pbias_lite | PBIASLITEPWRDNZ1 | PBIASSPEEDCTRL0 | PBIASLITEPWRDNZ0, &t2_base->pbias_lite); @@ -663,7 +658,8 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, case 1: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE; #if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \ - defined(CONFIG_DRA7XX)) && defined(CONFIG_HSMMC2_8BIT) + defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX)) && \ + defined(CONFIG_HSMMC2_8BIT) /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif @@ -672,7 +668,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, #ifdef OMAP_HSMMC3_BASE case 2: priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE; -#if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT) +#if (defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX)) && defined(CONFIG_HSMMC3_8BIT) /* Enable 8-bit interface for eMMC on DRA7XX */ host_caps_val |= MMC_MODE_8BIT; #endif diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index ed83a14..76ba93b 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -103,20 +103,18 @@ static int mmcif_wait_interrupt_flag(struct sh_mmcif_host *host) static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) { - int i; - sh_mmcif_bitclr(CLK_ENABLE, &host->regs->ce_clk_ctrl); sh_mmcif_bitclr(CLK_CLEAR, &host->regs->ce_clk_ctrl); if (!clk) return; - if (clk == CLKDEV_EMMC_DATA) { + + if (clk == CLKDEV_EMMC_DATA) sh_mmcif_bitset(CLK_PCLK, &host->regs->ce_clk_ctrl); - } else { - for (i = 1; (unsigned int)host->clk / (1 << i) >= clk; i++) - ; - sh_mmcif_bitset((i - 1) << 16, &host->regs->ce_clk_ctrl); - } + else + sh_mmcif_bitset((fls(DIV_ROUND_UP(host->clk, + clk) - 1) - 1) << 16, + &host->regs->ce_clk_ctrl); sh_mmcif_bitset(CLK_ENABLE, &host->regs->ce_clk_ctrl); } @@ -581,8 +579,6 @@ static struct mmc_config sh_mmcif_cfg = { .host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC, .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, - .f_min = CLKDEV_MMC_INIT, - .f_max = CLKDEV_EMMC_DATA, .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, }; @@ -599,6 +595,9 @@ int mmcif_mmc_init(void) host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR; host->clk = CONFIG_SH_MMCIF_CLK; + sh_mmcif_cfg.f_min = MMC_CLK_DIV_MIN(host->clk); + sh_mmcif_cfg.f_max = MMC_CLK_DIV_MAX(host->clk); + mmc = mmc_create(&sh_mmcif_cfg, host); if (mmc == NULL) { free(host); diff --git a/drivers/mmc/sh_mmcif.h b/drivers/mmc/sh_mmcif.h index bd6fbf7..4b6752f 100644 --- a/drivers/mmc/sh_mmcif.h +++ b/drivers/mmc/sh_mmcif.h @@ -199,7 +199,13 @@ struct sh_mmcif_regs { #define SOFT_RST_OFF (0 << 31) #define CLKDEV_EMMC_DATA 52000000 /* 52MHz */ -#define CLKDEV_MMC_INIT 400000 /* 100 - 400 KHz */ +#ifdef CONFIG_RMOBILE +#define MMC_CLK_DIV_MIN(clk) (clk / (1 << 9)) +#define MMC_CLK_DIV_MAX(clk) (clk / (1 << 1)) +#else +#define MMC_CLK_DIV_MIN(clk) (clk / (1 << 8)) +#define MMC_CLK_DIV_MAX(clk) CLKDEV_EMMC_DATA +#endif #define MMC_BUS_WIDTH_1 0 #define MMC_BUS_WIDTH_4 2 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 75c2c06..c242214 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -1,9 +1,16 @@ menu "NAND Device Support" +config SYS_NAND_SELF_INIT + bool + help + This option, if enabled, provides more flexible and linux-like + NAND initialization process. + if !SPL_BUILD config NAND_DENALI bool "Support Denali NAND controller" + select SYS_NAND_SELF_INIT help Enable support for the Denali NAND controller. diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 308b784..9e0429a 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -44,7 +44,7 @@ static int onfi_timing_mode = NAND_DEFAULT_TIMINGS; * this macro allows us to convert from an MTD structure to our own * device context (denali) structure. */ -#define mtd_to_denali(m) (((struct nand_chip *)mtd->priv)->priv) +#define mtd_to_denali(m) container_of(m->priv, struct denali_nand_info, nand) /* These constants are defined by the driver to enable common driver * configuration options. */ @@ -1144,70 +1144,128 @@ static void denali_hw_init(struct denali_nand_info *denali) static struct nand_ecclayout nand_oob; -static int denali_nand_init(struct nand_chip *nand) +static int denali_init(struct denali_nand_info *denali) { - struct denali_nand_info *denali; + int ret; - denali = malloc(sizeof(*denali)); - if (!denali) - return -ENOMEM; + denali_hw_init(denali); - nand->priv = denali; + denali->mtd->name = "denali-nand"; + denali->mtd->owner = THIS_MODULE; + denali->mtd->priv = &denali->nand; - denali->flash_reg = (void __iomem *)CONFIG_SYS_NAND_REGS_BASE; - denali->flash_mem = (void __iomem *)CONFIG_SYS_NAND_DATA_BASE; + /* register the driver with the NAND core subsystem */ + denali->nand.select_chip = denali_select_chip; + denali->nand.cmdfunc = denali_cmdfunc; + denali->nand.read_byte = denali_read_byte; + denali->nand.read_buf = denali_read_buf; + denali->nand.waitfunc = denali_waitfunc; + + /* + * scan for NAND devices attached to the controller + * this is the first stage in a two step process to register + * with the nand subsystem + */ + if (nand_scan_ident(denali->mtd, denali->max_banks, NULL)) { + ret = -ENXIO; + goto fail; + } #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT /* check whether flash got BBT table (located at end of flash). As we * use NAND_BBT_NO_OOB, the BBT page will start with * bbt_pattern. We will have mirror pattern too */ - nand->bbt_options |= NAND_BBT_USE_FLASH; + denali->nand.bbt_options |= NAND_BBT_USE_FLASH; /* * We are using main + spare with ECC support. As BBT need ECC support, * we need to ensure BBT code don't write to OOB for the BBT pattern. * All BBT info will be stored into data area with ECC support. */ - nand->bbt_options |= NAND_BBT_NO_OOB; + denali->nand.bbt_options |= NAND_BBT_NO_OOB; #endif - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.size = CONFIG_NAND_DENALI_ECC_SIZE; - nand->ecc.read_oob = denali_read_oob; - nand->ecc.write_oob = denali_write_oob; - nand->ecc.read_page = denali_read_page; - nand->ecc.read_page_raw = denali_read_page_raw; - nand->ecc.write_page = denali_write_page; - nand->ecc.write_page_raw = denali_write_page_raw; + denali->nand.ecc.mode = NAND_ECC_HW; + denali->nand.ecc.size = CONFIG_NAND_DENALI_ECC_SIZE; + /* * Tell driver the ecc strength. This register may be already set * correctly. So we read this value out. */ - nand->ecc.strength = readl(denali->flash_reg + ECC_CORRECTION); - switch (nand->ecc.size) { + denali->nand.ecc.strength = readl(denali->flash_reg + ECC_CORRECTION); + switch (denali->nand.ecc.size) { case 512: - nand->ecc.bytes = (nand->ecc.strength * 13 + 15) / 16 * 2; + denali->nand.ecc.bytes = + (denali->nand.ecc.strength * 13 + 15) / 16 * 2; break; case 1024: - nand->ecc.bytes = (nand->ecc.strength * 14 + 15) / 16 * 2; + denali->nand.ecc.bytes = + (denali->nand.ecc.strength * 14 + 15) / 16 * 2; break; default: pr_err("Unsupported ECC size\n"); - return -EINVAL; + ret = -EINVAL; + goto fail; } - nand_oob.eccbytes = nand->ecc.bytes; - nand->ecc.layout = &nand_oob; - - /* Set address of hardware control function */ - nand->cmdfunc = denali_cmdfunc; - nand->read_byte = denali_read_byte; - nand->read_buf = denali_read_buf; - nand->select_chip = denali_select_chip; - nand->waitfunc = denali_waitfunc; - denali_hw_init(denali); - return 0; + nand_oob.eccbytes = denali->nand.ecc.bytes; + denali->nand.ecc.layout = &nand_oob; + + writel(denali->mtd->erasesize / denali->mtd->writesize, + denali->flash_reg + PAGES_PER_BLOCK); + writel(denali->nand.options & NAND_BUSWIDTH_16 ? 1 : 0, + denali->flash_reg + DEVICE_WIDTH); + writel(denali->mtd->writesize, + denali->flash_reg + DEVICE_MAIN_AREA_SIZE); + writel(denali->mtd->oobsize, + denali->flash_reg + DEVICE_SPARE_AREA_SIZE); + if (readl(denali->flash_reg + DEVICES_CONNECTED) == 0) + writel(1, denali->flash_reg + DEVICES_CONNECTED); + + /* override the default operations */ + denali->nand.ecc.read_page = denali_read_page; + denali->nand.ecc.read_page_raw = denali_read_page_raw; + denali->nand.ecc.write_page = denali_write_page; + denali->nand.ecc.write_page_raw = denali_write_page_raw; + denali->nand.ecc.read_oob = denali_read_oob; + denali->nand.ecc.write_oob = denali_write_oob; + + if (nand_scan_tail(denali->mtd)) { + ret = -ENXIO; + goto fail; + } + + ret = nand_register(0); + +fail: + return ret; +} + +static int __board_nand_init(void) +{ + struct denali_nand_info *denali; + + denali = kzalloc(sizeof(*denali), GFP_KERNEL); + if (!denali) + return -ENOMEM; + + /* + * If CONFIG_SYS_NAND_SELF_INIT is defined, each driver is responsible + * for instantiating struct nand_chip, while drivers/mtd/nand/nand.c + * still provides a "struct mtd_info nand_info" instance. + */ + denali->mtd = &nand_info[0]; + + /* + * In the future, these base addresses should be taken from + * Device Tree or platform data. + */ + denali->flash_reg = (void __iomem *)CONFIG_SYS_NAND_REGS_BASE; + denali->flash_mem = (void __iomem *)CONFIG_SYS_NAND_DATA_BASE; + + return denali_init(denali); } -int board_nand_init(struct nand_chip *chip) +void board_nand_init(void) { - return denali_nand_init(chip); + if (__board_nand_init() < 0) + pr_warn("Failed to initialize Denali NAND controller.\n"); } diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 3277da7..a258df0 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -434,9 +434,8 @@ struct nand_buf { #define DT 3 struct denali_nand_info { - struct mtd_info mtd; - struct nand_chip *nand; - + struct mtd_info *mtd; + struct nand_chip nand; int flash_bank; /* currently selected chip */ int status; int platform; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0b6e7ee..70e780c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -634,6 +634,11 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, { struct nand_chip *chip = mtd->priv; + if (!(chip->options & NAND_BBT_SCANNED)) { + chip->scan_bbt(mtd); + chip->options |= NAND_BBT_SCANNED; + } + if (!chip->bbt) return chip->block_bad(mtd, ofs, getchip); @@ -4322,10 +4327,9 @@ int nand_scan_tail(struct mtd_info *mtd) /* Check, if we should skip the bad block table scan */ if (chip->options & NAND_SKIP_BBTSCAN) - return 0; + chip->options |= NAND_BBT_SCANNED; - /* Build bad block table */ - return chip->scan_bbt(mtd); + return 0; } EXPORT_SYMBOL(nand_scan_tail); diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index 40d6705..93829a4 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -73,14 +73,11 @@ static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd, writeb(cmd, this->IO_ADDR_W); } -#ifdef CONFIG_SPL_BUILD /* Check wait pin as dev ready indicator */ -static int omap_spl_dev_ready(struct mtd_info *mtd) +static int omap_dev_ready(struct mtd_info *mtd) { return gpmc_cfg->status & (1 << 8); } -#endif - /* * gen_true_ecc - This function will generate true ECC value, which @@ -887,7 +884,9 @@ int board_nand_init(struct nand_chip *nand) nand->read_buf = nand_read_buf16; else nand->read_buf = nand_read_buf; - nand->dev_ready = omap_spl_dev_ready; #endif + + nand->dev_ready = omap_dev_ready; + return 0; } diff --git a/drivers/mtd/nand/s3c2410_nand.c b/drivers/mtd/nand/s3c2410_nand.c index db87d07..b3a2a60 100644 --- a/drivers/mtd/nand/s3c2410_nand.c +++ b/drivers/mtd/nand/s3c2410_nand.c @@ -38,10 +38,10 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) } #endif -static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void s3c24x0_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *chip = mtd->priv; - struct s3c2410_nand *nand = s3c2410_get_base_nand(); + struct s3c24x0_nand *nand = s3c24x0_get_base_nand(); debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl); @@ -67,35 +67,35 @@ static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) writeb(cmd, chip->IO_ADDR_W); } -static int s3c2410_dev_ready(struct mtd_info *mtd) +static int s3c24x0_dev_ready(struct mtd_info *mtd) { - struct s3c2410_nand *nand = s3c2410_get_base_nand(); + struct s3c24x0_nand *nand = s3c24x0_get_base_nand(); debug("dev_ready\n"); return readl(&nand->nfstat) & 0x01; } #ifdef CONFIG_S3C2410_NAND_HWECC -void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode) +void s3c24x0_nand_enable_hwecc(struct mtd_info *mtd, int mode) { - struct s3c2410_nand *nand = s3c2410_get_base_nand(); - debug("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode); + struct s3c24x0_nand *nand = s3c24x0_get_base_nand(); + debug("s3c24x0_nand_enable_hwecc(%p, %d)\n", mtd, mode); writel(readl(&nand->nfconf) | S3C2410_NFCONF_INITECC, &nand->nfconf); } -static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, +static int s3c24x0_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { - struct s3c2410_nand *nand = s3c2410_get_base_nand(); + struct s3c24x0_nand *nand = s3c24x0_get_base_nand(); ecc_code[0] = readb(&nand->nfecc); ecc_code[1] = readb(&nand->nfecc + 1); ecc_code[2] = readb(&nand->nfecc + 2); - debug("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n", - mtd , ecc_code[0], ecc_code[1], ecc_code[2]); + debug("s3c24x0_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n", + mtd , ecc_code[0], ecc_code[1], ecc_code[2]); return 0; } -static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, +static int s3c24x0_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { if (read_ecc[0] == calc_ecc[0] && @@ -103,7 +103,7 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, read_ecc[2] == calc_ecc[2]) return 0; - printf("s3c2410_nand_correct_data: not implemented\n"); + printf("s3c24x0_nand_correct_data: not implemented\n"); return -1; } #endif @@ -113,7 +113,7 @@ int board_nand_init(struct nand_chip *nand) u_int32_t cfg; u_int8_t tacls, twrph0, twrph1; struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - struct s3c2410_nand *nand_reg = s3c2410_get_base_nand(); + struct s3c24x0_nand *nand_reg = s3c24x0_get_base_nand(); debug("board_nand_init()\n"); @@ -149,14 +149,14 @@ int board_nand_init(struct nand_chip *nand) #endif /* hwcontrol always must be implemented */ - nand->cmd_ctrl = s3c2410_hwcontrol; + nand->cmd_ctrl = s3c24x0_hwcontrol; - nand->dev_ready = s3c2410_dev_ready; + nand->dev_ready = s3c24x0_dev_ready; #ifdef CONFIG_S3C2410_NAND_HWECC - nand->ecc.hwctl = s3c2410_nand_enable_hwecc; - nand->ecc.calculate = s3c2410_nand_calculate_ecc; - nand->ecc.correct = s3c2410_nand_correct_data; + nand->ecc.hwctl = s3c24x0_nand_enable_hwecc; + nand->ecc.calculate = s3c24x0_nand_calculate_ecc; + nand->ecc.correct = s3c24x0_nand_correct_data; nand->ecc.mode = NAND_ECC_HW; nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 7feb3a7..928d58b 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -611,6 +611,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); } + /* Disable subpage writes as we do not provide ecc->hwctl */ + chip->options |= NAND_NO_SUBPAGE_WRITE; + chip->dev_ready = vf610_nfc_dev_ready; chip->cmdfunc = vf610_nfc_command; chip->read_byte = vf610_nfc_read_byte; diff --git a/drivers/net/fm/Makefile b/drivers/net/fm/Makefile index 5ae3b16..d052fcb 100644 --- a/drivers/net/fm/Makefile +++ b/drivers/net/fm/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_PPC_T1040) += t1040.o obj-$(CONFIG_PPC_T1042) += t1040.o obj-$(CONFIG_PPC_T1020) += t1040.o obj-$(CONFIG_PPC_T1022) += t1040.o +obj-$(CONFIG_PPC_T1023) += t1024.o +obj-$(CONFIG_PPC_T1024) += t1024.o obj-$(CONFIG_PPC_T2080) += t2080.o obj-$(CONFIG_PPC_T2081) += t2080.o obj-$(CONFIG_PPC_T4240) += t4240.o diff --git a/drivers/net/fm/b4860.c b/drivers/net/fm/b4860.c index 373cc4f..eb058c9 100644 --- a/drivers/net/fm/b4860.c +++ b/drivers/net/fm/b4860.c @@ -10,6 +10,7 @@ #include <asm/io.h> #include <asm/immap_85xx.h> #include <asm/fsl_serdes.h> +#include <hwconfig.h> u32 port_to_devdisr[] = { [FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1, @@ -46,15 +47,76 @@ void fman_enable_port(enum fm_port port) phy_interface_t fman_port_enet_if(enum fm_port port) { +#if defined(CONFIG_B4860QDS) + u32 serdes2_prtcl; + char buffer[HWCONFIG_BUFFER_SIZE]; + char *buf = NULL; + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); +#endif + if (is_device_disabled(port)) return PHY_INTERFACE_MODE_NONE; /*B4860 has two 10Gig Mac*/ if ((port == FM1_10GEC1 || port == FM1_10GEC2) && ((is_serdes_configured(XAUI_FM1_MAC9)) || - (is_serdes_configured(XAUI_FM1_MAC10)))) + #if !defined(CONFIG_B4860QDS) + (is_serdes_configured(XFI_FM1_MAC9)) || + (is_serdes_configured(XFI_FM1_MAC10)) || + #endif + (is_serdes_configured(XAUI_FM1_MAC10)) + )) return PHY_INTERFACE_MODE_XGMII; +#if defined(CONFIG_B4860QDS) + serdes2_prtcl = in_be32(&gur->rcwsr[4]) & + FSL_CORENET2_RCWSR4_SRDS2_PRTCL; + + if (serdes2_prtcl) { + serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; + switch (serdes2_prtcl) { + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + case 0x8c: + case 0x8d: + case 0x8e: + case 0xb1: + case 0xb2: + /* + * Extract hwconfig from environment since environment + * is not setup yet + */ + getenv_f("hwconfig", buffer, sizeof(buffer)); + buf = buffer; + + /* check if XFI interface enable in hwconfig for 10g */ + if (hwconfig_subarg_cmp_f("fsl_b4860_serdes2", + "sfp_amc", "sfp", buf)) { + if ((port == FM1_10GEC1 || + port == FM1_10GEC2) && + ((is_serdes_configured(XFI_FM1_MAC9)) || + (is_serdes_configured(XFI_FM1_MAC10)))) + return PHY_INTERFACE_MODE_XGMII; + else if ((port == FM1_DTSEC1) || + (port == FM1_DTSEC2) || + (port == FM1_DTSEC3) || + (port == FM1_DTSEC4)) + return PHY_INTERFACE_MODE_NONE; + } + } + } +#endif + /* Fix me need to handle RGMII here first */ switch (port) { diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 218a5ed..f1e39b9 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -39,9 +39,14 @@ static void dtsec_configure_serdes(struct fm_eth *priv) u32 value; struct mii_dev bus; bus.priv = priv->mac->phyregs; + bool sgmii_2500 = (priv->enet_if == + PHY_INTERFACE_MODE_SGMII_2500) ? true : false; + + /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */ + value = PHY_SGMII_IF_MODE_SGMII; + if (!sgmii_2500) + value |= PHY_SGMII_IF_MODE_AN; - /* SGMII IF mode + AN enable */ - value = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII; memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value); /* Dev ability according to SGMII specification */ @@ -54,7 +59,9 @@ static void dtsec_configure_serdes(struct fm_eth *priv) memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xd40); /* Restart AN */ - value = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN; + value = PHY_SGMII_CR_DEF_VAL; + if (!sgmii_2500) + value |= PHY_SGMII_CR_RESET_AN; memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0, value); #else struct dtsec *regs = priv->mac->base; @@ -83,7 +90,8 @@ static void dtsec_init_phy(struct eth_device *dev) out_be32(®s->tbipa, CONFIG_SYS_TBIPA_VALUE); #endif - if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII) + if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII || + fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII_2500) dtsec_configure_serdes(fm_eth); } @@ -557,9 +565,11 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) num = fm_eth->num; #ifdef CONFIG_SYS_FMAN_V3 +#ifndef CONFIG_FSL_FM_10GEC_REGULAR_NOTATION if (fm_eth->type == FM_ETH_10G_E) { - /* 10GEC1/10GEC2 use mEMAC9/mEMAC10 - * 10GEC3/10GEC4 use mEMAC1/mEMAC2 + /* 10GEC1/10GEC2 use mEMAC9/mEMAC10 on T2080/T4240. + * 10GEC3/10GEC4 use mEMAC1/mEMAC2 on T2080. + * 10GEC1 uses mEMAC1 on T1024. * so it needs to change the num. */ if (fm_eth->num >= 2) @@ -567,6 +577,7 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) else num += 8; } +#endif base = ®->memac[num].fm_memac; phyregs = ®->memac[num].fm_memac_mdio; #else diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c index 6cf21c6..5d82f29 100644 --- a/drivers/net/fm/init.c +++ b/drivers/net/fm/init.c @@ -254,8 +254,10 @@ static void ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop) */ if (((info->port == FM1_DTSEC9) && (PORT_IS_ENABLED(FM1_10GEC1))) || ((info->port == FM1_DTSEC10) && (PORT_IS_ENABLED(FM1_10GEC2))) || + ((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC1))) || ((info->port == FM1_DTSEC1) && (PORT_IS_ENABLED(FM1_10GEC3))) || ((info->port == FM1_DTSEC2) && (PORT_IS_ENABLED(FM1_10GEC4))) || + ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC1))) || ((info->port == FM1_10GEC1) && (PORT_IS_ENABLED(FM1_DTSEC9))) || ((info->port == FM1_10GEC2) && (PORT_IS_ENABLED(FM1_DTSEC10))) || ((info->port == FM1_10GEC3) && (PORT_IS_ENABLED(FM1_DTSEC1))) || diff --git a/drivers/net/fm/t1024.c b/drivers/net/fm/t1024.c new file mode 100644 index 0000000..9b31173 --- /dev/null +++ b/drivers/net/fm/t1024.c @@ -0,0 +1,88 @@ +/* Copyright 2014 Freescale Semiconductor, Inc. + * + * Shengzhou Liu <Shengzhou.Liu@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <phy.h> +#include <fm_eth.h> +#include <asm/immap_85xx.h> +#include <asm/fsl_serdes.h> + +u32 port_to_devdisr[] = { + [FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1, + [FM1_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC1_2, + [FM1_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC1_3, + [FM1_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC1_4, + [FM1_10GEC1] = FSL_CORENET_DEVDISR2_10GEC1_1, /* MAC1 */ +}; + +static int is_device_disabled(enum fm_port port) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 devdisr2 = in_be32(&gur->devdisr2); + + return port_to_devdisr[port] & devdisr2; +} + +void fman_disable_port(enum fm_port port) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + + setbits_be32(&gur->devdisr2, port_to_devdisr[port]); +} + +phy_interface_t fman_port_enet_if(enum fm_port port) +{ + ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 rcwsr13 = in_be32(&gur->rcwsr[13]); + + if (is_device_disabled(port)) + return PHY_INTERFACE_MODE_NONE; + + if ((port == FM1_10GEC1) && (is_serdes_configured(XFI_FM1_MAC1))) + return PHY_INTERFACE_MODE_XGMII; + + if ((port == FM1_DTSEC3) && ((rcwsr13 & FSL_CORENET_RCWSR13_EC2) == + FSL_CORENET_RCWSR13_EC2_RGMII) && + (!is_serdes_configured(QSGMII_FM1_A))) + return PHY_INTERFACE_MODE_RGMII; + + if ((port == FM1_DTSEC4) && ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == + FSL_CORENET_RCWSR13_EC1_RGMII) && + (!is_serdes_configured(QSGMII_FM1_A))) + return PHY_INTERFACE_MODE_RGMII; + + /* handle SGMII */ + switch (port) { + case FM1_DTSEC1: + case FM1_DTSEC2: + case FM1_DTSEC3: + if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1)) + return PHY_INTERFACE_MODE_SGMII; + else if (is_serdes_configured(SGMII_2500_FM1_DTSEC1 + + port - FM1_DTSEC1)) + return PHY_INTERFACE_MODE_SGMII_2500; + break; + default: + break; + } + + /* handle QSGMII */ + switch (port) { + case FM1_DTSEC1: + case FM1_DTSEC2: + case FM1_DTSEC3: + case FM1_DTSEC4: + /* check lane A on SerDes1 */ + if (is_serdes_configured(QSGMII_FM1_A)) + return PHY_INTERFACE_MODE_QSGMII; + break; + default: + break; + } + + return PHY_INTERFACE_MODE_NONE; +} diff --git a/drivers/net/fm/t1040.c b/drivers/net/fm/t1040.c index 4cce46d..d2a097e 100644 --- a/drivers/net/fm/t1040.c +++ b/drivers/net/fm/t1040.c @@ -25,8 +25,6 @@ phy_interface_t fman_port_enet_if(enum fm_port port) else if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_MII) return PHY_INTERFACE_MODE_MII; - else - return PHY_INTERFACE_MODE_NONE; } if ((port == FM1_DTSEC4) && @@ -38,8 +36,6 @@ phy_interface_t fman_port_enet_if(enum fm_port port) else if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_MII) return PHY_INTERFACE_MODE_MII; - else - return PHY_INTERFACE_MODE_NONE; } if (port == FM1_DTSEC5) { diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 9556536..f46bf00 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_PHYLIB) += phy.o obj-$(CONFIG_PHYLIB_10G) += generic_10g.o obj-$(CONFIG_PHY_ATHEROS) += atheros.o obj-$(CONFIG_PHY_BROADCOM) += broadcom.o +obj-$(CONFIG_PHY_CORTINA) += cortina.o obj-$(CONFIG_PHY_DAVICOM) += davicom.o obj-$(CONFIG_PHY_ET1011C) += et1011c.o obj-$(CONFIG_PHY_LXT) += lxt.o diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c new file mode 100644 index 0000000..254f056 --- /dev/null +++ b/drivers/net/phy/cortina.c @@ -0,0 +1,333 @@ +/* + * Cortina CS4315/CS4340 10G PHY drivers + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Copyright 2014 Freescale Semiconductor, Inc. + * + */ + +#include <config.h> +#include <common.h> +#include <malloc.h> +#include <linux/ctype.h> +#include <linux/string.h> +#include <linux/err.h> +#include <phy.h> +#include <cortina.h> +#ifdef CONFIG_SYS_CORTINA_FW_IN_NAND +#include <nand.h> +#elif defined(CONFIG_SYS_CORTINA_FW_IN_SPIFLASH) +#include <spi_flash.h> +#elif defined(CONFIG_SYS_CORTINA_FW_IN_MMC) +#include <mmc.h> +#endif + +#ifndef CONFIG_PHYLIB_10G +#error The Cortina PHY needs 10G support +#endif + +struct cortina_reg_config cortina_reg_cfg[] = { + /* CS4315_enable_sr_mode */ + {VILLA_GLOBAL_MSEQCLKCTRL, 0x8004}, + {VILLA_MSEQ_OPTIONS, 0xf}, + {VILLA_MSEQ_PC, 0x0}, + {VILLA_MSEQ_BANKSELECT, 0x4}, + {VILLA_LINE_SDS_COMMON_SRX0_RX_CPA, 0x55}, + {VILLA_LINE_SDS_COMMON_SRX0_RX_LOOP_FILTER, 0x30}, + {VILLA_DSP_SDS_SERDES_SRX_DFE0_SELECT, 0x1}, + {VILLA_DSP_SDS_DSP_COEF_DFE0_SELECT, 0x2}, + {VILLA_LINE_SDS_COMMON_SRX0_RX_CPB, 0x2003}, + {VILLA_DSP_SDS_SERDES_SRX_FFE_DELAY_CTRL, 0xF047}, + {VILLA_MSEQ_ENABLE_MSB, 0x0000}, + {VILLA_MSEQ_SPARE21_LSB, 0x6}, + {VILLA_MSEQ_RESET_COUNT_LSB, 0x0}, + {VILLA_MSEQ_SPARE12_MSB, 0x0000}, + /* + * to invert the receiver path, uncomment the next line + * write (VILLA_MSEQ_SPARE12_MSB, 0x4000) + * + * SPARE2_LSB is used to configure the device while in sr mode to + * enable power savings and to use the optical module LOS signal. + * in power savings mode, the internal prbs checker can not be used. + * if the optical module LOS signal is used as an input to the micro + * code, then the micro code will wait until the optical module + * LOS = 0 before turning on the adaptive equalizer. + * Setting SPARE2_LSB bit 0 to 1 places the devie in power savings mode + * while setting bit 0 to 0 disables power savings mode. + * Setting SPARE2_LSB bit 2 to 0 configures the device to use the + * optical module LOS signal while setting bit 2 to 1 configures the + * device so that it will ignore the optical module LOS SPARE2_LSB = 0 + */ + + /* enable power savings, ignore optical module LOS */ + {VILLA_MSEQ_SPARE2_LSB, 0x5}, + + {VILLA_MSEQ_SPARE7_LSB, 0x1e}, + {VILLA_MSEQ_BANKSELECT, 0x4}, + {VILLA_MSEQ_SPARE9_LSB, 0x2}, + {VILLA_MSEQ_SPARE3_LSB, 0x0F53}, + {VILLA_MSEQ_SPARE3_MSB, 0x2006}, + {VILLA_MSEQ_SPARE8_LSB, 0x3FF7}, + {VILLA_MSEQ_SPARE8_MSB, 0x0A46}, + {VILLA_MSEQ_COEF8_FFE0_LSB, 0xD500}, + {VILLA_MSEQ_COEF8_FFE1_LSB, 0x0200}, + {VILLA_MSEQ_COEF8_FFE2_LSB, 0xBA00}, + {VILLA_MSEQ_COEF8_FFE3_LSB, 0x0100}, + {VILLA_MSEQ_COEF8_FFE4_LSB, 0x0300}, + {VILLA_MSEQ_COEF8_FFE5_LSB, 0x0300}, + {VILLA_MSEQ_COEF8_DFE0_LSB, 0x0700}, + {VILLA_MSEQ_COEF8_DFE0N_LSB, 0x0E00}, + {VILLA_MSEQ_COEF8_DFE1_LSB, 0x0B00}, + {VILLA_DSP_SDS_DSP_COEF_LARGE_LEAK, 0x2}, + {VILLA_DSP_SDS_SERDES_SRX_DAC_ENABLEB_LSB, 0xD000}, + {VILLA_MSEQ_POWER_DOWN_LSB, 0xFFFF}, + {VILLA_MSEQ_POWER_DOWN_MSB, 0x0}, + {VILLA_MSEQ_CAL_RX_SLICER, 0x80}, + {VILLA_DSP_SDS_SERDES_SRX_DAC_BIAS_SELECT1_MSB, 0x3f}, + {VILLA_GLOBAL_MSEQCLKCTRL, 0x4}, + {VILLA_MSEQ_OPTIONS, 0x7}, + + /* set up min value for ffe1 */ + {VILLA_MSEQ_COEF_INIT_SEL, 0x2}, + {VILLA_DSP_SDS_DSP_PRECODEDINITFFE21, 0x41}, + + /* CS4315_sr_rx_pre_eq_set_4in */ + {VILLA_GLOBAL_MSEQCLKCTRL, 0x8004}, + {VILLA_MSEQ_OPTIONS, 0xf}, + {VILLA_MSEQ_BANKSELECT, 0x4}, + {VILLA_MSEQ_PC, 0x0}, + + /* for lengths from 3.5 to 4.5inches */ + {VILLA_MSEQ_SERDES_PARAM_LSB, 0x0306}, + {VILLA_MSEQ_SPARE25_LSB, 0x0306}, + {VILLA_MSEQ_SPARE21_LSB, 0x2}, + {VILLA_MSEQ_SPARE23_LSB, 0x2}, + {VILLA_MSEQ_CAL_RX_DFE_EQ, 0x0}, + + {VILLA_GLOBAL_MSEQCLKCTRL, 0x4}, + {VILLA_MSEQ_OPTIONS, 0x7}, + + /* CS4315_rx_drive_4inch */ + /* for length 4inches */ + {VILLA_GLOBAL_VILLA2_COMPATIBLE, 0x0000}, + {VILLA_HOST_SDS_COMMON_STX0_TX_OUTPUT_CTRLA, 0x3023}, + {VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLB, 0xc01E}, + + /* CS4315_tx_drive_4inch */ + /* for length 4inches */ + {VILLA_GLOBAL_VILLA2_COMPATIBLE, 0x0000}, + {VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLA, 0x3023}, + {VILLA_LINE_SDS_COMMON_STX0_TX_OUTPUT_CTRLB, 0xc01E}, +}; + +void cs4340_upload_firmware(struct phy_device *phydev) +{ + char line_temp[0x50] = {0}; + char reg_addr[0x50] = {0}; + char reg_data[0x50] = {0}; + int i, line_cnt = 0, column_cnt = 0; + struct cortina_reg_config fw_temp; + char *addr = NULL; + +#if defined(CONFIG_SYS_CORTINA_FW_IN_NOR) || \ + defined(CONFIG_SYS_CORTINA_FW_IN_REMOTE) + + addr = (char *)CONFIG_CORTINA_FW_ADDR; +#elif defined(CONFIG_SYS_CORTINA_FW_IN_NAND) + int ret; + size_t fw_length = CONFIG_CORTINA_FW_LENGTH; + + addr = malloc(CONFIG_CORTINA_FW_LENGTH); + ret = nand_read(&nand_info[0], (loff_t)CONFIG_CORTINA_FW_ADDR, + &fw_length, (u_char *)addr); + if (ret == -EUCLEAN) { + printf("NAND read of Cortina firmware at 0x%x failed %d\n", + CONFIG_CORTINA_FW_ADDR, ret); + } +#elif defined(CONFIG_SYS_CORTINA_FW_IN_SPIFLASH) + int ret; + struct spi_flash *ucode_flash; + + addr = malloc(CONFIG_CORTINA_FW_LENGTH); + ucode_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, + CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); + if (!ucode_flash) { + puts("SF: probe for Cortina ucode failed\n"); + } else { + ret = spi_flash_read(ucode_flash, CONFIG_CORTINA_FW_ADDR, + CONFIG_CORTINA_FW_LENGTH, addr); + if (ret) + puts("SF: read for Cortina ucode failed\n"); + spi_flash_free(ucode_flash); + } +#elif defined(CONFIG_SYS_CORTINA_FW_IN_MMC) + int dev = CONFIG_SYS_MMC_ENV_DEV; + u32 cnt = CONFIG_CORTINA_FW_LENGTH / 512; + u32 blk = CONFIG_CORTINA_FW_ADDR / 512; + struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); + + if (!mmc) { + puts("Failed to find MMC device for Cortina ucode\n"); + } else { + addr = malloc(CONFIG_CORTINA_FW_LENGTH); + printf("MMC read: dev # %u, block # %u, count %u ...\n", + dev, blk, cnt); + mmc_init(mmc); + (void)mmc->block_dev.block_read(dev, blk, cnt, addr); + /* flush cache after read */ + flush_cache((ulong)addr, cnt * 512); + } +#endif + + while (*addr != 'Q') { + i = 0; + + while (*addr != 0x0a) { + line_temp[i++] = *addr++; + if (0x50 < i) { + printf("Not found Cortina PHY ucode at 0x%x\n", + CONFIG_CORTINA_FW_ADDR); + return; + } + } + + addr++; /* skip '\n' */ + line_cnt++; + column_cnt = i; + line_temp[column_cnt] = '\0'; + + if (CONFIG_CORTINA_FW_LENGTH < line_cnt) + return; + + for (i = 0; i < column_cnt; i++) { + if (isspace(line_temp[i++])) + break; + } + + memcpy(reg_addr, line_temp, i); + memcpy(reg_data, &line_temp[i], column_cnt - i); + strim(reg_addr); + strim(reg_data); + fw_temp.reg_addr = (simple_strtoul(reg_addr, NULL, 0)) & 0xffff; + fw_temp.reg_value = (simple_strtoul(reg_data, NULL, 0)) & + 0xffff; + phy_write(phydev, 0x00, fw_temp.reg_addr, fw_temp.reg_value); + } +} + +int cs4340_phy_init(struct phy_device *phydev) +{ + int timeout = 100; /* 100ms */ + int reg_value; + + /* step1: BIST test */ + phy_write(phydev, 0x00, VILLA_GLOBAL_MSEQCLKCTRL, 0x0004); + phy_write(phydev, 0x00, VILLA_GLOBAL_LINE_SOFT_RESET, 0x0000); + phy_write(phydev, 0x00, VILLA_GLOBAL_BIST_CONTROL, 0x0001); + while (--timeout) { + reg_value = phy_read(phydev, 0x00, VILLA_GLOBAL_BIST_STATUS); + if (reg_value & mseq_edc_bist_done) { + if (0 == (reg_value & mseq_edc_bist_fail)) + break; + } + udelay(1000); + } + + if (!timeout) { + printf("%s BIST mseq_edc_bist_done timeout!\n", __func__); + return -1; + } + + /* setp2: upload ucode */ + cs4340_upload_firmware(phydev); + reg_value = phy_read(phydev, 0x00, VILLA_GLOBAL_DWNLD_CHECKSUM_STATUS); + if (reg_value) { + debug("%s checksum status failed.\n", __func__); + return -1; + } + + return 0; +} + +int cs4340_config(struct phy_device *phydev) +{ + cs4340_phy_init(phydev); + return 0; +} + +int cs4340_startup(struct phy_device *phydev) +{ + phydev->link = 1; + + /* For now just lie and say it's 10G all the time */ + phydev->speed = SPEED_10000; + phydev->duplex = DUPLEX_FULL; + return 0; +} + +struct phy_driver cs4340_driver = { + .name = "Cortina CS4315/CS4340", + .uid = PHY_UID_CS4340, + .mask = 0xfffffff0, + .features = PHY_10G_FEATURES, + .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS | MDIO_DEVS_AN | + MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2), + .config = &cs4340_config, + .startup = &cs4340_startup, + .shutdown = &gen10g_shutdown, +}; + +int phy_cortina_init(void) +{ + phy_register(&cs4340_driver); + return 0; +} + +int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id) +{ + int phy_reg; + bool is_cortina_phy = false; + + switch (addr) { +#ifdef CORTINA_PHY_ADDR1 + case CORTINA_PHY_ADDR1: +#endif +#ifdef CORTINA_PHY_ADDR2 + case CORTINA_PHY_ADDR2: +#endif +#ifdef CORTINA_PHY_ADDR3 + case CORTINA_PHY_ADDR3: +#endif +#ifdef CORTINA_PHY_ADDR4 + case CORTINA_PHY_ADDR4: +#endif + is_cortina_phy = true; + break; + default: + break; + } + + /* Cortina PHY has non-standard offset of PHY ID registers */ + if (is_cortina_phy) + phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_LSB); + else + phy_reg = bus->read(bus, addr, devad, MII_PHYSID1); + + if (phy_reg < 0) + return -EIO; + + *phy_id = (phy_reg & 0xffff) << 16; + if (is_cortina_phy) + phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_MSB); + else + phy_reg = bus->read(bus, addr, devad, MII_PHYSID2); + + if (phy_reg < 0) + return -EIO; + + *phy_id |= (phy_reg & 0xffff); + + return 0; +} diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 467c972..5b04c85 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -448,6 +448,9 @@ int phy_init(void) #ifdef CONFIG_PHY_BROADCOM phy_broadcom_init(); #endif +#ifdef CONFIG_PHY_CORTINA + phy_cortina_init(); +#endif #ifdef CONFIG_PHY_DAVICOM phy_davicom_init(); #endif diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 2b29cd8..20a6746 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -1,8 +1,8 @@ /* * Vitesse PHY drivers * - * Copyright 2010-2012 Freescale Semiconductor, Inc. - * Author: Andy Fleming + * Copyright 2010-2014 Freescale Semiconductor, Inc. + * Original Author: Andy Fleming * Add vsc8662 phy support - Priyanka Jain * SPDX-License-Identifier: GPL-2.0+ */ @@ -50,6 +50,7 @@ #define MIIM_VSC8574_18G_CMDSTAT 0x8000 /* Vitesse VSC8514 control register */ +#define MIIM_VSC8514_MAC_SERDES_CON 0x10 #define MIIM_VSC8514_GENERAL18 0x12 #define MIIM_VSC8514_GENERAL19 0x13 #define MIIM_VSC8514_GENERAL23 0x17 @@ -246,6 +247,14 @@ static int vsc8514_config(struct phy_device *phydev) val = (val & 0xf8ff); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val); + /* Enable Serdes Auto-negotiation */ + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, + PHY_EXT_PAGE_ACCESS_EXTENDED3); + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON); + val = val | MIIM_VSC8574_MAC_SERDES_ANEG; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON, val); + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); + genphy_config_aneg(phydev); return 0; diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index e73a498..55d6a9b 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -6,7 +6,7 @@ # obj-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o -obj-$(CONFIG_PCI) += pci.o pci_auto.o +obj-$(CONFIG_PCI) += pci.o pci_auto.o pci_rom.o obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o obj-$(CONFIG_PCI_GT64120) += pci_gt64120.o obj-$(CONFIG_PCI_MSC01) += pci_msc01.o diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7ee21d1..3daf73c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -366,9 +366,27 @@ phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, return phys_addr; } -/* - * - */ +void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum, + u32 addr_and_ctrl) +{ + int bar; + + bar = PCI_BASE_ADDRESS_0 + barnum * 4; + pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl); +} + +u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum) +{ + u32 addr; + int bar; + + bar = PCI_BASE_ADDRESS_0 + barnum * 4; + pci_hose_read_config_dword(hose, dev, bar, &addr); + if (addr & PCI_BASE_ADDRESS_SPACE_IO) + return addr & PCI_BASE_ADDRESS_IO_MASK; + else + return addr & PCI_BASE_ADDRESS_MEM_MASK; +} int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev, diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c new file mode 100644 index 0000000..af6a3ae --- /dev/null +++ b/drivers/pci/pci_rom.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2014 Google, Inc + * + * From coreboot, originally based on the Linux kernel (drivers/pci/pci.c). + * + * Modifications are: + * Copyright (C) 2003-2004 Linux Networx + * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx) + * Copyright (C) 2003-2006 Ronald G. Minnich <rminnich@gmail.com> + * Copyright (C) 2004-2005 Li-Ta Lo <ollie@lanl.gov> + * Copyright (C) 2005-2006 Tyan + * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan) + * Copyright (C) 2005-2009 coresystems GmbH + * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH) + * + * PCI Bus Services, see include/linux/pci.h for further explanation. + * + * Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter, + * David Mosberger-Tang + * + * Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> + + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <bios_emul.h> +#include <errno.h> +#include <malloc.h> +#include <pci.h> +#include <pci_rom.h> +#include <vbe.h> +#include <video_fb.h> + +#ifdef CONFIG_HAVE_ACPI_RESUME +#include <asm/acpi.h> +#endif + +__weak bool board_should_run_oprom(pci_dev_t dev) +{ + return true; +} + +static bool should_load_oprom(pci_dev_t dev) +{ +#ifdef CONFIG_HAVE_ACPI_RESUME + if (acpi_get_slp_type() == 3) + return false; +#endif + if (IS_ENABLED(CONFIG_ALWAYS_LOAD_OPROM)) + return 1; + if (board_should_run_oprom(dev)) + return 1; + + return 0; +} + +__weak uint32_t board_map_oprom_vendev(uint32_t vendev) +{ + return vendev; +} + +static int pci_rom_probe(pci_dev_t dev, uint class, + struct pci_rom_header **hdrp) +{ + struct pci_rom_header *rom_header; + struct pci_rom_data *rom_data; + u16 vendor, device; + u32 vendev; + u32 mapped_vendev; + u32 rom_address; + + pci_read_config_word(dev, PCI_VENDOR_ID, &vendor); + pci_read_config_word(dev, PCI_DEVICE_ID, &device); + vendev = vendor << 16 | device; + mapped_vendev = board_map_oprom_vendev(vendev); + if (vendev != mapped_vendev) + debug("Device ID mapped to %#08x\n", mapped_vendev); + +#ifdef CONFIG_X86_OPTION_ROM_ADDR + rom_address = CONFIG_X86_OPTION_ROM_ADDR; +#else + pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK); + pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address); + if (rom_address == 0x00000000 || rom_address == 0xffffffff) { + debug("%s: rom_address=%x\n", __func__, rom_address); + return -ENOENT; + } + + /* Enable expansion ROM address decoding. */ + pci_write_config_dword(dev, PCI_ROM_ADDRESS, + rom_address | PCI_ROM_ADDRESS_ENABLE); +#endif + debug("Option ROM address %x\n", rom_address); + rom_header = (struct pci_rom_header *)rom_address; + + debug("PCI expansion ROM, signature %#04x, INIT size %#04x, data ptr %#04x\n", + le32_to_cpu(rom_header->signature), + rom_header->size * 512, le32_to_cpu(rom_header->data)); + + if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) { + printf("Incorrect expansion ROM header signature %04x\n", + le32_to_cpu(rom_header->signature)); + return -EINVAL; + } + + rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data)); + + debug("PCI ROM image, vendor ID %04x, device ID %04x,\n", + rom_data->vendor, rom_data->device); + + /* If the device id is mapped, a mismatch is expected */ + if ((vendor != rom_data->vendor || device != rom_data->device) && + (vendev == mapped_vendev)) { + printf("ID mismatch: vendor ID %04x, device ID %04x\n", + rom_data->vendor, rom_data->device); + return -EPERM; + } + + debug("PCI ROM image, Class Code %04x%02x, Code Type %02x\n", + rom_data->class_hi, rom_data->class_lo, rom_data->type); + + if (class != ((rom_data->class_hi << 8) | rom_data->class_lo)) { + debug("Class Code mismatch ROM %08x, dev %08x\n", + (rom_data->class_hi << 8) | rom_data->class_lo, + class); + } + *hdrp = rom_header; + + return 0; +} + +int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header, + struct pci_rom_header **ram_headerp) +{ + struct pci_rom_data *rom_data; + unsigned int rom_size; + unsigned int image_size = 0; + void *target; + + do { + /* Get next image, until we see an x86 version */ + rom_header = (struct pci_rom_header *)((void *)rom_header + + image_size); + + rom_data = (struct pci_rom_data *)((void *)rom_header + + le32_to_cpu(rom_header->data)); + + image_size = le32_to_cpu(rom_data->ilen) * 512; + } while ((rom_data->type != 0) && (rom_data->indicator != 0)); + + if (rom_data->type != 0) + return -EACCES; + + rom_size = rom_header->size * 512; + + target = (void *)PCI_VGA_RAM_IMAGE_START; + if (target != rom_header) { + debug("Copying VGA ROM Image from %p to %p, 0x%x bytes\n", + rom_header, target, rom_size); + memcpy(target, rom_header, rom_size); + if (memcmp(target, rom_header, rom_size)) { + printf("VGA ROM copy failed\n"); + return -EFAULT; + } + } + *ram_headerp = target; + + return 0; +} + +static struct vbe_mode_info mode_info; + +int vbe_get_video_info(struct graphic_device *gdev) +{ +#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE + struct vesa_mode_info *vesa = &mode_info.vesa; + + gdev->winSizeX = vesa->x_resolution; + gdev->winSizeY = vesa->y_resolution; + + gdev->plnSizeX = vesa->x_resolution; + gdev->plnSizeY = vesa->y_resolution; + + gdev->gdfBytesPP = vesa->bits_per_pixel / 8; + + switch (vesa->bits_per_pixel) { + case 24: + gdev->gdfIndex = GDF_32BIT_X888RGB; + break; + case 16: + gdev->gdfIndex = GDF_16BIT_565RGB; + break; + default: + gdev->gdfIndex = GDF__8BIT_INDEX; + break; + } + + gdev->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS; + gdev->pciBase = vesa->phys_base_ptr; + + gdev->frameAdrs = vesa->phys_base_ptr; + gdev->memSize = vesa->bytes_per_scanline * vesa->y_resolution; + + gdev->vprBase = vesa->phys_base_ptr; + gdev->cprBase = vesa->phys_base_ptr; + + return 0; +#else + return -ENOSYS; +#endif +} + +int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate) +{ + struct pci_rom_header *rom, *ram; + int vesa_mode = -1; + uint16_t class; + int ret; + + /* Only execute VGA ROMs */ + pci_read_config_word(dev, PCI_CLASS_DEVICE, &class); + if ((class ^ PCI_CLASS_DISPLAY_VGA) & 0xff00) { + debug("%s: Class %#x, should be %#x\n", __func__, class, + PCI_CLASS_DISPLAY_VGA); + return -ENODEV; + } + + if (!should_load_oprom(dev)) + return -ENXIO; + + ret = pci_rom_probe(dev, class, &rom); + if (ret) + return ret; + + ret = pci_rom_load(class, rom, &ram); + if (ret) + return ret; + + if (!board_should_run_oprom(dev)) + return -ENXIO; + +#if defined(CONFIG_FRAMEBUFFER_SET_VESA_MODE) && \ + defined(CONFIG_FRAMEBUFFER_VESA_MODE) + vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE; +#endif + debug("Selected vesa mode %d\b", vesa_mode); + if (emulate) { +#ifdef CONFIG_BIOSEMU + BE_VGAInfo *info; + + ret = biosemu_setup(dev, &info); + if (ret) + return ret; + biosemu_set_interrupt_handler(0x15, int15_handler); + ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, true, + vesa_mode, &mode_info); + if (ret) + return ret; +#else + printf("BIOS emulation not available - see CONFIG_BIOSEMU\n"); + return -ENOSYS; +#endif + } else { +#ifdef CONFIG_X86 + bios_set_interrupt_handler(0x15, int15_handler); + + bios_run_on_x86(dev, (unsigned long)ram, vesa_mode, + &mode_info); +#else + printf("BIOS native execution is only available on x86\n"); + return -ENOSYS; +#endif + } + debug("Final vesa mode %d\n", mode_info.video_mode); + + return 0; +} diff --git a/drivers/power/palmas.c b/drivers/power/palmas.c index cfbc9dc..6430fe0 100644 --- a/drivers/power/palmas.c +++ b/drivers/power/palmas.c @@ -27,7 +27,7 @@ int palmas_mmc1_poweron_ldo(void) { u8 val = 0; -#if defined(CONFIG_DRA7XX) +#if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX) /* * Currently valid for the dra7xx_evm board: * Set TPS659038 LDO1 to 3.0 V diff --git a/drivers/power/pmic/pmic_max77686.c b/drivers/power/pmic/pmic_max77686.c index df1fd91..95b1a57 100644 --- a/drivers/power/pmic/pmic_max77686.c +++ b/drivers/power/pmic/pmic_max77686.c @@ -42,11 +42,30 @@ static unsigned int max77686_ldo_volt2hex(int ldo, ulong uV) return 0; } +static int max77686_buck_volt2hex(int buck, ulong uV) +{ + int hex = 0; + + if (buck < 5 || buck > 9) { + debug("%s: buck %d is not supported\n", __func__, buck); + return -EINVAL; + } + + hex = (uV - 750000) / 50000; + + if (hex >= 0 && hex <= MAX77686_BUCK_VOLT_MAX_HEX) + return hex; + + debug("%s: %ld is wrong voltage value for BUCK%d\n", + __func__, uV, buck); + return -EINVAL; +} + int max77686_set_ldo_voltage(struct pmic *p, int ldo, ulong uV) { unsigned int val, ret, hex, adr; - if (ldo < 1 && ldo > 26) { + if (ldo < 1 || ldo > 26) { printf("%s: %d is wrong ldo number\n", __func__, ldo); return -1; } @@ -68,11 +87,38 @@ int max77686_set_ldo_voltage(struct pmic *p, int ldo, ulong uV) return ret; } +int max77686_set_buck_voltage(struct pmic *p, int buck, ulong uV) +{ + unsigned int val, adr; + int hex, ret; + + if (buck < 5 || buck > 9) { + printf("%s: %d is an unsupported bucket number\n", + __func__, buck); + return -EINVAL; + } + + adr = max77686_buck_addr[buck] + 1; + hex = max77686_buck_volt2hex(buck, uV); + + if (hex < 0) + return hex; + + ret = pmic_reg_read(p, adr, &val); + if (ret) + return ret; + + val &= ~MAX77686_BUCK_VOLT_MASK; + ret |= pmic_reg_write(p, adr, val | hex); + + return ret; +} + int max77686_set_ldo_mode(struct pmic *p, int ldo, char opmode) { unsigned int val, ret, adr, mode; - if (ldo < 1 && 26 < ldo) { + if (ldo < 1 || 26 < ldo) { printf("%s: %d is wrong ldo number\n", __func__, ldo); return -1; } @@ -157,7 +203,7 @@ int max77686_set_buck_mode(struct pmic *p, int buck, char opmode) /* mode */ switch (opmode) { case OPMODE_OFF: - mode = MAX77686_BUCK_MODE_OFF; + mode = MAX77686_BUCK_MODE_OFF << mode_shift; break; case OPMODE_STANDBY: switch (buck) { diff --git a/drivers/power/power_i2c.c b/drivers/power/power_i2c.c index 594cd11..0dcf9fe 100644 --- a/drivers/power/power_i2c.c +++ b/drivers/power/power_i2c.c @@ -14,7 +14,7 @@ #include <linux/types.h> #include <power/pmic.h> #include <i2c.h> -#include <compiler.h> +#include <linux/compiler.h> int pmic_reg_write(struct pmic *p, u32 reg, u32 val) { diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c index e578ae6..7f1fdd1 100644 --- a/drivers/power/twl4030.c +++ b/drivers/power/twl4030.c @@ -91,17 +91,23 @@ void twl4030_power_init(void) TWL4030_PM_RECEIVER_DEV_GRP_P1); } -void twl4030_power_mmc_init(void) +void twl4030_power_mmc_init(int dev_index) { - /* Set VMMC1 to 3.15 Volts */ - twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VMMC1_DEDICATED, - TWL4030_PM_RECEIVER_VMMC1_VSEL_32, - TWL4030_PM_RECEIVER_VMMC1_DEV_GRP, - TWL4030_PM_RECEIVER_DEV_GRP_P1); + if (dev_index == 0) { + /* Set VMMC1 to 3.15 Volts */ + twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VMMC1_DEDICATED, + TWL4030_PM_RECEIVER_VMMC1_VSEL_32, + TWL4030_PM_RECEIVER_VMMC1_DEV_GRP, + TWL4030_PM_RECEIVER_DEV_GRP_P1); - /* Set VMMC2 to 3.15 Volts */ - twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VMMC2_DEDICATED, - TWL4030_PM_RECEIVER_VMMC2_VSEL_32, - TWL4030_PM_RECEIVER_VMMC2_DEV_GRP, - TWL4030_PM_RECEIVER_DEV_GRP_P1); + mdelay(100); /* ramp-up delay from Linux code */ + } else if (dev_index == 1) { + /* Set VMMC2 to 3.15 Volts */ + twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VMMC2_DEDICATED, + TWL4030_PM_RECEIVER_VMMC2_VSEL_32, + TWL4030_PM_RECEIVER_VMMC2_DEV_GRP, + TWL4030_PM_RECEIVER_DEV_GRP_P1); + + mdelay(100); /* ramp-up delay from Linux code */ + } } diff --git a/drivers/qe/Makefile b/drivers/qe/Makefile index 7f1bd06..8fa4866 100644 --- a/drivers/qe/Makefile +++ b/drivers/qe/Makefile @@ -4,5 +4,6 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y := qe.o uccf.o uec.o uec_phy.o +obj-$(CONFIG_QE) += qe.o uccf.o uec.o uec_phy.o +obj-$(CONFIG_U_QE) += qe.o obj-$(CONFIG_OF_LIBFDT) += fdt.o diff --git a/drivers/qe/fdt.c b/drivers/qe/fdt.c index d9a7d82..dfae4bf 100644 --- a/drivers/qe/fdt.c +++ b/drivers/qe/fdt.c @@ -12,6 +12,7 @@ #include <fdt_support.h> #include "qe.h" +#ifdef CONFIG_QE DECLARE_GLOBAL_DATA_PTR; /* @@ -72,3 +73,4 @@ void ft_qe_setup(void *blob) "clock-frequency", gd->arch.qe_clk / 2, 1); fdt_fixup_qe_firmware(blob); } +#endif diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 4358a91..bc94673 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -40,6 +40,7 @@ void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data) return; } +#ifdef CONFIG_QE uint qe_muram_alloc(uint size, uint align) { uint retloc; @@ -70,6 +71,7 @@ uint qe_muram_alloc(uint size, uint align) return retloc; } +#endif void *qe_muram_addr(uint offset) { @@ -180,6 +182,17 @@ void qe_init(uint qe_base) qe_snums_init(); } +#ifdef CONFIG_U_QE +void u_qe_init(void) +{ + uint qe_base = CONFIG_SYS_IMMR + 0x01400000; /* QE immr base */ + qe_immr = (qe_map_t *)qe_base; + + u_qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR); + out_be32(&qe_immr->iram.iready, QE_IRAM_READY); +} +#endif + void qe_reset(void) { qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID, @@ -212,6 +225,7 @@ void qe_assign_page(uint snum, uint para_ram_base) #define BRG_CLK (gd->arch.brg_clk) +#ifdef CONFIG_QE int qe_set_brg(uint brg, uint rate) { volatile uint *bp; @@ -239,6 +253,7 @@ int qe_set_brg(uint brg, uint rate) return 0; } +#endif /* Set ethernet MII clock master */ @@ -429,6 +444,131 @@ int qe_upload_firmware(const struct qe_firmware *firmware) return 0; } +#ifdef CONFIG_U_QE +/* + * Upload a microcode to the I-RAM at a specific address. + * + * See docs/README.qe_firmware for information on QE microcode uploading. + * + * Currently, only version 1 is supported, so the 'version' field must be + * set to 1. + * + * The SOC model and revision are not validated, they are only displayed for + * informational purposes. + * + * 'calc_size' is the calculated size, in bytes, of the firmware structure and + * all of the microcode structures, minus the CRC. + * + * 'length' is the size that the structure says it is, including the CRC. + */ +int u_qe_upload_firmware(const struct qe_firmware *firmware) +{ + unsigned int i; + unsigned int j; + u32 crc; + size_t calc_size = sizeof(struct qe_firmware); + size_t length; + const struct qe_header *hdr; +#ifdef CONFIG_DEEP_SLEEP + ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); +#endif + if (!firmware) { + printf("Invalid address\n"); + return -EINVAL; + } + + hdr = &firmware->header; + length = be32_to_cpu(hdr->length); + + /* Check the magic */ + if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || + (hdr->magic[2] != 'F')) { + printf("Not a microcode\n"); +#ifdef CONFIG_DEEP_SLEEP + setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); +#endif + return -EPERM; + } + + /* Check the version */ + if (hdr->version != 1) { + printf("Unsupported version\n"); + return -EPERM; + } + + /* Validate some of the fields */ + if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) { + printf("Invalid data\n"); + return -EINVAL; + } + + /* Validate the length and check if there's a CRC */ + calc_size += (firmware->count - 1) * sizeof(struct qe_microcode); + + for (i = 0; i < firmware->count; i++) + /* + * For situations where the second RISC uses the same microcode + * as the first, the 'code_offset' and 'count' fields will be + * zero, so it's okay to add those. + */ + calc_size += sizeof(u32) * + be32_to_cpu(firmware->microcode[i].count); + + /* Validate the length */ + if (length != calc_size + sizeof(u32)) { + printf("Invalid length\n"); + return -EPERM; + } + + /* + * Validate the CRC. We would normally call crc32_no_comp(), but that + * function isn't available unless you turn on JFFS support. + */ + crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size)); + if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) { + printf("Firmware CRC is invalid\n"); + return -EIO; + } + + /* + * If the microcode calls for it, split the I-RAM. + */ + if (!firmware->split) { + out_be16(&qe_immr->cp.cercr, + in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR); + } + + if (firmware->soc.model) + printf("Firmware '%s' for %u V%u.%u\n", + firmware->id, be16_to_cpu(firmware->soc.model), + firmware->soc.major, firmware->soc.minor); + else + printf("Firmware '%s'\n", firmware->id); + + /* Loop through each microcode. */ + for (i = 0; i < firmware->count; i++) { + const struct qe_microcode *ucode = &firmware->microcode[i]; + + /* Upload a microcode if it's present */ + if (ucode->code_offset) + qe_upload_microcode(firmware, ucode); + + /* Program the traps for this processor */ + for (j = 0; j < 16; j++) { + u32 trap = be32_to_cpu(ucode->traps[j]); + + if (trap) + out_be32(&qe_immr->rsp[i].tibcr[j], trap); + } + + /* Enable traps */ + out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); + } + + return 0; +} +#endif + struct qe_firmware_info *qe_get_firmware_info(void) { return qe_firmware_uploaded ? &qe_firmware_info : NULL; diff --git a/drivers/qe/qe.h b/drivers/qe/qe.h index ebb7c5f..33878f8 100644 --- a/drivers/qe/qe.h +++ b/drivers/qe/qe.h @@ -285,4 +285,9 @@ void ft_qe_setup(void *blob); void qe_init(uint qe_base); void qe_reset(void); +#ifdef CONFIG_U_QE +void u_qe_init(void); +int u_qe_upload_firmware(const struct qe_firmware *firmware); +#endif + #endif /* __QE_H__ */ diff --git a/drivers/rtc/bfin_rtc.c b/drivers/rtc/bfin_rtc.c index 21a2189..4cf2d83 100644 --- a/drivers/rtc/bfin_rtc.c +++ b/drivers/rtc/bfin_rtc.c @@ -27,7 +27,7 @@ #define NUM_SECS_IN_DAY DAYS_TO_SECS(1) /* Enable the RTC prescaler enable register */ -static void rtc_init(void) +void rtc_init(void) { if (!(bfin_read_RTC_PREN() & 0x1)) bfin_write_RTC_PREN(0x1); diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c index f7cf106..39e6041 100644 --- a/drivers/rtc/mc146818.c +++ b/drivers/rtc/mc146818.c @@ -14,6 +14,7 @@ #include <common.h> #include <command.h> #include <rtc.h> +#include <version.h> #if defined(__I386__) || defined(CONFIG_MALTA) #include <asm/io.h> @@ -23,6 +24,9 @@ #if defined(CONFIG_CMD_DATE) +/* Set this to 1 to clear the CMOS RAM */ +#define CLEAR_CMOS 0 + static uchar rtc_read (uchar reg); static void rtc_write (uchar reg, uchar val); @@ -41,7 +45,14 @@ static void rtc_write (uchar reg, uchar val); #define RTC_CONFIG_B 0x0B #define RTC_CONFIG_C 0x0C #define RTC_CONFIG_D 0x0D +#define RTC_REG_SIZE 0x80 + +#define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5) +#define RTC_CONFIG_A_RATE_1024HZ 6 +#define RTC_CONFIG_B_24H (1 << 1) + +#define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80 /* ------------------------------------------------------------------------- */ @@ -128,25 +139,49 @@ void rtc_reset (void) */ static uchar rtc_read (uchar reg) { - return(in8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg)); + return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg); } static void rtc_write (uchar reg, uchar val) { - out8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg, val); + out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val); } #else static uchar rtc_read (uchar reg) { out8(RTC_PORT_MC146818,reg); - return(in8(RTC_PORT_MC146818+1)); + return in8(RTC_PORT_MC146818 + 1); } static void rtc_write (uchar reg, uchar val) { out8(RTC_PORT_MC146818,reg); - out8(RTC_PORT_MC146818+1,val); + out8(RTC_PORT_MC146818+1, val); } #endif +void rtc_init(void) +{ +#if CLEAR_CMOS + int i; + + rtc_write(RTC_SECONDS_ALARM, 0); + rtc_write(RTC_MINUTES_ALARM, 0); + rtc_write(RTC_HOURS_ALARM, 0); + for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++) + rtc_write(i, 0); + printf("RTC: zeroing CMOS RAM\n"); +#endif + + /* Setup the real time clock */ + rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H); + /* Setup the frequency it operates at */ + rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | + RTC_CONFIG_A_RATE_1024HZ); + /* Ensure all reserved bits are 0 in register D */ + rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); + + /* Clear any pending interrupts */ + rtc_read(RTC_CONFIG_C); +} #endif diff --git a/drivers/rtc/mvrtc.h b/drivers/rtc/mvrtc.h index ebddc12..424743c 100644 --- a/drivers/rtc/mvrtc.h +++ b/drivers/rtc/mvrtc.h @@ -13,7 +13,7 @@ #define _MVRTC_H_ #include <asm/arch/soc.h> -#include <compiler.h> +#include <linux/compiler.h> /* RTC registers */ struct mvrtc_registers { diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 8f05191..af5beba 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -132,11 +132,12 @@ static void NS16550_setbrg(NS16550_t com_port, int baud_divisor) void NS16550_init(NS16550_t com_port, int baud_divisor) { -#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_OMAP34XX)) +#if (defined(CONFIG_SPL_BUILD) && \ + (defined(CONFIG_OMAP34XX) || defined(CONFIG_OMAP44XX))) /* - * On some OMAP3 devices when UART3 is configured for boot mode before - * SPL starts only THRE bit is set. We have to empty the transmitter - * before initialization starts. + * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode + * before SPL starts only THRE bit is set. We have to empty the + * transmitter before initialization starts. */ if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE)) == UART_LSR_THRE) { diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index b09053f..d1b5777 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -39,7 +39,7 @@ static void serial_find_console_or_panic(void) /* Check for a chosen console */ node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); if (node < 0) - node = fdtdec_get_alias_node(gd->fdt_blob, "console"); + node = fdt_path_offset(gd->fdt_blob, "console"); if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) { gd->cur_serial_dev = dev; return; diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 38dda91..e1bf496 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -72,30 +72,39 @@ static int pl01x_tstc(struct pl01x_regs *regs) static int pl01x_generic_serial_init(struct pl01x_regs *regs, enum pl01x_type type) { - unsigned int lcr; - + switch (type) { + case TYPE_PL010: + /* disable everything */ + writel(0, ®s->pl010_cr); + break; + case TYPE_PL011: #ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT - if (type == TYPE_PL011) { /* Empty RX fifo if necessary */ if (readl(®s->pl011_cr) & UART_PL011_CR_UARTEN) { while (!(readl(®s->fr) & UART_PL01x_FR_RXFE)) readl(®s->dr); } - } #endif + /* disable everything */ + writel(0, ®s->pl011_cr); + break; + default: + return -EINVAL; + } - /* First, disable everything */ - writel(0, ®s->pl010_cr); + return 0; +} - /* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */ +static int set_line_control(struct pl01x_regs *regs) +{ + unsigned int lcr; + /* + * Internal update of baud rate register require line + * control register write + */ lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN; - writel(lcr, ®s->pl011_lcrh); - - switch (type) { - case TYPE_PL010: - break; - case TYPE_PL011: { #ifdef CONFIG_PL011_SERIAL_RLCR + { int i; /* @@ -107,15 +116,9 @@ static int pl01x_generic_serial_init(struct pl01x_regs *regs, writel(lcr, ®s->fr); writel(lcr, ®s->pl011_rlcr); - /* lcrh needs to be set again for change to be effective */ - writel(lcr, ®s->pl011_lcrh); -#endif - break; - } - default: - return -EINVAL; } - +#endif + writel(lcr, ®s->pl011_lcrh); return 0; } @@ -175,6 +178,7 @@ static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type, writel(divider, ®s->pl011_ibrd); writel(fraction, ®s->pl011_fbrd); + set_line_control(regs); /* Finally, enable the UART */ writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE | UART_PL011_CR_RTS, ®s->pl011_cr); @@ -201,7 +205,7 @@ static void pl01x_serial_init_baud(int baudrate) base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX]; pl01x_generic_serial_init(base_regs, pl01x_type); - pl01x_generic_setbrg(base_regs, TYPE_PL010, clock, baudrate); + pl01x_generic_setbrg(base_regs, pl01x_type, clock, baudrate); } /* diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c index 6046efb..e8a1608 100644 --- a/drivers/serial/serial_uniphier.c +++ b/drivers/serial/serial_uniphier.c @@ -11,6 +11,7 @@ #include <dm/device.h> #include <dm/platform_data/serial-uniphier.h> #include <serial.h> +#include <fdtdec.h> #define UART_REG(x) \ u8 x; \ @@ -113,19 +114,21 @@ static int uniphier_serial_remove(struct udevice *dev) } #ifdef CONFIG_OF_CONTROL -static const struct udevice_id uniphier_uart_of_match = { - { .compatible = "panasonic,uniphier-uart"}, +static const struct udevice_id uniphier_uart_of_match[] = { + { .compatible = "panasonic,uniphier-uart" }, {}, }; static int uniphier_serial_ofdata_to_platdata(struct udevice *dev) { - /* - * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com) - * - * Implement conversion code from DTB to platform data - * when supporting CONFIG_OF_CONTROL on UniPhir platform. - */ + struct uniphier_serial_platform_data *plat = dev_get_platdata(dev); + DECLARE_GLOBAL_DATA_PTR; + + plat->base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); + plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "clock-frequency", 0); + + return 0; } #endif diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c index fd7fea8..857b604 100644 --- a/drivers/spi/ti_qspi.c +++ b/drivers/spi/ti_qspi.c @@ -102,7 +102,7 @@ static void ti_spi_setup_spi_register(struct ti_qspi_slave *qslave) struct spi_slave *slave = &qslave->slave; u32 memval = 0; -#ifdef CONFIG_DRA7XX +#if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX) slave->memory_map = (void *)MMAP_START_ADDR_DRA; #else slave->memory_map = (void *)MMAP_START_ADDR_AM43x; @@ -244,7 +244,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, uint status; int timeout; -#ifdef CONFIG_DRA7XX +#if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX) int val; #endif @@ -254,7 +254,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, /* Setup mmap flags */ if (flags & SPI_XFER_MMAP) { writel(MM_SWITCH, &qslave->base->memswitch); -#ifdef CONFIG_DRA7XX +#if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX) val = readl(CORE_CTRL_IO); val |= MEM_CS; writel(val, CORE_CTRL_IO); @@ -262,7 +262,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, return 0; } else if (flags & SPI_XFER_MMAP_END) { writel(~MM_SWITCH, &qslave->base->memswitch); -#ifdef CONFIG_DRA7XX +#if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX) val = readl(CORE_CTRL_IO); val &= MEM_CS_UNSELECT; writel(val, CORE_CTRL_IO); diff --git a/drivers/tpm/tpm.c b/drivers/tpm/tpm.c index bc0f964..31761ec 100644 --- a/drivers/tpm/tpm.c +++ b/drivers/tpm/tpm.c @@ -34,7 +34,7 @@ #include <config.h> #include <common.h> -#include <compiler.h> +#include <linux/compiler.h> #include <fdtdec.h> #include <i2c.h> #include <tpm.h> diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 2dd8501..c1bbed4 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -38,7 +38,7 @@ #include <common.h> #include <fdtdec.h> -#include <compiler.h> +#include <linux/compiler.h> #include <i2c.h> #include <tpm.h> #include <asm-generic/errno.h> diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index edd91a8..6fdbf57 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -85,15 +85,10 @@ static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos) } #endif -/* Setup the EHCI host controller. */ -static void setup_usb_phy(struct exynos_usb_phy *usb) +static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb) { u32 hsic_ctrl; - set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN); - - set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN); - clrbits_le32(&usb->usbphyctrl0, HOST_CTRL0_FSEL_MASK | HOST_CTRL0_COMMONON_N | @@ -150,8 +145,34 @@ static void setup_usb_phy(struct exynos_usb_phy *usb) EHCICTRL_ENAINCR16); } -/* Reset the EHCI host controller. */ -static void reset_usb_phy(struct exynos_usb_phy *usb) +static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb) +{ + writel(CLK_24MHZ, &usb->usbphyclk); + + clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 | + PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 | + PHYPWR_NORMAL_MASK_PHY0)); + + setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST)); + udelay(10); + clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST)); +} + +static void setup_usb_phy(struct exynos_usb_phy *usb) +{ + set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN); + + set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN); + + if (cpu_is_exynos5()) + exynos5_setup_usb_phy(usb); + else if (cpu_is_exynos4()) + if (proid_is_exynos4412()) + exynos4412_setup_usb_phy((struct exynos4412_usb_phy *) + usb); +} + +static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb) { u32 hsic_ctrl; @@ -171,6 +192,24 @@ static void reset_usb_phy(struct exynos_usb_phy *usb) setbits_le32(&usb->hsicphyctrl1, hsic_ctrl); setbits_le32(&usb->hsicphyctrl2, hsic_ctrl); +} + +static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb) +{ + setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 | + PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 | + PHYPWR_NORMAL_MASK_PHY0)); +} + +/* Reset the EHCI host controller. */ +static void reset_usb_phy(struct exynos_usb_phy *usb) +{ + if (cpu_is_exynos5()) + exynos5_reset_usb_phy(usb); + else if (cpu_is_exynos4()) + if (proid_is_exynos4412()) + exynos4412_reset_usb_phy((struct exynos4412_usb_phy *) + usb); set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE); } diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 45062e6..8f55464 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -14,7 +14,7 @@ #include <asm/io.h> #include <usb/ehci-fsl.h> #include <hwconfig.h> -#include <asm/fsl_errata.h> +#include <fsl_usb.h> #include "ehci.h" @@ -130,8 +130,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, in_le32(&ehci->usbmode); - if (SVR_SOC_VER(get_svr()) == SVR_T4240 && - IS_SVR_REV(get_svr(), 2, 0)) + if (has_erratum_a007798()) set_txfifothresh(ehci, TXFIFOTHRESH); return 0; diff --git a/drivers/usb/host/ehci-uniphier.c b/drivers/usb/host/ehci-uniphier.c index 77f6c9d..32a4375 100644 --- a/drivers/usb/host/ehci-uniphier.c +++ b/drivers/usb/host/ehci-uniphier.c @@ -6,10 +6,43 @@ */ #include <common.h> +#include <linux/err.h> #include <usb.h> #include <asm/arch/ehci-uniphier.h> #include "ehci.h" +#ifdef CONFIG_OF_CONTROL +#include <fdtdec.h> +DECLARE_GLOBAL_DATA_PTR; + +#define FDT gd->fdt_blob +#define COMPAT "panasonic,uniphier-ehci" + +static int get_uniphier_ehci_base(int index, struct ehci_hccr **base) +{ + int offset; + + for (offset = fdt_node_offset_by_compatible(FDT, 0, COMPAT); + offset >= 0; + offset = fdt_node_offset_by_compatible(FDT, offset, COMPAT)) { + if (index == 0) { + *base = (struct ehci_hccr *) + fdtdec_get_addr(FDT, offset, "reg"); + return 0; + } + index--; + } + + return -ENODEV; /* not found */ +} +#else +static int get_uniphier_ehci_base(int index, struct ehci_hccr **base) +{ + *base = (struct ehci_hccr *)uniphier_ehci_platdata[index].base; + return 0; +} +#endif + /* * Create the appropriate control structures to manage * a new EHCI host controller. @@ -17,12 +50,15 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { + int ret; struct ehci_hccr *cr; struct ehci_hcor *or; uniphier_ehci_reset(index, 0); - cr = (struct ehci_hccr *)(uniphier_ehci_platdata[index].base); + ret = get_uniphier_ehci_base(index, &cr); + if (ret < 0) + return ret; or = (void *)cr + HC_LENGTH(ehci_readl(&cr->cr_capbase)); *hccr = cr; diff --git a/drivers/usb/phy/omap_usb_phy.c b/drivers/usb/phy/omap_usb_phy.c index f78d532..52a3664 100644 --- a/drivers/usb/phy/omap_usb_phy.c +++ b/drivers/usb/phy/omap_usb_phy.c @@ -118,7 +118,6 @@ void usb_phy_power(int on) void omap_usb3_phy_init(struct omap_usb3_phy *phy_regs) { omap_usb_dpll_lock(phy_regs); - usb3_phy_partial_powerup(phy_regs); /* * Give enough time for the PHY to partially power-up before @@ -126,7 +125,6 @@ void omap_usb3_phy_init(struct omap_usb3_phy *phy_regs) * team. */ mdelay(100); - usb3_phy_power(1); } static void omap_enable_usb3_phy(struct omap_xhci *omap) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 14a6781..00b563f 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -39,8 +39,10 @@ obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o obj-$(CONFIG_VIDEO_SED13806) += sed13806.o obj-$(CONFIG_VIDEO_SM501) += sm501.o obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o +obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o obj-$(CONFIG_VIDEO_TEGRA) += tegra.o obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o +obj-$(CONFIG_VIDEO_X86) += x86_fb.o obj-$(CONFIG_FORMIKE) += formike.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-$(CONFIG_VIDEO_PARADE) += parade.o diff --git a/drivers/video/ati_radeon_fb.c b/drivers/video/ati_radeon_fb.c index 618f5d9..5748951 100644 --- a/drivers/video/ati_radeon_fb.c +++ b/drivers/video/ati_radeon_fb.c @@ -19,6 +19,7 @@ #include <common.h> #include <command.h> +#include <bios_emul.h> #include <pci.h> #include <asm/processor.h> #include <asm/errno.h> @@ -544,7 +545,6 @@ void radeon_setmode_9200(int vesa_idx, int bpp) } #include "../bios_emulator/include/biosemu.h" -extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp); int radeon_probe(struct radeonfb_info *rinfo) { diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c new file mode 100644 index 0000000..d241397 --- /dev/null +++ b/drivers/video/sunxi_display.c @@ -0,0 +1,451 @@ +/* + * Display driver for Allwinner SoCs. + * + * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#include <asm/arch/clock.h> +#include <asm/arch/display.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <fdtdec.h> +#include <fdt_support.h> +#include <linux/fb.h> +#include <video_fb.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct sunxi_display { + GraphicDevice graphic_device; + bool enabled; +} sunxi_display; + +static int sunxi_hdmi_hpd_detect(void) +{ + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_hdmi_reg * const hdmi = + (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; + + /* Set pll3 to 300MHz */ + clock_set_pll3(300000000); + + /* Set hdmi parent to pll3 */ + clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK, + CCM_HDMI_CTRL_PLL3); + + /* Set ahb gating to pass */ +#ifdef CONFIG_MACH_SUN6I + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI); +#endif + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI); + + /* Clock on */ + setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE); + + writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl); + writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0); + + udelay(1000); + + if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT) + return 1; + + /* No need to keep these running */ + clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE); + clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE); + clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI); +#ifdef CONFIG_MACH_SUN6I + clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI); +#endif + clock_set_pll3(0); + + return 0; +} + +/* + * This is the entity that mixes and matches the different layers and inputs. + * Allwinner calls it the back-end, but i like composer better. + */ +static void sunxi_composer_init(void) +{ + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_de_be_reg * const de_be = + (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; + int i; + +#ifdef CONFIG_MACH_SUN6I + /* Reset off */ + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0); +#endif + + /* Clocks on */ + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0); + setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0); + clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000); + + /* Engine bug, clear registers after reset */ + for (i = 0x0800; i < 0x1000; i += 4) + writel(0, SUNXI_DE_BE0_BASE + i); + + setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE); +} + +static void sunxi_composer_mode_set(struct fb_videomode *mode, + unsigned int address) +{ + struct sunxi_de_be_reg * const de_be = + (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; + + writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres), + &de_be->disp_size); + writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres), + &de_be->layer0_size); + writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride); + writel(address << 3, &de_be->layer0_addr_low32b); + writel(address >> 29, &de_be->layer0_addr_high4b); + writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl); + + setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE); +} + +/* + * LCDC, what allwinner calls a CRTC, so timing controller and serializer. + */ +static void sunxi_lcdc_pll_set(int dotclock, int *clk_div, int *clk_double) +{ + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + int value, n, m, diff; + int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF; + int best_double = 0; + + /* + * Find the lowest divider resulting in a matching clock, if there + * is no match, pick the closest lower clock, as monitors tend to + * not sync to higher frequencies. + */ + for (m = 15; m > 0; m--) { + n = (m * dotclock) / 3000; + + if ((n >= 9) && (n <= 127)) { + value = (3000 * n) / m; + diff = dotclock - value; + if (diff < best_diff) { + best_diff = diff; + best_m = m; + best_n = n; + best_double = 0; + } + } + + /* These are just duplicates */ + if (!(m & 1)) + continue; + + n = (m * dotclock) / 6000; + if ((n >= 9) && (n <= 127)) { + value = (6000 * n) / m; + diff = dotclock - value; + if (diff < best_diff) { + best_diff = diff; + best_m = m; + best_n = n; + best_double = 1; + } + } + } + + debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n", + dotclock, (best_double + 1) * 3000 * best_n / best_m, + best_double + 1, best_n, best_m); + + clock_set_pll3(best_n * 3000000); + + writel(CCM_LCD_CH1_CTRL_GATE | + (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X : CCM_LCD_CH1_CTRL_PLL3) | + CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg); + + *clk_div = best_m; + *clk_double = best_double; +} + +static void sunxi_lcdc_init(void) +{ + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_lcdc_reg * const lcdc = + (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; + + /* Reset off */ +#ifdef CONFIG_MACH_SUN6I + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0); +#else + setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST); +#endif + + /* Clock on */ + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0); + + /* Init lcdc */ + writel(0, &lcdc->ctrl); /* Disable tcon */ + writel(0, &lcdc->int0); /* Disable all interrupts */ + + /* Disable tcon0 dot clock */ + clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE); + + /* Set all io lines to tristate */ + writel(0xffffffff, &lcdc->tcon0_io_tristate); + writel(0xffffffff, &lcdc->tcon1_io_tristate); +} + +static void sunxi_lcdc_mode_set(struct fb_videomode *mode, + int *clk_div, int *clk_double) +{ + struct sunxi_lcdc_reg * const lcdc = + (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; + int bp, total; + + /* Use tcon1 */ + clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK, + SUNXI_LCDC_CTRL_IO_MAP_TCON1); + + /* Enabled, 0x1e start delay */ + writel(SUNXI_LCDC_TCON1_CTRL_ENABLE | + SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(0x1e), &lcdc->tcon1_ctrl); + + writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres), + &lcdc->tcon1_timing_source); + writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres), + &lcdc->tcon1_timing_scale); + writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres), + &lcdc->tcon1_timing_out); + + bp = mode->hsync_len + mode->left_margin; + total = mode->xres + mode->right_margin + bp; + writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) | + SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h); + + bp = mode->vsync_len + mode->upper_margin; + total = mode->yres + mode->lower_margin + bp; + writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) | + SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v); + + writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len), + &lcdc->tcon1_timing_sync); + + sunxi_lcdc_pll_set(mode->pixclock, clk_div, clk_double); +} + +#ifdef CONFIG_MACH_SUN6I +static void sunxi_drc_init(void) +{ + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + + /* On sun6i the drc must be clocked even when in pass-through mode */ + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0); + clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000); +} +#endif + +static void sunxi_hdmi_mode_set(struct fb_videomode *mode, + int clk_div, int clk_double) +{ + struct sunxi_hdmi_reg * const hdmi = + (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; + int x, y; + + /* Write clear interrupt status bits */ + writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq); + + /* Init various registers, select pll3 as clock source */ + writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity); + writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0); + writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1); + writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl); + writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0); + + /* Setup clk div and doubler */ + clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK, + SUNXI_HDMI_PLL_CTRL_DIV(clk_div)); + if (!clk_double) + setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE); + + /* Setup timing registers */ + writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres), + &hdmi->video_size); + + x = mode->hsync_len + mode->left_margin; + y = mode->vsync_len + mode->upper_margin; + writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp); + + x = mode->right_margin; + y = mode->lower_margin; + writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp); + + x = mode->hsync_len; + y = mode->vsync_len; + writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw); + + if (mode->sync & FB_SYNC_HOR_HIGH_ACT) + setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR); + + if (mode->sync & FB_SYNC_VERT_HIGH_ACT) + setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER); +} + +static void sunxi_engines_init(void) +{ + sunxi_composer_init(); + sunxi_lcdc_init(); +#ifdef CONFIG_MACH_SUN6I + sunxi_drc_init(); +#endif +} + +static void sunxi_mode_set(struct fb_videomode *mode, unsigned int address) +{ + struct sunxi_de_be_reg * const de_be = + (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; + struct sunxi_lcdc_reg * const lcdc = + (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; + struct sunxi_hdmi_reg * const hdmi = + (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; + int clk_div, clk_double; + int retries = 3; + +retry: + clrbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE); + clrbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE); + clrbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START); + + sunxi_composer_mode_set(mode, address); + sunxi_lcdc_mode_set(mode, &clk_div, &clk_double); + sunxi_hdmi_mode_set(mode, clk_div, clk_double); + + setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS); + setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START); + + udelay(1000000 / mode->refresh + 500); + + setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE); + + udelay(1000000 / mode->refresh + 500); + + setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE); + + udelay(1000000 / mode->refresh + 500); + + /* + * Sometimes the display pipeline does not sync up properly, if + * this happens the hdmi fifo underrun or overrun bits are set. + */ + if (readl(&hdmi->irq) & + (SUNXI_HDMI_IRQ_STATUS_FIFO_UF | SUNXI_HDMI_IRQ_STATUS_FIFO_OF)) { + if (retries--) + goto retry; + printf("HDMI fifo under or overrun\n"); + } +} + +void *video_hw_init(void) +{ + static GraphicDevice *graphic_device = &sunxi_display.graphic_device; + /* + * Vesa standard 1024x768@60 + * 65.0 1024 1048 1184 1344 768 771 777 806 -hsync -vsync + */ + struct fb_videomode mode = { + .name = "1024x768", + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = 65000, + .left_margin = 160, + .right_margin = 24, + .upper_margin = 29, + .lower_margin = 3, + .hsync_len = 136, + .vsync_len = 6, + .sync = 0, + .vmode = 0, + .flag = 0, + }; + int ret; + + memset(&sunxi_display, 0, sizeof(struct sunxi_display)); + + printf("Reserved %dkB of RAM for Framebuffer.\n", + CONFIG_SUNXI_FB_SIZE >> 10); + gd->fb_base = gd->ram_top; + + ret = sunxi_hdmi_hpd_detect(); + if (!ret) + return NULL; + + printf("HDMI connected.\n"); + sunxi_display.enabled = true; + + printf("Setting up a %s console.\n", mode.name); + sunxi_engines_init(); + sunxi_mode_set(&mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE); + + /* + * These are the only members of this structure that are used. All the + * others are driver specific. There is nothing to decribe pitch or + * stride, but we are lucky with our hw. + */ + graphic_device->frameAdrs = gd->fb_base; + graphic_device->gdfIndex = GDF_32BIT_X888RGB; + graphic_device->gdfBytesPP = 4; + graphic_device->winSizeX = mode.xres; + graphic_device->winSizeY = mode.yres; + + return graphic_device; +} + +/* + * Simplefb support. + */ +#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB) +int sunxi_simplefb_setup(void *blob) +{ + static GraphicDevice *graphic_device = &sunxi_display.graphic_device; + int offset, ret; + + if (!sunxi_display.enabled) + return 0; + + /* Find a framebuffer node, with pipeline == "de_be0-lcd0-hdmi" */ + offset = fdt_node_offset_by_compatible(blob, -1, + "allwinner,simple-framebuffer"); + while (offset >= 0) { + ret = fdt_find_string(blob, offset, "allwinner,pipeline", + "de_be0-lcd0-hdmi"); + if (ret == 0) + break; + offset = fdt_node_offset_by_compatible(blob, offset, + "allwinner,simple-framebuffer"); + } + if (offset < 0) { + eprintf("Cannot setup simplefb: node not found\n"); + return 0; /* Keep older kernels working */ + } + + ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base, + graphic_device->winSizeX, graphic_device->winSizeY, + graphic_device->winSizeX * graphic_device->gdfBytesPP, + "x8r8g8b8"); + if (ret) + eprintf("Cannot setup simplefb: Error setting properties\n"); + + return ret; +} +#endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */ diff --git a/drivers/video/x86_fb.c b/drivers/video/x86_fb.c new file mode 100644 index 0000000..8743a8c --- /dev/null +++ b/drivers/video/x86_fb.c @@ -0,0 +1,37 @@ +/* + * + * Vesa frame buffer driver for x86 + * + * Copyright (C) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <video_fb.h> +#include <vbe.h> +#include "videomodes.h" + +/* + * The Graphic Device + */ +GraphicDevice ctfb; + +void *video_hw_init(void) +{ + GraphicDevice *gdev = &ctfb; + int bits_per_pixel; + + printf("Video: "); + if (vbe_get_video_info(gdev)) { + printf("No video mode configured\n"); + return NULL; + } + + bits_per_pixel = gdev->gdfBytesPP * 8; + sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY, + bits_per_pixel); + printf("%s\n", gdev->modeIdent); + + return (void *)gdev; +} |