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

master
Albert ARIBAUD 10 years ago
commit 5ed28948a3
  1. 20
      arch/arm/cpu/armv7/am33xx/board.c
  2. 11
      arch/arm/cpu/armv7/am33xx/clock.c
  3. 9
      arch/arm/cpu/armv7/am33xx/clock_am43xx.c
  4. 4
      arch/arm/cpu/armv7/am33xx/emif4.c
  5. 9
      arch/arm/cpu/armv7/keystone/init.c
  6. 12
      arch/arm/cpu/armv7/omap3/mem.c
  7. 1
      arch/arm/include/asm/arch-am33xx/clock.h
  8. 35
      arch/arm/include/asm/arch-am33xx/cpu.h
  9. 2
      arch/arm/include/asm/arch-keystone/hardware-k2hk.h
  10. 3
      arch/arm/include/asm/arch-keystone/hardware.h
  11. 8
      arch/arm/include/asm/arch-omap3/mem.h
  12. 2
      board/BuR/tseries/board.c
  13. 9
      board/BuR/tseries/mux.c
  14. 12
      board/compulab/cm_t35/cm_t35.c
  15. 2
      board/ti/am43xx/Makefile
  16. 55
      board/ti/am43xx/board.c
  17. 1
      boards.cfg
  18. 60
      doc/README.nand
  19. 2
      drivers/mtd/nand/am335x_spl_bch.c
  20. 2
      drivers/mtd/nand/atmel_nand.c
  21. 11
      drivers/mtd/nand/nand_base.c
  22. 2
      drivers/mtd/nand/nand_spl_simple.c
  23. 28
      drivers/mtd/nand/omap_elm.c
  24. 193
      drivers/mtd/nand/omap_gpmc.c
  25. 1
      drivers/power/pmic/Makefile
  26. 97
      drivers/power/pmic/pmic_tps65218.c
  27. 1
      drivers/spi/ti_qspi.c
  28. 1
      include/configs/am3517_crane.h
  29. 45
      include/configs/am43xx_evm.h
  30. 4
      include/configs/bur_am335x_common.h
  31. 1
      include/configs/cm_t335.h
  32. 1
      include/configs/cm_t35.h
  33. 1
      include/configs/devkit8000.h
  34. 1
      include/configs/dig297.h
  35. 4
      include/configs/k2hk_evm.h
  36. 1
      include/configs/omap3_beagle.h
  37. 2
      include/configs/omap3_evm_common.h
  38. 1
      include/configs/omap3_igep00x0.h
  39. 1
      include/configs/omap3_logic.h
  40. 1
      include/configs/omap3_overo.h
  41. 1
      include/configs/omap3_zoom1.h
  42. 1
      include/configs/pengwyn.h
  43. 2
      include/configs/tam3517-common.h
  44. 2
      include/configs/tao3530.h
  45. 9
      include/configs/ti_am335x_common.h
  46. 3
      include/configs/ti_armv7_common.h
  47. 1
      include/configs/tseries.h
  48. 19
      include/linux/mtd/nand.h
  49. 11
      include/linux/mtd/omap_elm.h
  50. 11
      include/linux/mtd/omap_gpmc.h
  51. 63
      include/power/tps65218.h

@ -144,6 +144,19 @@ int arch_misc_init(void)
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*
* In the case of non-SPL based booting we'll want to call these
* functions a tiny bit later as it will require gd to be set and cleared
* and that's not true in s_init in this case so we cannot do it there.
*/
int board_early_init_f(void)
{
prcm_init();
set_mux_conf_regs();
return 0;
}
/*
* This function is the place to do per-board things such as ramp up the
* MPU clock frequency.
*/
@ -224,7 +237,7 @@ void s_init(void)
set_uart_mux_conf();
setup_clocks_for_console();
uart_soft_reset();
#ifdef CONFIG_NOR_BOOT
#if defined(CONFIG_NOR_BOOT) || defined(CONFIG_QSPI_BOOT)
gd->baudrate = CONFIG_BAUDRATE;
serial_init();
gd->have_console = 1;
@ -232,13 +245,14 @@ void s_init(void)
gd = &gdata;
preloader_console_init();
#endif
prcm_init();
set_mux_conf_regs();
#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
/* Enable RTC32K clock */
rtc32k_enable();
#endif
#ifdef CONFIG_SPL_BUILD
board_early_init_f();
sdram_init();
#endif
}
#endif

@ -170,8 +170,19 @@ void do_enable_clocks(u32 *const *clk_domains,
};
}
/*
* Before scaling up the clocks we need to have the PMIC scale up the
* voltages first. This will be dependent on which PMIC is in use
* and in some cases we may not be scaling things up at all and thus not
* need to do anything here.
*/
__weak void scale_vcores(void)
{
}
void prcm_init()
{
enable_basic_clocks();
scale_vcores();
setup_dplls();
}

