Merge branch 'u-boot-sunxi/master' into 'u-boot-arm/master'

This commit is contained in:
Albert ARIBAUD 2014-07-28 10:12:45 +02:00
commit 740f41d3cb
38 changed files with 1011 additions and 265 deletions

View File

@ -11,6 +11,8 @@ obj-y += timer.o
obj-y += board.o
obj-y += clock.o
obj-y += pinmux.o
obj-$(CONFIG_SUN4I) += clock_sun4i.o
obj-$(CONFIG_SUN5I) += clock_sun4i.o
obj-$(CONFIG_SUN7I) += clock_sun4i.o
ifndef CONFIG_SPL_BUILD
@ -18,6 +20,8 @@ obj-y += cpu_info.o
endif
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SUN4I) += dram.o
obj-$(CONFIG_SUN5I) += dram.o
obj-$(CONFIG_SUN7I) += dram.o
ifdef CONFIG_SPL_FEL
obj-y += start.o

View File

@ -11,6 +11,7 @@
*/
#include <common.h>
#include <i2c.h>
#include <netdev.h>
#include <miiphy.h>
#include <serial.h>
@ -24,6 +25,8 @@
#include <asm/arch/sys_proto.h>
#include <asm/arch/timer.h>
#include <linux/compiler.h>
#ifdef CONFIG_SPL_BUILD
/* Pointer to the global data structure for SPL */
DECLARE_GLOBAL_DATA_PTR;
@ -47,15 +50,38 @@ u32 spl_boot_mode(void)
int gpio_init(void)
{
#if CONFIG_CONS_INDEX == 1 && (defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I))
sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUN4I_GPB22_UART0_TX);
sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUN4I_GPB23_UART0_RX);
sunxi_gpio_set_pull(SUNXI_GPB(23), 1);
#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_SUN5I)
sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN5I_GPB19_UART0_TX);
sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN5I_GPB20_UART0_RX);
sunxi_gpio_set_pull(SUNXI_GPB(20), 1);
#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_SUN5I)
sunxi_gpio_set_cfgpin(SUNXI_GPG(3), SUN5I_GPG3_UART1_TX);
sunxi_gpio_set_cfgpin(SUNXI_GPG(4), SUN5I_GPG4_UART1_RX);
sunxi_gpio_set_pull(SUNXI_GPG(4), 1);
#else
#error Unsupported console port number. Please fix pin mux settings in board.c
#endif
return 0;
}
void reset_cpu(ulong addr)
{
static const struct sunxi_wdog *wdog =
&((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
/* Set the watchdog for its shortest interval (.5s) and wait */
writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl);
while (1) {
/* sun5i sometimes gets stuck without this */
writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
}
}
/* do some early init */
@ -72,11 +98,16 @@ void s_init(void)
clock_init();
timer_init();
gpio_init();
i2c_init_board();
#ifdef CONFIG_SPL_BUILD
gd = &gdata;
preloader_console_init();
#ifdef CONFIG_SPL_I2C_SUPPORT
/* Needed early by sunxi_board_init if PMU is enabled */
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
#endif
sunxi_board_init();
#endif
}
@ -96,7 +127,15 @@ void enable_caches(void)
*/
int cpu_eth_init(bd_t *bis)
{
int rc;
__maybe_unused int rc;
#ifdef CONFIG_SUNXI_EMAC
rc = sunxi_emac_initialize(bis);
if (rc < 0) {
printf("sunxi: failed to initialize emac\n");
return rc;
}
#endif
#ifdef CONFIG_SUNXI_GMAC
rc = sunxi_gmac_initialize(bis);

View File

@ -36,8 +36,7 @@ void clock_init_safe(void)
CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
&ccm->cpu_ahb_apb0_cfg);
#ifdef CONFIG_SUN7I
writel(0x1 << AHB_GATE_OFFSET_DMA | readl(&ccm->ahb_gate0),
&ccm->ahb_gate0);
setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_DMA);
#endif
writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg);
}

View File

@ -13,7 +13,22 @@
#ifdef CONFIG_DISPLAY_CPUINFO
int print_cpuinfo(void)
{
#ifdef CONFIG_SUN4I
puts("CPU: Allwinner A10 (SUN4I)\n");
#elif defined CONFIG_SUN5I
u32 val = readl(SUNXI_SID_BASE + 0x08);
switch ((val >> 12) & 0xf) {
case 0: puts("CPU: Allwinner A12 (SUN5I)\n"); break;
case 3: puts("CPU: Allwinner A13 (SUN5I)\n"); break;
case 7: puts("CPU: Allwinner A10s (SUN5I)\n"); break;
default: puts("CPU: Allwinner A1X (SUN5I)\n");
}
#elif defined CONFIG_SUN7I
puts("CPU: Allwinner A20 (SUN7I)\n");
#else
#warning Please update cpu_info.c with correct CPU information
puts("CPU: SUNXI Family\n");
#endif
return 0;
}
#endif

View File

@ -53,16 +53,37 @@ static void mctl_ddr3_reset(void)
struct sunxi_dram_reg *dram =
(struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
udelay(2);
setbits_le32(&dram->mcr, DRAM_MCR_RESET);
#ifdef CONFIG_SUN4I
struct sunxi_timer_reg *timer =
(struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
u32 reg_val;
writel(0, &timer->cpu_cfg);
reg_val = readl(&timer->cpu_cfg);
if ((reg_val & CPU_CFG_CHIP_VER_MASK) !=
CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) {
setbits_le32(&dram->mcr, DRAM_MCR_RESET);
udelay(2);
clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
} else
#endif
{
clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
udelay(2);
setbits_le32(&dram->mcr, DRAM_MCR_RESET);
}
}
static void mctl_set_drive(void)
{
struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
#ifdef CONFIG_SUN7I
clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
#else
clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3),
#endif
DRAM_MCR_MODE_EN(0x3) |
0xffc);
}
@ -134,6 +155,26 @@ static void mctl_enable_dllx(u32 phase)
}
static u32 hpcr_value[32] = {
#ifdef CONFIG_SUN5I
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0x1031, 0x1031, 0x0735, 0x1035,
0x1035, 0x0731, 0x1031, 0,
0x0301, 0x0301, 0x0301, 0x0301,
0x0301, 0x0301, 0x0301, 0
#endif
#ifdef CONFIG_SUN4I
0x0301, 0x0301, 0x0301, 0x0301,
0x0301, 0x0301, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0x1031, 0x1031, 0x0735, 0x5031,
0x1035, 0x0731, 0x1031, 0x0735,
0x1035, 0x1031, 0x0731, 0x1035,
0x1031, 0x0301, 0x0301, 0x0731
#endif
#ifdef CONFIG_SUN7I
0x0301, 0x0301, 0x0301, 0x0301,
0x0301, 0x0301, 0x0301, 0x0301,
@ -223,22 +264,38 @@ static void mctl_setup_dram_clock(u32 clk)
clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
#endif
#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
/* setup MBUS clock */
reg_val = CCM_MBUS_CTRL_GATE |
#ifdef CONFIG_SUN7I
CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) |
CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
#else /* defined(CONFIG_SUN5I) */
CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) |
CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
#endif
writel(reg_val, &ccm->mbus_clk_cfg);
#endif
/*
* open DRAMC AHB & DLL register clock
* close it first
*/
#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
#else
clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
#endif
udelay(22);
/* then open it */
#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
#else
setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
#endif
udelay(22);
}
@ -385,6 +442,13 @@ static void dramc_clock_output_en(u32 on)
else
clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
#endif
#ifdef CONFIG_SUN4I
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
if (on)
setbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
else
clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
#endif
}
static const u16 tRFC_table[2][6] = {
@ -420,12 +484,25 @@ unsigned long dramc_init(struct dram_para *para)
/* setup DRAM relative clock */
mctl_setup_dram_clock(para->clock);
#ifdef CONFIG_SUN5I
/* Disable any pad power save control */
writel(0, &dram->ppwrsctl);
#endif
/* reset external DRAM */
#ifndef CONFIG_SUN7I
mctl_ddr3_reset();
#endif
mctl_set_drive();
/* dram clock off */
dramc_clock_output_en(0);
#ifdef CONFIG_SUN4I
/* select dram controller 1 */
writel(DRAM_CSEL_MAGIC, &dram->csel);
#endif
mctl_itm_disable();
mctl_enable_dll0(para->tpr3);
@ -482,6 +559,9 @@ unsigned long dramc_init(struct dram_para *para)
mctl_ddr3_reset();
else
setbits_le32(&dram->mcr, DRAM_MCR_RESET);
#else
/* dram clock on */
dramc_clock_output_en(1);
#endif
udelay(1);
@ -490,6 +570,22 @@ unsigned long dramc_init(struct dram_para *para)
mctl_enable_dllx(para->tpr3);
#ifdef CONFIG_SUN4I
/* set odt impedance divide ratio */
reg_val = ((para->zq) >> 8) & 0xfffff;
reg_val |= ((para->zq) & 0xff) << 20;
reg_val |= (para->zq) & 0xf0000000;
writel(reg_val, &dram->zqcr0);
#endif
#ifdef CONFIG_SUN4I
/* set I/O configure register */
reg_val = 0x00cc0000;
reg_val |= (para->odt_en) & 0x3;
reg_val |= ((para->odt_en) & 0x3) << 30;
writel(reg_val, &dram->iocr);
#endif
/* set refresh period */
dramc_set_autorefresh_cycle(para->clock, para->type - 2, density);

View File

@ -26,6 +26,11 @@ SECTIONS
*(.data*)
}
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
. = .;

