summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/bios_emulator/Makefile2
-rw-r--r--drivers/bios_emulator/atibios.c198
-rw-r--r--drivers/bios_emulator/besys.c100
-rw-r--r--drivers/bios_emulator/bios.c4
-rw-r--r--drivers/bios_emulator/biosemui.h2
-rw-r--r--drivers/bios_emulator/include/biosemu.h53
-rw-r--r--drivers/bios_emulator/include/x86emu.h7
-rw-r--r--drivers/bios_emulator/include/x86emu/debug.h20
-rw-r--r--drivers/bios_emulator/include/x86emu/regs.h2
-rw-r--r--drivers/bios_emulator/x86emu/debug.c10
-rw-r--r--drivers/bios_emulator/x86emu/decode.c24
-rw-r--r--drivers/bios_emulator/x86emu/ops.c58
-rw-r--r--drivers/bios_emulator/x86emu/ops2.c4
-rw-r--r--drivers/bios_emulator/x86emu/sys.c5
-rw-r--r--drivers/block/ahci.c2
-rw-r--r--drivers/block/ata_piix.c5
-rw-r--r--drivers/block/dwc_ahsata.c23
-rw-r--r--drivers/block/fsl_sata.c5
-rw-r--r--drivers/block/pata_bfin.c5
-rw-r--r--drivers/block/pata_bfin.h1
-rw-r--r--drivers/block/sata_dwc.c5
-rw-r--r--drivers/block/sata_sil.c7
-rw-r--r--drivers/block/sata_sil3114.c5
-rw-r--r--drivers/core/Makefile3
-rw-r--r--drivers/core/device-remove.c187
-rw-r--r--drivers/core/device.c178
-rw-r--r--drivers/core/lists.c50
-rw-r--r--drivers/core/root.c4
-rw-r--r--drivers/ddr/fsl/arm_ddr_gen3.c45
-rw-r--r--drivers/ddr/fsl/ctrl_regs.c53
-rw-r--r--drivers/ddr/fsl/ddr4_dimm_params.c22
-rw-r--r--drivers/ddr/fsl/fsl_ddr_gen4.c44
-rw-r--r--drivers/ddr/fsl/lc_common_dimm_params.c62
-rw-r--r--drivers/ddr/fsl/main.c3
-rw-r--r--drivers/ddr/fsl/mpc85xx_ddr_gen3.c67
-rw-r--r--drivers/dfu/dfu.c2
-rw-r--r--drivers/fpga/zynqpl.c10
-rw-r--r--drivers/gpio/at91_gpio.c241
-rw-r--r--drivers/gpio/gpio-uclass.c19
-rw-r--r--drivers/gpio/intel_ich6_gpio.c79
-rw-r--r--drivers/i2c/Makefile2
-rw-r--r--drivers/i2c/adi_i2c.c305
-rw-r--r--drivers/i2c/bfin-twi_i2c.c379
-rw-r--r--drivers/i2c/fsl_i2c.c2
-rw-r--r--drivers/i2c/i2c_core.c8
-rw-r--r--drivers/misc/cros_ec.c1
-rw-r--r--drivers/misc/cros_ec_spi.c2
-rw-r--r--drivers/misc/mxc_ocotp.c6
-rw-r--r--drivers/misc/mxs_ocotp.c14
-rw-r--r--drivers/mmc/fsl_esdhc.c10
-rw-r--r--drivers/mmc/mmc.c7
-rw-r--r--drivers/mmc/omap_hsmmc.c12
-rw-r--r--drivers/mmc/pxa_mmc_gen.c6
-rw-r--r--drivers/mmc/sh_mmcif.c19
-rw-r--r--drivers/mmc/sh_mmcif.h8
-rw-r--r--drivers/mtd/cfi_mtd.c1
-rw-r--r--drivers/mtd/jedec_flash.c51
-rw-r--r--drivers/mtd/nand/Kconfig7
-rw-r--r--drivers/mtd/nand/atmel_nand.c115
-rw-r--r--drivers/mtd/nand/atmel_nand_ecc.h4
-rw-r--r--drivers/mtd/nand/denali.c132
-rw-r--r--drivers/mtd/nand/denali.h5
-rw-r--r--drivers/mtd/nand/denali_spl.c2
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c2
-rw-r--r--drivers/mtd/nand/fsl_ifc_spl.c10
-rw-r--r--drivers/mtd/nand/nand_base.c10
-rw-r--r--drivers/mtd/nand/omap_gpmc.c9
-rw-r--r--drivers/mtd/nand/s3c2410_nand.c38
-rw-r--r--drivers/mtd/nand/vf610_nfc.c3
-rw-r--r--drivers/mtd/spi/sandbox.c6
-rw-r--r--drivers/mtd/spi/sf_ops.c5
-rw-r--r--drivers/net/fm/Makefile2
-rw-r--r--drivers/net/fm/b4860.c64
-rw-r--r--drivers/net/fm/eth.c23
-rw-r--r--drivers/net/fm/init.c2
-rw-r--r--drivers/net/fm/memac.c12
-rw-r--r--drivers/net/fm/memac_phy.c7
-rw-r--r--drivers/net/fm/t1024.c88
-rw-r--r--drivers/net/fm/t1040.c4
-rw-r--r--drivers/net/macb.c17
-rw-r--r--drivers/net/netconsole.c2
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/cortina.c333
-rw-r--r--drivers/net/phy/phy.c3
-rw-r--r--drivers/net/phy/vitesse.c13
-rw-r--r--drivers/pci/Makefile3
-rw-r--r--drivers/pci/pci.c33
-rw-r--r--drivers/pci/pci_auto.c2
-rw-r--r--drivers/pci/pci_rom.c278
-rw-r--r--drivers/pci/pcie_layerscape.c51
-rw-r--r--drivers/power/palmas.c2
-rw-r--r--drivers/power/pmic/pmic_max77686.c52
-rw-r--r--drivers/power/power_i2c.c2
-rw-r--r--drivers/power/twl4030.c28
-rw-r--r--drivers/qe/Makefile3
-rw-r--r--drivers/qe/fdt.c2
-rw-r--r--drivers/qe/qe.c140
-rw-r--r--drivers/qe/qe.h5
-rw-r--r--drivers/rtc/bfin_rtc.c2
-rw-r--r--drivers/rtc/mc146818.c43
-rw-r--r--drivers/rtc/mvrtc.h2
-rw-r--r--drivers/serial/atmel_usart.c116
-rw-r--r--drivers/serial/ns16550.c9
-rw-r--r--drivers/serial/serial-uclass.c112
-rw-r--r--drivers/serial/serial_pl01x.c48
-rw-r--r--drivers/serial/serial_sh.h2
-rw-r--r--drivers/serial/serial_tegra.c16
-rw-r--r--drivers/serial/serial_uniphier.c19
-rw-r--r--drivers/serial/usbtty.c2
-rw-r--r--drivers/spi/atmel_spi.h4
-rw-r--r--drivers/spi/fsl_espi.c4
-rw-r--r--drivers/spi/mxc_spi.c2
-rw-r--r--drivers/spi/spi-uclass.c36
-rw-r--r--drivers/spi/ti_qspi.c8
-rw-r--r--drivers/thermal/Makefile9
-rw-r--r--drivers/thermal/imx_thermal.c175
-rw-r--r--drivers/thermal/thermal-uclass.c30
-rw-r--r--drivers/tpm/tpm.c2
-rw-r--r--drivers/tpm/tpm_tis_i2c.c2
-rw-r--r--drivers/tpm/tpm_tis_lpc.c2
-rw-r--r--drivers/usb/gadget/composite.c4
-rw-r--r--drivers/usb/gadget/designware_udc.c4
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c3
-rw-r--r--drivers/usb/gadget/s3c_udc_otg_xfer_dma.c4
-rw-r--r--drivers/usb/host/dwc2.c14
-rw-r--r--drivers/usb/host/ehci-exynos.c55
-rw-r--r--drivers/usb/host/ehci-fsl.c191
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-uniphier.c38
-rw-r--r--drivers/usb/host/isp116x-hcd.c6
-rw-r--r--drivers/usb/host/ohci-hcd.c5
-rw-r--r--drivers/usb/host/ohci-s3c24xx.c3
-rw-r--r--drivers/usb/host/r8a66597-hcd.c3
-rw-r--r--drivers/usb/host/xhci-ring.c2
-rw-r--r--drivers/usb/host/xhci.c2
-rw-r--r--drivers/usb/musb/musb_hcd.h3
-rw-r--r--drivers/usb/phy/omap_usb_phy.c2
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/ati_radeon_fb.c7
-rw-r--r--drivers/video/cfb_console.c27
-rw-r--r--drivers/video/sunxi_display.c451
-rw-r--r--drivers/video/x86_fb.c37
143 files changed, 4206 insertions, 1275 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 33227c8..5ef58c0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -16,8 +16,10 @@ 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/
# SOC specific infrastructure drivers.
obj-y += soc/
+obj-y += thermal/
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, &regs, &sregs);
/*Cleanup and exit*/
- BE_getVGA(VGAInfo);
+ BE_getVGA(vga_info);
+
+ if (vesa_mode != -1)
+ atibios_set_vesa_mode(&regs, 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/ahci.c b/drivers/block/ahci.c
index a93a8e1..c9a3beb 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -730,7 +730,7 @@ static int ata_scsiop_read_write(ccb *pccb, u8 is_write)
u16 now_blocks; /* number of blocks per iteration */
u32 transfer_size; /* number of bytes per iteration */
- now_blocks = min(MAX_SATA_BLOCKS_READ_WRITE, blocks);
+ now_blocks = min((u16)MAX_SATA_BLOCKS_READ_WRITE, blocks);
transfer_size = ATA_SECT_SIZE * now_blocks;
if (transfer_size > user_buffer_size) {
diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c
index 5cf91ad..3042684 100644
--- a/drivers/block/ata_piix.c
+++ b/drivers/block/ata_piix.c
@@ -192,6 +192,11 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
static inline u8 sata_inb(unsigned long ioaddr)
{
return inb(ioaddr);
diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c
index c68fd2f..01a4148 100644
--- a/drivers/block/dwc_ahsata.c
+++ b/drivers/block/dwc_ahsata.c
@@ -592,6 +592,29 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ struct ahci_probe_ent *probe_ent;
+ struct sata_host_regs *host_mmio;
+
+ if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
+ printf("The sata index %d is out of ranges\n\r", dev);
+ return -1;
+ }
+
+ probe_ent = (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ if (NULL == probe_ent)
+ /* not initialized, so nothing to reset */
+ return 0;
+
+ host_mmio = (struct sata_host_regs *)probe_ent->mmio_base;
+ setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR);
+ while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR)
+ udelay(100);
+
+ return 0;
+}
+
static void dwc_ahsata_print_info(int dev)
{
block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
diff --git a/drivers/block/fsl_sata.c b/drivers/block/fsl_sata.c
index ebd6261..71d7cec 100644
--- a/drivers/block/fsl_sata.c
+++ b/drivers/block/fsl_sata.c
@@ -255,6 +255,11 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
static void fsl_sata_dump_regs(fsl_sata_reg_t __iomem *reg)
{
printf("\n\rSATA: %08x\n\r", (u32)reg);
diff --git a/drivers/block/pata_bfin.c b/drivers/block/pata_bfin.c
index b7fd1cd..c2673bd 100644
--- a/drivers/block/pata_bfin.c
+++ b/drivers/block/pata_bfin.c
@@ -1009,6 +1009,11 @@ int init_sata(int dev)
return res;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
/* Read up to 255 sectors
*
* Returns sectors read
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/block/sata_dwc.c b/drivers/block/sata_dwc.c
index efca5ea..9e8b067 100644
--- a/drivers/block/sata_dwc.c
+++ b/drivers/block/sata_dwc.c
@@ -423,6 +423,11 @@ int init_sata(int dev)
return rc;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
static u8 ata_check_altstatus(struct ata_port *ap)
{
u8 val = 0;
diff --git a/drivers/block/sata_sil.c b/drivers/block/sata_sil.c
index 1f510cd..daff7d4 100644
--- a/drivers/block/sata_sil.c
+++ b/drivers/block/sata_sil.c
@@ -519,7 +519,7 @@ int init_sata(int dev)
u16 word;
if (init_done == 1 && dev < sata_info.maxport)
- return 1;
+ return 0;
init_done = 1;
@@ -571,6 +571,11 @@ int init_sata(int dev)
return 0;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
/*
* SATA interface between low level driver and command layer
*/
diff --git a/drivers/block/sata_sil3114.c b/drivers/block/sata_sil3114.c
index 3aa6fc9..61ffb66 100644
--- a/drivers/block/sata_sil3114.c
+++ b/drivers/block/sata_sil3114.c
@@ -702,6 +702,11 @@ int init_sata (int dev)
return res;
}
+int reset_sata(int dev)
+{
+ return 0;
+}
+
/* Check if device is connected to port */
int sata_bus_probe (int portno)
{
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index 151c239..f14695b 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -4,5 +4,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y := device.o lists.o root.o uclass.o util.o
+obj-$(CONFIG_DM) += device.o lists.o root.o uclass.o util.o
obj-$(CONFIG_OF_CONTROL) += simple-bus.o
+obj-$(CONFIG_DM_DEVICE_REMOVE) += device-remove.o
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
new file mode 100644
index 0000000..8fc6b71
--- /dev/null
+++ b/drivers/core/device-remove.c
@@ -0,0 +1,187 @@
+/*
+ * Device manager
+ *
+ * Copyright (c) 2014 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/uclass.h>
+#include <dm/uclass-internal.h>
+#include <dm/util.h>
+
+/**
+ * device_chld_unbind() - Unbind all device's children from the device
+ *
+ * On error, the function continues to unbind all children, and reports the
+ * first error.
+ *
+ * @dev: The device that is to be stripped of its children
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_unbind(struct udevice *dev)
+{
+ struct udevice *pos, *n;
+ int ret, saved_ret = 0;
+
+ assert(dev);
+
+ list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+ ret = device_unbind(pos);
+ if (ret && !saved_ret)
+ saved_ret = ret;
+ }
+
+ return saved_ret;
+}
+
+/**
+ * device_chld_remove() - Stop all device's children
+ * @dev: The device whose children are to be removed
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_remove(struct udevice *dev)
+{
+ struct udevice *pos, *n;
+ int ret;
+
+ assert(dev);
+
+ list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+ ret = device_remove(pos);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int device_unbind(struct udevice *dev)
+{
+ struct driver *drv;
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (dev->flags & DM_FLAG_ACTIVATED)
+ return -EINVAL;
+
+ drv = dev->driver;
+ assert(drv);
+
+ if (drv->unbind) {
+ ret = drv->unbind(dev);
+ if (ret)
+ return ret;
+ }
+
+ ret = device_chld_unbind(dev);
+ if (ret)
+ return ret;
+
+ ret = uclass_unbind_device(dev);
+ if (ret)
+ return ret;
+
+ if (dev->parent)
+ list_del(&dev->sibling_node);
+ free(dev);
+
+ return 0;
+}
+
+/**
+ * device_free() - Free memory buffers allocated by a device
+ * @dev: Device that is to be started
+ */
+void device_free(struct udevice *dev)
+{
+ int size;
+
+ if (dev->driver->priv_auto_alloc_size) {
+ free(dev->priv);
+ dev->priv = NULL;
+ }
+ if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+ free(dev->platdata);
+ dev->platdata = NULL;
+ }
+ size = dev->uclass->uc_drv->per_device_auto_alloc_size;
+ if (size) {
+ free(dev->uclass_priv);
+ dev->uclass_priv = NULL;
+ }
+ if (dev->parent) {
+ size = dev->parent->driver->per_child_auto_alloc_size;
+ if (size) {
+ free(dev->parent_priv);
+ dev->parent_priv = NULL;
+ }
+ }
+}
+
+int device_remove(struct udevice *dev)
+{
+ struct driver *drv;
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (!(dev->flags & DM_FLAG_ACTIVATED))
+ return 0;
+
+ drv = dev->driver;
+ assert(drv);
+
+ ret = uclass_pre_remove_device(dev);
+ if (ret)
+ return ret;
+
+ ret = device_chld_remove(dev);
+ if (ret)
+ goto err;
+
+ if (drv->remove) {
+ ret = drv->remove(dev);
+ if (ret)
+ goto err_remove;
+ }
+
+ if (dev->parent && dev->parent->driver->child_post_remove) {
+ ret = dev->parent->driver->child_post_remove(dev);
+ if (ret) {
+ dm_warn("%s: Device '%s' failed child_post_remove()",
+ __func__, dev->name);
+ }
+ }
+
+ device_free(dev);
+
+ dev->seq = -1;
+ dev->flags &= ~DM_FLAG_ACTIVATED;
+
+ return ret;
+
+err_remove:
+ /* We can't put the children back */
+ dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
+ __func__, dev->name);
+err:
+ ret = uclass_post_probe_device(dev);
+ if (ret) {
+ dm_warn("%s: Device '%s' failed to post_probe on error path\n",
+ __func__, dev->name);
+ }
+
+ return ret;
+}
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 49faa29..6793e1c 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -24,52 +24,6 @@
DECLARE_GLOBAL_DATA_PTR;
-/**
- * device_chld_unbind() - Unbind all device's children from the device
- *
- * On error, the function continues to unbind all children, and reports the
- * first error.
- *
- * @dev: The device that is to be stripped of its children
- * @return 0 on success, -ve on error
- */
-static int device_chld_unbind(struct udevice *dev)
-{
- struct udevice *pos, *n;
- int ret, saved_ret = 0;
-
- assert(dev);
-
- list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
- ret = device_unbind(pos);
- if (ret && !saved_ret)
- saved_ret = ret;
- }
-
- return saved_ret;
-}
-
-/**
- * device_chld_remove() - Stop all device's children
- * @dev: The device whose children are to be removed
- * @return 0 on success, -ve on error
- */
-static int device_chld_remove(struct udevice *dev)
-{
- struct udevice *pos, *n;
- int ret;
-
- assert(dev);
-
- list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
- ret = device_remove(pos);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
int device_bind(struct udevice *parent, struct driver *drv, const char *name,
void *platdata, int of_offset, struct udevice **devp)
{
@@ -167,71 +121,6 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
-1, devp);
}
-int device_unbind(struct udevice *dev)
-{
- struct driver *drv;
- int ret;
-
- if (!dev)
- return -EINVAL;
-
- if (dev->flags & DM_FLAG_ACTIVATED)
- return -EINVAL;
-
- drv = dev->driver;
- assert(drv);
-
- if (drv->unbind) {
- ret = drv->unbind(dev);
- if (ret)
- return ret;
- }
-
- ret = device_chld_unbind(dev);
- if (ret)
- return ret;
-
- ret = uclass_unbind_device(dev);
- if (ret)
- return ret;
-
- if (dev->parent)
- list_del(&dev->sibling_node);
- free(dev);
-
- return 0;
-}
-
-/**
- * device_free() - Free memory buffers allocated by a device
- * @dev: Device that is to be started
- */
-static void device_free(struct udevice *dev)
-{
- int size;
-
- if (dev->driver->priv_auto_alloc_size) {
- free(dev->priv);
- dev->priv = NULL;
- }
- if (dev->flags & DM_FLAG_ALLOC_PDATA) {
- free(dev->platdata);
- dev->platdata = NULL;
- }
- size = dev->uclass->uc_drv->per_device_auto_alloc_size;
- if (size) {
- free(dev->uclass_priv);
- dev->uclass_priv = NULL;
- }
- if (dev->parent) {
- size = dev->parent->driver->per_child_auto_alloc_size;
- if (size) {
- free(dev->parent_priv);
- dev->parent_priv = NULL;
- }
- }
-}
-
int device_probe_child(struct udevice *dev, void *parent_priv)
{
struct driver *drv;
@@ -342,63 +231,6 @@ int device_probe(struct udevice *dev)
return device_probe_child(dev, NULL);
}
-int device_remove(struct udevice *dev)
-{
- struct driver *drv;
- int ret;
-
- if (!dev)
- return -EINVAL;
-
- if (!(dev->flags & DM_FLAG_ACTIVATED))
- return 0;
-
- drv = dev->driver;
- assert(drv);
-
- ret = uclass_pre_remove_device(dev);
- if (ret)
- return ret;
-
- ret = device_chld_remove(dev);
- if (ret)
- goto err;
-
- if (drv->remove) {
- ret = drv->remove(dev);
- if (ret)
- goto err_remove;
- }
-
- if (dev->parent && dev->parent->driver->child_post_remove) {
- ret = dev->parent->driver->child_post_remove(dev);
- if (ret) {
- dm_warn("%s: Device '%s' failed child_post_remove()",
- __func__, dev->name);
- }
- }
-
- device_free(dev);
-
- dev->seq = -1;
- dev->flags &= ~DM_FLAG_ACTIVATED;
-
- return ret;
-
-err_remove:
- /* We can't put the children back */
- dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
- __func__, dev->name);
-err:
- ret = uclass_post_probe_device(dev);
- if (ret) {
- dm_warn("%s: Device '%s' failed to post_probe on error path\n",
- __func__, dev->name);
- }
-
- return ret;
-}
-
void *dev_get_platdata(struct udevice *dev)
{
if (!dev) {
@@ -548,3 +380,13 @@ int device_find_next_child(struct udevice **devp)
return 0;
}
+
+struct udevice *dev_get_parent(struct udevice *child)
+{
+ return child->parent;
+}
+
+ulong dev_get_of_data(struct udevice *dev)
+{
+ return dev->of_id->data;
+}
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 3a1ea85..ff115c4 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -25,9 +25,6 @@ struct driver *lists_driver_lookup_name(const char *name)
const int n_ents = ll_entry_count(struct driver, driver);
struct driver *entry;
- if (!drv || !n_ents)
- return NULL;
-
for (entry = drv; entry != drv + n_ents; entry++) {
if (!strcmp(name, entry->name))
return entry;
@@ -44,9 +41,6 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id)
const int n_ents = ll_entry_count(struct uclass_driver, uclass);
struct uclass_driver *entry;
- if ((id == UCLASS_INVALID) || !uclass)
- return NULL;
-
for (entry = uclass; entry != uclass + n_ents; entry++) {
if (entry->id == id)
return entry;
@@ -77,34 +71,60 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
return result;
}
+int device_bind_driver(struct udevice *parent, const char *drv_name,
+ const char *dev_name, struct udevice **devp)
+{
+ struct driver *drv;
+ int ret;
+
+ drv = lists_driver_lookup_name(drv_name);
+ if (!drv) {
+ printf("Cannot find driver '%s'\n", drv_name);
+ return -ENOENT;
+ }
+ ret = device_bind(parent, drv, dev_name, NULL, -1, devp);
+ if (ret) {
+ printf("Cannot create device named '%s' (err=%d)\n",
+ dev_name, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_OF_CONTROL
/**
* driver_check_compatible() - Check if a driver is compatible with this node
*
* @param blob: Device tree pointer
* @param offset: Offset of node in device tree
- * @param of_matchL List of compatible strings to match
+ * @param of_match: List of compatible strings to match
+ * @param of_idp: Returns the match that was found
* @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
* does not have a compatible string, other error <0 if there is a device
* tree error
*/
static int driver_check_compatible(const void *blob, int offset,
- const struct udevice_id *of_match)
+ const struct udevice_id *of_match,
+ const struct udevice_id **of_idp)
{
int ret;
+ *of_idp = NULL;
if (!of_match)
return -ENOENT;
while (of_match->compatible) {
ret = fdt_node_check_compatible(blob, offset,
of_match->compatible);
- if (!ret)
+ if (!ret) {
+ *of_idp = of_match;
return 0;
- else if (ret == -FDT_ERR_NOTFOUND)
+ } else if (ret == -FDT_ERR_NOTFOUND) {
return -ENODEV;
- else if (ret < 0)
+ } else if (ret < 0) {
return -EINVAL;
+ }
of_match++;
}
@@ -116,6 +136,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
{
struct driver *driver = ll_entry_start(struct driver, driver);
const int n_ents = ll_entry_count(struct driver, driver);
+ const struct udevice_id *id;
struct driver *entry;
struct udevice *dev;
bool found = false;
@@ -127,7 +148,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
if (devp)
*devp = NULL;
for (entry = driver; entry != driver + n_ents; entry++) {
- ret = driver_check_compatible(blob, offset, entry->of_match);
+ ret = driver_check_compatible(blob, offset, entry->of_match,
+ &id);
name = fdt_get_name(blob, offset, NULL);
if (ret == -ENOENT) {
continue;
@@ -136,8 +158,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
break;
} else if (ret) {
dm_warn("Device tree error at offset %d\n", offset);
- if (!result || ret != -ENOENT)
- result = ret;
+ result = ret;
break;
}
@@ -147,6 +168,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
dm_warn("Error binding driver '%s'\n", entry->name);
return ret;
} else {
+ dev->of_id = id;
found = true;
if (devp)
*devp = dev;
diff --git a/drivers/core/root.c b/drivers/core/root.c
index a328a48..47b3acf 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -73,10 +73,8 @@ int dm_scan_platdata(bool pre_reloc_only)
dm_warn("Some drivers were not found\n");
ret = 0;
}
- if (ret)
- return ret;
- return 0;
+ return ret;
}
#ifdef CONFIG_OF_CONTROL
diff --git a/drivers/ddr/fsl/arm_ddr_gen3.c b/drivers/ddr/fsl/arm_ddr_gen3.c
index 59f2fd6..c139da6 100644
--- a/drivers/ddr/fsl/arm_ddr_gen3.c
+++ b/drivers/ddr/fsl/arm_ddr_gen3.c
@@ -92,7 +92,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->timing_cfg_0, regs->timing_cfg_0);
ddr_out32(&ddr->timing_cfg_1, regs->timing_cfg_1);
ddr_out32(&ddr->timing_cfg_2, regs->timing_cfg_2);
- ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
ddr_out32(&ddr->sdram_mode, regs->ddr_sdram_mode);
ddr_out32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
ddr_out32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
@@ -105,9 +104,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->sdram_interval, regs->ddr_sdram_interval);
ddr_out32(&ddr->sdram_data_init, regs->ddr_data_init);
ddr_out32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
- ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
- ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
-
ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg_4);
ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg_5);
ddr_out32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
@@ -128,7 +124,24 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
ddr_out32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
ddr_out32(&ddr->ddr_cdr1, regs->ddr_cdr1);
- ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+#ifdef CONFIG_DEEP_SLEEP
+ if (is_warm_boot()) {
+ ddr_out32(&ddr->sdram_cfg_2,
+ regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+ ddr_out32(&ddr->init_addr, CONFIG_SYS_SDRAM_BASE);
+ ddr_out32(&ddr->init_ext_addr, DDR_INIT_ADDR_EXT_UIA);
+
+ /* DRAM VRef will not be trained */
+ ddr_out32(&ddr->ddr_cdr2,
+ regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
+ } else
+#endif
+ {
+ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
+ ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+ ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+ }
ddr_out32(&ddr->err_disable, regs->err_disable);
ddr_out32(&ddr->err_int_en, regs->err_int_en);
for (i = 0; i < 32; i++) {
@@ -167,8 +180,20 @@ step2:
udelay(500);
asm volatile("dsb sy;isb");
+#ifdef CONFIG_DEEP_SLEEP
+ if (is_warm_boot()) {
+ /* enter self-refresh */
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg_2);
+ temp_sdram_cfg |= SDRAM_CFG2_FRC_SR;
+ ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+ /* do board specific memory setup */
+ board_mem_sleep_setup();
+
+ temp_sdram_cfg = (ddr_in32(&ddr->sdram_cfg) | SDRAM_CFG_BI);
+ } else
+#endif
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
/* Let the controller go */
- temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
asm volatile("dsb sy;isb");
@@ -211,4 +236,12 @@ step2:
if (timeout <= 0)
printf("Waiting for D_INIT timeout. Memory may not work.\n");
+#ifdef CONFIG_DEEP_SLEEP
+ if (is_warm_boot()) {
+ /* exit self-refresh */
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg_2);
+ temp_sdram_cfg &= ~SDRAM_CFG2_FRC_SR;
+ ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+ }
+#endif
}
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 9a156bf..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;
}
@@ -303,7 +311,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
#ifdef CONFIG_SYS_FSL_DDR4
/* tXP=max(4nCK, 6ns) */
- int txp = max(mclk_ps * 4, 6000); /* unit=ps */
+ int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
trwt_mclk = 2;
twrt_mclk = 1;
act_pd_exit_mclk = picos_to_mclk(txp);
@@ -312,10 +320,11 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
* MRS_CYC = max(tMRD, tMOD)
* tMRD = 8nCK, tMOD = max(24nCK, 15ns)
*/
- tmrd_mclk = max(24, picos_to_mclk(15000));
+ tmrd_mclk = max(24U, picos_to_mclk(15000));
#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,
@@ -325,19 +334,29 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
* spec has not the tAXPD, we use
* tAXPD=1, need design to confirm.
*/
- txp = max(mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
+ txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
tmrd_mclk = 4;
/* 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,
@@ -511,8 +530,8 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
#ifdef CONFIG_SYS_FSL_DDR4
refrec_ctrl = picos_to_mclk(common_dimm->trfc1_ps) - 8;
wrrec_mclk = picos_to_mclk(common_dimm->twr_ps);
- acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4);
- wrtord_mclk = max(2, picos_to_mclk(2500));
+ acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4U);
+ wrtord_mclk = max(2U, picos_to_mclk(2500));
if ((wrrec_mclk < 1) || (wrrec_mclk > 24))
printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
else
@@ -627,14 +646,14 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
wr_data_delay = popts->write_data_delay;
#ifdef CONFIG_SYS_FSL_DDR4
cpo = 0;
- cke_pls = max(3, picos_to_mclk(5000));
+ cke_pls = max(3U, picos_to_mclk(5000));
#elif defined(CONFIG_SYS_FSL_DDR3)
/*
* cke pulse = max(3nCK, 7.5ns) for DDR3-800
* max(3nCK, 5.625ns) for DDR3-1066, 1333
* max(3nCK, 5ns) for DDR3-1600, 1866, 2133
*/
- cke_pls = max(3, picos_to_mclk(mclk_ps > 1870 ? 7500 :
+ cke_pls = max(3U, picos_to_mclk(mclk_ps > 1870 ? 7500 :
(mclk_ps > 1245 ? 5625 : 5000)));
#else
cke_pls = FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR;
@@ -1810,9 +1829,9 @@ static void set_timing_cfg_7(fsl_ddr_cfg_regs_t *ddr,
unsigned int txpr, tcksre, tcksrx;
unsigned int cke_rst, cksre, cksrx, par_lat, cs_to_cmd;
- txpr = max(5, picos_to_mclk(common_dimm->trfc1_ps + 10000));
- tcksre = max(5, picos_to_mclk(10000));
- tcksrx = max(5, picos_to_mclk(10000));
+ txpr = max(5U, picos_to_mclk(common_dimm->trfc1_ps + 10000));
+ tcksre = max(5U, picos_to_mclk(10000));
+ tcksrx = max(5U, picos_to_mclk(10000));
par_lat = 0;
cs_to_cmd = 0;
@@ -1877,7 +1896,7 @@ static void set_timing_cfg_8(fsl_ddr_cfg_regs_t *ddr,
}
acttoact_bg = picos_to_mclk(common_dimm->trrdl_ps);
- wrtord_bg = max(4, picos_to_mclk(7500));
+ wrtord_bg = max(4U, picos_to_mclk(7500));
if (popts->otf_burst_chop_en)
wrtord_bg += 2;
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/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index e024db9..a3c01e7 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -103,7 +103,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->dq_map_1, regs->dq_map_1);
ddr_out32(&ddr->dq_map_2, regs->dq_map_2);
ddr_out32(&ddr->dq_map_3, regs->dq_map_3);
- ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
ddr_out32(&ddr->sdram_cfg_3, regs->ddr_sdram_cfg_3);
ddr_out32(&ddr->sdram_mode, regs->ddr_sdram_mode);
ddr_out32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
@@ -124,8 +123,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
ddr_out32(&ddr->sdram_interval, regs->ddr_sdram_interval);
ddr_out32(&ddr->sdram_data_init, regs->ddr_data_init);
- ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
- ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
ddr_out32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
#ifndef CONFIG_SYS_FSL_DDR_EMU
/*
@@ -147,7 +144,24 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->ddr_sdram_rcw_5, regs->ddr_sdram_rcw_5);
ddr_out32(&ddr->ddr_sdram_rcw_6, regs->ddr_sdram_rcw_6);
ddr_out32(&ddr->ddr_cdr1, regs->ddr_cdr1);
- ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+#ifdef CONFIG_DEEP_SLEEP
+ if (is_warm_boot()) {
+ ddr_out32(&ddr->sdram_cfg_2,
+ regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+ ddr_out32(&ddr->init_addr, CONFIG_SYS_SDRAM_BASE);
+ ddr_out32(&ddr->init_ext_addr, DDR_INIT_ADDR_EXT_UIA);
+
+ /* DRAM VRef will not be trained */
+ ddr_out32(&ddr->ddr_cdr2,
+ regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
+ } else
+#endif
+ {
+ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
+ ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+ ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+ }
ddr_out32(&ddr->err_disable, regs->err_disable);
ddr_out32(&ddr->err_int_en, regs->err_int_en);
for (i = 0; i < 32; i++) {
@@ -187,8 +201,20 @@ step2:
mb();
isb();
+#ifdef CONFIG_DEEP_SLEEP
+ if (is_warm_boot()) {
+ /* enter self-refresh */
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg_2);
+ temp_sdram_cfg |= SDRAM_CFG2_FRC_SR;
+ ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+ /* do board specific memory setup */
+ board_mem_sleep_setup();
+
+ temp_sdram_cfg = (ddr_in32(&ddr->sdram_cfg) | SDRAM_CFG_BI);
+ } else
+#endif
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
/* Let the controller go */
- temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
mb();
isb();
@@ -233,4 +259,12 @@ step2:
if (timeout <= 0)
printf("Waiting for D_INIT timeout. Memory may not work.\n");
+#ifdef CONFIG_DEEP_SLEEP
+ if (is_warm_boot()) {
+ /* exit self-refresh */
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg_2);
+ temp_sdram_cfg &= ~SDRAM_CFG2_FRC_SR;
+ ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+ }
+#endif
}
diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c
index 05a24dd..73db444 100644
--- a/drivers/ddr/fsl/lc_common_dimm_params.c
+++ b/drivers/ddr/fsl/lc_common_dimm_params.c
@@ -289,48 +289,58 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
* Find minimum tckmax_ps to find fastest slow speed,
* i.e., this is the slowest the whole system can go.
*/
- tckmax_ps = min(tckmax_ps, dimm_params[i].tckmax_ps);
+ tckmax_ps = min(tckmax_ps,
+ (unsigned int)dimm_params[i].tckmax_ps);
#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
- taamin_ps = max(taamin_ps, dimm_params[i].taa_ps);
+ taamin_ps = max(taamin_ps,
+ (unsigned int)dimm_params[i].taa_ps);
#endif
- tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps);
- trcd_ps = max(trcd_ps, dimm_params[i].trcd_ps);
- trp_ps = max(trp_ps, dimm_params[i].trp_ps);
- tras_ps = max(tras_ps, dimm_params[i].tras_ps);
+ tckmin_x_ps = max(tckmin_x_ps,
+ (unsigned int)dimm_params[i].tckmin_x_ps);
+ trcd_ps = max(trcd_ps, (unsigned int)dimm_params[i].trcd_ps);
+ trp_ps = max(trp_ps, (unsigned int)dimm_params[i].trp_ps);
+ tras_ps = max(tras_ps, (unsigned int)dimm_params[i].tras_ps);
#ifdef CONFIG_SYS_FSL_DDR4
- trfc1_ps = max(trfc1_ps, dimm_params[i].trfc1_ps);
- trfc2_ps = max(trfc2_ps, dimm_params[i].trfc2_ps);
- trfc4_ps = max(trfc4_ps, dimm_params[i].trfc4_ps);
- trrds_ps = max(trrds_ps, dimm_params[i].trrds_ps);
- trrdl_ps = max(trrdl_ps, dimm_params[i].trrdl_ps);
- tccdl_ps = max(tccdl_ps, dimm_params[i].tccdl_ps);
+ trfc1_ps = max(trfc1_ps,
+ (unsigned int)dimm_params[i].trfc1_ps);
+ trfc2_ps = max(trfc2_ps,
+ (unsigned int)dimm_params[i].trfc2_ps);
+ trfc4_ps = max(trfc4_ps,
+ (unsigned int)dimm_params[i].trfc4_ps);
+ trrds_ps = max(trrds_ps,
+ (unsigned int)dimm_params[i].trrds_ps);
+ trrdl_ps = max(trrdl_ps,
+ (unsigned int)dimm_params[i].trrdl_ps);
+ tccdl_ps = max(tccdl_ps,
+ (unsigned int)dimm_params[i].tccdl_ps);
#else
- twr_ps = max(twr_ps, dimm_params[i].twr_ps);
- twtr_ps = max(twtr_ps, dimm_params[i].twtr_ps);
- trfc_ps = max(trfc_ps, dimm_params[i].trfc_ps);
- trrd_ps = max(trrd_ps, dimm_params[i].trrd_ps);
- trtp_ps = max(trtp_ps, dimm_params[i].trtp_ps);
+ twr_ps = max(twr_ps, (unsigned int)dimm_params[i].twr_ps);
+ twtr_ps = max(twtr_ps, (unsigned int)dimm_params[i].twtr_ps);
+ trfc_ps = max(trfc_ps, (unsigned int)dimm_params[i].trfc_ps);
+ trrd_ps = max(trrd_ps, (unsigned int)dimm_params[i].trrd_ps);
+ trtp_ps = max(trtp_ps, (unsigned int)dimm_params[i].trtp_ps);
#endif
- trc_ps = max(trc_ps, dimm_params[i].trc_ps);
+ trc_ps = max(trc_ps, (unsigned int)dimm_params[i].trc_ps);
#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
- tis_ps = max(tis_ps, dimm_params[i].tis_ps);
- tih_ps = max(tih_ps, dimm_params[i].tih_ps);
- tds_ps = max(tds_ps, dimm_params[i].tds_ps);
- tdh_ps = max(tdh_ps, dimm_params[i].tdh_ps);
- tqhs_ps = max(tqhs_ps, dimm_params[i].tqhs_ps);
+ tis_ps = max(tis_ps, (unsigned int)dimm_params[i].tis_ps);
+ tih_ps = max(tih_ps, (unsigned int)dimm_params[i].tih_ps);
+ tds_ps = max(tds_ps, (unsigned int)dimm_params[i].tds_ps);
+ tdh_ps = max(tdh_ps, (unsigned int)dimm_params[i].tdh_ps);
+ tqhs_ps = max(tqhs_ps, (unsigned int)dimm_params[i].tqhs_ps);
/*
* Find maximum tdqsq_max_ps to find slowest.
*
* FIXME: is finding the slowest value the correct
* strategy for this parameter?
*/
- tdqsq_max_ps = max(tdqsq_max_ps, dimm_params[i].tdqsq_max_ps);
+ tdqsq_max_ps = max(tdqsq_max_ps,
+ (unsigned int)dimm_params[i].tdqsq_max_ps);
#endif
refresh_rate_ps = max(refresh_rate_ps,
- dimm_params[i].refresh_rate_ps);
+ (unsigned int)dimm_params[i].refresh_rate_ps);
/* extended_op_srt is either 0 or 1, 0 having priority */
extended_op_srt = min(extended_op_srt,
- dimm_params[i].extended_op_srt);
+ (unsigned int)dimm_params[i].extended_op_srt);
}
outpdimm->ndimms_present = number_of_dimms - temp1;
diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c
index b43b669..6f291eb 100644
--- a/drivers/ddr/fsl/main.c
+++ b/drivers/ddr/fsl/main.c
@@ -106,7 +106,8 @@ static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
i2c_write(SPD_SPA1_ADDRESS, 0, 1, &dummy, 1);
ret = i2c_read(i2c_address, 0, 1,
(uchar *)((ulong)spd + 256),
- min(256, sizeof(generic_spd_eeprom_t) - 256));
+ min(256,
+ (int)sizeof(generic_spd_eeprom_t) - 256));
}
#else
ret = i2c_read(i2c_address, 0, 1, (uchar *)spd,
diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
index 4d5572e..8f4d01a 100644
--- a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
+++ b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
@@ -15,8 +15,6 @@
#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
#endif
-DECLARE_GLOBAL_DATA_PTR;
-
/*
* regs has the to-be-set values for DDR controller registers
* ctrl_num is the DDR controller number
@@ -44,16 +42,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
u32 save1, save2;
#endif
-#ifdef CONFIG_DEEP_SLEEP
- const ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
- bool sleep_flag = 0;
-#endif
-
-#ifdef CONFIG_DEEP_SLEEP
- if (in_be32(&gur->scrtsr[0]) & (1 << 3))
- sleep_flag = 1;
-#endif
-
switch (ctrl_num) {
case 0:
ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
@@ -130,13 +118,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
-#ifdef CONFIG_DEEP_SLEEP
- if (sleep_flag)
- out_be32(&ddr->sdram_cfg_2,
- regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
- else
-#endif
- out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
@@ -149,17 +130,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
-#ifdef CONFIG_DEEP_SLEEP
- if (sleep_flag) {
- out_be32(&ddr->init_addr, 0);
- out_be32(&ddr->init_ext_addr, (1 << 31));
- } else
-#endif
- {
- out_be32(&ddr->init_addr, regs->ddr_init_addr);
- out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
- }
-
out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4);
out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5);
out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
@@ -180,7 +150,24 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1);
- out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+#ifdef CONFIG_DEEP_SLEEP
+ if (is_warm_boot()) {
+ out_be32(&ddr->sdram_cfg_2,
+ regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+ out_be32(&ddr->init_addr, CONFIG_SYS_SDRAM_BASE);
+ out_be32(&ddr->init_ext_addr, DDR_INIT_ADDR_EXT_UIA);
+
+ /* DRAM VRef will not be trained */
+ out_be32(&ddr->ddr_cdr2,
+ regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
+ } else
+#endif
+ {
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ out_be32(&ddr->init_addr, regs->ddr_init_addr);
+ out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+ out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+ }
out_be32(&ddr->err_disable, regs->err_disable);
out_be32(&ddr->err_int_en, regs->err_int_en);
for (i = 0; i < 32; i++) {
@@ -400,21 +387,17 @@ step2:
asm volatile("sync;isync");
#ifdef CONFIG_DEEP_SLEEP
- if (sleep_flag) {
+ if (is_warm_boot()) {
/* enter self-refresh */
- setbits_be32(&ddr->sdram_cfg_2, (1 << 31));
+ setbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_FRC_SR);
/* do board specific memory setup */
board_mem_sleep_setup();
- }
-#endif
-
- /* Let the controller go */
-#ifdef CONFIG_DEEP_SLEEP
- if (sleep_flag)
temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) | SDRAM_CFG_BI);
- else
+ } else
#endif
temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI);
+
+ /* Let the controller go */
out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
asm volatile("sync;isync");
@@ -566,8 +549,8 @@ step2:
}
#endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */
#ifdef CONFIG_DEEP_SLEEP
- if (sleep_flag)
+ if (is_warm_boot())
/* exit self-refresh */
- clrbits_be32(&ddr->sdram_cfg_2, (1 << 31));
+ clrbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_FRC_SR);
#endif
}
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index deafda2..14cb366 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -289,7 +289,7 @@ static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size)
readn = 0;
while (size > 0) {
/* get chunk that can be read */
- chunk = min(size, dfu->b_left);
+ chunk = min((long)size, dfu->b_left);
/* consume */
if (chunk > 0) {
memcpy(buf, dfu->i_buf, chunk);
diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
index 68fe0f3..6a74f89 100644
--- a/drivers/fpga/zynqpl.c
+++ b/drivers/fpga/zynqpl.c
@@ -406,8 +406,8 @@ static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
unsigned long ts; /* Timestamp */
u32 isr_status, swap;
u32 partialbit = 0;
- u32 blocksize;
- u32 pos = 0;
+ loff_t blocksize, actread;
+ loff_t pos = 0;
int fstype;
char *interface, *dev_part, *filename;
@@ -420,7 +420,7 @@ static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
if (fs_set_blk_dev(interface, dev_part, fstype))
return FPGA_FAIL;
- if (fs_read(filename, (u32) buf, pos, blocksize) < 0)
+ if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
return FPGA_FAIL;
if (zynq_validate_bitstream(desc, buf, bsize, blocksize, &swap,
@@ -443,10 +443,10 @@ static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
return FPGA_FAIL;
if (bsize > blocksize) {
- if (fs_read(filename, (u32) buf, pos, blocksize) < 0)
+ if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
return FPGA_FAIL;
} else {
- if (fs_read(filename, (u32) buf, pos, bsize) < 0)
+ if (fs_read(filename, (u32) buf, pos, bsize, &actread) < 0)
return FPGA_FAIL;
}
} while (bsize > blocksize);
diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c
index 6517af1..6129c02 100644
--- a/drivers/gpio/at91_gpio.c
+++ b/drivers/gpio/at91_gpio.c
@@ -10,11 +10,14 @@
#include <config.h>
#include <common.h>
+#include <dm.h>
#include <asm/io.h>
#include <linux/sizes.h>
+#include <asm/gpio.h>
#include <asm/arch/hardware.h>
#include <asm/arch/at91_pio.h>
-#include <asm/arch/gpio.h>
+
+#define GPIO_PER_BANK 32
static struct at91_port *at91_pio_get_port(unsigned port)
{
@@ -39,19 +42,25 @@ static struct at91_port *at91_pio_get_port(unsigned port)
}
}
+static void at91_set_port_pullup(struct at91_port *at91_port, unsigned offset,
+ int use_pullup)
+{
+ u32 mask;
+
+ mask = 1 << offset;
+ if (use_pullup)
+ writel(mask, &at91_port->puer);
+ else
+ writel(mask, &at91_port->pudr);
+ writel(mask, &at91_port->per);
+}
+
int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
{
struct at91_port *at91_port = at91_pio_get_port(port);
- u32 mask;
- if (at91_port && (pin < 32)) {
- mask = 1 << pin;
- if (use_pullup)
- writel(1 << pin, &at91_port->puer);
- else
- writel(1 << pin, &at91_port->pudr);
- writel(mask, &at91_port->per);
- }
+ if (at91_port && (pin < GPIO_PER_BANK))
+ at91_set_port_pullup(at91_port, pin, use_pullup);
return 0;
}
@@ -64,7 +73,7 @@ int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(mask, &at91_port->idr);
at91_set_pio_pullup(port, pin, use_pullup);
@@ -82,7 +91,7 @@ int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(mask, &at91_port->idr);
at91_set_pio_pullup(port, pin, use_pullup);
@@ -108,7 +117,7 @@ int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(mask, &at91_port->idr);
at91_set_pio_pullup(port, pin, use_pullup);
@@ -135,7 +144,7 @@ int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(mask, &at91_port->idr);
at91_set_pio_pullup(port, pin, use_pullup);
@@ -157,7 +166,7 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(mask, &at91_port->idr);
at91_set_pio_pullup(port, pin, use_pullup);
@@ -172,6 +181,29 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
}
#endif
+#ifdef CONFIG_DM_GPIO
+static bool at91_get_port_output(struct at91_port *at91_port, int offset)
+{
+ u32 mask, val;
+
+ mask = 1 << offset;
+ val = readl(&at91_port->osr);
+ return val & mask;
+}
+#endif
+
+static void at91_set_port_input(struct at91_port *at91_port, int offset,
+ int use_pullup)
+{
+ u32 mask;
+
+ mask = 1 << offset;
+ writel(mask, &at91_port->idr);
+ at91_set_port_pullup(at91_port, offset, use_pullup);
+ writel(mask, &at91_port->odr);
+ writel(mask, &at91_port->per);
+}
+
/*
* mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
* configure it for an input.
@@ -179,19 +211,29 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
{
struct at91_port *at91_port = at91_pio_get_port(port);
- u32 mask;
- if (at91_port && (pin < 32)) {
- mask = 1 << pin;
- writel(mask, &at91_port->idr);
- at91_set_pio_pullup(port, pin, use_pullup);
- writel(mask, &at91_port->odr);
- writel(mask, &at91_port->per);
- }
+ if (at91_port && (pin < GPIO_PER_BANK))
+ at91_set_port_input(at91_port, pin, use_pullup);
return 0;
}
+static void at91_set_port_output(struct at91_port *at91_port, int offset,
+ int value)
+{
+ u32 mask;
+
+ mask = 1 << offset;
+ writel(mask, &at91_port->idr);
+ writel(mask, &at91_port->pudr);
+ if (value)
+ writel(mask, &at91_port->sodr);
+ else
+ writel(mask, &at91_port->codr);
+ writel(mask, &at91_port->oer);
+ writel(mask, &at91_port->per);
+}
+
/*
* mux the pin to the gpio controller (instead of "A" or "B" peripheral),
* and configure it for an output.
@@ -199,19 +241,9 @@ int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
int at91_set_pio_output(unsigned port, u32 pin, int value)
{
struct at91_port *at91_port = at91_pio_get_port(port);
- u32 mask;
- if (at91_port && (port < ATMEL_PIO_PORTS) && (pin < 32)) {
- mask = 1 << pin;
- writel(mask, &at91_port->idr);
- writel(mask, &at91_port->pudr);
- if (value)
- writel(mask, &at91_port->sodr);
- else
- writel(mask, &at91_port->codr);
- writel(mask, &at91_port->oer);
- writel(mask, &at91_port->per);
- }
+ if (at91_port && (pin < GPIO_PER_BANK))
+ at91_set_port_output(at91_port, pin, value);
return 0;
}
@@ -224,7 +256,7 @@ int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
if (is_on) {
#if defined(CPU_HAS_PIO3)
@@ -248,7 +280,7 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
if (is_on) {
writel(mask, &at91_port->ifscer);
@@ -271,7 +303,7 @@ int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(mask, &at91_port->pudr);
if (is_on)
@@ -291,7 +323,7 @@ int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(readl(&at91_port->schmitt) | mask,
&at91_port->schmitt);
@@ -310,7 +342,7 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
struct at91_port *at91_port = at91_pio_get_port(port);
u32 mask;
- if (at91_port && (pin < 32)) {
+ if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
if (is_on)
writel(mask, &at91_port->mder);
@@ -321,41 +353,54 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
return 0;
}
+static void at91_set_port_value(struct at91_port *at91_port, int offset,
+ int value)
+{
+ u32 mask;
+
+ mask = 1 << offset;
+ if (value)
+ writel(mask, &at91_port->sodr);
+ else
+ writel(mask, &at91_port->codr);
+}
+
/*
* assuming the pin is muxed as a gpio output, set its value.
*/
int at91_set_pio_value(unsigned port, unsigned pin, int value)
{
struct at91_port *at91_port = at91_pio_get_port(port);
- u32 mask;
- if (at91_port && (pin < 32)) {
- mask = 1 << pin;
- if (value)
- writel(mask, &at91_port->sodr);
- else
- writel(mask, &at91_port->codr);
- }
+ if (at91_port && (pin < GPIO_PER_BANK))
+ at91_set_port_value(at91_port, pin, value);
return 0;
}
+static int at91_get_port_value(struct at91_port *at91_port, int offset)
+{
+ u32 pdsr = 0, mask;
+
+ mask = 1 << offset;
+ pdsr = readl(&at91_port->pdsr) & mask;
+
+ return pdsr != 0;
+}
/*
* read the pin's value (works even if it's not muxed as a gpio).
*/
int at91_get_pio_value(unsigned port, unsigned pin)
{
struct at91_port *at91_port = at91_pio_get_port(port);
- u32 pdsr = 0, mask;
- if (at91_port && (pin < 32)) {
- mask = 1 << pin;
- pdsr = readl(&at91_port->pdsr) & mask;
- }
+ if (at91_port && (pin < GPIO_PER_BANK))
+ return at91_get_port_value(at91_port, pin);
- return pdsr != 0;
+ return 0;
}
+#ifndef CONFIG_DM_GPIO
/* Common GPIO API */
int gpio_request(unsigned gpio, const char *label)
@@ -395,3 +440,91 @@ int gpio_set_value(unsigned gpio, int value)
return 0;
}
+#endif
+
+#ifdef CONFIG_DM_GPIO
+
+struct at91_port_priv {
+ struct at91_port *regs;
+};
+
+/* set GPIO pin 'gpio' as an input */
+static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+ struct at91_port_priv *port = dev_get_platdata(dev);
+
+ at91_set_port_input(port->regs, offset, 0);
+
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct at91_port_priv *port = dev_get_platdata(dev);
+
+ at91_set_port_output(port->regs, offset, value);
+
+ return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+ struct at91_port_priv *port = dev_get_platdata(dev);
+
+ return at91_get_port_value(port->regs, offset);
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct at91_port_priv *port = dev_get_platdata(dev);
+
+ at91_set_port_value(port->regs, offset, value);
+
+ return 0;
+}
+
+static int at91_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct at91_port_priv *port = dev_get_platdata(dev);
+
+ /* GPIOF_FUNC is not implemented yet */
+ if (at91_get_port_output(port->regs, offset))
+ return GPIOF_OUTPUT;
+ else
+ return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_at91_ops = {
+ .direction_input = at91_gpio_direction_input,
+ .direction_output = at91_gpio_direction_output,
+ .get_value = at91_gpio_get_value,
+ .set_value = at91_gpio_set_value,
+ .get_function = at91_gpio_get_function,
+};
+
+static int at91_gpio_probe(struct udevice *dev)
+{
+ struct at91_port_priv *port = dev_get_priv(dev);
+ struct at91_port_platdata *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ uc_priv->bank_name = plat->bank_name;
+ uc_priv->gpio_count = GPIO_PER_BANK;
+ port->regs = (struct at91_port *)plat->base_addr;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(gpio_at91) = {
+ .name = "gpio_at91",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_at91_ops,
+ .probe = at91_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct at91_port_priv),
+};
+#endif
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 45e9a5a..255700a 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -390,6 +390,25 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
return 0;
}
+/*
+ * get a number comprised of multiple GPIO values. gpio_num_array points to
+ * the array of gpio pin numbers to scan, terminated by -1.
+ */
+unsigned gpio_get_values_as_int(const int *gpio_num_array)
+{
+ int gpio;
+ unsigned bitmask = 1;
+ unsigned vector = 0;
+
+ while (bitmask &&
+ ((gpio = *gpio_num_array++) != -1)) {
+ if (gpio_get_value(gpio))
+ vector |= bitmask;
+ bitmask <<= 1;
+ }
+ return vector;
+}
+
/* We need to renumber the GPIOs when any driver is probed/removed */
static int gpio_renumber(struct udevice *removed_dev)
{
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index d3381b0..b095d17 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -33,6 +33,11 @@
#include <pci.h>
#include <asm/gpio.h>
#include <asm/io.h>
+#include <asm/pci.h>
+#ifdef CONFIG_X86_RESET_VECTOR
+#include <asm/arch/pch.h>
+#define SUPPORT_GPIO_SETUP
+#endif
#define GPIO_PER_BANK 32
@@ -46,6 +51,53 @@ struct ich6_bank_priv {
uint32_t lvl;
};
+#ifdef SUPPORT_GPIO_SETUP
+static void setup_pch_gpios(const struct pch_gpio_map *gpio)
+{
+ u16 gpiobase = pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc;
+
+ /* GPIO Set 1 */
+ if (gpio->set1.level)
+ outl(*((u32 *)gpio->set1.level), gpiobase + GP_LVL);
+ if (gpio->set1.mode)
+ outl(*((u32 *)gpio->set1.mode), gpiobase + GPIO_USE_SEL);
+ if (gpio->set1.direction)
+ outl(*((u32 *)gpio->set1.direction), gpiobase + GP_IO_SEL);
+ if (gpio->set1.reset)
+ outl(*((u32 *)gpio->set1.reset), gpiobase + GP_RST_SEL1);
+ if (gpio->set1.invert)
+ outl(*((u32 *)gpio->set1.invert), gpiobase + GPI_INV);
+ if (gpio->set1.blink)
+ outl(*((u32 *)gpio->set1.blink), gpiobase + GPO_BLINK);
+
+ /* GPIO Set 2 */
+ if (gpio->set2.level)
+ outl(*((u32 *)gpio->set2.level), gpiobase + GP_LVL2);
+ if (gpio->set2.mode)
+ outl(*((u32 *)gpio->set2.mode), gpiobase + GPIO_USE_SEL2);
+ if (gpio->set2.direction)
+ outl(*((u32 *)gpio->set2.direction), gpiobase + GP_IO_SEL2);
+ if (gpio->set2.reset)
+ outl(*((u32 *)gpio->set2.reset), gpiobase + GP_RST_SEL2);
+
+ /* GPIO Set 3 */
+ if (gpio->set3.level)
+ outl(*((u32 *)gpio->set3.level), gpiobase + GP_LVL3);
+ if (gpio->set3.mode)
+ outl(*((u32 *)gpio->set3.mode), gpiobase + GPIO_USE_SEL3);
+ if (gpio->set3.direction)
+ outl(*((u32 *)gpio->set3.direction), gpiobase + GP_IO_SEL3);
+ if (gpio->set3.reset)
+ outl(*((u32 *)gpio->set3.reset), gpiobase + GP_RST_SEL3);
+}
+
+/* TODO: Move this to device tree, or platform data */
+void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
+{
+ gd->arch.gpio_map = map;
+}
+#endif /* SUPPORT_GPIO_SETUP */
+
static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
{
struct ich6_bank_platdata *plat = dev_get_platdata(dev);
@@ -60,13 +112,13 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
pci_dev = PCI_BDF(0, 0x1f, 0);
/* Is the device present? */
- pci_read_config_word(pci_dev, PCI_VENDOR_ID, &tmpword);
+ tmpword = pci_read_config16(pci_dev, PCI_VENDOR_ID);
if (tmpword != PCI_VENDOR_ID_INTEL) {
debug("%s: wrong VendorID\n", __func__);
return -ENODEV;
}
- pci_read_config_word(pci_dev, PCI_DEVICE_ID, &tmpword);
+ tmpword = pci_read_config16(pci_dev, PCI_DEVICE_ID);
debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
/*
* We'd like to validate the Device ID too, but pretty much any
@@ -76,34 +128,34 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
*/
/* I/O should already be enabled (it's a RO bit). */
- pci_read_config_word(pci_dev, PCI_COMMAND, &tmpword);
+ tmpword = pci_read_config16(pci_dev, PCI_COMMAND);
if (!(tmpword & PCI_COMMAND_IO)) {
debug("%s: device IO not enabled\n", __func__);
return -ENODEV;
}
/* Header Type must be normal (bits 6-0 only; see spec.) */
- pci_read_config_byte(pci_dev, PCI_HEADER_TYPE, &tmpbyte);
+ tmpbyte = pci_read_config8(pci_dev, PCI_HEADER_TYPE);
if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
debug("%s: invalid Header type\n", __func__);
return -ENODEV;
}
/* Base Class must be a bridge device */
- pci_read_config_byte(pci_dev, PCI_CLASS_CODE, &tmpbyte);
+ tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_CODE);
if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
debug("%s: invalid class\n", __func__);
return -ENODEV;
}
/* Sub Class must be ISA */
- pci_read_config_byte(pci_dev, PCI_CLASS_SUB_CODE, &tmpbyte);
+ tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_SUB_CODE);
if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
debug("%s: invalid subclass\n", __func__);
return -ENODEV;
}
/* Programming Interface must be 0x00 (no others exist) */
- pci_read_config_byte(pci_dev, PCI_CLASS_PROG, &tmpbyte);
+ tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_PROG);
if (tmpbyte != 0x00) {
debug("%s: invalid interface type\n", __func__);
return -ENODEV;
@@ -114,7 +166,7 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
* that it was unused (or undocumented). Check that it looks
* okay: not all ones or zeros, and mapped to I/O space (bit 0).
*/
- pci_read_config_dword(pci_dev, PCI_CFG_GPIOBASE, &tmplong);
+ tmplong = pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
!(tmplong & 0x00000001)) {
debug("%s: unexpected GPIOBASE value\n", __func__);
@@ -140,12 +192,18 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
return 0;
}
-int ich6_gpio_probe(struct udevice *dev)
+static int ich6_gpio_probe(struct udevice *dev)
{
struct ich6_bank_platdata *plat = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct ich6_bank_priv *bank = dev_get_priv(dev);
+#ifdef SUPPORT_GPIO_SETUP
+ if (gd->arch.gpio_map) {
+ setup_pch_gpios(gd->arch.gpio_map);
+ gd->arch.gpio_map = NULL;
+ }
+#endif
uc_priv->gpio_count = GPIO_PER_BANK;
uc_priv->bank_name = plat->bank_name;
bank->use_sel = plat->base_addr;
@@ -155,7 +213,8 @@ int ich6_gpio_probe(struct udevice *dev)
return 0;
}
-int ich6_gpio_request(struct udevice *dev, unsigned offset, const char *label)
+static int ich6_gpio_request(struct udevice *dev, unsigned offset,
+ const char *label)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index d067897..dae3d71 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -5,7 +5,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-$(CONFIG_BFIN_TWI_I2C) += bfin-twi_i2c.o
+obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o
obj-$(CONFIG_I2C_MV) += mv_i2c.o
obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c
new file mode 100644
index 0000000..20495b1
--- /dev/null
+++ b/drivers/i2c/adi_i2c.c
@@ -0,0 +1,305 @@
+/*
+ * i2c.c - driver for ADI TWI/I2C
+ *
+ * Copyright (c) 2006-2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <asm/clock.h>
+#include <asm/twi.h>
+#include <asm/io.h>
+
+static struct twi_regs *i2c_get_base(struct i2c_adapter *adap);
+
+/* Every register is 32bit aligned, but only 16bits in size */
+#define ureg(name) u16 name; u16 __pad_##name;
+struct twi_regs {
+ ureg(clkdiv);
+ ureg(control);
+ ureg(slave_ctl);
+ ureg(slave_stat);
+ ureg(slave_addr);
+ ureg(master_ctl);
+ ureg(master_stat);
+ ureg(master_addr);
+ ureg(int_stat);
+ ureg(int_mask);
+ ureg(fifo_ctl);
+ ureg(fifo_stat);
+ char __pad[0x50];
+ ureg(xmt_data8);
+ ureg(xmt_data16);
+ ureg(rcv_data8);
+ ureg(rcv_data16);
+};
+#undef ureg
+
+#ifdef TWI_CLKDIV
+#define TWI0_CLKDIV TWI_CLKDIV
+# ifdef CONFIG_SYS_MAX_I2C_BUS
+# undef CONFIG_SYS_MAX_I2C_BUS
+# endif
+#define CONFIG_SYS_MAX_I2C_BUS 1
+#endif
+
+/*
+ * The way speed is changed into duty often results in integer truncation
+ * with 50% duty, so we'll force rounding up to the next duty by adding 1
+ * to the max. In practice this will get us a speed of something like
+ * 385 KHz. The other limit is easy to handle as it is only 8 bits.
+ */
+#define I2C_SPEED_MAX 400000
+#define I2C_SPEED_TO_DUTY(speed) (5000000 / (speed))
+#define I2C_DUTY_MAX (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1)
+#define I2C_DUTY_MIN 0xff /* 8 bit limited */
+#define SYS_I2C_DUTY I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED)
+/* Note: duty is inverse of speed, so the comparisons below are correct */
+#if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN
+# error "The I2C hardware can only operate 20KHz - 400KHz"
+#endif
+
+/* All transfers are described by this data structure */
+struct i2c_msg {
+ u8 flags;
+#define I2C_M_COMBO 0x4
+#define I2C_M_STOP 0x2
+#define I2C_M_READ 0x1
+ int len; /* msg length */
+ u8 *buf; /* pointer to msg data */
+ int alen; /* addr length */
+ u8 *abuf; /* addr buffer */
+};
+
+/* Allow msec timeout per ~byte transfer */
+#define I2C_TIMEOUT 10
+
+/**
+ * wait_for_completion - manage the actual i2c transfer
+ * @msg: the i2c msg
+ */
+static int wait_for_completion(struct twi_regs *twi, struct i2c_msg *msg)
+{
+ u16 int_stat, ctl;
+ ulong timebase = get_timer(0);
+
+ do {
+ int_stat = readw(&twi->int_stat);
+
+ if (int_stat & XMTSERV) {
+ writew(XMTSERV, &twi->int_stat);
+ if (msg->alen) {
+ writew(*(msg->abuf++), &twi->xmt_data8);
+ --msg->alen;
+ } else if (!(msg->flags & I2C_M_COMBO) && msg->len) {
+ writew(*(msg->buf++), &twi->xmt_data8);
+ --msg->len;
+ } else {
+ ctl = readw(&twi->master_ctl);
+ if (msg->flags & I2C_M_COMBO)
+ writew(ctl | RSTART | MDIR,
+ &twi->master_ctl);
+ else
+ writew(ctl | STOP, &twi->master_ctl);
+ }
+ }
+ if (int_stat & RCVSERV) {
+ writew(RCVSERV, &twi->int_stat);
+ if (msg->len) {
+ *(msg->buf++) = readw(&twi->rcv_data8);
+ --msg->len;
+ } else if (msg->flags & I2C_M_STOP) {
+ ctl = readw(&twi->master_ctl);
+ writew(ctl | STOP, &twi->master_ctl);
+ }
+ }
+ if (int_stat & MERR) {
+ writew(MERR, &twi->int_stat);
+ return msg->len;
+ }
+ if (int_stat & MCOMP) {
+ writew(MCOMP, &twi->int_stat);
+ if (msg->flags & I2C_M_COMBO && msg->len) {
+ ctl = readw(&twi->master_ctl);
+ ctl = (ctl & ~RSTART) |
+ (min(msg->len, 0xff) << 6) | MEN | MDIR;
+ writew(ctl, &twi->master_ctl);
+ } else
+ break;
+ }
+
+ /* If we were able to do something, reset timeout */
+ if (int_stat)
+ timebase = get_timer(0);
+
+ } while (get_timer(timebase) < I2C_TIMEOUT);
+
+ return msg->len;
+}
+
+static int i2c_transfer(struct i2c_adapter *adap, uint8_t chip, uint addr,
+ int alen, uint8_t *buffer, int len, uint8_t flags)
+{
+ struct twi_regs *twi = i2c_get_base(adap);
+ int ret;
+ u16 ctl;
+ uchar addr_buffer[] = {
+ (addr >> 0),
+ (addr >> 8),
+ (addr >> 16),
+ };
+ struct i2c_msg msg = {
+ .flags = flags | (len >= 0xff ? I2C_M_STOP : 0),
+ .buf = buffer,
+ .len = len,
+ .abuf = addr_buffer,
+ .alen = alen,
+ };
+
+ /* wait for things to settle */
+ while (readw(&twi->master_stat) & BUSBUSY)
+ if (ctrlc())
+ return 1;
+
+ /* Set Transmit device address */
+ writew(chip, &twi->master_addr);
+
+ /* Clear the FIFO before starting things */
+ writew(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl);
+ writew(0, &twi->fifo_ctl);
+
+ /* prime the pump */
+ if (msg.alen) {
+ len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len;
+ writew(*(msg.abuf++), &twi->xmt_data8);
+ --msg.alen;
+ } else if (!(msg.flags & I2C_M_READ) && msg.len) {
+ writew(*(msg.buf++), &twi->xmt_data8);
+ --msg.len;
+ }
+
+ /* clear int stat */
+ writew(-1, &twi->master_stat);
+ writew(-1, &twi->int_stat);
+ writew(0, &twi->int_mask);
+
+ /* Master enable */
+ ctl = readw(&twi->master_ctl);
+ ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN |
+ ((msg.flags & I2C_M_READ) ? MDIR : 0);
+ writew(ctl, &twi->master_ctl);
+
+ /* process the rest */
+ ret = wait_for_completion(twi, &msg);
+
+ if (ret) {
+ ctl = readw(&twi->master_ctl) & ~MEN;
+ writew(ctl, &twi->master_ctl);
+ ctl = readw(&twi->control) & ~TWI_ENA;
+ writew(ctl, &twi->control);
+ ctl = readw(&twi->control) | TWI_ENA;
+ writew(ctl, &twi->control);
+ }
+
+ return ret;
+}
+
+static uint adi_i2c_setspeed(struct i2c_adapter *adap, uint speed)
+{
+ struct twi_regs *twi = i2c_get_base(adap);
+ u16 clkdiv = I2C_SPEED_TO_DUTY(speed);
+
+ /* Set TWI interface clock */
+ if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN)
+ return -1;
+ clkdiv = (clkdiv << 8) | (clkdiv & 0xff);
+ writew(clkdiv, &twi->clkdiv);
+
+ /* Don't turn it on */
+ writew(speed > 100000 ? FAST : 0, &twi->master_ctl);
+
+ return 0;
+}
+
+static void adi_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
+{
+ struct twi_regs *twi = i2c_get_base(adap);
+ u16 prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
+
+ /* Set TWI internal clock as 10MHz */
+ writew(prescale, &twi->control);
+
+ /* Set TWI interface clock as specified */
+ i2c_set_bus_speed(speed);
+
+ /* Enable it */
+ writew(TWI_ENA | prescale, &twi->control);
+}
+
+static int adi_i2c_read(struct i2c_adapter *adap, uint8_t chip,
+ uint addr, int alen, uint8_t *buffer, int len)
+{
+ return i2c_transfer(adap, chip, addr, alen, buffer,
+ len, alen ? I2C_M_COMBO : I2C_M_READ);
+}
+
+static int adi_i2c_write(struct i2c_adapter *adap, uint8_t chip,
+ uint addr, int alen, uint8_t *buffer, int len)
+{
+ return i2c_transfer(adap, chip, addr, alen, buffer, len, 0);
+}
+
+static int adi_i2c_probe(struct i2c_adapter *adap, uint8_t chip)
+{
+ u8 byte;
+ return adi_i2c_read(adap, chip, 0, 0, &byte, 1);
+}
+
+static struct twi_regs *i2c_get_base(struct i2c_adapter *adap)
+{
+ switch (adap->hwadapnr) {
+#if CONFIG_SYS_MAX_I2C_BUS > 2
+ case 2:
+ return (struct twi_regs *)TWI2_CLKDIV;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 1
+ case 1:
+ return (struct twi_regs *)TWI1_CLKDIV;
+#endif
+ case 0:
+ return (struct twi_regs *)TWI0_CLKDIV;
+
+ default:
+ printf("wrong hwadapnr: %d\n", adap->hwadapnr);
+ }
+
+ return NULL;
+}
+
+U_BOOT_I2C_ADAP_COMPLETE(adi_i2c0, adi_i2c_init, adi_i2c_probe,
+ adi_i2c_read, adi_i2c_write,
+ adi_i2c_setspeed,
+ CONFIG_SYS_I2C_SPEED,
+ 0,
+ 0)
+
+#if CONFIG_SYS_MAX_I2C_BUS > 1
+U_BOOT_I2C_ADAP_COMPLETE(adi_i2c1, adi_i2c_init, adi_i2c_probe,
+ adi_i2c_read, adi_i2c_write,
+ adi_i2c_setspeed,
+ CONFIG_SYS_I2C_SPEED,
+ 0,
+ 1)
+#endif
+
+#if CONFIG_SYS_MAX_I2C_BUS > 2
+U_BOOT_I2C_ADAP_COMPLETE(adi_i2c2, adi_i2c_init, adi_i2c_probe,
+ adi_i2c_read, adi_i2c_write,
+ adi_i2c_setspeed,
+ CONFIG_SYS_I2C_SPEED,
+ 0,
+ 2)
+#endif
diff --git a/drivers/i2c/bfin-twi_i2c.c b/drivers/i2c/bfin-twi_i2c.c
deleted file mode 100644
index cfab064..0000000
--- a/drivers/i2c/bfin-twi_i2c.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * i2c.c - driver for Blackfin on-chip TWI/I2C
- *
- * Copyright (c) 2006-2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <i2c.h>
-
-#include <asm/blackfin.h>
-#include <asm/clock.h>
-#include <asm/mach-common/bits/twi.h>
-
-/* Every register is 32bit aligned, but only 16bits in size */
-#define ureg(name) u16 name; u16 __pad_##name;
-struct twi_regs {
- ureg(clkdiv);
- ureg(control);
- ureg(slave_ctl);
- ureg(slave_stat);
- ureg(slave_addr);
- ureg(master_ctl);
- ureg(master_stat);
- ureg(master_addr);
- ureg(int_stat);
- ureg(int_mask);
- ureg(fifo_ctl);
- ureg(fifo_stat);
- char __pad[0x50];
- ureg(xmt_data8);
- ureg(xmt_data16);
- ureg(rcv_data8);
- ureg(rcv_data16);
-};
-#undef ureg
-
-/* U-Boot I2C framework allows only one active device at a time. */
-#ifdef TWI_CLKDIV
-#define TWI0_CLKDIV TWI_CLKDIV
-#endif
-static volatile struct twi_regs *twi = (void *)TWI0_CLKDIV;
-
-#ifdef DEBUG
-# define dmemset(s, c, n) memset(s, c, n)
-#else
-# define dmemset(s, c, n)
-#endif
-#define debugi(fmt, args...) \
- debug( \
- "MSTAT:0x%03x FSTAT:0x%x ISTAT:0x%02x\t%-20s:%-3i: " fmt "\n", \
- twi->master_stat, twi->fifo_stat, twi->int_stat, \
- __func__, __LINE__, ## args)
-
-#ifdef CONFIG_TWICLK_KHZ
-# error do not define CONFIG_TWICLK_KHZ ... use CONFIG_SYS_I2C_SPEED
-#endif
-
-/*
- * The way speed is changed into duty often results in integer truncation
- * with 50% duty, so we'll force rounding up to the next duty by adding 1
- * to the max. In practice this will get us a speed of something like
- * 385 KHz. The other limit is easy to handle as it is only 8 bits.
- */
-#define I2C_SPEED_MAX 400000
-#define I2C_SPEED_TO_DUTY(speed) (5000000 / (speed))
-#define I2C_DUTY_MAX (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1)
-#define I2C_DUTY_MIN 0xff /* 8 bit limited */
-#define SYS_I2C_DUTY I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED)
-/* Note: duty is inverse of speed, so the comparisons below are correct */
-#if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN
-# error "The Blackfin I2C hardware can only operate 20KHz - 400KHz"
-#endif
-
-/* All transfers are described by this data structure */
-struct i2c_msg {
- u8 flags;
-#define I2C_M_COMBO 0x4
-#define I2C_M_STOP 0x2
-#define I2C_M_READ 0x1
- int len; /* msg length */
- u8 *buf; /* pointer to msg data */
- int alen; /* addr length */
- u8 *abuf; /* addr buffer */
-};
-
-/* Allow msec timeout per ~byte transfer */
-#define I2C_TIMEOUT 10
-
-/**
- * wait_for_completion - manage the actual i2c transfer
- * @msg: the i2c msg
- */
-static int wait_for_completion(struct i2c_msg *msg)
-{
- uint16_t int_stat;
- ulong timebase = get_timer(0);
-
- do {
- int_stat = twi->int_stat;
-
- if (int_stat & XMTSERV) {
- debugi("processing XMTSERV");
- twi->int_stat = XMTSERV;
- SSYNC();
- if (msg->alen) {
- twi->xmt_data8 = *(msg->abuf++);
- --msg->alen;
- } else if (!(msg->flags & I2C_M_COMBO) && msg->len) {
- twi->xmt_data8 = *(msg->buf++);
- --msg->len;
- } else {
- twi->master_ctl |= (msg->flags & I2C_M_COMBO) ? RSTART | MDIR : STOP;
- SSYNC();
- }
- }
- if (int_stat & RCVSERV) {
- debugi("processing RCVSERV");
- twi->int_stat = RCVSERV;
- SSYNC();
- if (msg->len) {
- *(msg->buf++) = twi->rcv_data8;
- --msg->len;
- } else if (msg->flags & I2C_M_STOP) {
- twi->master_ctl |= STOP;
- SSYNC();
- }
- }
- if (int_stat & MERR) {
- debugi("processing MERR");
- twi->int_stat = MERR;
- SSYNC();
- return msg->len;
- }
- if (int_stat & MCOMP) {
- debugi("processing MCOMP");
- twi->int_stat = MCOMP;
- SSYNC();
- if (msg->flags & I2C_M_COMBO && msg->len) {
- twi->master_ctl = (twi->master_ctl & ~RSTART) |
- (min(msg->len, 0xff) << 6) | MEN | MDIR;
- SSYNC();
- } else
- break;
- }
-
- /* If we were able to do something, reset timeout */
- if (int_stat)
- timebase = get_timer(0);
-
- } while (get_timer(timebase) < I2C_TIMEOUT);
-
- return msg->len;
-}
-
-/**
- * i2c_transfer - setup an i2c transfer
- * @return: 0 if things worked, non-0 if things failed
- *
- * Here we just get the i2c stuff all prepped and ready, and then tail off
- * into wait_for_completion() for all the bits to go.
- */
-static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, int len, u8 flags)
-{
- uchar addr_buffer[] = {
- (addr >> 0),
- (addr >> 8),
- (addr >> 16),
- };
- struct i2c_msg msg = {
- .flags = flags | (len >= 0xff ? I2C_M_STOP : 0),
- .buf = buffer,
- .len = len,
- .abuf = addr_buffer,
- .alen = alen,
- };
- int ret;
-
- dmemset(buffer, 0xff, len);
- debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i flags=0x%02x[%s] ",
- chip, addr, alen, buffer[0], len, flags, (flags & I2C_M_READ ? "rd" : "wr"));
-
- /* wait for things to settle */
- while (twi->master_stat & BUSBUSY)
- if (ctrlc())
- return 1;
-
- /* Set Transmit device address */
- twi->master_addr = chip;
-
- /* Clear the FIFO before starting things */
- twi->fifo_ctl = XMTFLUSH | RCVFLUSH;
- SSYNC();
- twi->fifo_ctl = 0;
- SSYNC();
-
- /* prime the pump */
- if (msg.alen) {
- len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len;
- debugi("first byte=0x%02x", *msg.abuf);
- twi->xmt_data8 = *(msg.abuf++);
- --msg.alen;
- } else if (!(msg.flags & I2C_M_READ) && msg.len) {
- debugi("first byte=0x%02x", *msg.buf);
- twi->xmt_data8 = *(msg.buf++);
- --msg.len;
- }
-
- /* clear int stat */
- twi->master_stat = -1;
- twi->int_stat = -1;
- twi->int_mask = 0;
- SSYNC();
-
- /* Master enable */
- twi->master_ctl =
- (twi->master_ctl & FAST) |
- (min(len, 0xff) << 6) | MEN |
- ((msg.flags & I2C_M_READ) ? MDIR : 0);
- SSYNC();
- debugi("CTL=0x%04x", twi->master_ctl);
-
- /* process the rest */
- ret = wait_for_completion(&msg);
- debugi("ret=%d", ret);
-
- if (ret) {
- twi->master_ctl &= ~MEN;
- twi->control &= ~TWI_ENA;
- SSYNC();
- twi->control |= TWI_ENA;
- SSYNC();
- }
-
- return ret;
-}
-
-/**
- * i2c_set_bus_speed - set i2c bus speed
- * @speed: bus speed (in HZ)
- */
-int i2c_set_bus_speed(unsigned int speed)
-{
- u16 clkdiv = I2C_SPEED_TO_DUTY(speed);
-
- /* Set TWI interface clock */
- if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN)
- return -1;
- twi->clkdiv = (clkdiv << 8) | (clkdiv & 0xff);
-
- /* Don't turn it on */
- twi->master_ctl = (speed > 100000 ? FAST : 0);
-
- return 0;
-}
-
-/**
- * i2c_get_bus_speed - get i2c bus speed
- * @speed: bus speed (in HZ)
- */
-unsigned int i2c_get_bus_speed(void)
-{
- /* 10 MHz / (2 * CLKDIV) -> 5 MHz / CLKDIV */
- return 5000000 / (twi->clkdiv & 0xff);
-}
-
-/**
- * i2c_init - initialize the i2c bus
- * @speed: bus speed (in HZ)
- * @slaveaddr: address of device in slave mode (0 - not slave)
- *
- * Slave mode isn't actually implemented. It'll stay that way until
- * we get a real request for it.
- */
-void i2c_init(int speed, int slaveaddr)
-{
- uint8_t prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
-
- /* Set TWI internal clock as 10MHz */
- twi->control = prescale;
-
- /* Set TWI interface clock as specified */
- i2c_set_bus_speed(speed);
-
- /* Enable it */
- twi->control = TWI_ENA | prescale;
- SSYNC();
-
- debugi("CONTROL:0x%04x CLKDIV:0x%04x", twi->control, twi->clkdiv);
-
-#if CONFIG_SYS_I2C_SLAVE
-# error I2C slave support not tested/supported
- /* If they want us as a slave, do it */
- if (slaveaddr) {
- twi->slave_addr = slaveaddr;
- twi->slave_ctl = SEN;
- }
-#endif
-}
-
-/**
- * i2c_probe - test if a chip exists at a given i2c address
- * @chip: i2c chip addr to search for
- * @return: 0 if found, non-0 if not found
- */
-int i2c_probe(uchar chip)
-{
- u8 byte;
- return i2c_read(chip, 0, 0, &byte, 1);
-}
-
-/**
- * i2c_read - read data from an i2c device
- * @chip: i2c chip addr
- * @addr: memory (register) address in the chip
- * @alen: byte size of address
- * @buffer: buffer to store data read from chip
- * @len: how many bytes to read
- * @return: 0 on success, non-0 on failure
- */
-int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- return i2c_transfer(chip, addr, alen, buffer, len, (alen ? I2C_M_COMBO : I2C_M_READ));
-}
-
-/**
- * i2c_write - write data to an i2c device
- * @chip: i2c chip addr
- * @addr: memory (register) address in the chip
- * @alen: byte size of address
- * @buffer: buffer holding data to write to chip
- * @len: how many bytes to write
- * @return: 0 on success, non-0 on failure
- */
-int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- return i2c_transfer(chip, addr, alen, buffer, len, 0);
-}
-
-/**
- * i2c_set_bus_num - change active I2C bus
- * @bus: bus index, zero based
- * @returns: 0 on success, non-0 on failure
- */
-int i2c_set_bus_num(unsigned int bus)
-{
- switch (bus) {
-#if CONFIG_SYS_MAX_I2C_BUS > 0
- case 0: twi = (void *)TWI0_CLKDIV; return 0;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 1
- case 1: twi = (void *)TWI1_CLKDIV; return 0;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 2
- case 2: twi = (void *)TWI2_CLKDIV; return 0;
-#endif
- default: return -1;
- }
-}
-
-/**
- * i2c_get_bus_num - returns index of active I2C bus
- */
-unsigned int i2c_get_bus_num(void)
-{
- switch ((unsigned long)twi) {
-#if CONFIG_SYS_MAX_I2C_BUS > 0
- case TWI0_CLKDIV: return 0;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 1
- case TWI1_CLKDIV: return 1;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 2
- case TWI2_CLKDIV: return 2;
-#endif
- default: return -1;
- }
-}
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index 7bb1702..ff7f25a 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -127,7 +127,7 @@ static const struct {
static unsigned int set_i2c_bus_speed(const struct fsl_i2c *dev,
unsigned int i2c_clk, unsigned int speed)
{
- unsigned short divider = min(i2c_clk / speed, (unsigned short) -1);
+ unsigned short divider = min(i2c_clk / speed, (unsigned int)USHRT_MAX);
/*
* We want to choose an FDR/DFSR that generates an I2C bus speed that
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/misc/cros_ec.c b/drivers/misc/cros_ec.c
index 521edfd..9b4effb 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -701,6 +701,7 @@ static int cros_ec_check_version(struct cros_ec_dev *dev)
/* Try sending a version 3 packet */
dev->protocol_version = 3;
+ req.in_data = 0;
if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
(uint8_t **)&resp, sizeof(*resp)) > 0) {
return 0;
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
index e403664..e6dba29 100644
--- a/drivers/misc/cros_ec_spi.c
+++ b/drivers/misc/cros_ec_spi.c
@@ -143,7 +143,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
return -1;
}
- len = min(p[1], din_len);
+ len = min((int)p[1], din_len);
cros_ec_dump_data("in", -1, p, len + 3);
/* Response code is first byte of message */
diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c
index 3de1245..d92044e 100644
--- a/drivers/misc/mxc_ocotp.c
+++ b/drivers/misc/mxc_ocotp.c
@@ -81,8 +81,6 @@ static int finish_access(struct ocotp_regs *regs, const char *caller)
err = !!(readl(&regs->ctrl) & BM_CTRL_ERROR);
clear_error(regs);
- enable_ocotp_clk(0);
-
if (err) {
printf("mxc_ocotp %s(): Access protect error\n", caller);
return -EIO;
@@ -122,8 +120,8 @@ static void set_timing(struct ocotp_regs *regs)
relax = DIV_ROUND_UP(ipg_clk * BV_TIMING_RELAX_NS, 1000000000) - 1;
strobe_read = DIV_ROUND_UP(ipg_clk * BV_TIMING_STROBE_READ_NS,
1000000000) + 2 * (relax + 1) - 1;
- strobe_prog = DIV_ROUND(ipg_clk * BV_TIMING_STROBE_PROG_US, 1000000) +
- 2 * (relax + 1) - 1;
+ strobe_prog = DIV_ROUND_CLOSEST(ipg_clk * BV_TIMING_STROBE_PROG_US,
+ 1000000) + 2 * (relax + 1) - 1;
timing = BF(strobe_read, TIMING_STROBE_READ) |
BF(relax, TIMING_RELAX) |
diff --git a/drivers/misc/mxs_ocotp.c b/drivers/misc/mxs_ocotp.c
index 545d3eb..6f0a1d3 100644
--- a/drivers/misc/mxs_ocotp.c
+++ b/drivers/misc/mxs_ocotp.c
@@ -187,6 +187,8 @@ static int mxs_ocotp_write_fuse(uint32_t addr, uint32_t mask)
uint32_t hclk_val, vddio_val;
int ret;
+ mxs_ocotp_clear_error();
+
/* Make sure the banks are closed for reading. */
ret = mxs_ocotp_read_bank_open(0);
if (ret) {
@@ -221,13 +223,17 @@ static int mxs_ocotp_write_fuse(uint32_t addr, uint32_t mask)
goto fail;
}
+ /* Check for errors */
+ if (readl(&ocotp_regs->hw_ocotp_ctrl) & OCOTP_CTRL_ERROR) {
+ puts("Failed writing fuses!\n");
+ ret = -EPERM;
+ goto fail;
+ }
+
fail:
mxs_ocotp_scale_vddio(0, &vddio_val);
- ret = mxs_ocotp_scale_hclk(0, &hclk_val);
- if (ret) {
+ if (mxs_ocotp_scale_hclk(0, &hclk_val))
puts("Failed scaling up the HCLK!\n");
- return ret;
- }
return ret;
}
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 2640607..c55eb28 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -23,6 +23,13 @@
DECLARE_GLOBAL_DATA_PTR;
+#define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \
+ IRQSTATEN_CINT | \
+ IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \
+ IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \
+ IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \
+ IRQSTATEN_DINT)
+
struct fsl_esdhc {
uint dsaddr; /* SDMA system address register */
uint blkattr; /* Block attributes register */
@@ -558,6 +565,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
| SYSCTL_IPGEN | SYSCTL_CKEN);
+ writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
memset(&cfg->cfg, 0, sizeof(cfg->cfg));
voltage_caps = 0;
@@ -610,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, 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/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index 1f29757..25ab0b1 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -197,7 +197,7 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
while (len) {
/* The controller has data ready */
if (readl(&regs->i_reg) & MMC_I_REG_RXFIFO_RD_REQ) {
- size = min(len, PXAMMC_FIFO_SIZE);
+ size = min(len, (uint32_t)PXAMMC_FIFO_SIZE);
len -= size;
size /= 4;
@@ -233,14 +233,14 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
while (len) {
/* The controller is ready to receive data */
if (readl(&regs->i_reg) & MMC_I_REG_TXFIFO_WR_REQ) {
- size = min(len, PXAMMC_FIFO_SIZE);
+ size = min(len, (uint32_t)PXAMMC_FIFO_SIZE);
len -= size;
size /= 4;
while (size--)
writel(*buf++, &regs->txfifo);
- if (min(len, PXAMMC_FIFO_SIZE) < 32)
+ if (min(len, (uint32_t)PXAMMC_FIFO_SIZE) < 32)
writel(MMC_PRTBUF_BUF_PART_FULL, &regs->prtbuf);
}
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/cfi_mtd.c b/drivers/mtd/cfi_mtd.c
index ac805ff..709a486 100644
--- a/drivers/mtd/cfi_mtd.c
+++ b/drivers/mtd/cfi_mtd.c
@@ -226,6 +226,7 @@ int cfi_mtd_init(void)
mtd->flags = MTD_CAP_NORFLASH;
mtd->size = fi->size;
mtd->writesize = 1;
+ mtd->writebufsize = mtd->writesize;
mtd->_erase = cfi_mtd_erase;
mtd->_read = cfi_mtd_read;
diff --git a/drivers/mtd/jedec_flash.c b/drivers/mtd/jedec_flash.c
index 593b9b8..ce9af8f 100644
--- a/drivers/mtd/jedec_flash.c
+++ b/drivers/mtd/jedec_flash.c
@@ -333,6 +333,57 @@ static const struct amd_flash_info jedec_table[] = {
}
},
{
+ .mfr_id = (u16)AMD_MANUFACT,
+ .dev_id = AM29LV800BT,
+ .name = "AMD AM29LV800BT",
+ .uaddr = {
+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
+ },
+ .DevSize = SIZE_1MiB,
+ .CmdSet = CFI_CMDSET_AMD_LEGACY,
+ .NumEraseRegions= 4,
+ .regions = {
+ ERASEINFO(0x10000, 15),
+ ERASEINFO(0x08000, 1),
+ ERASEINFO(0x02000, 2),
+ ERASEINFO(0x04000, 1),
+ }
+ },
+ {
+ .mfr_id = (u16)MX_MANUFACT,
+ .dev_id = AM29LV800BT,
+ .name = "MXIC MX29LV800BT",
+ .uaddr = {
+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
+ },
+ .DevSize = SIZE_1MiB,
+ .CmdSet = CFI_CMDSET_AMD_LEGACY,
+ .NumEraseRegions= 4,
+ .regions = {
+ ERASEINFO(0x10000, 15),
+ ERASEINFO(0x08000, 1),
+ ERASEINFO(0x02000, 2),
+ ERASEINFO(0x04000, 1),
+ }
+ },
+ {
+ .mfr_id = (u16)EON_ALT_MANU,
+ .dev_id = AM29LV800BT,
+ .name = "EON EN29LV800BT",
+ .uaddr = {
+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
+ },
+ .DevSize = SIZE_1MiB,
+ .CmdSet = CFI_CMDSET_AMD_LEGACY,
+ .NumEraseRegions= 4,
+ .regions = {
+ ERASEINFO(0x10000, 15),
+ ERASEINFO(0x08000, 1),
+ ERASEINFO(0x02000, 2),
+ ERASEINFO(0x04000, 1),
+ }
+ },
+ {
.mfr_id = (u16)STM_MANUFACT,
.dev_id = STM29F400BB,
.name = "ST Micro M29F400BB",
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/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 9114a86..620b6e8 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -18,6 +18,7 @@
#include <malloc.h>
#include <nand.h>
#include <watchdog.h>
+#include <linux/mtd/nand_ecc.h>
#ifdef CONFIG_ATMEL_NAND_HWECC
@@ -762,6 +763,62 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
}
#endif
+#if defined(NO_GALOIS_TABLE_IN_ROM)
+static uint16_t *pmecc_galois_table;
+static inline int deg(unsigned int poly)
+{
+ /* polynomial degree is the most-significant bit index */
+ return fls(poly) - 1;
+}
+
+static int build_gf_tables(int mm, unsigned int poly,
+ int16_t *index_of, int16_t *alpha_to)
+{
+ unsigned int i, x = 1;
+ const unsigned int k = 1 << deg(poly);
+ unsigned int nn = (1 << mm) - 1;
+
+ /* primitive polynomial must be of degree m */
+ if (k != (1u << mm))
+ return -EINVAL;
+
+ for (i = 0; i < nn; i++) {
+ alpha_to[i] = x;
+ index_of[x] = i;
+ if (i && (x == 1))
+ /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
+ return -EINVAL;
+ x <<= 1;
+ if (x & k)
+ x ^= poly;
+ }
+
+ alpha_to[nn] = 1;
+ index_of[0] = 0;
+
+ return 0;
+}
+
+static uint16_t *create_lookup_table(int sector_size)
+{
+ int degree = (sector_size == 512) ?
+ PMECC_GF_DIMENSION_13 :
+ PMECC_GF_DIMENSION_14;
+ unsigned int poly = (sector_size == 512) ?
+ PMECC_GF_13_PRIMITIVE_POLY :
+ PMECC_GF_14_PRIMITIVE_POLY;
+ int table_size = (sector_size == 512) ?
+ PMECC_INDEX_TABLE_SIZE_512 :
+ PMECC_INDEX_TABLE_SIZE_1024;
+
+ int16_t *addr = kzalloc(2 * table_size * sizeof(uint16_t), GFP_KERNEL);
+ if (addr && build_gf_tables(degree, poly, addr, addr + table_size))
+ return NULL;
+
+ return (uint16_t *)addr;
+}
+#endif
+
static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
struct mtd_info *mtd)
{
@@ -809,11 +866,18 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
sector_size = host->pmecc_sector_size;
/* TODO: need check whether cap & sector_size is validate */
-
+#if defined(NO_GALOIS_TABLE_IN_ROM)
+ /*
+ * As pmecc_rom_base is the begin of the gallois field table, So the
+ * index offset just set as 0.
+ */
+ host->pmecc_index_table_offset = 0;
+#else
if (host->pmecc_sector_size == 512)
host->pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_512;
else
host->pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_1024;
+#endif
MTDDEBUG(MTD_DEBUG_LEVEL1,
"Initialize PMECC params, cap: %d, sector: %d\n",
@@ -822,7 +886,17 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
host->pmecc = (struct pmecc_regs __iomem *) ATMEL_BASE_PMECC;
host->pmerrloc = (struct pmecc_errloc_regs __iomem *)
ATMEL_BASE_PMERRLOC;
+#if defined(NO_GALOIS_TABLE_IN_ROM)
+ pmecc_galois_table = create_lookup_table(host->pmecc_sector_size);
+ if (!pmecc_galois_table) {
+ dev_err(host->dev, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ host->pmecc_rom_base = (void __iomem *)pmecc_galois_table;
+#else
host->pmecc_rom_base = (void __iomem *) ATMEL_BASE_ROM;
+#endif
/* ECC is calculated for the whole page (1 step) */
nand->ecc.size = mtd->writesize;
@@ -1187,7 +1261,7 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd)
void (*hwctrl)(struct mtd_info *mtd, int cmd,
unsigned int ctrl) = this->cmd_ctrl;
- while (this->dev_ready(&mtd))
+ while (!this->dev_ready(&mtd))
;
if (cmd == NAND_CMD_READOOB) {
@@ -1212,7 +1286,7 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd)
hwctrl(&mtd, NAND_CMD_READSTART, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- while (this->dev_ready(&mtd))
+ while (!this->dev_ready(&mtd))
;
return 0;
@@ -1273,6 +1347,39 @@ static int nand_read_page(int block, int page, void *dst)
return 0;
}
+
+int spl_nand_erase_one(int block, int page)
+{
+ struct nand_chip *this = mtd.priv;
+ void (*hwctrl)(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl) = this->cmd_ctrl;
+ int page_addr;
+
+ if (nand_chip.select_chip)
+ nand_chip.select_chip(&mtd, 0);
+
+ page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
+ hwctrl(&mtd, NAND_CMD_ERASE1, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ /* Row address */
+ hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ hwctrl(&mtd, ((page_addr >> 8) & 0xff),
+ NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
+ /* One more address cycle for devices > 128MiB */
+ hwctrl(&mtd, (page_addr >> 16) & 0x0f,
+ NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+#endif
+
+ hwctrl(&mtd, NAND_CMD_ERASE2, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ udelay(2000);
+
+ while (!this->dev_ready(&mtd))
+ ;
+
+ nand_deselect();
+
+ return 0;
+}
#else
static int nand_read_page(int block, int page, void *dst)
{
@@ -1319,7 +1426,7 @@ int at91_nand_wait_ready(struct mtd_info *mtd)
udelay(this->chip_delay);
- return 0;
+ return 1;
}
int board_nand_init(struct nand_chip *nand)
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
index 92d4ec5..eac860d 100644
--- a/drivers/mtd/nand/atmel_nand_ecc.h
+++ b/drivers/mtd/nand/atmel_nand_ecc.h
@@ -141,6 +141,10 @@ struct pmecc_errloc_regs {
#define PMECC_GF_DIMENSION_13 13
#define PMECC_GF_DIMENSION_14 14
+/* Primitive Polynomial used by PMECC */
+#define PMECC_GF_13_PRIMITIVE_POLY 0x201b
+#define PMECC_GF_14_PRIMITIVE_POLY 0x4443
+
#define PMECC_INDEX_TABLE_SIZE_512 0x2000
#define PMECC_INDEX_TABLE_SIZE_1024 0x4000
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/denali_spl.c b/drivers/mtd/nand/denali_spl.c
index 65fdde8..e98f537 100644
--- a/drivers/mtd/nand/denali_spl.c
+++ b/drivers/mtd/nand/denali_spl.c
@@ -203,7 +203,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
if (ret < 0)
return ret;
- readlen = min(page_size - column, size);
+ readlen = min(page_size - column, (int)size);
memcpy(dst, page_buffer, readlen);
column = 0;
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 81b5070..b283eae 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -292,7 +292,7 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
struct fsl_ifc *ifc = ctrl->regs;
u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
u32 time_start;
- u32 eccstat[4];
+ u32 eccstat[4] = {0};
int i;
/* set the chip select for NAND Transaction */
diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c
index e336cb1..fb827c5 100644
--- a/drivers/mtd/nand/fsl_ifc_spl.c
+++ b/drivers/mtd/nand/fsl_ifc_spl.c
@@ -254,3 +254,13 @@ void nand_boot(void)
uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
uboot();
}
+
+#ifndef CONFIG_SPL_NAND_INIT
+void nand_init(void)
+{
+}
+
+void nand_deselect(void)
+{
+}
+#endif
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/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 1cf2f98..3024b98 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -315,7 +315,7 @@ int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size)
int ret;
while (size > 0) {
- todo = min(size, sizeof(sandbox_sf_0xff));
+ todo = min(size, (int)sizeof(sandbox_sf_0xff));
ret = os_write(sbsf->fd, sandbox_sf_0xff, todo);
if (ret != todo)
return ret;
@@ -602,14 +602,14 @@ static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum,
spec, ret);
return ret;
}
- ret = device_find_child_by_seq(bus, cs, true, &slave);
+ ret = spi_find_chip_select(bus, cs, &slave);
if (!ret) {
printf("Chip select %d already exists for spec '%s'\n", cs,
spec);
return -EEXIST;
}
- ret = spi_bind_device(bus, cs, "spi_flash_std", spec, &slave);
+ ret = device_bind_driver(bus, "spi_flash_std", spec, &slave);
if (ret)
return ret;
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index 85cf22d..759231f 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -313,10 +313,11 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
return ret;
#endif
byte_addr = offset % page_size;
- chunk_len = min(len - actual, page_size - byte_addr);
+ chunk_len = min(len - actual, (size_t)(page_size - byte_addr));
if (flash->spi->max_write_size)
- chunk_len = min(chunk_len, flash->spi->max_write_size);
+ chunk_len = min(chunk_len,
+ (size_t)flash->spi->max_write_size);
spi_flash_addr(write_addr, cmd);
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(&regs->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 = &reg->memac[num].fm_memac;
phyregs = &reg->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/memac.c b/drivers/net/fm/memac.c
index 9499290..60e898c 100644
--- a/drivers/net/fm/memac.c
+++ b/drivers/net/fm/memac.c
@@ -37,7 +37,8 @@ static void memac_enable_mac(struct fsl_enet_mac *mac)
{
struct memac *regs = mac->base;
- setbits_be32(&regs->command_config, MEMAC_CMD_CFG_RXTX_EN);
+ setbits_be32(&regs->command_config,
+ MEMAC_CMD_CFG_RXTX_EN | MEMAC_CMD_CFG_NO_LEN_CHK);
}
static void memac_disable_mac(struct fsl_enet_mac *mac)
@@ -93,11 +94,16 @@ static void memac_set_interface_mode(struct fsl_enet_mac *mac,
if_mode &= ~IF_MODE_MASK;
if_mode |= (IF_MODE_GMII);
break;
+ case PHY_INTERFACE_MODE_XGMII:
+ if_mode &= ~IF_MODE_MASK;
+ if_mode |= IF_MODE_XGMII;
+ break;
default:
break;
}
- /* Enable automatic speed selection */
- if_mode |= IF_MODE_EN_AUTO;
+ /* Enable automatic speed selection for Non-XGMII */
+ if (type != PHY_INTERFACE_MODE_XGMII)
+ if_mode |= IF_MODE_EN_AUTO;
if (type == PHY_INTERFACE_MODE_RGMII) {
if_mode &= ~IF_MODE_EN_AUTO;
diff --git a/drivers/net/fm/memac_phy.c b/drivers/net/fm/memac_phy.c
index 5f910c2..a155d89 100644
--- a/drivers/net/fm/memac_phy.c
+++ b/drivers/net/fm/memac_phy.c
@@ -71,6 +71,8 @@ int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
u32 c45 = 1;
if (dev_addr == MDIO_DEVAD_NONE) {
+ if (!strcmp(bus->name, DEFAULT_FM_TGEC_MDIO_NAME))
+ return 0xffff;
c45 = 0; /* clause 22 */
dev_addr = regnum & 0x1f;
clrbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
@@ -137,9 +139,12 @@ int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
* is zero, so MDIO clock is disabled.
* So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to
* be properly initialized.
+ * NEG bit default should be '1' as per FMAN-v3 RM, but on platform
+ * like T2080QDS, this bit default is '0', which leads to MDIO failure
+ * on XAUI PHY, so set this bit definitely.
*/
setbits_be32(&((struct memac_mdio_controller *)info->regs)->mdio_stat,
- MDIO_STAT_CLKDIV(258));
+ MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
return mdio_register(bus);
}
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/macb.c b/drivers/net/macb.c
index 375c8a4..9c2ff48 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -525,6 +525,7 @@ static int macb_phy_init(struct macb_device *macb)
return 1;
}
+static int macb_write_hwaddr(struct eth_device *dev);
static int macb_init(struct eth_device *netdev, bd_t *bd)
{
struct macb_device *macb = to_macb(netdev);
@@ -565,7 +566,13 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
macb_writel(macb, TBQP, macb->tx_ring_dma);
if (macb_is_gem(macb)) {
-#ifdef CONFIG_RGMII
+ /*
+ * When the GMAC IP with GE feature, this bit is used to
+ * select interface between RGMII and GMII.
+ * When the GMAC IP without GE feature, this bit is used
+ * to select interface between RMII and MII.
+ */
+#if defined(CONFIG_RGMII) || defined(CONFIG_RMII)
gem_writel(macb, UR, GEM_BIT(RGMII));
#else
gem_writel(macb, UR, 0);
@@ -587,6 +594,14 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
#endif /* CONFIG_RMII */
}
+ /* update the ethaddr */
+ if (is_valid_ether_addr(netdev->enetaddr)) {
+ macb_write_hwaddr(netdev);
+ } else {
+ printf("%s: mac address is not valid\n", netdev->name);
+ return -1;
+ }
+
if (!macb_phy_init(macb))
return -1;
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 623f749..677c89f 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -256,7 +256,7 @@ static void nc_puts(struct stdio_dev *dev, const char *s)
len = strlen(s);
while (len) {
- int send_len = min(len, sizeof(input_buffer));
+ int send_len = min(len, (int)sizeof(input_buffer));
nc_send_packet(s, send_len);
len -= send_len;
s += send_len;
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..85e82bd 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
@@ -17,3 +17,4 @@ obj-$(CONFIG_SH7751_PCI) +=pci_sh7751.o
obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o
obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o
obj-$(CONFIG_WINBOND_83C553) += w83c553f.o
+obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 60c333e..3daf73c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -195,6 +195,9 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
bdf < PCI_BDF(bus + 1, 0, 0);
#endif
bdf += PCI_BDF(0, 0, 1)) {
+ if (pci_skip_dev(hose, bdf))
+ continue;
+
if (!PCI_FUNC(bdf)) {
pci_read_config_byte(bdf,
PCI_HEADER_TYPE,
@@ -363,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,
@@ -662,13 +683,15 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus)
#endif
#ifdef CONFIG_PCI_PNP
- sub_bus = max(pciauto_config_device(hose, dev), sub_bus);
+ sub_bus = max((unsigned int)pciauto_config_device(hose, dev),
+ sub_bus);
#else
cfg = pci_find_config(hose, class, vendor, device,
PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
if (cfg) {
cfg->config_device(hose, dev, cfg);
- sub_bus = max(sub_bus, hose->current_busno);
+ sub_bus = max(sub_bus,
+ (unsigned int)hose->current_busno);
}
#endif
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index 86ba6b5..44470fa 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -387,7 +387,7 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
n = pci_hose_scan_bus(hose, hose->current_busno);
/* figure out the deepest we've gone for this leg */
- sub_bus = max(n, sub_bus);
+ sub_bus = max((unsigned int)n, sub_bus);
pciauto_postscan_setup_bridge(hose, dev, sub_bus);
sub_bus = hose->current_busno;
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/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c
new file mode 100644
index 0000000..291c249
--- /dev/null
+++ b/drivers/pci/pcie_layerscape.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ * Layerscape PCIe driver
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/pcie_layerscape.h>
+
+#ifdef CONFIG_OF_BOARD_SETUP
+#include <libfdt.h>
+#include <fdt_support.h>
+
+static void ft_pcie_ls_setup(void *blob, const char *pci_compat,
+ unsigned long ctrl_addr, enum srds_prtcl dev)
+{
+ int off;
+
+ off = fdt_node_offset_by_compat_reg(blob, pci_compat,
+ (phys_addr_t)ctrl_addr);
+ if (off < 0)
+ return;
+
+ if (!is_serdes_configured(dev))
+ fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
+}
+
+void ft_pcie_setup(void *blob, bd_t *bd)
+{
+ #ifdef CONFIG_PCIE1
+ ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE1_ADDR, PCIE1);
+ #endif
+
+ #ifdef CONFIG_PCIE2
+ ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE2_ADDR, PCIE2);
+ #endif
+}
+
+#else
+void ft_pcie_setup(void *blob, bd_t *bd)
+{
+}
+#endif
+
+void pci_init_board(void)
+{
+}
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/atmel_usart.c b/drivers/serial/atmel_usart.c
index 8f0e348..4fe992b 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -7,11 +7,16 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
+#include <dm.h>
+#include <errno.h>
#include <watchdog.h>
#include <serial.h>
#include <linux/compiler.h>
#include <asm/io.h>
+#ifdef CONFIG_DM_SERIAL
+#include <asm/arch/atmel_serial.h>
+#endif
#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
@@ -19,9 +24,9 @@
DECLARE_GLOBAL_DATA_PTR;
-static void atmel_serial_setbrg(void)
+static void atmel_serial_setbrg_internal(atmel_usart3_t *usart, int id,
+ int baudrate)
{
- atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
unsigned long divisor;
unsigned long usart_hz;
@@ -30,15 +35,13 @@ static void atmel_serial_setbrg(void)
* Baud Rate = --------------
* 16 * CD
*/
- usart_hz = get_usart_clk_rate(CONFIG_USART_ID);
- divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
+ usart_hz = get_usart_clk_rate(id);
+ divisor = (usart_hz / 16 + baudrate / 2) / baudrate;
writel(USART3_BF(CD, divisor), &usart->brgr);
}
-static int atmel_serial_init(void)
+static void atmel_serial_init_internal(atmel_usart3_t *usart)
{
- atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
-
/*
* Just in case: drain transmitter register
* 1000us is enough for baudrate >= 9600
@@ -47,9 +50,10 @@ static int atmel_serial_init(void)
__udelay(1000);
writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
+}
- serial_setbrg();
-
+static void atmel_serial_activate(atmel_usart3_t *usart)
+{
writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
| USART3_BF(USCLKS, USART3_USCLKS_MCK)
| USART3_BF(CHRL, USART3_CHRL_8)
@@ -59,6 +63,22 @@ static int atmel_serial_init(void)
writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
/* 100us is enough for the new settings to be settled */
__udelay(100);
+}
+
+#ifndef CONFIG_DM_SERIAL
+static void atmel_serial_setbrg(void)
+{
+ atmel_serial_setbrg_internal((atmel_usart3_t *)CONFIG_USART_BASE,
+ CONFIG_USART_ID, gd->baudrate);
+}
+
+static int atmel_serial_init(void)
+{
+ atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
+
+ atmel_serial_init_internal(usart);
+ serial_setbrg();
+ atmel_serial_activate(usart);
return 0;
}
@@ -109,3 +129,81 @@ __weak struct serial_device *default_serial_console(void)
{
return &atmel_serial_drv;
}
+#endif
+
+#ifdef CONFIG_DM_SERIAL
+
+struct atmel_serial_priv {
+ atmel_usart3_t *usart;
+};
+
+int atmel_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ atmel_serial_setbrg_internal(priv->usart, 0 /* ignored */, baudrate);
+ atmel_serial_activate(priv->usart);
+
+ return 0;
+}
+
+static int atmel_serial_getc(struct udevice *dev)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(&priv->usart->csr) & USART3_BIT(RXRDY)))
+ return -EAGAIN;
+
+ return readl(&priv->usart->rhr);
+}
+
+static int atmel_serial_putc(struct udevice *dev, const char ch)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(&priv->usart->csr) & USART3_BIT(TXRDY)))
+ return -EAGAIN;
+
+ writel(ch, &priv->usart->thr);
+
+ return 0;
+}
+
+static int atmel_serial_pending(struct udevice *dev, bool input)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+ uint32_t csr = readl(&priv->usart->csr);
+
+ if (input)
+ return csr & USART3_BIT(RXRDY) ? 1 : 0;
+ else
+ return csr & USART3_BIT(TXEMPTY) ? 0 : 1;
+}
+
+static const struct dm_serial_ops atmel_serial_ops = {
+ .putc = atmel_serial_putc,
+ .pending = atmel_serial_pending,
+ .getc = atmel_serial_getc,
+ .setbrg = atmel_serial_setbrg,
+};
+
+static int atmel_serial_probe(struct udevice *dev)
+{
+ struct atmel_serial_platdata *plat = dev->platdata;
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ priv->usart = (atmel_usart3_t *)plat->base_addr;
+ atmel_serial_init_internal(priv->usart);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(serial_atmel) = {
+ .name = "serial_atmel",
+ .id = UCLASS_SERIAL,
+ .probe = atmel_serial_probe,
+ .ops = &atmel_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+ .priv_auto_alloc_size = sizeof(struct atmel_serial_priv),
+};
+#endif
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 71f1a5c..d1b5777 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <dm.h>
+#include <environment.h>
#include <errno.h>
#include <fdtdec.h>
#include <os.h>
@@ -19,8 +20,10 @@
DECLARE_GLOBAL_DATA_PTR;
-/* The currently-selected console serial device */
-struct udevice *cur_dev __attribute__ ((section(".data")));
+/*
+ * Table with supported baudrates (defined in config_xyz.h)
+ */
+static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
#ifndef CONFIG_SYS_MALLOC_F_LEN
#error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
@@ -28,25 +31,30 @@ struct udevice *cur_dev __attribute__ ((section(".data")));
static void serial_find_console_or_panic(void)
{
+ struct udevice *dev;
+
#ifdef CONFIG_OF_CONTROL
int node;
/* 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");
- if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev))
+ 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;
+ }
/*
* If the console is not marked to be bound before relocation, bind
* it anyway.
*/
if (node > 0 &&
- !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) {
- if (!device_probe(cur_dev))
+ !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) {
+ if (!device_probe(dev)) {
+ gd->cur_serial_dev = dev;
return;
- cur_dev = NULL;
+ }
}
#endif
/*
@@ -61,11 +69,12 @@ static void serial_find_console_or_panic(void)
#else
#define INDEX 0
#endif
- if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) &&
- uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) &&
- (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev))
+ if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) &&
+ uclass_get_device(UCLASS_SERIAL, INDEX, &dev) &&
+ (uclass_first_device(UCLASS_SERIAL, &dev) || !dev))
panic("No serial driver found");
#undef INDEX
+ gd->cur_serial_dev = dev;
}
/* Called prior to relocation */
@@ -127,40 +136,42 @@ static int _serial_tstc(struct udevice *dev)
void serial_putc(char ch)
{
- _serial_putc(cur_dev, ch);
+ _serial_putc(gd->cur_serial_dev, ch);
}
void serial_puts(const char *str)
{
- _serial_puts(cur_dev, str);
+ _serial_puts(gd->cur_serial_dev, str);
}
int serial_getc(void)
{
- return _serial_getc(cur_dev);
+ return _serial_getc(gd->cur_serial_dev);
}
int serial_tstc(void)
{
- return _serial_tstc(cur_dev);
+ return _serial_tstc(gd->cur_serial_dev);
}
void serial_setbrg(void)
{
- struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+ struct dm_serial_ops *ops = serial_get_ops(gd->cur_serial_dev);
if (ops->setbrg)
- ops->setbrg(cur_dev, gd->baudrate);
+ ops->setbrg(gd->cur_serial_dev, gd->baudrate);
}
void serial_stdio_init(void)
{
}
+#ifdef CONFIG_DM_STDIO
static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
{
_serial_putc(sdev->priv, ch);
}
+#endif
void serial_stub_puts(struct stdio_dev *sdev, const char *str)
{
@@ -177,11 +188,74 @@ int serial_stub_tstc(struct stdio_dev *sdev)
return _serial_tstc(sdev->priv);
}
+/**
+ * on_baudrate() - Update the actual baudrate when the env var changes
+ *
+ * This will check for a valid baudrate and only apply it if valid.
+ */
+static int on_baudrate(const char *name, const char *value, enum env_op op,
+ int flags)
+{
+ int i;
+ int baudrate;
+
+ switch (op) {
+ case env_op_create:
+ case env_op_overwrite:
+ /*
+ * Switch to new baudrate if new baudrate is supported
+ */
+ baudrate = simple_strtoul(value, NULL, 10);
+
+ /* Not actually changing */
+ if (gd->baudrate == baudrate)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
+ if (baudrate == baudrate_table[i])
+ break;
+ }
+ if (i == ARRAY_SIZE(baudrate_table)) {
+ if ((flags & H_FORCE) == 0)
+ printf("## Baudrate %d bps not supported\n",
+ baudrate);
+ return 1;
+ }
+ if ((flags & H_INTERACTIVE) != 0) {
+ printf("## Switch baudrate to %d bps and press ENTER ...\n",
+ baudrate);
+ udelay(50000);
+ }
+
+ gd->baudrate = baudrate;
+
+ serial_setbrg();
+
+ udelay(50000);
+
+ if ((flags & H_INTERACTIVE) != 0)
+ while (1) {
+ if (getc() == '\r')
+ break;
+ }
+
+ return 0;
+ case env_op_delete:
+ printf("## Baudrate may not be deleted\n");
+ return 1;
+ default:
+ return 0;
+ }
+}
+U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
+
static int serial_post_probe(struct udevice *dev)
{
- struct stdio_dev sdev;
struct dm_serial_ops *ops = serial_get_ops(dev);
+#ifdef CONFIG_DM_STDIO
struct serial_dev_priv *upriv = dev->uclass_priv;
+ struct stdio_dev sdev;
+#endif
int ret;
/* Set the baud rate */
@@ -191,9 +265,9 @@ static int serial_post_probe(struct udevice *dev)
return ret;
}
+#ifdef CONFIG_DM_STDIO
if (!(gd->flags & GD_FLG_RELOC))
return 0;
-
memset(&sdev, '\0', sizeof(sdev));
strncpy(sdev.name, dev->name, sizeof(sdev.name));
@@ -204,7 +278,7 @@ static int serial_post_probe(struct udevice *dev)
sdev.getc = serial_stub_getc;
sdev.tstc = serial_stub_tstc;
stdio_register_dev(&sdev, &upriv->sdev);
-
+#endif
return 0;
}
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, &regs->pl010_cr);
+ break;
+ case TYPE_PL011:
#ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT
- if (type == TYPE_PL011) {
/* Empty RX fifo if necessary */
if (readl(&regs->pl011_cr) & UART_PL011_CR_UARTEN) {
while (!(readl(&regs->fr) & UART_PL01x_FR_RXFE))
readl(&regs->dr);
}
- }
#endif
+ /* disable everything */
+ writel(0, &regs->pl011_cr);
+ break;
+ default:
+ return -EINVAL;
+ }
- /* First, disable everything */
- writel(0, &regs->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, &regs->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, &regs->fr);
writel(lcr, &regs->pl011_rlcr);
- /* lcrh needs to be set again for change to be effective */
- writel(lcr, &regs->pl011_lcrh);
-#endif
- break;
- }
- default:
- return -EINVAL;
}
-
+#endif
+ writel(lcr, &regs->pl011_lcrh);
return 0;
}
@@ -175,6 +178,7 @@ static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type,
writel(divider, &regs->pl011_ibrd);
writel(fraction, &regs->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, &regs->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_sh.h b/drivers/serial/serial_sh.h
index 53406e5..ef88c8f 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -433,7 +433,7 @@ static inline void sci_##name##_out(struct uart_port *port,\
SCI_OUT(sci_size, sci_offset, value);\
}
-#if defined(CONFIG_SH3) || \
+#if defined(CONFIG_CPU_SH3) || \
defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \
defined(CONFIG_ARCH_SH7372) || \
diff --git a/drivers/serial/serial_tegra.c b/drivers/serial/serial_tegra.c
index 7eb70e1..b9227f0 100644
--- a/drivers/serial/serial_tegra.c
+++ b/drivers/serial/serial_tegra.c
@@ -9,6 +9,7 @@
#include <ns16550.h>
#include <serial.h>
+#ifdef CONFIG_OF_CONTROL
static const struct udevice_id tegra_serial_ids[] = {
{ .compatible = "nvidia,tegra20-uart" },
{ }
@@ -26,13 +27,28 @@ static int tegra_serial_ofdata_to_platdata(struct udevice *dev)
return 0;
}
+#else
+struct ns16550_platdata tegra_serial = {
+ .base = CONFIG_SYS_NS16550_COM1,
+ .reg_shift = 2,
+ .clock = V_NS16550_CLK,
+};
+
+U_BOOT_DEVICE(ns16550_serial) = {
+ "serial_tegra20", &tegra_serial
+};
+#endif
+
U_BOOT_DRIVER(serial_ns16550) = {
.name = "serial_tegra20",
.id = UCLASS_SERIAL,
+#ifdef CONFIG_OF_CONTROL
.of_match = tegra_serial_ids,
.ofdata_to_platdata = tegra_serial_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+#endif
.priv_auto_alloc_size = sizeof(struct NS16550),
.probe = ns16550_serial_probe,
.ops = &ns16550_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
};
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/serial/usbtty.c b/drivers/serial/usbtty.c
index 7fb0b92..75f0ec3 100644
--- a/drivers/serial/usbtty.c
+++ b/drivers/serial/usbtty.c
@@ -882,7 +882,7 @@ static int write_buffer (circbuf_t * buf)
space_avail =
current_urb->buffer_length -
current_urb->actual_length;
- popnum = min(space_avail, buf->size);
+ popnum = min(space_avail, (int)buf->size);
if (popnum == 0)
break;
diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h
index d240945..1538a23 100644
--- a/drivers/spi/atmel_spi.h
+++ b/drivers/spi/atmel_spi.h
@@ -94,3 +94,7 @@ static inline struct atmel_spi_slave *to_atmel_spi(struct spi_slave *slave)
readl(as->regs + ATMEL_SPI_##reg)
#define spi_writel(as, reg, value) \
writel(value, as->regs + ATMEL_SPI_##reg)
+
+#if !defined(CONFIG_SYS_SPI_WRITE_TOUT)
+#define CONFIG_SYS_SPI_WRITE_TOUT (5 * CONFIG_SYS_HZ)
+#endif
diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c
index ae0fe58..375dc07 100644
--- a/drivers/spi/fsl_espi.c
+++ b/drivers/spi/fsl_espi.c
@@ -273,7 +273,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
spi_cs_deactivate(slave);
return 0;
}
- buf_len = 2 * cmd_len + min(data_len, max_tran_len);
+ buf_len = 2 * cmd_len + min(data_len, (size_t)max_tran_len);
len = cmd_len + data_len;
rx_offset = cmd_len;
buffer = (unsigned char *)malloc(buf_len);
@@ -306,7 +306,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
if (data_in)
din = buffer + rx_offset;
dout = buffer;
- tran_len = min(data_len , max_tran_len);
+ tran_len = min(data_len, (size_t)max_tran_len);
num_blks = DIV_ROUND_UP(tran_len + cmd_len, 4);
num_bytes = (tran_len + cmd_len) % 4;
fsl->data_len = tran_len + cmd_len;
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index 23f2ba6..0881599 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -315,7 +315,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
tmp = reg_read(&regs->rxdata);
data = cpu_to_be32(tmp);
debug("SPI Rx: 0x%x 0x%x\n", tmp, data);
- cnt = min(nbytes, sizeof(data));
+ cnt = min_t(u32, nbytes, sizeof(data));
if (din) {
memcpy(din, &data, cnt);
din += cnt;
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 13c6b77..7a57bce 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -57,7 +57,7 @@ int spi_claim_bus(struct spi_slave *slave)
speed = slave->max_hz;
if (spi->max_hz) {
if (speed)
- speed = min(speed, spi->max_hz);
+ speed = min(speed, (int)spi->max_hz);
else
speed = spi->max_hz;
}
@@ -115,16 +115,7 @@ int spi_chip_select(struct udevice *dev)
return slave ? slave->cs : -ENOENT;
}
-/**
- * spi_find_chip_select() - Find the slave attached to chip select
- *
- * @bus: SPI bus to search
- * @cs: Chip select to look for
- * @devp: Returns the slave device if found
- * @return 0 if found, -ENODEV on error
- */
-static int spi_find_chip_select(struct udevice *bus, int cs,
- struct udevice **devp)
+int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp)
{
struct udevice *dev;
@@ -197,27 +188,6 @@ int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info)
return -ENODEV;
}
-int spi_bind_device(struct udevice *bus, int cs, const char *drv_name,
- const char *dev_name, struct udevice **devp)
-{
- struct driver *drv;
- int ret;
-
- drv = lists_driver_lookup_name(drv_name);
- if (!drv) {
- printf("Cannot find driver '%s'\n", drv_name);
- return -ENOENT;
- }
- ret = device_bind(bus, drv, dev_name, NULL, -1, devp);
- if (ret) {
- printf("Cannot create device named '%s' (err=%d)\n",
- dev_name, ret);
- return ret;
- }
-
- return 0;
-}
-
int spi_find_bus_and_cs(int busnum, int cs, struct udevice **busp,
struct udevice **devp)
{
@@ -264,7 +234,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
if (ret == -ENODEV && drv_name) {
debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
__func__, dev_name, busnum, cs, drv_name);
- ret = spi_bind_device(bus, cs, drv_name, dev_name, &dev);
+ ret = device_bind_driver(bus, drv_name, dev_name, &dev);
if (ret)
return ret;
created = true;
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/thermal/Makefile b/drivers/thermal/Makefile
new file mode 100644
index 0000000..6d4cacd
--- /dev/null
+++ b/drivers/thermal/Makefile
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2014 Freescale Semiconductor, Inc.
+# Author: Nitin Garg <nitin.garg@freescale.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_DM_THERMAL) += thermal-uclass.o
+obj-$(CONFIG_IMX6_THERMAL) += imx_thermal.o
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
new file mode 100644
index 0000000..0bd9cfd
--- /dev/null
+++ b/drivers/thermal/imx_thermal.c
@@ -0,0 +1,175 @@
+/*
+ * (C) Copyright 2014 Freescale Semiconductor, Inc.
+ * Author: Nitin Garg <nitin.garg@freescale.com>
+ * Ye Li <Ye.Li@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <div64.h>
+#include <fuse.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <thermal.h>
+#include <imx_thermal.h>
+
+#define TEMPERATURE_MIN -40
+#define TEMPERATURE_HOT 80
+#define TEMPERATURE_MAX 125
+#define FACTOR0 10000000
+#define FACTOR1 15976
+#define FACTOR2 4297157
+#define MEASURE_FREQ 327
+
+#define TEMPSENSE0_TEMP_CNT_SHIFT 8
+#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
+#define TEMPSENSE0_FINISHED (1 << 2)
+#define TEMPSENSE0_MEASURE_TEMP (1 << 1)
+#define TEMPSENSE0_POWER_DOWN (1 << 0)
+#define MISC0_REFTOP_SELBIASOFF (1 << 3)
+#define TEMPSENSE1_MEASURE_FREQ 0xffff
+
+static int read_cpu_temperature(struct udevice *dev)
+{
+ int temperature;
+ unsigned int reg, n_meas;
+ const struct imx_thermal_plat *pdata = dev_get_platdata(dev);
+ struct anatop_regs *anatop = (struct anatop_regs *)pdata->regs;
+ unsigned int *priv = dev_get_priv(dev);
+ u32 fuse = *priv;
+ int t1, n1;
+ u32 c1, c2;
+ u64 temp64;
+
+ /*
+ * Sensor data layout:
+ * [31:20] - sensor value @ 25C
+ * We use universal formula now and only need sensor value @ 25C
+ * slope = 0.4297157 - (0.0015976 * 25C fuse)
+ */
+ n1 = fuse >> 20;
+ t1 = 25; /* t1 always 25C */
+
+ /*
+ * Derived from linear interpolation:
+ * slope = 0.4297157 - (0.0015976 * 25C fuse)
+ * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
+ * (Nmeas - n1) / (Tmeas - t1) = slope
+ * We want to reduce this down to the minimum computation necessary
+ * for each temperature read. Also, we want Tmeas in millicelsius
+ * and we don't want to lose precision from integer division. So...
+ * Tmeas = (Nmeas - n1) / slope + t1
+ * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
+ * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
+ * Let constant c1 = (-1000 / slope)
+ * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
+ * Let constant c2 = n1 *c1 + 1000 * t1
+ * milli_Tmeas = c2 - Nmeas * c1
+ */
+ temp64 = FACTOR0;
+ temp64 *= 1000;
+ do_div(temp64, FACTOR1 * n1 - FACTOR2);
+ c1 = temp64;
+ c2 = n1 * c1 + 1000 * t1;
+
+ /*
+ * now we only use single measure, every time we read
+ * the temperature, we will power on/down anadig thermal
+ * module
+ */
+ writel(TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr);
+ writel(MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
+
+ /* setup measure freq */
+ reg = readl(&anatop->tempsense1);
+ reg &= ~TEMPSENSE1_MEASURE_FREQ;
+ reg |= MEASURE_FREQ;
+ writel(reg, &anatop->tempsense1);
+
+ /* start the measurement process */
+ writel(TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr);
+ writel(TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
+ writel(TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set);
+
+ /* make sure that the latest temp is valid */
+ while ((readl(&anatop->tempsense0) &
+ TEMPSENSE0_FINISHED) == 0)
+ udelay(10000);
+
+ /* read temperature count */
+ reg = readl(&anatop->tempsense0);
+ n_meas = (reg & TEMPSENSE0_TEMP_CNT_MASK)
+ >> TEMPSENSE0_TEMP_CNT_SHIFT;
+ writel(TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
+
+ /* milli_Tmeas = c2 - Nmeas * c1 */
+ temperature = (c2 - n_meas * c1)/1000;
+
+ /* power down anatop thermal sensor */
+ writel(TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set);
+ writel(MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr);
+
+ return temperature;
+}
+
+int imx_thermal_get_temp(struct udevice *dev, int *temp)
+{
+ int cpu_tmp = 0;
+
+ cpu_tmp = read_cpu_temperature(dev);
+ while (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) {
+ if (cpu_tmp >= TEMPERATURE_HOT) {
+ printf("CPU Temperature is %d C, too hot to boot, waiting...\n",
+ cpu_tmp);
+ udelay(5000000);
+ cpu_tmp = read_cpu_temperature(dev);
+ } else {
+ break;
+ }
+ }
+
+ *temp = cpu_tmp;
+
+ return 0;
+}
+
+static const struct dm_thermal_ops imx_thermal_ops = {
+ .get_temp = imx_thermal_get_temp,
+};
+
+static int imx_thermal_probe(struct udevice *dev)
+{
+ unsigned int fuse = ~0;
+
+ const struct imx_thermal_plat *pdata = dev_get_platdata(dev);
+ unsigned int *priv = dev_get_priv(dev);
+
+ /* Read Temperature calibration data fuse */
+ fuse_read(pdata->fuse_bank, pdata->fuse_word, &fuse);
+
+ /* Check for valid fuse */
+ if (fuse == 0 || fuse == ~0) {
+ printf("CPU: Thermal invalid data, fuse: 0x%x\n", fuse);
+ return -EPERM;
+ }
+
+ *priv = fuse;
+
+ enable_thermal_clk();
+
+ return 0;
+}
+
+U_BOOT_DRIVER(imx_thermal) = {
+ .name = "imx_thermal",
+ .id = UCLASS_THERMAL,
+ .ops = &imx_thermal_ops,
+ .probe = imx_thermal_probe,
+ .priv_auto_alloc_size = sizeof(unsigned int),
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/thermal/thermal-uclass.c b/drivers/thermal/thermal-uclass.c
new file mode 100644
index 0000000..3bee1a7
--- /dev/null
+++ b/drivers/thermal/thermal-uclass.c
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2014 Freescale Semiconductor, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <thermal.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <linux/list.h>
+
+
+int thermal_get_temp(struct udevice *dev, int *temp)
+{
+ const struct dm_thermal_ops *ops = device_get_ops(dev);
+
+ if (!ops->get_temp)
+ return -ENOSYS;
+
+ return ops->get_temp(dev, temp);
+}
+
+UCLASS_DRIVER(thermal) = {
+ .id = UCLASS_THERMAL,
+ .name = "thermal",
+};
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/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c
index eecf18c..d09f8ce 100644
--- a/drivers/tpm/tpm_tis_lpc.c
+++ b/drivers/tpm/tpm_tis_lpc.c
@@ -274,7 +274,7 @@ static u32 tis_senddata(const u8 * const data, u32 len)
* changes to zero exactly after the last byte is fed into the
* FIFO.
*/
- count = min(burst, len - offset - 1);
+ count = min((u32)burst, len - offset - 1);
while (count--)
tpm_write_byte(data[offset++],
&lpc_tpm_dev[locality].data);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 7bd2562..a4c5606 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -743,8 +743,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (!gadget_is_dualspeed(gadget))
break;
device_qual(cdev);
- value = min(w_length,
- sizeof(struct usb_qualifier_descriptor));
+ value = min_t(int, w_length,
+ sizeof(struct usb_qualifier_descriptor));
break;
case USB_DT_OTHER_SPEED_CONFIG:
if (!gadget_is_dualspeed(gadget))
diff --git a/drivers/usb/gadget/designware_udc.c b/drivers/usb/gadget/designware_udc.c
index 3559400..0db7a3b 100644
--- a/drivers/usb/gadget/designware_udc.c
+++ b/drivers/usb/gadget/designware_udc.c
@@ -269,8 +269,8 @@ static void dw_write_noniso_tx_fifo(struct usb_endpoint_instance
UDCDBGA("urb->buffer %p, buffer_length %d, actual_length %d",
urb->buffer, urb->buffer_length, urb->actual_length);
- last = min(urb->actual_length - endpoint->sent,
- endpoint->tx_packetSize);
+ last = min_t(u32, urb->actual_length - endpoint->sent,
+ endpoint->tx_packetSize);
if (last) {
u8 *cp = urb->buffer + endpoint->sent;
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index efd5c7f..9423555 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -65,7 +65,8 @@ static int udc_write_urb(struct usb_endpoint_instance *endpoint)
if (!urb || !urb->actual_length)
return -1;
- n = min(urb->actual_length - endpoint->sent, endpoint->tx_packetSize);
+ n = min_t(unsigned int, urb->actual_length - endpoint->sent,
+ endpoint->tx_packetSize);
if (n <= 0)
return -1;
diff --git a/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c
index 9c54b46..7e7a2c2 100644
--- a/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c
+++ b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c
@@ -97,8 +97,8 @@ static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req)
u32 ep_num = ep_index(ep);
buf = req->req.buf + req->req.actual;
- length = min(req->req.length - req->req.actual,
- ep_num ? DMA_BUFFER_SIZE : ep->ep.maxpacket);
+ length = min_t(u32, req->req.length - req->req.actual,
+ ep_num ? DMA_BUFFER_SIZE : ep->ep.maxpacket);
ep->len = length;
ep->dma_buf = buf;
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 2a5bbf5..e8142ac 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -503,23 +503,23 @@ static int dwc_otg_submit_rh_msg_in_descriptor(struct usb_device *dev,
case 0:
switch (wValue & 0xff00) {
case 0x0100: /* device descriptor */
- len = min3(txlen, sizeof(root_hub_dev_des), wLength);
+ len = min3(txlen, (int)sizeof(root_hub_dev_des), (int)wLength);
memcpy(buffer, root_hub_dev_des, len);
break;
case 0x0200: /* configuration descriptor */
- len = min3(txlen, sizeof(root_hub_config_des), wLength);
+ len = min3(txlen, (int)sizeof(root_hub_config_des), (int)wLength);
memcpy(buffer, root_hub_config_des, len);
break;
case 0x0300: /* string descriptors */
switch (wValue & 0xff) {
case 0x00:
- len = min3(txlen, sizeof(root_hub_str_index0),
- wLength);
+ len = min3(txlen, (int)sizeof(root_hub_str_index0),
+ (int)wLength);
memcpy(buffer, root_hub_str_index0, len);
break;
case 0x01:
- len = min3(txlen, sizeof(root_hub_str_index1),
- wLength);
+ len = min3(txlen, (int)sizeof(root_hub_str_index1),
+ (int)wLength);
memcpy(buffer, root_hub_str_index1, len);
break;
}
@@ -556,7 +556,7 @@ static int dwc_otg_submit_rh_msg_in_descriptor(struct usb_device *dev,
data[10] = data[9];
}
- len = min3(txlen, data[0], wLength);
+ len = min3(txlen, (int)data[0], (int)wLength);
memcpy(buffer, data, len);
break;
default:
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..5d4288d 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -14,10 +14,15 @@
#include <asm/io.h>
#include <usb/ehci-fsl.h>
#include <hwconfig.h>
-#include <asm/fsl_errata.h>
+#include <fsl_usb.h>
+#include <fdt_support.h>
#include "ehci.h"
+#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
+#endif
+
static void set_txfifothresh(struct usb_ehci *, u32);
/* Check USB PHY clock valid */
@@ -130,8 +135,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;
@@ -159,3 +163,184 @@ static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh)
cmd |= TXFIFO_THRESH(txfifo_thresh);
ehci_writel(&ehci->txfilltuning, cmd);
}
+
+#if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB)
+static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
+ const char *phy_type, int start_offset)
+{
+ const char *compat_dr = "fsl-usb2-dr";
+ const char *compat_mph = "fsl-usb2-mph";
+ const char *prop_mode = "dr_mode";
+ const char *prop_type = "phy_type";
+ const char *node_type = NULL;
+ int node_offset;
+ int err;
+
+ node_offset = fdt_node_offset_by_compatible(blob,
+ start_offset, compat_mph);
+ if (node_offset < 0) {
+ node_offset = fdt_node_offset_by_compatible(blob,
+ start_offset,
+ compat_dr);
+ if (node_offset < 0) {
+ printf("WARNING: could not find compatible node: %s",
+ fdt_strerror(node_offset));
+ return -1;
+ }
+ node_type = compat_dr;
+ } else {
+ node_type = compat_mph;
+ }
+
+ if (mode) {
+ err = fdt_setprop(blob, node_offset, prop_mode, mode,
+ strlen(mode) + 1);
+ if (err < 0)
+ printf("WARNING: could not set %s for %s: %s.\n",
+ prop_mode, node_type, fdt_strerror(err));
+ }
+
+ if (phy_type) {
+ err = fdt_setprop(blob, node_offset, prop_type, phy_type,
+ strlen(phy_type) + 1);
+ if (err < 0)
+ printf("WARNING: could not set %s for %s: %s.\n",
+ prop_type, node_type, fdt_strerror(err));
+ }
+
+ return node_offset;
+}
+
+static const char *fdt_usb_get_node_type(void *blob, int start_offset,
+ int *node_offset)
+{
+ const char *compat_dr = "fsl-usb2-dr";
+ const char *compat_mph = "fsl-usb2-mph";
+ const char *node_type = NULL;
+
+ *node_offset = fdt_node_offset_by_compatible(blob, start_offset,
+ compat_mph);
+ if (*node_offset < 0) {
+ *node_offset = fdt_node_offset_by_compatible(blob,
+ start_offset,
+ compat_dr);
+ if (*node_offset < 0) {
+ printf("ERROR: could not find compatible node: %s\n",
+ fdt_strerror(*node_offset));
+ } else {
+ node_type = compat_dr;
+ }
+ } else {
+ node_type = compat_mph;
+ }
+
+ return node_type;
+}
+
+static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum,
+ int start_offset)
+{
+ int node_offset, err;
+ const char *node_type = NULL;
+
+ node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset);
+ if (!node_type)
+ return -1;
+
+ err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0);
+ if (err < 0) {
+ printf("ERROR: could not set %s for %s: %s.\n",
+ prop_erratum, node_type, fdt_strerror(err));
+ }
+
+ return node_offset;
+}
+
+void fdt_fixup_dr_usb(void *blob, bd_t *bd)
+{
+ static const char * const modes[] = { "host", "peripheral", "otg" };
+ static const char * const phys[] = { "ulpi", "utmi" };
+ int usb_erratum_a006261_off = -1;
+ int usb_erratum_a007075_off = -1;
+ int usb_erratum_a007792_off = -1;
+ int usb_mode_off = -1;
+ int usb_phy_off = -1;
+ char str[5];
+ int i, j;
+
+ for (i = 1; i <= CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
+ const char *dr_mode_type = NULL;
+ const char *dr_phy_type = NULL;
+ int mode_idx = -1, phy_idx = -1;
+
+ snprintf(str, 5, "%s%d", "usb", i);
+ if (hwconfig(str)) {
+ for (j = 0; j < ARRAY_SIZE(modes); j++) {
+ if (hwconfig_subarg_cmp(str, "dr_mode",
+ modes[j])) {
+ mode_idx = j;
+ break;
+ }
+ }
+
+ for (j = 0; j < ARRAY_SIZE(phys); j++) {
+ if (hwconfig_subarg_cmp(str, "phy_type",
+ phys[j])) {
+ phy_idx = j;
+ break;
+ }
+ }
+
+ if (mode_idx < 0 && phy_idx < 0) {
+ printf("WARNING: invalid phy or mode\n");
+ return;
+ }
+
+ if (mode_idx > -1)
+ dr_mode_type = modes[mode_idx];
+
+ if (phy_idx > -1)
+ dr_phy_type = phys[phy_idx];
+ }
+
+ usb_mode_off = fdt_fixup_usb_mode_phy_type(blob,
+ dr_mode_type, NULL,
+ usb_mode_off);
+
+ if (usb_mode_off < 0)
+ return;
+
+ usb_phy_off = fdt_fixup_usb_mode_phy_type(blob,
+ NULL, dr_phy_type,
+ usb_phy_off);
+
+ if (usb_phy_off < 0)
+ return;
+
+ if (has_erratum_a006261()) {
+ usb_erratum_a006261_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a006261",
+ usb_erratum_a006261_off);
+ if (usb_erratum_a006261_off < 0)
+ return;
+ }
+ if (has_erratum_a007075()) {
+ usb_erratum_a007075_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a007075",
+ usb_erratum_a007075_off);
+ if (usb_erratum_a007075_off < 0)
+ return;
+ }
+ if (has_erratum_a007792()) {
+ usb_erratum_a007792_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a007792",
+ usb_erratum_a007792_off);
+ if (usb_erratum_a007792_off < 0)
+ return;
+ }
+ }
+}
+#endif
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 54e948a..bc76066 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -910,7 +910,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
}
mdelay(1);
- len = min3(srclen, le16_to_cpu(req->length), length);
+ len = min3(srclen, (int)le16_to_cpu(req->length), length);
if (srcptr != NULL && len > 0)
memcpy(buffer, srcptr, len);
else
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/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 46e4cee..0556f32 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -103,12 +103,6 @@ static int rh_devnum; /* address of Root Hub endpoint */
/* ------------------------------------------------------------------------- */
-#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL))
-#define min_t(type,x,y) \
- ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
-
-/* ------------------------------------------------------------------------- */
-
static int isp116x_reset(struct isp116x *isp116x);
/* --- Debugging functions ------------------------------------------------- */
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index dc0a4e3..97a7ede 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -47,7 +47,7 @@
#include <asm/arch/hardware.h> /* needed for AT91_USB_HOST_BASE */
#endif
-#if defined(CONFIG_ARM920T) || \
+#if defined(CONFIG_CPU_ARM920T) || \
defined(CONFIG_S3C24X0) || \
defined(CONFIG_440EP) || \
defined(CONFIG_PCI_OHCI) || \
@@ -65,9 +65,6 @@
#define OHCI_CONTROL_INIT \
(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
-#define min_t(type, x, y) \
- ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-
#ifdef CONFIG_PCI_OHCI
static struct pci_device_id ohci_pci_ids[] = {
{0x10b9, 0x5237}, /* ULI1575 PCI OHCI module ids */
diff --git a/drivers/usb/host/ohci-s3c24xx.c b/drivers/usb/host/ohci-s3c24xx.c
index 3c659c6..8bb2275 100644
--- a/drivers/usb/host/ohci-s3c24xx.c
+++ b/drivers/usb/host/ohci-s3c24xx.c
@@ -35,9 +35,6 @@
#define OHCI_CONTROL_INIT \
(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
-#define min_t(type, x, y) \
- ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
-
#undef DEBUG
#ifdef DEBUG
#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 5114544..6f33456 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -550,9 +550,6 @@ static int check_usb_device_connecting(struct r8a66597 *r8a66597)
return -1; /* fail */
}
-/* based on usb_ohci.c */
-#define min_t(type, x, y) \
- ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
/*-------------------------------------------------------------------------*
* Virtual Root Hub
*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 19c3ec6..b5aade9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -511,7 +511,7 @@ static void record_transfer_result(struct usb_device *udev,
union xhci_trb *event, int length)
{
udev->act_len = min(length, length -
- EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len)));
+ (int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len)));
switch (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len))) {
case COMP_SUCCESS:
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 59dc096..87f2972 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -829,7 +829,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe,
debug("scrlen = %d\n req->length = %d\n",
srclen, le16_to_cpu(req->length));
- len = min(srclen, le16_to_cpu(req->length));
+ len = min(srclen, (int)le16_to_cpu(req->length));
if (srcptr != NULL && len > 0)
memcpy(buffer, srcptr, len);
diff --git a/drivers/usb/musb/musb_hcd.h b/drivers/usb/musb/musb_hcd.h
index 02b9adc..0c8e75d 100644
--- a/drivers/usb/musb/musb_hcd.h
+++ b/drivers/usb/musb/musb_hcd.h
@@ -37,9 +37,6 @@ extern unsigned char new[];
((readb(&musbr->power) & MUSB_POWER_HSMODE) \
>> MUSB_POWER_HSMODE_SHIFT)
-#define min_t(type, x, y) \
- ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
-
/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
/* destination of request */
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 38d2eb1..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>
@@ -39,11 +40,6 @@
#define DPRINT(x...) do{}while(0)
#endif
-#ifndef min_t
-#define min_t(type,x,y) \
- ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#endif
-
#define MAX_MAPPED_VRAM (2048*2048*4)
#define MIN_MAPPED_VRAM (1024*768*1)
@@ -549,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/cfb_console.c b/drivers/video/cfb_console.c
index 6aa50cb..a653bb4 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -1160,10 +1160,19 @@ static void video_putc(struct stdio_dev *dev, const char c)
static void video_puts(struct stdio_dev *dev, const char *s)
{
+ int flush = cfb_do_flush_cache;
int count = strlen(s);
+ /* temporarily disable cache flush */
+ cfb_do_flush_cache = 0;
+
while (count--)
video_putc(dev, *s++);
+
+ if (flush) {
+ cfb_do_flush_cache = flush;
+ flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
+ }
}
/*
@@ -1532,14 +1541,14 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
#ifdef CONFIG_SPLASH_SCREEN_ALIGN
if (x == BMP_ALIGN_CENTER)
- x = max(0, (VIDEO_VISIBLE_COLS - width) / 2);
+ x = max(0, (int)(VIDEO_VISIBLE_COLS - width) / 2);
else if (x < 0)
- x = max(0, VIDEO_VISIBLE_COLS - width + x + 1);
+ x = max(0, (int)(VIDEO_VISIBLE_COLS - width + x + 1));
if (y == BMP_ALIGN_CENTER)
- y = max(0, (VIDEO_VISIBLE_ROWS - height) / 2);
+ y = max(0, (int)(VIDEO_VISIBLE_ROWS - height) / 2);
else if (y < 0)
- y = max(0, VIDEO_VISIBLE_ROWS - height + y + 1);
+ y = max(0, (int)(VIDEO_VISIBLE_ROWS - height + y + 1));
#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
/*
@@ -1865,14 +1874,14 @@ static void plot_logo_or_black(void *screen, int width, int x, int y, int black)
#ifdef CONFIG_SPLASH_SCREEN_ALIGN
if (x == BMP_ALIGN_CENTER)
- x = max(0, (VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
+ x = max(0, (int)(VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
else if (x < 0)
- x = max(0, VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1);
+ x = max(0, (int)(VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1));
if (y == BMP_ALIGN_CENTER)
- y = max(0, (VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
+ y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
else if (y < 0)
- y = max(0, VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1);
+ y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1));
#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
dest = (unsigned char *)screen + (y * width + x) * VIDEO_PIXEL_SIZE;
@@ -2019,7 +2028,7 @@ static void *video_logo(void)
* we need to adjust the logo height
*/
if (video_logo_ypos == BMP_ALIGN_CENTER)
- video_logo_height += max(0, (VIDEO_VISIBLE_ROWS - \
+ video_logo_height += max(0, (int)(VIDEO_VISIBLE_ROWS -
VIDEO_LOGO_HEIGHT) / 2);
else if (video_logo_ypos > 0)
video_logo_height += video_logo_ypos;
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;
+}