@ -53,6 +53,8 @@ const struct dpll_regs dpll_ddr_regs = {
void setup_clocks_for_console(void)
{
u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
/* Do not add any spl_debug prints in this function */
clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
@ -63,6 +65,13 @@ void setup_clocks_for_console(void)
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
(idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
clkctrl = readl(&cmwkup->wkup_uart0ctrl);
idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
MODULE_CLKCTRL_IDLEST_SHIFT;
}
}
void enable_basic_clocks(void)

@ -21,6 +21,10 @@ DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
sdram_init();
#endif
/* dram_init must store complete ramsize in gd->ram_size */
gd->ram_size = get_ram_size(
(void *)CONFIG_SYS_SDRAM_BASE,

@ -8,6 +8,7 @@
*/
#include <common.h>
#include <ns16550.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/hardware.h>
@ -30,6 +31,14 @@ int arch_cpu_init(void)
share_all_segments(11); /* PCIE */
#endif
/*
* just initialise the COM2 port so that TI specific
* UART register PWREMU_MGMT is initialized. Linux UART
* driver doesn't handle this.
*/
NS16550_init((NS16550_t)(CONFIG_SYS_NS16550_COM2),
CONFIG_SYS_NS16550_CLK / 16 / CONFIG_BAUDRATE);
return 0;
}

@ -21,17 +21,6 @@
struct gpmc *gpmc_cfg;
#if defined(CONFIG_CMD_NAND)
#if defined(GPMC_NAND_ECC_SP_x8_LAYOUT) || defined(GPMC_NAND_ECC_LP_x8_LAYOUT)
static const u32 gpmc_m_nand[GPMC_MAX_REG] = {
SMNAND_GPMC_CONFIG1,
SMNAND_GPMC_CONFIG2,
SMNAND_GPMC_CONFIG3,
SMNAND_GPMC_CONFIG4,
SMNAND_GPMC_CONFIG5,
SMNAND_GPMC_CONFIG6,
0,
};
#else
static const u32 gpmc_m_nand[GPMC_MAX_REG] = {
M_NAND_GPMC_CONFIG1,
M_NAND_GPMC_CONFIG2,
@ -40,7 +29,6 @@ static const u32 gpmc_m_nand[GPMC_MAX_REG] = {
M_NAND_GPMC_CONFIG5,
M_NAND_GPMC_CONFIG6, 0
};
#endif
#endif /* CONFIG_CMD_NAND */
#if defined(CONFIG_CMD_ONENAND)

@ -107,6 +107,7 @@ const struct dpll_params *get_dpll_mpu_params(void);
const struct dpll_params *get_dpll_core_params(void);
const struct dpll_params *get_dpll_per_params(void);
const struct dpll_params *get_dpll_ddr_params(void);
void scale_vcores(void);
void do_setup_dpll(const struct dpll_regs *, const struct dpll_params *);
void prcm_init(void);
void enable_basic_clocks(void);

@ -26,7 +26,17 @@
#define TCLR_PRE BIT(5) /* Pre-scaler enable */
#define TCLR_PTV_SHIFT (2) /* Pre-scaler shift value */
#define TCLR_PRE_DISABLE CL_BIT(5) /* Pre-scalar disable */
#define TCLR_CE BIT(6) /* compare mode enable */
#define TCLR_SCPWM BIT(7) /* pwm outpin behaviour */
#define TCLR_TCM BIT(8) /* edge detection of input pin*/
#define TCLR_TRG_SHIFT (10) /* trigmode on pwm outpin */
#define TCLR_PT BIT(12) /* pulse/toggle mode of outpin*/
#define TCLR_CAPTMODE BIT(13) /* capture mode */
#define TCLR_GPOCFG BIT(14) /* 0=output,1=input */
#define TCFG_RESET BIT(0) /* software reset */
#define TCFG_EMUFREE BIT(1) /* behaviour of tmr on debug */
#define TCFG_IDLEMOD_SHIFT (2) /* power management */
/* device type */
#define DEVICE_MASK (BIT(8) | BIT(9) | BIT(10))
#define TST_DEVICE 0x0
@ -87,7 +97,8 @@ struct cm_wkuppll {
unsigned int wkctrlclkctrl; /* offset 0x04 */
unsigned int wkgpio0clkctrl; /* offset 0x08 */
unsigned int wkl4wkclkctrl; /* offset 0x0c */
unsigned int resv2[4];
unsigned int timer0clkctrl; /* offset 0x10 */
unsigned int resv2[3];
unsigned int idlestdpllmpu; /* offset 0x20 */
unsigned int resv3[2];
unsigned int clkseldpllmpu; /* offset 0x2c */
@ -121,7 +132,9 @@ struct cm_wkuppll {
unsigned int wkup_uart0ctrl; /* offset 0xB4 */
unsigned int wkup_i2c0ctrl; /* offset 0xB8 */
unsigned int wkup_adctscctrl; /* offset 0xBC */
unsigned int resv12[6];
unsigned int resv12;
unsigned int timer1clkctrl; /* offset 0xC4 */
unsigned int resv13[4];
unsigned int divm6dpllcore; /* offset 0xD8 */
};
@ -178,7 +191,9 @@ struct cm_perpll {
unsigned int epwmss2clkctrl; /* offset 0xD8 */
unsigned int l3instrclkctrl; /* offset 0xDC */
unsigned int l3clkctrl; /* Offset 0xE0 */
unsigned int resv8[4];
unsigned int resv8[2];
unsigned int timer5clkctrl; /* offset 0xEC */
unsigned int timer6clkctrl; /* offset 0xF0 */
unsigned int mmc1clkctrl; /* offset 0xF4 */
unsigned int mmc2clkctrl; /* offset 0xF8 */
unsigned int resv9[8];
@ -191,9 +206,17 @@ struct cm_perpll {
/* Encapsulating Display pll registers */
struct cm_dpll {
unsigned int resv1[2];
unsigned int resv1;
unsigned int clktimer7clk; /* offset 0x04 */
unsigned int clktimer2clk; /* offset 0x08 */
unsigned int resv2[10];
unsigned int clktimer3clk; /* offset 0x0C */
unsigned int clktimer4clk; /* offset 0x10 */
unsigned int resv2;
unsigned int clktimer5clk; /* offset 0x18 */
unsigned int clktimer6clk; /* offset 0x1C */
unsigned int resv3[2];
unsigned int clktimer1clk; /* offset 0x28 */
unsigned int resv4[2];
unsigned int clklcdcpixelclk; /* offset 0x34 */
};
#else

@ -115,8 +115,6 @@
#define K2HK_LPSC_ARM_SREFLEX 51
#define K2HK_LPSC_TETRIS 52
#define K2HK_UART0_BASE 0x02530c00
/* DDR3A definitions */
#define K2HK_DDR3A_EMIF_CTRL_BASE 0x21010000
#define K2HK_DDR3A_EMIF_DATA_BASE 0x80000000

@ -142,6 +142,9 @@ struct ddr3_emif_config {
#define KS2_DDR3_PMCTL_OFFSET 0x38
#define KS2_DDR3_ZQCFG_OFFSET 0xC8
#define KS2_UART0_BASE 0x02530c00
#define KS2_UART1_BASE 0x02531000
#ifdef CONFIG_SOC_K2HK
#include <asm/arch/hardware-k2hk.h>
#endif

@ -354,14 +354,6 @@ enum {
#define GPMC_CS_ENABLE 0x1
#define SMNAND_GPMC_CONFIG1 0x00000800
#define SMNAND_GPMC_CONFIG2 0x00141400
#define SMNAND_GPMC_CONFIG3 0x00141400
#define SMNAND_GPMC_CONFIG4 0x0F010F01
#define SMNAND_GPMC_CONFIG5 0x010C1414
#define SMNAND_GPMC_CONFIG6 0x1F0F0A80
#define SMNAND_GPMC_CONFIG7 0x00000C44
#define M_NAND_GPMC_CONFIG1 0x00001800
#define M_NAND_GPMC_CONFIG2 0x00141400
#define M_NAND_GPMC_CONFIG3 0x00141400

@ -117,7 +117,9 @@ void sdram_init(void)
int board_init(void)
{
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
#ifdef CONFIG_NAND
gpmc_init();
#endif
return 0;
}

@ -27,6 +27,11 @@ static struct module_pin_mux uart0_pin_mux[] = {
};
#ifdef CONFIG_MMC
static struct module_pin_mux mmc1_pin_mux[] = {
{OFFSET(gpmc_ad7), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT7 */
{OFFSET(gpmc_ad6), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT6 */
{OFFSET(gpmc_ad5), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT5 */
{OFFSET(gpmc_ad4), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT4 */
{OFFSET(gpmc_ad3), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT3 */
{OFFSET(gpmc_ad2), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT2 */
{OFFSET(gpmc_ad1), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT1 */
@ -125,7 +130,7 @@ static struct module_pin_mux gpIOs[] = {
{OFFSET(mmc0_dat3), (MODE(3) | PULLUDEN | RXACTIVE)},
/* TIMER6 (MMC0_DAT2) - PWM_BACK_3V3, later used as MODE3 for PWM */
{OFFSET(mmc0_dat2), (MODE(7) | PULLUDEN | RXACTIVE)},
/* GPIO2_28 (MMC0_DAT1) - MII_nNAND */
/* GPIO2_27 (MMC0_DAT1) - MII_nNAND */
{OFFSET(mmc0_dat1), (MODE(7) | PULLUDEN | RXACTIVE)},
/* GPIO2_29 (MMC0_DAT0) - NAND_1n0 */
{OFFSET(mmc0_dat0), (MODE(7) | PULLUDEN | RXACTIVE)},
@ -148,7 +153,7 @@ static struct module_pin_mux gpIOs[] = {
* DISPLAY_ONOFF (Backlight Enable at LVDS Versions)
*/
{OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN | RXACTIVE)},
/* GPIO0_19 (DMA_INTR0) - ISPLAY_MODE (CPLD) */
/* GPIO0_19 (DMA_INTR0) - DISPLAY_MODE (CPLD) */
{OFFSET(xdma_event_intr0), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* GPIO0_20 (DMA_INTR1) - REP-Switch */
{OFFSET(xdma_event_intr1), (MODE(7) | PULLUP_EN | RXACTIVE)},

@ -54,12 +54,12 @@ static u32 gpmc_net_config[GPMC_MAX_REG] = {
};
static u32 gpmc_nand_config[GPMC_MAX_REG] = {
SMNAND_GPMC_CONFIG1,
SMNAND_GPMC_CONFIG2,
SMNAND_GPMC_CONFIG3,
SMNAND_GPMC_CONFIG4,
SMNAND_GPMC_CONFIG5,
SMNAND_GPMC_CONFIG6,
M_NAND_GPMC_CONFIG1,
M_NAND_GPMC_CONFIG2,
M_NAND_GPMC_CONFIG3,
M_NAND_GPMC_CONFIG4,
M_NAND_GPMC_CONFIG5,
M_NAND_GPMC_CONFIG6,
0,
};

@ -6,7 +6,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
ifdef CONFIG_SPL_BUILD
ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),)
obj-y := mux.o
endif

@ -19,6 +19,7 @@
#include <asm/arch/gpio.h>
#include <asm/emif.h>
#include "board.h"
#include <power/tps65218.h>
#include <miiphy.h>
#include <cpsw.h>
@ -70,7 +71,7 @@ static int read_eeprom(struct am43xx_board_id *header)
return 0;
}
#ifdef CONFIG_SPL_BUILD
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
#define NUM_OPPS 6
@ -254,13 +255,6 @@ void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size)
const struct dpll_params *get_dpll_ddr_params(void)
{
struct am43xx_board_id header;
enable_i2c0_pin_mux();
i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
if (read_eeprom(&header) < 0)
puts("Could not get board ID.\n");
if (board_is_eposevm())
return &epos_evm_dpll_ddr;
else if (board_is_gpevm())
@ -302,7 +296,10 @@ static u32 get_sys_clk_index(void)
static int get_opp_offset(int max_off, int min_off)
{
struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE;
int opp = readl(&ctrl->dev_attr), offset, i;
int opp, offset, i;
/* Bits 0:11 are defined to be the MPU_MAX_FREQ */
opp = readl(&ctrl->dev_attr) & ~0xFFFFF000;
for (i = max_off; i >= min_off; i--) {
offset = opp & (1 << i);
@ -335,6 +332,46 @@ const struct dpll_params *get_dpll_per_params(void)
return &dpll_per[ind];
}
void scale_vcores(void)
{
const struct dpll_params *mpu_params;
int mpu_vdd;
struct am43xx_board_id header;
enable_i2c0_pin_mux();
i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
if (read_eeprom(&header) < 0)
puts("Could not get board ID.\n");
/* Get the frequency */
mpu_params = get_dpll_mpu_params();
if (i2c_probe(TPS65218_CHIP_PM))
return;
if (mpu_params->m == 1000) {
mpu_vdd = TPS65218_DCDC_VOLT_SEL_1330MV;
} else if (mpu_params->m == 600) {
mpu_vdd = TPS65218_DCDC_VOLT_SEL_1100MV;
} else {
puts("Unknown MPU clock, not scaling\n");
return;
}
/* Set DCDC1 (CORE) voltage to 1.1V */
if (tps65218_voltage_update(TPS65218_DCDC1,
TPS65218_DCDC_VOLT_SEL_1100MV)) {
puts("tps65218_voltage_update failure\n");
return;
}
/* Set DCDC2 (MPU) voltage */
if (tps65218_voltage_update(TPS65218_DCDC2, mpu_vdd)) {
puts("tps65218_voltage_update failure\n");
return;
}
}
void set_uart_mux_conf(void)
{
enable_uart0_pin_mux();

@ -279,6 +279,7 @@ Active arm armv7 am33xx ti am335x
Active arm armv7 am33xx ti am335x am335x_evm_uart5 am335x_evm:SERIAL6,CONS_INDEX=6,NAND Tom Rini <trini@ti.com>
Active arm armv7 am33xx ti am335x am335x_evm_usbspl am335x_evm:SERIAL1,CONS_INDEX=1,NAND,SPL_USBETH_SUPPORT Tom Rini <trini@ti.com>
Active arm armv7 am33xx ti am43xx am43xx_evm am43xx_evm:SERIAL1,CONS_INDEX=1 Lokesh Vutla <lokeshvutla@ti.com>
Active arm armv7 am33xx ti am43xx am43xx_evm_qspiboot am43xx_evm:SERIAL1,CONS_INDEX=1,QSPI,QSPI_BOOT Lokesh Vutla <lokeshvutla@ti.com>
Active arm armv7 am33xx ti ti814x ti814x_evm - Matt Porter <matt.porter@linaro.org>
Active arm armv7 am33xx ti ti816x ti816x_evm - -
Active arm armv7 at91 atmel sama5d3_xplained sama5d3_xplained_mmc sama5d3_xplained:SAMA5D3,SYS_USE_MMC Bo Shen <voice.shen@atmel.com>

@ -190,6 +190,24 @@ Configuration Options:
This is used by SoC platforms which do not have built-in ELM
hardware engine required for BCH ECC correction.
CONFIG_SYS_NAND_BUSWIDTH_16BIT
Indicates that NAND device has 16-bit wide data-bus. In absence of this
config, bus-width of NAND device is assumed to be either 8-bit and later
determined by reading ONFI params.
Above config is useful when NAND device's bus-width information cannot
be determined from on-chip ONFI params, like in following scenarios:
- SPL boot does not support reading of ONFI parameters. This is done to
keep SPL code foot-print small.
- In current U-Boot flow using nand_init(), driver initialization
happens in board_nand_init() which is called before any device probe
(nand_scan_ident + nand_scan_tail), thus device's ONFI parameters are
not available while configuring controller. So a static CONFIG_NAND_xx
is needed to know the device's bus-width in advance.
Some drivers using above config are:
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/ndfc.c
drivers/mtd/nand/omap_gpmc.c
Platform specific options
=========================
@ -231,6 +249,48 @@ Platform specific options
8-bit BCH code with
- ecc calculation using GPMC hardware engine,
- error detection using ELM hardware engine.
OMAP_ECC_BCH16_CODE_HW
16-bit BCH code with
- ecc calculation using GPMC hardware engine,
- error detection using ELM hardware engine.
How to select ECC scheme on OMAP and AMxx platforms ?
-----------------------------------------------------
Though higher ECC schemes have more capability to detect and correct
bit-flips, but still selection of ECC scheme is dependent on following
- hardware engines present in SoC.
Some legacy OMAP SoC do not have ELM h/w engine thus such
SoC cannot support BCHx_HW ECC schemes.
- size of OOB/Spare region
With higher ECC schemes, more OOB/Spare area is required to
store ECC. So choice of ECC scheme is limited by NAND oobsize.
In general following expression can help:
NAND_OOBSIZE >= 2 + (NAND_PAGESIZE / 512) * ECC_BYTES
where
NAND_OOBSIZE = number of bytes available in
OOB/spare area per NAND page.
NAND_PAGESIZE = bytes in main-area of NAND page.
ECC_BYTES = number of ECC bytes generated to
protect 512 bytes of data, which is:
3 for HAM1_xx ecc schemes
7 for BCH4_xx ecc schemes
14 for BCH8_xx ecc schemes
26 for BCH16_xx ecc schemes
example to check for BCH16 on 2K page NAND
NAND_PAGESIZE = 2048
NAND_OOBSIZE = 64
2 + (2048 / 512) * 26 = 106 > NAND_OOBSIZE
Thus BCH16 cannot be supported on 2K page NAND.
However, for 4K pagesize NAND
NAND_PAGESIZE = 4096
NAND_OOBSIZE = 64
ECC_BYTES = 26
2 + (4096 / 512) * 26 = 210 < NAND_OOBSIZE
Thus BCH16 can be supported on 4K page NAND.
NOTE:
=====

@ -55,7 +55,7 @@ static int nand_command(int block, int page, uint32_t offs,
}
/* Shift the offset from byte addressing to word addressing. */
if (this->options & NAND_BUSWIDTH_16)
if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd))
offs >>= 1;
/* Set ALE and clear CLE to start address cycle */

@ -1195,7 +1195,7 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd)
hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
if (this->options & NAND_BUSWIDTH_16)
if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd))
offs >>= 1;
hwctrl(&mtd, offs & 0xff, NAND_CTRL_ALE | NAND_CTRL_CHANGE);

@ -575,7 +575,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (chip->options & NAND_BUSWIDTH_16)
if ((chip->options & NAND_BUSWIDTH_16) &&
!nand_opcode_8bits(command))
column >>= 1;
chip->cmd_ctrl(mtd, column, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
@ -668,7 +669,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (chip->options & NAND_BUSWIDTH_16)
if ((chip->options & NAND_BUSWIDTH_16) &&
!nand_opcode_8bits(command))
column >>= 1;
chip->cmd_ctrl(mtd, column, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
@ -2582,7 +2584,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
int *busw)
{
struct nand_onfi_params *p = &chip->onfi_params;
int i;
int i, j;
int val;
/* Try ONFI for unknown chip or LP */
@ -2593,7 +2595,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
for (j = 0; j < sizeof(*p); j++)
((uint8_t *)p)[j] = chip->read_byte(mtd);
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
le16_to_cpu(p->crc)) {
pr_info("ONFI param page %d valid\n", i);

@ -78,7 +78,7 @@ static int nand_command(int block, int page, uint32_t offs,
}
/* Shift the offset from byte addressing to word addressing. */
if (this->options & NAND_BUSWIDTH_16)
if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd))
offs >>= 1;
/* Begin command latch cycle */

@ -16,23 +16,21 @@
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <linux/mtd/omap_gpmc.h>
#include <linux/mtd/omap_elm.h>
#include <asm/arch/hardware.h>
#define DRIVER_NAME "omap-elm"
#define ELM_DEFAULT_POLY (0)
struct elm *elm_cfg;
/**
* elm_load_syndromes - Load BCH syndromes based on nibble selection
* elm_load_syndromes - Load BCH syndromes based on bch_type selection
* @syndrome: BCH syndrome
* @nibbles:
* @bch_type: BCH4/BCH8/BCH16
* @poly: Syndrome Polynomial set to use
*
* Load BCH syndromes based on nibble selection
*/
static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly)
static void elm_load_syndromes(u8 *syndrome, enum bch_level bch_type, u8 poly)
{
u32 *ptr;
u32 val;
@ -48,8 +46,7 @@ static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly)
(syndrome[7] << 24);
writel(val, ptr);
/* BCH 8-bit with 26 nibbles (4*8=32) */
if (nibbles > 13) {
if (bch_type == BCH_8_BIT || bch_type == BCH_16_BIT) {
/* reg 2 */
ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[2];
val = syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) |
@ -62,8 +59,7 @@ static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly)
writel(val, ptr);
}
/* BCH 16-bit with 52 nibbles (7*8=56) */
if (nibbles > 26) {
if (bch_type == BCH_16_BIT) {
/* reg 4 */
ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[4];
val = syndrome[16] | (syndrome[17] << 8) |
@ -87,7 +83,7 @@ static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly)
/**
* elm_check_errors - Check for BCH errors and return error locations
* @syndrome: BCH syndrome
* @nibbles:
* @bch_type: BCH4/BCH8/BCH16
* @error_count: Returns number of errrors in the syndrome
* @error_locations: Returns error locations (in decimal) in this array
*
@ -95,14 +91,14 @@ static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly)
* and locations in the array passed. Returns -1 if error is not correctable,
* else returns 0
*/
int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count,
int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count,
u32 *error_locations)
{
u8 poly = ELM_DEFAULT_POLY;
s8 i;
u32 location_status;
elm_load_syndromes(syndrome, nibbles, poly);
elm_load_syndromes(syndrome, bch_type, poly);
/* start processing */
writel((readl(&elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6])
@ -118,8 +114,10 @@ int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count,
/* check if correctable */
location_status = readl(&elm_cfg->error_location[poly].location_status);
if (!(location_status & ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK))
return -1;
if (!(location_status & ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK)) {
printf("%s: uncorrectable ECC errors\n", DRIVER_NAME);
return -EBADMSG;
}
/* get error count */
*error_count = readl(&elm_cfg->error_location[poly].location_status) &

@ -148,35 +148,20 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
}
/*
* Generic BCH interface
* Driver configurations
*/
struct nand_bch_priv {
uint8_t mode;
uint8_t type;
uint8_t nibbles;
struct omap_nand_info {
struct bch_control *control;
enum omap_ecc ecc_scheme;
};
/* bch types */
#define ECC_BCH4 0
#define ECC_BCH8 1
#define ECC_BCH16 2
/* BCH nibbles for diff bch levels */
#define ECC_BCH4_NIBBLES 13
#define ECC_BCH8_NIBBLES 26
#define ECC_BCH16_NIBBLES 52
/*
* This can be a single instance cause all current users have only one NAND
* with nearly the same setup (BCH8, some with ELM and others with sw BCH
* library).
* When some users with other BCH strength will exists this have to change!
*/
static __maybe_unused struct nand_bch_priv bch_priv = {
.type = ECC_BCH8,
.nibbles = ECC_BCH8_NIBBLES,
static __maybe_unused struct omap_nand_info omap_nand_info = {
.control = NULL
};
@ -206,7 +191,7 @@ __maybe_unused
static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
{
struct nand_chip *nand = mtd->priv;
struct nand_bch_priv *bch = nand->priv;
struct omap_nand_info *info = nand->priv;
unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
unsigned int ecc_algo = 0;
unsigned int bch_type = 0;
@ -215,7 +200,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
u32 ecc_config_val = 0;
/* configure GPMC for specific ecc-scheme */
switch (bch->ecc_scheme) {
switch (info->ecc_scheme) {
case OMAP_ECC_HAM1_CODE_SW:
return;
case OMAP_ECC_HAM1_CODE_HW:
@ -239,6 +224,19 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
eccsize1 = 2; /* non-ECC bits in nibbles per sector */
}
break;
case OMAP_ECC_BCH16_CODE_HW:
ecc_algo = 0x1;
bch_type = 0x2;
if (mode == NAND_ECC_WRITE) {
bch_wrapmode = 0x01;
eccsize0 = 0; /* extra bits in nibbles per sector */
eccsize1 = 52; /* OOB bits in nibbles per sector */
} else {
bch_wrapmode = 0x01;
eccsize0 = 52; /* ECC bits in nibbles per sector */
eccsize1 = 0; /* non-ECC bits in nibbles per sector */
}
break;
default:
return;
}
@ -277,11 +275,11 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc_code)
{
struct nand_chip *chip = mtd->priv;
struct nand_bch_priv *bch = chip->priv;
struct omap_nand_info *info = chip->priv;
uint32_t *ptr, val = 0;
int8_t i = 0, j;
switch (bch->ecc_scheme) {
switch (info->ecc_scheme) {
case OMAP_ECC_HAM1_CODE_HW:
val = readl(&gpmc_cfg->ecc1_result);
ecc_code[0] = val & 0xFF;
@ -305,11 +303,34 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
ptr--;
}
break;
case OMAP_ECC_BCH16_CODE_HW:
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[2]);
ecc_code[i++] = (val >> 8) & 0xFF;
ecc_code[i++] = (val >> 0) & 0xFF;
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[1]);
ecc_code[i++] = (val >> 24) & 0xFF;
ecc_code[i++] = (val >> 16) & 0xFF;
ecc_code[i++] = (val >> 8) & 0xFF;
ecc_code[i++] = (val >> 0) & 0xFF;
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[0]);
ecc_code[i++] = (val >> 24) & 0xFF;
ecc_code[i++] = (val >> 16) & 0xFF;
ecc_code[i++] = (val >> 8) & 0xFF;
ecc_code[i++] = (val >> 0) & 0xFF;
for (j = 3; j >= 0; j--) {
val = readl(&gpmc_cfg->bch_result_0_3[0].bch_result_x[j]
);
ecc_code[i++] = (val >> 24) & 0xFF;
ecc_code[i++] = (val >> 16) & 0xFF;
ecc_code[i++] = (val >> 8) & 0xFF;
ecc_code[i++] = (val >> 0) & 0xFF;
}
break;
default:
return -EINVAL;
}
/* ECC scheme specific syndrome customizations */
switch (bch->ecc_scheme) {
switch (info->ecc_scheme) {
case OMAP_ECC_HAM1_CODE_HW:
break;
#ifdef CONFIG_BCH
@ -323,6 +344,8 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
case OMAP_ECC_BCH8_CODE_HW:
ecc_code[chip->ecc.bytes - 1] = 0x00;
break;
case OMAP_ECC_BCH16_CODE_HW:
break;
default:
return -EINVAL;
}
@ -345,16 +368,17 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
{
struct nand_chip *chip = mtd->priv;
struct nand_bch_priv *bch = chip->priv;
uint32_t eccbytes = chip->ecc.bytes;
struct omap_nand_info *info = chip->priv;
struct nand_ecc_ctrl *ecc = &chip->ecc;
uint32_t error_count = 0, error_max;
uint32_t error_loc[8];
uint32_t error_loc[ELM_MAX_ERROR_COUNT];
enum bch_level bch_type;
uint32_t i, ecc_flag = 0;
uint8_t count, err = 0;
uint32_t byte_pos, bit_pos;
/* check calculated ecc */
for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
for (i = 0; i < ecc->bytes && !ecc_flag; i++) {
if (calc_ecc[i] != 0x00)
ecc_flag = 1;
}
@ -363,7 +387,7 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
/* check for whether its a erased-page */
ecc_flag = 0;
for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
for (i = 0; i < ecc->bytes && !ecc_flag; i++) {
if (read_ecc[i] != 0xff)
ecc_flag = 1;
}
@ -374,25 +398,33 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
* while reading ECC result we read it in big endian.
* Hence while loading to ELM we have rotate to get the right endian.
*/
switch (bch->ecc_scheme) {
switch (info->ecc_scheme) {
case OMAP_ECC_BCH8_CODE_HW:
omap_reverse_list(calc_ecc, eccbytes - 1);
bch_type = BCH_8_BIT;
omap_reverse_list(calc_ecc, ecc->bytes - 1);
break;
case OMAP_ECC_BCH16_CODE_HW:
bch_type = BCH_16_BIT;
omap_reverse_list(calc_ecc, ecc->bytes);
break;
default:
return -EINVAL;
}
/* use elm module to check for errors */
elm_config((enum bch_level)(bch->type));
if (elm_check_error(calc_ecc, bch->nibbles, &error_count, error_loc)) {
printf("nand: error: uncorrectable ECC errors\n");
return -EINVAL;
}
elm_config(bch_type);
err = elm_check_error(calc_ecc, bch_type, &error_count, error_loc);
if (err)
return err;
/* correct bch error */
for (count = 0; count < error_count; count++) {
switch (bch->type) {
case ECC_BCH8:
switch (info->ecc_scheme) {
case OMAP_ECC_BCH8_CODE_HW:
/* 14th byte in ECC is reserved to match ROM layout */
error_max = SECTOR_BYTES + (eccbytes - 1);
error_max = SECTOR_BYTES + (ecc->bytes - 1);
break;
case OMAP_ECC_BCH16_CODE_HW:
error_max = SECTOR_BYTES + ecc->bytes;
break;
default:
return -EINVAL;
@ -496,10 +528,10 @@ static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
/* cannot correct more than 8 errors */
unsigned int errloc[8];
struct nand_chip *chip = mtd->priv;
struct nand_bch_priv *chip_priv = chip->priv;
struct bch_control *bch = chip_priv->control;
struct omap_nand_info *info = chip->priv;
count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
count = decode_bch(info->control, NULL, 512, read_ecc, calc_ecc,
NULL, errloc);
if (count > 0) {
/* correct errors */
for (i = 0; i < count; i++) {
@ -535,15 +567,11 @@ static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct nand_bch_priv *chip_priv = chip->priv;
struct bch_control *bch = NULL;
if (chip_priv)
bch = chip_priv->control;
struct omap_nand_info *info = chip->priv;
if (bch) {
free_bch(bch);
chip_priv->control = NULL;
if (info->control) {
free_bch(info->control);
info->control = NULL;
}
}
#endif /* CONFIG_BCH */
@ -557,7 +585,7 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
*/
static int omap_select_ecc_scheme(struct nand_chip *nand,
enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
struct nand_bch_priv *bch = nand->priv;
struct omap_nand_info *info = nand->priv;
struct nand_ecclayout *ecclayout = &omap_ecclayout;
int eccsteps = pagesize / SECTOR_BYTES;
int i;
@ -567,12 +595,10 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
/* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
* initialized in nand_scan_tail(), so just set ecc.mode */
bch_priv.control = NULL;
bch_priv.type = 0;
info->control = NULL;
nand->ecc.mode = NAND_ECC_SOFT;
nand->ecc.layout = NULL;
nand->ecc.size = 0;
bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW;
break;
case OMAP_ECC_HAM1_CODE_HW:
@ -583,8 +609,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
(3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
return -EINVAL;
}
bch_priv.control = NULL;
bch_priv.type = 0;
info->control = NULL;
/* populate ecc specific fields */
memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
nand->ecc.mode = NAND_ECC_HW;
@ -605,7 +630,6 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
BADBLOCK_MARKER_LENGTH;
bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW;
break;
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
@ -618,12 +642,11 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
return -EINVAL;
}
/* check if BCH S/W library can be used for error detection */
bch_priv.control = init_bch(13, 8, 0x201b);
if (!bch_priv.control) {
info->control = init_bch(13, 8, 0x201b);
if (!info->control) {
printf("nand: error: could not init_bch()\n");
return -ENODEV;
}
bch_priv.type = ECC_BCH8;
/* populate ecc specific fields */
memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
nand->ecc.mode = NAND_ECC_HW;
@ -647,7 +670,6 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
BADBLOCK_MARKER_LENGTH;
bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
break;
#else
printf("nand: error: CONFIG_BCH required for ECC\n");
@ -665,7 +687,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
}
/* intialize ELM for ECC error detection */
elm_init();
bch_priv.type = ECC_BCH8;
info->control = NULL;
/* populate ecc specific fields */
memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
nand->ecc.mode = NAND_ECC_HW;
@ -683,13 +705,44 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
BADBLOCK_MARKER_LENGTH;
bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW;
break;
#else
printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
return -EINVAL;
#endif
case OMAP_ECC_BCH16_CODE_HW:
#ifdef CONFIG_NAND_OMAP_ELM
debug("nand: using OMAP_ECC_BCH16_CODE_HW\n");
/* check ecc-scheme requirements before updating ecc info */
if ((26 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
printf("nand: error: insufficient OOB: require=%d\n", (
(26 * eccsteps) + BADBLOCK_MARKER_LENGTH));
return -EINVAL;
}
/* intialize ELM for ECC error detection */
elm_init();
/* populate ecc specific fields */
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size = SECTOR_BYTES;
nand->ecc.bytes = 26;
nand->ecc.strength = 16;
nand->ecc.hwctl = omap_enable_hwecc;
nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc;
nand->ecc.read_page = omap_read_page_bch;
/* define ecc-layout */
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
for (i = 0; i < ecclayout->eccbytes; i++)
ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].length = oobsize - nand->ecc.bytes -
BADBLOCK_MARKER_LENGTH;
break;
#else
printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
return -EINVAL;
#endif
default:
debug("nand: error: ecc scheme not enabled or supported\n");
return -EINVAL;
@ -699,6 +752,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
nand->ecc.layout = ecclayout;
info->ecc_scheme = ecc_scheme;
return 0;
}
@ -802,16 +856,21 @@ int board_nand_init(struct nand_chip *nand)
nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
nand->priv = &bch_priv;
nand->priv = &omap_nand_info;
nand->cmd_ctrl = omap_nand_hwcontrol;
nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
/* If we are 16 bit dev, our gpmc config tells us that */
if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
nand->options |= NAND_BUSWIDTH_16;
nand->chip_delay = 100;
nand->ecc.layout = &omap_ecclayout;
/* configure driver and controller based on NAND device bus-width */
gpmc_config = readl(&gpmc_cfg->cs[cs].config1);
#if defined(CONFIG_SYS_NAND_BUSWIDTH_16BIT)
nand->options |= NAND_BUSWIDTH_16;
writel(gpmc_config | (0x1 << 12), &gpmc_cfg->cs[cs].config1);
#else
nand->options &= ~NAND_BUSWIDTH_16;
writel(gpmc_config & ~(0x1 << 12), &gpmc_cfg->cs[cs].config1);
#endif
/* select ECC scheme */
#if defined(CONFIG_NAND_OMAP_ECCSCHEME)
err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,

@ -13,4 +13,5 @@ obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
obj-$(CONFIG_POWER_TPS65090) += pmic_tps65090.o
obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o

@ -0,0 +1,97 @@
/*
* (C) Copyright 2011-2013
* Texas Instruments, <www.ti.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <i2c.h>
#include <power/tps65218.h>
/**
* tps65218_reg_write() - Generic function that can write a TPS65218 PMIC
* register or bit field regardless of protection
* level.
*
* @prot_level: Register password protection. Use
* TPS65218_PROT_LEVEL_NONE,
* TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2
* @dest_reg: Register address to write.
* @dest_val: Value to write.
* @mask: Bit mask (8 bits) to be applied. Function will only
* change bits that are set in the bit mask.
*
* @return: 0 for success, not 0 on failure, as per the i2c API
*/
int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
uchar mask)
{
uchar read_val;
uchar xor_reg;
int ret;
/*
* If we are affecting only a bit field, read dest_reg and apply the
* mask
*/
if (mask != TPS65218_MASK_ALL_BITS) {
ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
if (ret)
return ret;
read_val &= (~mask);
read_val |= (dest_val & mask);
dest_val = read_val;
}
if (prot_level > 0) {
xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
&xor_reg, 1);
if (ret)
return ret;
}
ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
if (ret)
return ret;
if (prot_level == TPS65218_PROT_LEVEL_2) {
ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
&xor_reg, 1);
if (ret)
return ret;
ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
if (ret)
return ret;
}
return 0;
}
/**
* tps65218_voltage_update() - Function to change a voltage level, as this
* is a multi-step process.
* @dc_cntrl_reg: DC voltage control register to change.
* @volt_sel: New value for the voltage register
* @return: 0 for success, not 0 on failure.
*/
int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
{
if ((dc_cntrl_reg != TPS65218_DCDC1) &&
(dc_cntrl_reg != TPS65218_DCDC2))
return 1;
/* set voltage level */
if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
TPS65218_MASK_ALL_BITS))
return 1;
/* set GO bit to initiate voltage transition */
if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
TPS65218_DCDC_GO, TPS65218_DCDC_GO))
return 1;
return 0;
}

@ -106,6 +106,7 @@ static void ti_spi_setup_spi_register(struct ti_qspi_slave *qslave)
slave->memory_map = (void *)MMAP_START_ADDR_DRA;
#else
slave->memory_map = (void *)MMAP_START_ADDR_AM43x;
slave->op_mode_rx = 8;
#endif
memval |= QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES |

@ -329,6 +329,7 @@
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
/* NAND boot config */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048

@ -32,11 +32,15 @@
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
#define CONFIG_SYS_I2C_MULTI_EEPROMS
/* Power */
#define CONFIG_POWER_TPS65218
/* SPL defines. */
#define CONFIG_SPL_TEXT_BASE 0x40300350
#define CONFIG_SPL_MAX_SIZE (220 << 10) /* 220KB */
#define CONFIG_SYS_SPL_ARGS_ADDR (CONFIG_SYS_SDRAM_BASE + \
(128 << 20))
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_YMODEM_SUPPORT
/* Enabling L2 Cache */
@ -48,15 +52,24 @@
* Since SPL did pll and ddr initialization for us,
* we don't need to do it twice.
*/
#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_NOR_BOOT)
#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_QSPI_BOOT)
#define CONFIG_SKIP_LOWLEVEL_INIT
#endif
/*
* When building U-Boot such that there is no previous loader
* we need to call board_early_init_f. This is taken care of in
* s_init when we have SPL used.
*/
#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && !defined(CONFIG_SPL)
#define CONFIG_BOARD_EARLY_INIT_F
#endif
/* Now bring in the rest of the common code. */
#include <configs/ti_armv7_common.h>
/* Always 128 KiB env size */
#define CONFIG_ENV_SIZE (128 << 10)
/* Always 64 KiB env size */
#define CONFIG_ENV_SIZE (64 << 10)
#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
@ -86,6 +99,30 @@
#define CONFIG_OMAP_USB_PHY
#define CONFIG_AM437X_USB2PHY2_HOST
#ifdef CONFIG_QSPI_BOOT
#define CONFIG_SYS_TEXT_BASE 0x30000000
#undef CONFIG_ENV_IS_NOWHERE
#define CONFIG_ENV_IS_IN_SPI_FLASH
#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
#define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64 KB sectors */
#define CONFIG_ENV_OFFSET 0x110000
#define CONFIG_ENV_OFFSET_REDUND 0x120000
#ifdef MTDIDS_DEFAULT
#undef MTDIDS_DEFAULT
#endif
#ifdef MTDPARTS_DEFAULT
#undef MTDPARTS_DEFAULT
#endif
#define MTDPARTS_DEFAULT "mtdparts=qspi.0:512k(QSPI.u-boot)," \
"512k(QSPI.u-boot.backup)," \
"512k(QSPI.u-boot-spl-os)," \
"64k(QSPI.u-boot-env)," \
"64k(QSPI.u-boot-env.backup)," \
"8m(QSPI.kernel)," \
"-(QSPI.file-system)"
#endif
/* SPI */
#undef CONFIG_OMAP3_SPI
#define CONFIG_TI_QSPI
@ -94,6 +131,7 @@
#define CONFIG_CMD_SF
#define CONFIG_CMD_SPI
#define CONFIG_TI_SPI_MMAP
#define CONFIG_SPI_FLASH_BAR
#define CONFIG_QSPI_SEL_GPIO 48
#define CONFIG_SF_DEFAULT_SPEED 48000000
#define CONFIG_DEFAULT_SPI_MODE SPI_MODE_3
@ -145,6 +183,7 @@
"loadfdt=load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}\0" \
"mmcboot=mmc dev ${mmcdev}; " \
"setenv devnum ${mmcdev}; " \
"setenv devtype mmc; " \
"if mmc rescan; then " \
"echo SD/MMC found on device ${devnum};" \
"if run loadbootenv; then " \

@ -12,6 +12,8 @@
#ifndef __BUR_AM335X_COMMON_H__
#define __BUR_AM335X_COMMON_H__
/* ------------------------------------------------------------------------- */
#define CONFIG_SYS_GENERIC_BOARD
#define CONFIG_AM33XX
#define CONFIG_OMAP
#define CONFIG_OMAP_COMMON
@ -94,7 +96,7 @@
#define CONFIG_SYS_OMAP24_I2C_SPEED 100000
#define CONFIG_SYS_OMAP24_I2C_SLAVE 1
#define CONFIG_SYS_I2C_OMAP24XX
#define CONFIG_CMD_I2C
/* GPIO */
#define CONFIG_OMAP_GPIO
#define CONFIG_CMD_GPIO

@ -141,7 +141,6 @@
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x200000
#define CONFIG_CMD_NAND
#define GPMC_NAND_ECC_LP_x8_LAYOUT
#define MTDIDS_DEFAULT "nand0=nand"
#define MTDPARTS_DEFAULT "mtdparts=nand:2m(spl)," \
"1m(u-boot),1m(u-boot-env)," \

@ -158,7 +158,6 @@
/* CS0 */
#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND */
/* devices */
#define GPMC_NAND_ECC_LP_x8_LAYOUT
/* Environment information */
#define CONFIG_BOOTDELAY 3

@ -314,6 +314,7 @@
#define CONFIG_SPL_BSS_MAX_SIZE 0x80000
/* NAND boot config */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048

@ -138,6 +138,7 @@
* Board NAND Info.
*/
#define CONFIG_NAND_OMAP_GPMC
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_SYS_NAND_ADDR NAND_BASE /* physical address */
/* to access nand */
#define CONFIG_SYS_NAND_BASE NAND_BASE /* physical address */

@ -71,7 +71,8 @@
#define CONFIG_SYS_NS16550_SERIAL
#define CONFIG_SYS_NS16550_MEM32
#define CONFIG_SYS_NS16550_REG_SIZE -4
#define CONFIG_SYS_NS16550_COM1 K2HK_UART0_BASE
#define CONFIG_SYS_NS16550_COM1 KS2_UART0_BASE
#define CONFIG_SYS_NS16550_COM2 KS2_UART1_BASE
#define CONFIG_SYS_NS16550_CLK clk_get_rate(K2HK_CLK1_6)
#define CONFIG_CONS_INDEX 1
#define CONFIG_BAUDRATE 115200
@ -130,6 +131,7 @@
/* NAND Configuration */
#define CONFIG_NAND_DAVINCI
#define CONFIG_CMD_NAND_ECCLAYOUT
#define CONFIG_SYS_NAND_CS 2
#define CONFIG_SYS_NAND_USE_FLASH_BBT
#define CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST

@ -295,6 +295,7 @@
#define CONFIG_SPL_OMAP3_ID_NAND
/* NAND boot config */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048

@ -120,7 +120,7 @@
/* Max number of NAND devices */
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
/* Timeout values (in ticks) */
#define CONFIG_SYS_FLASH_ERASE_TOUT (100 * CONFIG_SYS_HZ)
#define CONFIG_SYS_FLASH_WRITE_TOUT (100 * CONFIG_SYS_HZ)

@ -187,6 +187,7 @@
/* NAND boot config */
#ifdef CONFIG_NAND
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048

@ -141,6 +141,7 @@
#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of */
/* NAND devices */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_JFFS2_NAND
/* nand device jffs2 lives on */
#define CONFIG_JFFS2_DEV "nand0"

@ -206,6 +206,7 @@
#define CONFIG_SYS_CACHELINE_SIZE 64
/* NAND boot config */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048

@ -98,6 +98,7 @@
#define CONFIG_SYS_NAND_BASE NAND_BASE /* physical address */
/* to access nand at */
/* CS0 */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
/* Environment information */

@ -149,7 +149,6 @@
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000
#define GPMC_NAND_ECC_LP_x8_LAYOUT 1
#define MTDIDS_DEFAULT "nand0=omap2-nand.0"
#define MTDPARTS_DEFAULT "mtdparts=omap2-nand.0:128k(SPL)," \
"128k(SPL.backup1)," \

@ -185,6 +185,7 @@
/* Configure the PISMO */
#define PISMO1_NAND_SIZE GPMC_SIZE_128M
#define CONFIG_NAND
#define CONFIG_NAND_OMAP_GPMC
#define CONFIG_ENV_IS_IN_NAND
#define SMNAND_ENV_OFFSET 0x180000 /* environment starts here */
@ -249,6 +250,7 @@
#define CONFIG_SPL_BSS_MAX_SIZE 0x80000
/* NAND boot config */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048
#define CONFIG_SYS_NAND_OOBSIZE 64

@ -137,10 +137,10 @@
#define CONFIG_SYS_NAND_BASE NAND_BASE /* physical address */
/* to access nand at */
/* CS0 */
#define GPMC_NAND_ECC_LP_x16_LAYOUT
#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND */
/* devices */
#define CONFIG_SYS_NAND_BUSWIDTH_16BIT 16
/* Environment information */
#define CONFIG_BOOTDELAY 3

@ -75,6 +75,15 @@
#define CONFIG_SKIP_LOWLEVEL_INIT
#endif
/*
* When building U-Boot such that there is no previous loader
* we need to call board_early_init_f. This is taken care of in
* s_init when we have SPL used.
*/
#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && !defined(CONFIG_SPL)
#define CONFIG_BOARD_EARLY_INIT_F
#endif
#ifdef CONFIG_NAND
#define CONFIG_SPL_NAND_AM33XX_BCH /* ELM support */
#endif

@ -196,7 +196,8 @@
* under common/spl/. Given our generally common memory map, we set a
* number of related defaults and sizes here.
*/
#ifndef CONFIG_NOR_BOOT
#if !defined(CONFIG_NOR_BOOT) && \
!(defined(CONFIG_QSPI_BOOT) && defined(CONFIG_AM43XX))
#define CONFIG_SPL
#define CONFIG_SPL_FRAMEWORK
#define CONFIG_SPL_OS_BOOT

@ -157,7 +157,6 @@
/* don't change OMAP_ELM, ECCSCHEME. ROM code only supports this */
#define CONFIG_NAND_OMAP_ELM
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW
#define GPMC_NAND_ECC_LP_x16_LAYOUT 1
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_BLOCK_SIZE (128*1024)
#define CONFIG_SYS_NAND_PAGE_SIZE 2048

@ -719,4 +719,23 @@ static inline int onfi_get_sync_timing_mode(struct nand_chip *chip)
}
#endif
/**
* Check if the opcode's address should be sent only on the lower 8 bits
* @command: opcode to check
*/
static inline int nand_opcode_8bits(unsigned int command)
{
switch (command) {
case NAND_CMD_READID:
case NAND_CMD_PARAM:
case NAND_CMD_GET_FEATURES:
case NAND_CMD_SET_FEATURES:
return 1;
default:
break;
}
return 0;
}
#endif /* __LINUX_MTD_NAND_H */

@ -24,6 +24,9 @@
#define ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK (0x100)
#define ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK (0x1F)
#define ELM_MAX_CHANNELS 8
#define ELM_MAX_ERROR_COUNT 16
#ifndef __ASSEMBLY__
enum bch_level {
@ -43,7 +46,7 @@ struct syndrome {
struct location {
u32 location_status; /* 0x800 */
u8 res1[124]; /* 0x804 */
u32 error_location_x[16]; /* 0x880.... */
u32 error_location_x[ELM_MAX_ERROR_COUNT]; /* 0x880, 0x980, .. */
u8 res2[64]; /* 0x8c0 */
};
@ -63,12 +66,12 @@ struct elm {
u8 res2[92]; /* 0x024 */
u32 page_ctrl; /* 0x080 */
u8 res3[892]; /* 0x084 */
struct syndrome syndrome_fragments[8]; /* 0x400 */
struct syndrome syndrome_fragments[ELM_MAX_CHANNELS]; /* 0x400,0x420 */
u8 res4[512]; /* 0x600 */
struct location error_location[8]; /* 0x800 */
struct location error_location[ELM_MAX_CHANNELS]; /* 0x800,0x900 ... */
};
int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count,
int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count,
u32 *error_locations);
int elm_config(enum bch_level level);
void elm_reset(void);

@ -11,6 +11,7 @@
#define GPMC_BUF_EMPTY 0
#define GPMC_BUF_FULL 1
#define GPMC_MAX_SECTORS 8
enum omap_ecc {
/* 1-bit ECC calculation by Software, Error detection by Software */
@ -26,6 +27,8 @@ enum omap_ecc {
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
/* 8-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH8_CODE_HW,
/* 16-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH16_CODE_HW,
};
struct gpmc_cs {
@ -46,6 +49,10 @@ struct bch_res_0_3 {
u32 bch_result_x[4];
};
struct bch_res_4_6 {
u32 bch_result_x[3];
};
struct gpmc {
u8 res1[0x10];
u32 sysconfig; /* 0x10 */
@ -75,7 +82,9 @@ struct gpmc {
u8 res7[12]; /* 0x224 */
u32 testmomde_ctrl; /* 0x230 */
u8 res8[12]; /* 0x234 */
struct bch_res_0_3 bch_result_0_3[2]; /* 0x240 */
struct bch_res_0_3 bch_result_0_3[GPMC_MAX_SECTORS]; /* 0x240,0x250, */
u8 res9[16 * 4]; /* 0x2C0 - 0x2FF */
struct bch_res_4_6 bch_result_4_6[GPMC_MAX_SECTORS]; /* 0x300,0x310, */
};
/* Used for board specific gpmc initialization */

@ -0,0 +1,63 @@
/*
* (C) Copyright 2014
* Texas Instruments, <www.ti.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __POWER_TPS65218_H__
#define __POWER_TPS65218_H__
/* I2C chip address */
#define TPS65218_CHIP_PM 0x24
/* Registers */
enum {
TPS65218_CHIPID = 0x00,
TPS65218_INT1,
TPS65218_INT2,
TPS65218_INT_MASK1,
TPS65218_INT_MASK2,
TPS65218_STATUS,
TPS65218_CONTROL,
TPS65218_FLAG,
TPS65218_PASSWORD = 0x10,
TPS65218_ENABLE1,
TPS65218_ENABLE2,
TPS65218_CONFIG1,
TPS65218_CONFIG2,
TPS65218_CONFIG3,
TPS65218_DCDC1,
TPS65218_DCDC2,
TPS65218_DCDC3,
TPS65218_DCDC4,
TPS65218_SLEW,
TPS65218_LDO1,
TPS65218_SEQ1 = 0x20,
TPS65218_SEQ2,
TPS65218_SEQ3,
TPS65218_SEQ4,
TPS65218_SEQ5,
TPS65218_SEQ6,
TPS65218_SEQ7,
TPS65218_PMIC_NUM_OF_REGS,
};
#define TPS65218_PROT_LEVEL_NONE 0x00
#define TPS65218_PROT_LEVEL_1 0x01
#define TPS65218_PROT_LEVEL_2 0x02
#define TPS65218_PASSWORD_LOCK_FOR_WRITE 0x00
#define TPS65218_PASSWORD_UNLOCK 0x7D
#define TPS65218_DCDC_GO 0x80
#define TPS65218_MASK_ALL_BITS 0xFF
#define TPS65218_DCDC_VOLT_SEL_1100MV 0x19
#define TPS65218_DCDC_VOLT_SEL_1330MV 0x30
int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
uchar mask);
int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel);
#endif /* __POWER_TPS65218_H__ */
Loading…
Cancel
Save