View File

@ -27,6 +27,7 @@ SECTIONS
.text :
{
__start = .;
*(.vectors)
arch/arm/cpu/armv7/start.o (.text)
*(.text*)
} > .sram
@ -37,6 +38,11 @@ SECTIONS
. = ALIGN(4);
.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
} > .sram
. = ALIGN(4);
__image_copy_end = .;
_end = .;

View File

@ -129,7 +129,8 @@
*/
#ifdef CONFIG_CMD_I2C
#ifndef CONFIG_SYS_I2C_SOFT
#define CONFIG_I2C_MVTWSI
#define CONFIG_SYS_I2C
#define CONFIG_SYS_I2C_MVTWSI
#endif
#define CONFIG_SYS_I2C_SLAVE 0x0
#define CONFIG_SYS_I2C_SPEED 100000

View File

@ -143,5 +143,7 @@ int sunxi_gpio_set_cfgpin(u32 pin, u32 val);
int sunxi_gpio_get_cfgpin(u32 pin);
int sunxi_gpio_set_drv(u32 pin, u32 val);
int sunxi_gpio_set_pull(u32 pin, u32 val);
int sunxi_name_to_gpio(const char *name);
#define name_to_gpio(name) sunxi_name_to_gpio(name)
#endif /* _SUNXI_GPIO_H */

View File

@ -0,0 +1,15 @@
/*
* Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _SUNXI_I2C_H_
#define _SUNXI_I2C_H_
#include <asm/arch/cpu.h>
#define CONFIG_I2C_MVTWSI_BASE SUNXI_TWI0_BASE
/* This is abp0-clk on sun4i/5i/7i / abp1-clk on sun6i/sun8i which is 24MHz */
#define CONFIG_SYS_TCLK 24000000
#endif

View File

@ -11,6 +11,11 @@
#ifndef _SUNXI_TIMER_H_
#define _SUNXI_TIMER_H_
#define WDT_CTRL_RESTART (0x1 << 0)
#define WDT_CTRL_KEY (0x0a57 << 1)
#define WDT_MODE_EN (0x1 << 0)
#define WDT_MODE_RESET_EN (0x1 << 1)
#ifndef __ASSEMBLY__
#include <linux/types.h>

View File

@ -10,4 +10,8 @@
#
obj-y += board.o
obj-$(CONFIG_SUNXI_GMAC) += gmac.o
obj-$(CONFIG_A13_OLINUXINOM) += dram_a13_oli_micro.o
obj-$(CONFIG_CUBIEBOARD) += dram_cubieboard.o
obj-$(CONFIG_CUBIEBOARD2) += dram_cubieboard2.o
obj-$(CONFIG_CUBIETRUCK) += dram_cubietruck.o
obj-$(CONFIG_R7DONGLE) += dram_r7dongle.o

View File

@ -12,10 +12,19 @@
*/
#include <common.h>
#ifdef CONFIG_AXP152_POWER
#include <axp152.h>
#endif
#ifdef CONFIG_AXP209_POWER
#include <axp209.h>
#endif
#include <asm/arch/clock.h>
#include <asm/arch/cpu.h>
#include <asm/arch/dram.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mmc.h>
#include <asm/io.h>
#include <net.h>
DECLARE_GLOBAL_DATA_PTR;
@ -106,15 +115,73 @@ int board_mmc_init(bd_t *bis)
}
#endif
void i2c_init_board(void)
{
sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUNXI_GPB0_TWI0);
sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUNXI_GPB0_TWI0);
clock_twi_onoff(0, 1);
}
#ifdef CONFIG_SPL_BUILD
void sunxi_board_init(void)
{
int power_failed = 0;
unsigned long ramsize;
#ifdef CONFIG_AXP152_POWER
power_failed = axp152_init();
power_failed |= axp152_set_dcdc2(1400);
power_failed |= axp152_set_dcdc3(1500);
power_failed |= axp152_set_dcdc4(1250);
power_failed |= axp152_set_ldo2(3000);
#endif
#ifdef CONFIG_AXP209_POWER
power_failed |= axp209_init();
power_failed |= axp209_set_dcdc2(1400);
power_failed |= axp209_set_dcdc3(1250);
power_failed |= axp209_set_ldo2(3000);
power_failed |= axp209_set_ldo3(2800);
power_failed |= axp209_set_ldo4(2800);
#endif
printf("DRAM:");
ramsize = sunxi_dram_init();
printf(" %lu MiB\n", ramsize >> 20);
if (!ramsize)
hang();
/*
* Only clock up the CPU to full speed if we are reasonably
* assured it's being powered with suitable core voltage
*/
if (!power_failed)
clock_set_pll1(CONFIG_CLK_FULL_SPEED);
else
printf("Failed to set core voltage! Can't set CPU frequency\n");
}
#endif
#ifdef CONFIG_MISC_INIT_R
int misc_init_r(void)
{
if (!getenv("ethaddr")) {
uint32_t reg_val = readl(SUNXI_SID_BASE);
if (reg_val) {
uint8_t mac_addr[6];
mac_addr[0] = 0x02; /* Non OUI / registered MAC address */
mac_addr[1] = (reg_val >> 0) & 0xff;
reg_val = readl(SUNXI_SID_BASE + 0x0c);
mac_addr[2] = (reg_val >> 24) & 0xff;
mac_addr[3] = (reg_val >> 16) & 0xff;
mac_addr[4] = (reg_val >> 8) & 0xff;
mac_addr[5] = (reg_val >> 0) & 0xff;
eth_setenv_enetaddr("ethaddr", mac_addr);
}
}
return 0;
}
#endif

View File

@ -0,0 +1,32 @@
/* this file is generated, don't edit it yourself */
#include <common.h>
#include <asm/arch/dram.h>
static struct dram_para dram_para = {
.clock = 408,
.type = 3,
.rank_num = 1,
.density = 2048,
.io_width = 16,
.bus_width = 16,
.cas = 9,
.zq = 123,
.odt_en = 0,
.size = 256,
.tpr0 = 0x42d899b7,
.tpr1 = 0xa090,
.tpr2 = 0x22a00,
.tpr3 = 0,
.tpr4 = 0,
.tpr5 = 0,
.emr1 = 0,
.emr2 = 0x10,
.emr3 = 0,
};
unsigned long sunxi_dram_init(void)
{
return dramc_init(&dram_para);
}

