1370007Sdonner// SPDX-License-Identifier: GPL-2.0+ 2370007Sdonner/* 3370007Sdonner * Keystone2: Asynchronous EMIF Configuration 4370007Sdonner * 5370007Sdonner * (C) Copyright 2012-2014 6370007Sdonner * Texas Instruments Incorporated, <www.ti.com> 7370007Sdonner */ 8370007Sdonner 9370007Sdonner#include <common.h> 10370007Sdonner#include <asm/arch/hardware.h> 11370007Sdonner#include <asm/ti-common/ti-aemif.h> 12370007Sdonner 13370007Sdonner#define AEMIF_WAITCYCLE_CONFIG (KS2_AEMIF_CNTRL_BASE + 0x4) 14370007Sdonner#define AEMIF_NAND_CONTROL (KS2_AEMIF_CNTRL_BASE + 0x60) 15370007Sdonner#define AEMIF_ONENAND_CONTROL (KS2_AEMIF_CNTRL_BASE + 0x5c) 16370007Sdonner#define AEMIF_CONFIG(cs) (KS2_AEMIF_CNTRL_BASE + 0x10 + (cs * 4)) 17370007Sdonner 18370007Sdonner#define AEMIF_CFG_SELECT_STROBE(v) ((v) ? 1 << 31 : 0) 19370007Sdonner#define AEMIF_CFG_EXTEND_WAIT(v) ((v) ? 1 << 30 : 0) 20370007Sdonner#define AEMIF_CFG_WR_SETUP(v) (((v) & 0x0f) << 26) 21370007Sdonner#define AEMIF_CFG_WR_STROBE(v) (((v) & 0x3f) << 20) 22370007Sdonner#define AEMIF_CFG_WR_HOLD(v) (((v) & 0x07) << 17) 23370007Sdonner#define AEMIF_CFG_RD_SETUP(v) (((v) & 0x0f) << 13) 24370007Sdonner#define AEMIF_CFG_RD_STROBE(v) (((v) & 0x3f) << 7) 25370007Sdonner#define AEMIF_CFG_RD_HOLD(v) (((v) & 0x07) << 4) 26370007Sdonner#define AEMIF_CFG_TURN_AROUND(v) (((v) & 0x03) << 2) 27370007Sdonner#define AEMIF_CFG_WIDTH(v) (((v) & 0x03) << 0) 28370007Sdonner 29370007Sdonner#define set_config_field(reg, field, val) \ 30370007Sdonner do { \ 31370007Sdonner if (val != -1) { \ 32370007Sdonner reg &= ~AEMIF_CFG_##field(0xffffffff); \ 33370007Sdonner reg |= AEMIF_CFG_##field(val); \ 34370007Sdonner } \ 35370007Sdonner } while (0) 36370007Sdonner 37370007Sdonnerstatic void aemif_configure(int cs, struct aemif_config *cfg) 38370007Sdonner{ 39370007Sdonner unsigned long tmp; 40370007Sdonner 41370007Sdonner if (cfg->mode == AEMIF_MODE_NAND) { 42370007Sdonner tmp = __raw_readl(AEMIF_NAND_CONTROL); 43370007Sdonner tmp |= (1 << cs); 44370007Sdonner __raw_writel(tmp, AEMIF_NAND_CONTROL); 45370007Sdonner 46370007Sdonner } else if (cfg->mode == AEMIF_MODE_ONENAND) { 47370007Sdonner tmp = __raw_readl(AEMIF_ONENAND_CONTROL); 48370007Sdonner tmp |= (1 << cs); 49370007Sdonner __raw_writel(tmp, AEMIF_ONENAND_CONTROL); 50370007Sdonner } 51370007Sdonner 52370007Sdonner tmp = __raw_readl(AEMIF_CONFIG(cs)); 53370007Sdonner 54370007Sdonner set_config_field(tmp, SELECT_STROBE, cfg->select_strobe); 55370007Sdonner set_config_field(tmp, EXTEND_WAIT, cfg->extend_wait); 56370007Sdonner set_config_field(tmp, WR_SETUP, cfg->wr_setup); 57370007Sdonner set_config_field(tmp, WR_STROBE, cfg->wr_strobe); 58370007Sdonner set_config_field(tmp, WR_HOLD, cfg->wr_hold); 59370007Sdonner set_config_field(tmp, RD_SETUP, cfg->rd_setup); 60370007Sdonner set_config_field(tmp, RD_STROBE, cfg->rd_strobe); 61370007Sdonner set_config_field(tmp, RD_HOLD, cfg->rd_hold); 62370007Sdonner set_config_field(tmp, TURN_AROUND, cfg->turn_around); 63370007Sdonner set_config_field(tmp, WIDTH, cfg->width); 64370007Sdonner 65370007Sdonner __raw_writel(tmp, AEMIF_CONFIG(cs)); 66370007Sdonner} 67370007Sdonner 68370007Sdonnervoid aemif_init(int num_cs, struct aemif_config *config) 69370007Sdonner{ 70370007Sdonner int cs; 71370007Sdonner 72370007Sdonner if (num_cs > AEMIF_NUM_CS) { 73370007Sdonner num_cs = AEMIF_NUM_CS; 74370007Sdonner printf("AEMIF: csnum has to be <= 5"); 75370007Sdonner } 76370007Sdonner 77370007Sdonner for (cs = 0; cs < num_cs; cs++) 78370007Sdonner aemif_configure(cs, config + cs); 79370007Sdonner} 80370007Sdonner