View File

@ -0,0 +1,31 @@
/* this file is generated, don't edit it yourself */
#include <common.h>
#include <asm/arch/dram.h>
static struct dram_para dram_para = {
.clock = 480,
.type = 3,
.rank_num = 1,
.density = 4096,
.io_width = 16,
.bus_width = 32,
.cas = 6,
.zq = 123,
.odt_en = 0,
.size = 1024,
.tpr0 = 0x30926692,
.tpr1 = 0x1090,
.tpr2 = 0x1a0c8,
.tpr3 = 0,
.tpr4 = 0,
.tpr5 = 0,
.emr1 = 0,
.emr2 = 0,
.emr3 = 0,
};
unsigned long sunxi_dram_init(void)
{
return dramc_init(&dram_para);
}

View File

@ -0,0 +1,31 @@
/* this file is generated, don't edit it yourself */
#include <common.h>
#include <asm/arch/dram.h>
static struct dram_para dram_para = {
.clock = 480,
.type = 3,
.rank_num = 1,
.density = 4096,
.io_width = 16,
.bus_width = 32,
.cas = 9,
.zq = 0x7f,
.odt_en = 0,
.size = 1024,
.tpr0 = 0x42d899b7,
.tpr1 = 0xa090,
.tpr2 = 0x22a00,
.tpr3 = 0x0,
.tpr4 = 0x1,
.tpr5 = 0x0,
.emr1 = 0x4,
.emr2 = 0x10,
.emr3 = 0x0,
};
unsigned long sunxi_dram_init(void)
{
return dramc_init(&dram_para);
}

View File

@ -0,0 +1,31 @@
/* this file is generated, don't edit it yourself */
#include <common.h>
#include <asm/arch/dram.h>
static struct dram_para dram_para = {
.clock = 384,
.type = 3,
.rank_num = 1,
.density = 2048,
.io_width = 8,
.bus_width = 32,
.cas = 9,
.zq = 123,
.odt_en = 0,
.size = 1024,
.tpr0 = 0x42d899b7,
.tpr1 = 0xa090,
.tpr2 = 0x22a00,
.tpr3 = 0,
.tpr4 = 0,
.tpr5 = 0,
.emr1 = 0x04,
.emr2 = 0x10,
.emr3 = 0,
};
unsigned long sunxi_dram_init(void)
{
return dramc_init(&dram_para);
}

View File

@ -16,17 +16,28 @@ int sunxi_gmac_initialize(bd_t *bis)
setbits_le32(&ccm->ahb_gate1, 0x1 << AHB_GATE_OFFSET_GMAC);
/* Set MII clock */
#ifdef CONFIG_RGMII
setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII |
CCM_GMAC_CTRL_GPIT_RGMII);
#else
setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_MII |
CCM_GMAC_CTRL_GPIT_MII);
#endif
/* Configure pin mux settings for GMAC */
for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(16); pin++) {
#ifdef CONFIG_RGMII
/* skip unused pins in RGMII mode */
if (pin == SUNXI_GPA(9) || pin == SUNXI_GPA(14))
continue;
#endif
sunxi_gpio_set_cfgpin(pin, SUN7I_GPA0_GMAC);
sunxi_gpio_set_drv(pin, 3);
}
#ifdef CONFIG_RGMII
return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_RGMII);
#else
return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_MII);
#endif
}

View File

@ -377,8 +377,13 @@ Active arm armv7 rmobile renesas lager
Active arm armv7 s5pc1xx samsung goni s5p_goni - Robert Baldyga <r.baldyga@samsung.com>
Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang <mk7.kang@samsung.com>
Active arm armv7 socfpga altera socfpga socfpga_cyclone5 - -
Active arm armv7 sunxi - sunxi Cubietruck sun7i:CUBIETRUCK,SPL,SUNXI_GMAC,RGMII -
Active arm armv7 sunxi - sunxi Cubietruck_FEL sun7i:CUBIETRUCK,SPL_FEL,SUNXI_GMAC,RGMII -
Active arm armv7 sunxi - sunxi A13-OLinuXinoM sun5i:A13_OLINUXINOM,SPL,CONS_INDEX=2 Hans de Goede <hdegoede@redhat.com>
Active arm armv7 sunxi - sunxi Cubieboard sun4i:CUBIEBOARD,SPL,AXP209_POWER,SUNXI_EMAC Hans de Goede <hdegoede@redhat.com>
Active arm armv7 sunxi - sunxi Cubieboard2 sun7i:CUBIEBOARD2,SPL,SUNXI_GMAC Ian Campbell <ijc@hellion.org.uk>:Hans de Goede <hdegoede@redhat.com>
Active arm armv7 sunxi - sunxi Cubieboard2_FEL sun7i:CUBIEBOARD2,SPL_FEL,SUNXI_GMAC Ian Campbell <ijc@hellion.org.uk>:Hans de Goede <hdegoede@redhat.com>
Active arm armv7 sunxi - sunxi Cubietruck sun7i:CUBIETRUCK,SPL,AXP209_POWER,SUNXI_GMAC,RGMII Ian Campbell <ijc@hellion.org.uk>:Hans de Goede <hdegoede@redhat.com>
Active arm armv7 sunxi - sunxi Cubietruck_FEL sun7i:CUBIETRUCK,SPL_FEL,AXP209_POWER,SUNXI_GMAC,RGMII Ian Campbell <ijc@hellion.org.uk>:Hans de Goede <hdegoede@redhat.com>
Active arm armv7 sunxi - sunxi r7-tv-dongle sun5i:R7DONGLE,SPL,AXP152_POWER Hans de Goede <hdegoede@redhat.com>
Active arm armv7 u8500 st-ericsson snowball snowball - Mathieu Poirier <mathieu.poirier@linaro.org>
Active arm armv7 u8500 st-ericsson u8500 u8500_href - -
Active arm armv7 vf610 freescale vf610twr vf610twr vf610twr:IMX_CONFIG=board/freescale/vf610twr/imximage.cfg Alison Wang <b18965@freescale.com>

View File

@ -36,3 +36,4 @@ obj-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o
obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o
obj-$(CONFIG_TCA642X) += tca642x.o
oby-$(CONFIG_SX151X) += sx151x.o
obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o

102
drivers/gpio/sunxi_gpio.c Normal file
View File

@ -0,0 +1,102 @@
/*
* (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
*
* Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c:
*
* (C) Copyright 2007-2011
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Tom Cubie <tangliang@allwinnertech.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/gpio.h>
static int sunxi_gpio_output(u32 pin, u32 val)
{
u32 dat;
u32 bank = GPIO_BANK(pin);
u32 num = GPIO_NUM(pin);
struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
dat = readl(&pio->dat);
if (val)
dat |= 0x1 << num;
else
dat &= ~(0x1 << num);
writel(dat, &pio->dat);
return 0;
}
static int sunxi_gpio_input(u32 pin)
{
u32 dat;
u32 bank = GPIO_BANK(pin);
u32 num = GPIO_NUM(pin);
struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
dat = readl(&pio->dat);
dat >>= num;
return dat & 0x1;
}
int gpio_request(unsigned gpio, const char *label)
{
return 0;
}
int gpio_free(unsigned gpio)
{
return 0;
}
int gpio_direction_input(unsigned gpio)
{
sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
return sunxi_gpio_input(gpio);
}
int gpio_direction_output(unsigned gpio, int value)
{
sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
return sunxi_gpio_output(gpio, value);
}
int gpio_get_value(unsigned gpio)
{
return sunxi_gpio_input(gpio);
}
int gpio_set_value(unsigned gpio, int value)
{
return sunxi_gpio_output(gpio, value);
}
int sunxi_name_to_gpio(const char *name)
{
int group = 0;
int groupsize = 9 * 32;
long pin;
char *eptr;
if (*name == 'P' || *name == 'p')
name++;
if (*name >= 'A') {
group = *name - (*name > 'a' ? 'a' : 'A');
groupsize = 32;
name++;
}
pin = simple_strtol(name, &eptr, 10);
if (!*name || *eptr)
return -1;
if (pin < 0 || pin > groupsize || group >= 9)
return -1;
return group * 32 + pin;
}

View File

@ -7,7 +7,6 @@
obj-$(CONFIG_BFIN_TWI_I2C) += bfin-twi_i2c.o
obj-$(CONFIG_DW_I2C) += designware_i2c.o
obj-$(CONFIG_I2C_MVTWSI) += mvtwsi.o
obj-$(CONFIG_I2C_MV) += mv_i2c.o
obj-$(CONFIG_I2C_MXS) += mxs_i2c.o
obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
@ -20,6 +19,7 @@ obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o
obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o
obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o
obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o

View File

@ -22,6 +22,8 @@
#include <asm/arch/orion5x.h>
#elif defined(CONFIG_KIRKWOOD)
#include <asm/arch/kirkwood.h>
#elif defined(CONFIG_SUNXI)
#include <asm/arch/i2c.h>
#else
#error Driver mvtwsi not supported by SoC or board
#endif
@ -30,6 +32,20 @@
* TWSI register structure
*/
#ifdef CONFIG_SUNXI
struct mvtwsi_registers {
u32 slave_address;
u32 xtnd_slave_addr;
u32 data;
u32 control;
u32 status;
u32 baudrate;
u32 soft_reset;
};
#else
struct mvtwsi_registers {
u32 slave_address;
u32 data;
@ -43,6 +59,8 @@ struct mvtwsi_registers {
u32 soft_reset;
};
#endif
/*
* Control register fields
*/
@ -220,11 +238,10 @@ static int twsi_stop(int status)
/*
* Reset controller.
* Called at end of i2c_init unsuccessful i2c transactions.
* Controller reset also resets the baud rate and slave address, so
* re-establish them.
* they must be re-established afterwards.
*/
static void twsi_reset(u8 baud_rate, u8 slave_address)
static void twsi_reset(struct i2c_adapter *adap)
{
/* ensure controller will be enabled by any twsi*() function */
twsi_control_flags = MVTWSI_CONTROL_TWSIEN;
@ -232,23 +249,17 @@ static void twsi_reset(u8 baud_rate, u8 slave_address)
writel(0, &twsi->soft_reset);
/* wait 2 ms -- this is what the Marvell LSP does */
udelay(20000);
/* set baud rate */
writel(baud_rate, &twsi->baudrate);
/* set slave address even though we don't use it */
writel(slave_address, &twsi->slave_address);
writel(0, &twsi->xtnd_slave_addr);
/* assert STOP but don't care for the result */
(void) twsi_stop(0);
}
/*
* I2C init called by cmd_i2c when doing 'i2c reset'.
* Sets baud to the highest possible value not exceeding requested one.
*/
void i2c_init(int requested_speed, int slaveadd)
static unsigned int twsi_i2c_set_bus_speed(struct i2c_adapter *adap,
unsigned int requested_speed)
{
int tmp_speed, highest_speed, n, m;
int baud = 0x44; /* baudrate at controller reset */
unsigned int tmp_speed, highest_speed, n, m;
unsigned int baud = 0x44; /* baudrate at controller reset */
/* use actual speed to collect progressively higher values */
highest_speed = 0;
@ -263,8 +274,21 @@ void i2c_init(int requested_speed, int slaveadd)
}
}
}
writel(baud, &twsi->baudrate);
return 0;
}
static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
{
/* reset controller */
twsi_reset(baud, slaveadd);
twsi_reset(adap);
/* set speed */
twsi_i2c_set_bus_speed(adap, speed);
/* set slave address even though we don't use it */
writel(slaveadd, &twsi->slave_address);
writel(0, &twsi->xtnd_slave_addr);
/* assert STOP but don't care for the result */
(void) twsi_stop(0);
}
/*
@ -294,7 +318,7 @@ static int i2c_begin(int expected_start_status, u8 addr)
* I2C probe called by cmd_i2c when doing 'i2c probe'.
* Begin read, nak data byte, end.
*/
int i2c_probe(uchar chip)
static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip)
{
u8 dummy_byte;
int status;
@ -320,12 +344,13 @@ int i2c_probe(uchar chip)
* cmd_eeprom, so we have to choose here, and for the moment that'll be
* a repeated start without a preceding stop.
*/
int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
int alen, uchar *data, int length)
{
int status;
/* begin i2c write to send the address bytes */
status = i2c_begin(MVTWSI_STATUS_START, (dev << 1));
status = i2c_begin(MVTWSI_STATUS_START, (chip << 1));
/* send addr bytes */
while ((status == 0) && alen--)
status = twsi_send(addr >> (8*alen),
@ -333,7 +358,7 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
/* begin i2c read to receive eeprom data bytes */
if (status == 0)
status = i2c_begin(
MVTWSI_STATUS_REPEATED_START, (dev << 1) | 1);
MVTWSI_STATUS_REPEATED_START, (chip << 1) | 1);
/* prepare ACK if at least one byte must be received */
if (length > 0)
twsi_control_flags |= MVTWSI_CONTROL_ACK;
@ -355,12 +380,13 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
* I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c
* Begin write, send address byte(s), send data bytes, end.
*/
int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
int alen, uchar *data, int length)
{
int status;
/* begin i2c write to send the eeprom adress bytes then data bytes */
status = i2c_begin(MVTWSI_STATUS_START, (dev << 1));
status = i2c_begin(MVTWSI_STATUS_START, (chip << 1));
/* send addr bytes */
while ((status == 0) && alen--)
status = twsi_send(addr >> (8*alen),
@ -374,21 +400,7 @@ int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
return status;
}
/*
* Bus set routine: we only support bus 0.
*/
int i2c_set_bus_num(unsigned int bus)
{
if (bus > 0) {
return -1;
}
return 0;
}
/*
* Bus get routine: hard-return bus 0.
*/
unsigned int i2c_get_bus_num(void)
{
return 0;
}
U_BOOT_I2C_ADAP_COMPLETE(twsi0, twsi_i2c_init, twsi_i2c_probe,
twsi_i2c_read, twsi_i2c_write,
twsi_i2c_set_bus_speed,
CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 0)

View File

@ -16,28 +16,6 @@
#include <asm/arch/cpu.h>
#include <asm/arch/mmc.h>
struct sunxi_mmc_des {
u32 reserved1_1:1;
u32 dic:1; /* disable interrupt on completion */
u32 last_des:1; /* 1-this data buffer is the last buffer */
u32 first_des:1; /* 1-data buffer is the first buffer,
0-data buffer contained in the next
descriptor is 1st buffer */
u32 des_chain:1; /* 1-the 2nd address in the descriptor is the
next descriptor address */
u32 end_of_ring:1; /* 1-last descriptor flag when using dual
data buffer in descriptor */
u32 reserved1_2:24;
u32 card_err_sum:1; /* transfer error flag */
u32 own:1; /* des owner:1-idma owns it, 0-host owns it */
#define SDXC_DES_NUM_SHIFT 16
#define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT)
u32 data_buf1_sz:16;
u32 data_buf2_sz:16;
u32 buf_addr_ptr1;
u32 buf_addr_ptr2;
};
struct sunxi_mmc_host {
unsigned mmc_no;
uint32_t *mclkreg;
@ -189,6 +167,7 @@ static int mmc_core_init(struct mmc *mmc)
/* Reset controller */
writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
udelay(1000);
return 0;
}
@ -204,6 +183,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
unsigned timeout_msecs = 2000;
unsigned *buff = (unsigned int *)(reading ? data->dest : data->src);
/* Always read / write data through the CPU */
setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB);
for (i = 0; i < (byte_cnt >> 2); i++) {
while (readl(&mmchost->reg->status) & status_bit) {
if (!timeout_msecs--)
@ -220,85 +202,6 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
return 0;
}
static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data)
{
struct sunxi_mmc_host *mmchost = mmc->priv;
unsigned byte_cnt = data->blocksize * data->blocks;
unsigned char *buff;
unsigned des_idx = 0;
unsigned buff_frag_num =
(byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1) >> SDXC_DES_NUM_SHIFT;
unsigned remain;
unsigned i, rval;
ALLOC_CACHE_ALIGN_BUFFER(struct sunxi_mmc_des, pdes, buff_frag_num);
buff = data->flags & MMC_DATA_READ ?
(unsigned char *)data->dest : (unsigned char *)data->src;
remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1);
flush_cache((unsigned long)buff, (unsigned long)byte_cnt);
for (i = 0; i < buff_frag_num; i++, des_idx++) {
memset((void *)&pdes[des_idx], 0, sizeof(struct sunxi_mmc_des));
pdes[des_idx].des_chain = 1;
pdes[des_idx].own = 1;
pdes[des_idx].dic = 1;
if (buff_frag_num > 1 && i != buff_frag_num - 1)
pdes[des_idx].data_buf1_sz = 0; /* 0 == max_len */
else
pdes[des_idx].data_buf1_sz = remain;
pdes[des_idx].buf_addr_ptr1 =
(u32) buff + i * SDXC_DES_BUFFER_MAX_LEN;
if (i == 0)
pdes[des_idx].first_des = 1;
if (i == buff_frag_num - 1) {
pdes[des_idx].dic = 0;
pdes[des_idx].last_des = 1;
pdes[des_idx].end_of_ring = 1;
pdes[des_idx].buf_addr_ptr2 = 0;
} else {
pdes[des_idx].buf_addr_ptr2 = (u32)&pdes[des_idx + 1];
}
}
flush_cache((unsigned long)pdes,
sizeof(struct sunxi_mmc_des) * (des_idx + 1));
rval = readl(&mmchost->reg->gctrl);
/* Enable DMA */
writel(rval | SUNXI_MMC_GCTRL_DMA_RESET | SUNXI_MMC_GCTRL_DMA_ENABLE,
&mmchost->reg->gctrl);
/* Reset iDMA */
writel(SUNXI_MMC_IDMAC_RESET, &mmchost->reg->dmac);
/* Enable iDMA */
writel(SUNXI_MMC_IDMAC_FIXBURST | SUNXI_MMC_IDMAC_ENABLE,
&mmchost->reg->dmac);
rval = readl(&mmchost->reg->idie) &
~(SUNXI_MMC_IDIE_TXIRQ|SUNXI_MMC_IDIE_RXIRQ);
if (data->flags & MMC_DATA_WRITE)
rval |= SUNXI_MMC_IDIE_TXIRQ;
else
rval |= SUNXI_MMC_IDIE_RXIRQ;
writel(rval, &mmchost->reg->idie);
writel((u32) pdes, &mmchost->reg->dlba);
writel((0x2 << 28) | (0x7 << 16) | (0x01 << 3),
&mmchost->reg->ftrglevel);
return 0;
}
static void mmc_enable_dma_accesses(struct mmc *mmc, int dma)
{
struct sunxi_mmc_host *mmchost = mmc->priv;
unsigned int gctrl = readl(&mmchost->reg->gctrl);
if (dma)
gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
else
gctrl |= SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
writel(gctrl, &mmchost->reg->gctrl);
}
static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs,
unsigned int done_bit, const char *what)
{
@ -327,7 +230,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
unsigned int timeout_msecs;
int error = 0;
unsigned int status = 0;
unsigned int usedma = 0;
unsigned int bytecnt = 0;
if (mmchost->fatal_err)
@ -378,20 +280,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
bytecnt = data->blocksize * data->blocks;
debug("trans data %d bytes\n", bytecnt);
#if defined(CONFIG_MMC_SUNXI_USE_DMA) && !defined(CONFIG_SPL_BUILD)
if (bytecnt > 64) {
#else
if (0) {
#endif
usedma = 1;
mmc_enable_dma_accesses(mmc, 1);
ret = mmc_trans_data_by_dma(mmc, data);
writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
} else {
mmc_enable_dma_accesses(mmc, 0);
writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
ret = mmc_trans_data_by_cpu(mmc, data);
}
writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
ret = mmc_trans_data_by_cpu(mmc, data);
if (ret) {
error = readl(&mmchost->reg->rint) & \
SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT;
@ -405,7 +295,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
goto out;
if (data) {
timeout_msecs = usedma ? 120 * bytecnt : 120;
timeout_msecs = 120;
debug("cacl timeout %x msec\n", timeout_msecs);
error = mmc_rint_wait(mmc, timeout_msecs,
data->blocks > 1 ?
@ -442,23 +332,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
debug("mmc resp 0x%08x\n", cmd->response[0]);
}
out:
if (data && usedma) {
/* IDMASTAREG
* IDST[0] : idma tx int
* IDST[1] : idma rx int
* IDST[2] : idma fatal bus error
* IDST[4] : idma descriptor invalid
* IDST[5] : idma error summary
* IDST[8] : idma normal interrupt sumary
* IDST[9] : idma abnormal interrupt sumary
*/
status = readl(&mmchost->reg->idst);
writel(status, &mmchost->reg->idst);
writel(0, &mmchost->reg->idie);
writel(0, &mmchost->reg->dmac);
writel(readl(&mmchost->reg->gctrl) & ~SUNXI_MMC_GCTRL_DMA_ENABLE,
&mmchost->reg->gctrl);
}
if (error < 0) {
writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
mmc_update_clk(mmc);

View File

@ -20,6 +20,7 @@ obj-$(CONFIG_DNET) += dnet.o
obj-$(CONFIG_E1000) += e1000.o
obj-$(CONFIG_E1000_SPI) += e1000_spi.o
obj-$(CONFIG_EEPRO100) += eepro100.o
obj-$(CONFIG_SUNXI_EMAC) += sunxi_emac.o
obj-$(CONFIG_ENC28J60) += enc28j60.o
obj-$(CONFIG_EP93XX) += ep93xx_eth.o
obj-$(CONFIG_ETHOC) += ethoc.o
@ -51,7 +52,6 @@ obj-$(CONFIG_RTL8169) += rtl8169.o
obj-$(CONFIG_SH_ETHER) += sh_eth.o
obj-$(CONFIG_SMC91111) += smc91111.o
obj-$(CONFIG_SMC911X) += smc911x.o
obj-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o
obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
obj-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o

View File

@ -1,5 +1,5 @@
/*
* sunxi_wemac.c -- Allwinner A10 ethernet driver
* sunxi_emac.c -- Allwinner A10 ethernet driver
*
* (C) Copyright 2012, Stefan Roese <sr@denx.de>
*
@ -7,16 +7,16 @@
*/
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <miiphy.h>
#include <linux/err.h>
#include <malloc.h>
#include <miiphy.h>
#include <net.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/gpio.h>
/* EMAC register */
struct wemac_regs {
struct emac_regs {
u32 ctl; /* 0x00 */
u32 tx_mode; /* 0x04 */
u32 tx_flow; /* 0x08 */
@ -27,7 +27,7 @@ struct wemac_regs {
u32 tx_pl1; /* 0x1c */
u32 tx_sta; /* 0x20 */
u32 tx_io_data; /* 0x24 */
u32 tx_io_data1; /* 0x28 */
u32 tx_io_data1;/* 0x28 */
u32 tx_tsvl0; /* 0x2c */
u32 tx_tsvh0; /* 0x30 */
u32 tx_tsvl1; /* 0x34 */
@ -141,33 +141,33 @@ struct sunxi_sramc_regs {
#define EMAC_MAC_IPGT 0x15
#define EMAC_MAC_NBTB_IPG1 0xC
#define EMAC_MAC_NBTB_IPG1 0xc
#define EMAC_MAC_NBTB_IPG2 0x12
#define EMAC_MAC_CW 0x37
#define EMAC_MAC_RM 0xF
#define EMAC_MAC_RM 0xf
#define EMAC_MAC_MFL 0x0600
/* Receive status */
#define EMAC_CRCERR (1 << 4)
#define EMAC_LENERR (3 << 5)
#define EMAC_CRCERR (0x1 << 4)
#define EMAC_LENERR (0x3 << 5)
#define DMA_CPU_TRRESHOLD 2000
struct wemac_eth_dev {
struct emac_eth_dev {
u32 speed;
u32 duplex;
u32 phy_configured;
int link_printed;
};
struct wemac_rxhdr {
struct emac_rxhdr {
s16 rx_len;
u16 rx_status;
};
static void wemac_inblk_32bit(void *reg, void *data, int count)
static void emac_inblk_32bit(void *reg, void *data, int count)
{
int cnt = (count + 3) >> 2;
@ -181,7 +181,7 @@ static void wemac_inblk_32bit(void *reg, void *data, int count)
}
}
static void wemac_outblk_32bit(void *reg, void *data, int count)
static void emac_outblk_32bit(void *reg, void *data, int count)
{
int cnt = (count + 3) >> 2;
@ -194,14 +194,12 @@ static void wemac_outblk_32bit(void *reg, void *data, int count)
}
}
/*
* Read a word from phyxcer
*/
static int wemac_phy_read(const char *devname, unsigned char addr,
/* Read a word from phyxcer */
static int emac_phy_read(const char *devname, unsigned char addr,
unsigned char reg, unsigned short *value)
{
struct eth_device *dev = eth_get_dev_by_name(devname);
struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
struct emac_regs *regs = (struct emac_regs *)dev->iobase;
/* issue the phy address and reg */
writel(addr << 8 | reg, &regs->mac_madr);
@ -221,14 +219,12 @@ static int wemac_phy_read(const char *devname, unsigned char addr,
return 0;
}
/*
* Write a word to phyxcer
*/
static int wemac_phy_write(const char *devname, unsigned char addr,
/* Write a word to phyxcer */
static int emac_phy_write(const char *devname, unsigned char addr,
unsigned char reg, unsigned short value)
{
struct eth_device *dev = eth_get_dev_by_name(devname);
struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
struct emac_regs *regs = (struct emac_regs *)dev->iobase;
/* issue the phy address and reg */
writel(addr << 8 | reg, &regs->mac_madr);
@ -250,7 +246,7 @@ static int wemac_phy_write(const char *devname, unsigned char addr,
static void emac_setup(struct eth_device *dev)
{
struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
struct emac_regs *regs = (struct emac_regs *)dev->iobase;
u32 reg_val;
u16 phy_val;
u32 duplex_flag;
@ -266,7 +262,7 @@ static void emac_setup(struct eth_device *dev)
writel(EMAC_MAC_CTL0_SETUP, &regs->mac_ctl0);
/* Set MAC CTL1 */
wemac_phy_read(dev->name, 1, 0, &phy_val);
emac_phy_read(dev->name, 1, 0, &phy_val);
debug("PHY SETUP, reg 0 value: %x\n", phy_val);
duplex_flag = !!(phy_val & (1 << 8));
@ -288,9 +284,9 @@ static void emac_setup(struct eth_device *dev)
writel(EMAC_MAC_MFL, &regs->mac_maxf);
}
static void wemac_reset(struct eth_device *dev)
static void emac_reset(struct eth_device *dev)
{
struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
struct emac_regs *regs = (struct emac_regs *)dev->iobase;
debug("resetting device\n");
@ -302,10 +298,10 @@ static void wemac_reset(struct eth_device *dev)
udelay(200);
}
static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)
{
struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
struct wemac_eth_dev *priv = dev->priv;
struct emac_regs *regs = (struct emac_regs *)dev->iobase;
struct emac_eth_dev *priv = dev->priv;
u16 phy_reg;
/* Init EMAC */
@ -317,10 +313,7 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
/* Init MAC */
/* Soft reset MAC */
clrbits_le32(&regs->mac_ctl0, 1 << 15);
/* Set MII clock */
clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
clrbits_le32(&regs->mac_ctl0, 0x1 << 15);
/* Clear RX counter */
writel(0x0, &regs->rx_fbc);
@ -336,14 +329,14 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
mdelay(1);
wemac_reset(dev);
emac_reset(dev);
/* PHY POWER UP */
wemac_phy_read(dev->name, 1, 0, &phy_reg);
wemac_phy_write(dev->name, 1, 0, phy_reg & (~(1 << 11)));
emac_phy_read(dev->name, 1, 0, &phy_reg);
emac_phy_write(dev->name, 1, 0, phy_reg & (~(0x1 << 11)));
mdelay(1);
wemac_phy_read(dev->name, 1, 0, &phy_reg);
emac_phy_read(dev->name, 1, 0, &phy_reg);
priv->speed = miiphy_speed(dev->name, 0);
priv->duplex = miiphy_duplex(dev->name, 0);
@ -357,11 +350,11 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
/* Set EMAC SPEED depend on PHY */
clrsetbits_le32(&regs->mac_supp, 1 << 8,
((phy_reg & (1 << 13)) >> 13) << 8);
((phy_reg & (0x1 << 13)) >> 13) << 8);
/* Set duplex depend on phy */
clrsetbits_le32(&regs->mac_ctl1, 1 << 0,
((phy_reg & (1 << 8)) >> 8) << 0);
((phy_reg & (0x1 << 8)) >> 8) << 0);
/* Enable RX/TX */
setbits_le32(&regs->ctl, 0x7);
@ -369,15 +362,15 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
return 0;
}
static void sunxi_wemac_eth_halt(struct eth_device *dev)
static void sunxi_emac_eth_halt(struct eth_device *dev)
{
/* Nothing to do here */
}
static int sunxi_wemac_eth_recv(struct eth_device *dev)
static int sunxi_emac_eth_recv(struct eth_device *dev)
{
struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
struct wemac_rxhdr rxhdr;
struct emac_regs *regs = (struct emac_regs *)dev->iobase;
struct emac_rxhdr rxhdr;
u32 rxcount;
u32 reg_val;
int rx_len;
@ -386,8 +379,7 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev)
/* Check packet ready or not */
/*
* Race warning: The first packet might arrive with
/* Race warning: The first packet might arrive with
* the interrupts disabled, but the second will fix
*/
rxcount = readl(&regs->rx_fbc);
@ -401,26 +393,25 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev)
reg_val = readl(&regs->rx_io_data);
if (reg_val != 0x0143414d) {
/* Disable RX */
clrbits_le32(&regs->ctl, 1 << 2);
clrbits_le32(&regs->ctl, 0x1 << 2);
/* Flush RX FIFO */
setbits_le32(&regs->rx_ctl, 1 << 3);
while (readl(&regs->rx_ctl) & (1 << 3))
setbits_le32(&regs->rx_ctl, 0x1 << 3);
while (readl(&regs->rx_ctl) & (0x1 << 3))
;
/* Enable RX */
setbits_le32(&regs->ctl, 1 << 2);
setbits_le32(&regs->ctl, 0x1 << 2);
return 0;
}
/*
* A packet ready now
/* A packet ready now
* Get status/length
*/
good_packet = 1;
wemac_inblk_32bit(&regs->rx_io_data, &rxhdr, sizeof(rxhdr));
emac_inblk_32bit(&regs->rx_io_data, &rxhdr, sizeof(rxhdr));
rx_len = rxhdr.rx_len;
rx_status = rxhdr.rx_status;
@ -440,13 +431,13 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev)
printf("length error\n");
}
/* Move data from WEMAC */
/* Move data from EMAC */
if (good_packet) {
if (rx_len > DMA_CPU_TRRESHOLD) {
printf("Received packet is too big (len=%d)\n", rx_len);
} else {
wemac_inblk_32bit((void *)&regs->rx_io_data,
NetRxPackets[0], rx_len);
emac_inblk_32bit((void *)&regs->rx_io_data,
NetRxPackets[0], rx_len);
/* Pass to upper layer */
NetReceive(NetRxPackets[0], rx_len);
@ -457,15 +448,15 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev)
return 0;
}
static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len)
static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len)
{
struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
struct emac_regs *regs = (struct emac_regs *)dev->iobase;
/* Select channel 0 */
writel(0, &regs->tx_ins);
/* Write packet */
wemac_outblk_32bit((void *)&regs->tx_io_data, packet, len);
emac_outblk_32bit((void *)&regs->tx_io_data, packet, len);
/* Set TX len */
writel(len, &regs->tx_pl0);
@ -476,50 +467,55 @@ static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len)
return 0;
}
int sunxi_wemac_initialize(void)
int sunxi_emac_initialize(void)
{
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
struct sunxi_sramc_regs *sram =
(struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
struct emac_regs *regs =
(struct emac_regs *)SUNXI_EMAC_BASE;
struct eth_device *dev;
struct wemac_eth_dev *priv;
struct emac_eth_dev *priv;
int pin;
dev = malloc(sizeof(*dev));
if (dev == NULL)
return -ENOMEM;
priv = (struct wemac_eth_dev *)malloc(sizeof(struct wemac_eth_dev));
priv = (struct emac_eth_dev *)malloc(sizeof(struct emac_eth_dev));
if (!priv) {
free(dev);
return -ENOMEM;
}
memset(dev, 0, sizeof(*dev));
memset(priv, 0, sizeof(struct wemac_eth_dev));
memset(priv, 0, sizeof(struct emac_eth_dev));
/* Map SRAM to EMAC */
setbits_le32(&sram->ctrl1, 0x5 << 2);
/* Configure pin mux settings for MII Ethernet */
for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++)
sunxi_gpio_set_cfgpin(pin, 2);
sunxi_gpio_set_cfgpin(pin, SUNXI_GPA0_EMAC);
/* Set up clock gating */
setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_EMAC);
setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_EMAC);
dev->iobase = SUNXI_EMAC_BASE;
/* Set MII clock */
clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
dev->iobase = (int)regs;
dev->priv = priv;
dev->init = sunxi_wemac_eth_init;
dev->halt = sunxi_wemac_eth_halt;
dev->send = sunxi_wemac_eth_send;
dev->recv = sunxi_wemac_eth_recv;
strcpy(dev->name, "wemac");
dev->init = sunxi_emac_eth_init;
dev->halt = sunxi_emac_eth_halt;
dev->send = sunxi_emac_eth_send;
dev->recv = sunxi_emac_eth_recv;
strcpy(dev->name, "emac");
eth_register(dev);
miiphy_register(dev->name, wemac_phy_read, wemac_phy_write);
miiphy_register(dev->name, emac_phy_read, emac_phy_write);
return 0;
}

View File

@ -5,6 +5,8 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_AXP152_POWER) += axp152.o
obj-$(CONFIG_AXP209_POWER) += axp209.o
obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
obj-$(CONFIG_FTPMU010_POWER) += ftpmu010.o
obj-$(CONFIG_TPS6586X_POWER) += tps6586x.o

97
drivers/power/axp152.c Normal file
View File

@ -0,0 +1,97 @@
/*
* (C) Copyright 2012
* Henrik Nordstrom <henrik@henriknordstrom.net>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <i2c.h>
#include <axp152.h>
enum axp152_reg {
AXP152_CHIP_VERSION = 0x3,
AXP152_DCDC2_VOLTAGE = 0x23,
AXP152_DCDC3_VOLTAGE = 0x27,
AXP152_DCDC4_VOLTAGE = 0x2B,
AXP152_LDO2_VOLTAGE = 0x2A,
AXP152_SHUTDOWN = 0x32,
};
#define AXP152_POWEROFF (1 << 7)
static int axp152_write(enum axp152_reg reg, u8 val)
{
return i2c_write(0x30, reg, 1, &val, 1);
}
static int axp152_read(enum axp152_reg reg, u8 *val)
{
return i2c_read(0x30, reg, 1, val, 1);
}
static u8 axp152_mvolt_to_target(int mvolt, int min, int max, int div)
{
if (mvolt < min)
mvolt = min;
else if (mvolt > max)
mvolt = max;
return (mvolt - min) / div;
}
int axp152_set_dcdc2(int mvolt)
{
int rc;
u8 current, target;
target = axp152_mvolt_to_target(mvolt, 700, 2275, 25);
/* Do we really need to be this gentle? It has built-in voltage slope */
while ((rc = axp152_read(AXP152_DCDC2_VOLTAGE, &current)) == 0 &&
current != target) {
if (current < target)
current++;
else
current--;
rc = axp152_write(AXP152_DCDC2_VOLTAGE, current);
if (rc)
break;
}
return rc;
}
int axp152_set_dcdc3(int mvolt)
{
u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 25);
return axp152_write(AXP152_DCDC3_VOLTAGE, target);
}
int axp152_set_dcdc4(int mvolt)
{
u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 25);
return axp152_write(AXP152_DCDC4_VOLTAGE, target);
}
int axp152_set_ldo2(int mvolt)
{
u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 100);
return axp152_write(AXP152_LDO2_VOLTAGE, target);
}
int axp152_init(void)
{
u8 ver;
int rc;
rc = axp152_read(AXP152_CHIP_VERSION, &ver);
if (rc)
return rc;
if (ver != 0x05)
return -1;
return 0;
}

167
drivers/power/axp209.c Normal file
View File

@ -0,0 +1,167 @@
/*
* (C) Copyright 2012
* Henrik Nordstrom <henrik@henriknordstrom.net>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <i2c.h>
#include <axp209.h>
enum axp209_reg {
AXP209_POWER_STATUS = 0x00,
AXP209_CHIP_VERSION = 0x03,
AXP209_DCDC2_VOLTAGE = 0x23,
AXP209_DCDC3_VOLTAGE = 0x27,
AXP209_LDO24_VOLTAGE = 0x28,
AXP209_LDO3_VOLTAGE = 0x29,
AXP209_IRQ_STATUS5 = 0x4c,
AXP209_SHUTDOWN = 0x32,
};
#define AXP209_POWER_STATUS_ON_BY_DC (1 << 0)
#define AXP209_IRQ5_PEK_UP (1 << 6)
#define AXP209_IRQ5_PEK_DOWN (1 << 5)
#define AXP209_POWEROFF (1 << 7)
static int axp209_write(enum axp209_reg reg, u8 val)
{
return i2c_write(0x34, reg, 1, &val, 1);
}
static int axp209_read(enum axp209_reg reg, u8 *val)
{
return i2c_read(0x34, reg, 1, val, 1);
}
static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div)
{
if (mvolt < min)
mvolt = min;
else if (mvolt > max)
mvolt = max;
return (mvolt - min) / div;
}
int axp209_set_dcdc2(int mvolt)
{
int rc;
u8 cfg, current;
cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
/* Do we really need to be this gentle? It has built-in voltage slope */
while ((rc = axp209_read(AXP209_DCDC2_VOLTAGE, &current)) == 0 &&
current != cfg) {
if (current < cfg)
current++;
else
current--;
rc = axp209_write(AXP209_DCDC2_VOLTAGE, current);
if (rc)
break;
}
return rc;
}
int axp209_set_dcdc3(int mvolt)
{
u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
return axp209_write(AXP209_DCDC3_VOLTAGE, cfg);
}
int axp209_set_ldo2(int mvolt)
{
int rc;
u8 cfg, reg;
cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100);
rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
if (rc)
return rc;
/* LDO2 configuration is in upper 4 bits */
reg = (reg & 0x0f) | (cfg << 4);
return axp209_write(AXP209_LDO24_VOLTAGE, reg);
}
int axp209_set_ldo3(int mvolt)
{
u8 cfg;
if (mvolt == -1)
cfg = 0x80; /* determined by LDO3IN pin */
else
cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
return axp209_write(AXP209_LDO3_VOLTAGE, cfg);
}
int axp209_set_ldo4(int mvolt)
{
int rc;
static const int vindex[] = {
1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
2700, 2800, 3000, 3100, 3200, 3300
};
u8 cfg, reg;
/* Translate mvolt to register cfg value, requested <= selected */
for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--);
rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
if (rc)
return rc;
/* LDO4 configuration is in lower 4 bits */
reg = (reg & 0xf0) | (cfg << 0);
return axp209_write(AXP209_LDO24_VOLTAGE, reg);
}
int axp209_init(void)
{
u8 ver;
int rc;
rc = axp209_read(AXP209_CHIP_VERSION, &ver);
if (rc)
return rc;
/* Low 4 bits is chip version */
ver &= 0x0f;
if (ver != 0x1)
return -1;
return 0;
}
int axp209_poweron_by_dc(void)
{
u8 v;
if (axp209_read(AXP209_POWER_STATUS, &v))
return 0;
return (v & AXP209_POWER_STATUS_ON_BY_DC);
}
int axp209_power_button(void)
{
u8 v;
if (axp209_read(AXP209_IRQ_STATUS5, &v))
return 0;
axp209_write(AXP209_IRQ_STATUS5, AXP209_IRQ5_PEK_DOWN);
return v & AXP209_IRQ5_PEK_DOWN;
}

10
include/axp152.h Normal file
View File

@ -0,0 +1,10 @@
/*
* (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
*
* SPDX-License-Identifier: GPL-2.0+
*/
int axp152_set_dcdc2(int mvolt);
int axp152_set_dcdc3(int mvolt);
int axp152_set_dcdc4(int mvolt);
int axp152_set_ldo2(int mvolt);
int axp152_init(void);

14
include/axp209.h Normal file
View File

@ -0,0 +1,14 @@
/*
* (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
*
* SPDX-License-Identifier: GPL-2.0+
*/
extern int axp209_set_dcdc2(int mvolt);
extern int axp209_set_dcdc3(int mvolt);
extern int axp209_set_ldo2(int mvolt);
extern int axp209_set_ldo3(int mvolt);
extern int axp209_set_ldo4(int mvolt);
extern int axp209_init(void);
extern int axp209_poweron_by_dc(void);
extern int axp209_power_button(void);

View File

@ -187,7 +187,8 @@
* I2C related stuff
*/
#ifdef CONFIG_CMD_I2C
#define CONFIG_I2C_MVTWSI
#define CONFIG_SYS_I2C
#define CONFIG_SYS_I2C_MVTWSI
#define CONFIG_I2C_MVTWSI_BASE ORION5X_TWSI_BASE
#define CONFIG_SYS_I2C_SLAVE 0x0
#define CONFIG_SYS_I2C_SPEED 100000

24
include/configs/sun4i.h Normal file
View File

@ -0,0 +1,24 @@
/*
* (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
*
* Configuration settings for the Allwinner A10 (sun4i) CPU
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* A10 specific configuration
*/
#define CONFIG_SUN4I /* sun4i SoC generation */
#define CONFIG_CLK_FULL_SPEED 1008000000
#define CONFIG_SYS_PROMPT "sun4i# "
/*
* Include common sunxi configuration where most the settings are
*/
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */

24
include/configs/sun5i.h Normal file
View File

@ -0,0 +1,24 @@
/*
* (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
*
* Configuration settings for the Allwinner A13 (sun5i) CPU
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* High Level Configuration Options
*/
#define CONFIG_SUN5I /* sun5i SoC generation */
#define CONFIG_CLK_FULL_SPEED 1008000000
#define CONFIG_SYS_PROMPT "sun5i# "
/*
* Include common sunxi configuration where most the settings are
*/
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */

View File

@ -13,6 +13,7 @@
* A20 specific configuration
*/
#define CONFIG_SUN7I /* sun7i SoC generation */
#define CONFIG_CLK_FULL_SPEED 912000000
#define CONFIG_SYS_PROMPT "sun7i# "

View File

@ -70,7 +70,6 @@
#define CONFIG_CMD_MMC
#define CONFIG_MMC_SUNXI
#define CONFIG_MMC_SUNXI_SLOT 0
#define CONFIG_MMC_SUNXI_USE_DMA
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_SYS_MMC_ENV_DEV 0 /* first detected MMC controller */
@ -162,7 +161,31 @@
#undef CONFIG_CMD_NET
#undef CONFIG_CMD_NFS
/* I2C */
#define CONFIG_SPL_I2C_SUPPORT
#define CONFIG_SYS_I2C
#define CONFIG_SYS_I2C_MVTWSI
#define CONFIG_SYS_I2C_SPEED 400000
#define CONFIG_SYS_I2C_SLAVE 0x7f
#define CONFIG_CMD_I2C
/* PMU */
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || defined CONFIG_AXP221_POWER
#define CONFIG_SPL_POWER_SUPPORT
#endif
#ifndef CONFIG_CONS_INDEX
#define CONFIG_CONS_INDEX 1 /* UART0 */
#endif
/* GPIO */
#define CONFIG_SUNXI_GPIO
#define CONFIG_CMD_GPIO
/* Ethernet support */
#ifdef CONFIG_SUNXI_EMAC
#define CONFIG_MII /* MII PHY management */
#endif
#ifdef CONFIG_SUNXI_GMAC
#define CONFIG_DESIGNWARE_ETH /* GMAC can use designware driver */
@ -188,6 +211,8 @@
#define CONFIG_ENV_IS_NOWHERE
#endif
#define CONFIG_MISC_INIT_R
#ifndef CONFIG_SPL_BUILD
#include <config_distro_defaults.h>
#endif

View File

@ -78,8 +78,8 @@ int sh_eth_initialize(bd_t *bis);
int skge_initialize(bd_t *bis);
int smc91111_initialize(u8 dev_num, int base_addr);
int smc911x_initialize(u8 dev_num, int base_addr);
int sunxi_emac_initialize(bd_t *bis);
int sunxi_gmac_initialize(bd_t *bis);
int sunxi_wemac_initialize(bd_t *bis);
int tsi108_eth_initialize(bd_t *bis);
int uec_standard_init(bd_t *bis);
int uli526x_initialize(bd_t *bis);

View File

@ -77,7 +77,7 @@ int main(int argc, char *argv[])
{
int fd_in, fd_out;
struct boot_img img;
unsigned file_size, load_size;
unsigned file_size;
int count;
if (argc < 2) {
@ -101,8 +101,6 @@ int main(int argc, char *argv[])
if (file_size > SRAM_LOAD_MAX_SIZE) {
fprintf(stderr, "ERROR: File too large!\n");
return EXIT_FAILURE;
} else {
load_size = ALIGN(file_size, sizeof(int));
}
fd_out = open(argv[2], O_WRONLY | O_CREAT, 0666);
@ -113,8 +111,8 @@ int main(int argc, char *argv[])
/* read file to buffer to calculate checksum */
lseek(fd_in, 0, SEEK_SET);
count = read(fd_in, img.code, load_size);
if (count != load_size) {
count = read(fd_in, img.code, file_size);
if (count != file_size) {
perror("Reading input image");
return EXIT_FAILURE;
}
@ -126,7 +124,7 @@ int main(int argc, char *argv[])
& 0x00FFFFFF);
memcpy(img.header.magic, BOOT0_MAGIC, 8); /* no '0' termination */
img.header.length =
ALIGN(load_size + sizeof(struct boot_file_head), BLOCK_SIZE);
ALIGN(file_size + sizeof(struct boot_file_head), BLOCK_SIZE);
gen_check_sum(&img.header);
count = write(fd_out, &img, img.header.length);