From dacdb2402742a0365ca543798a349182872131b4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 26 Sep 2016 13:13:16 +0900 Subject: ARM: uniphier: do not setup pins for System Bus on NAND boot mode For LD11 and LD20 SoCs, the System Bus and NAND are multiplexed in the same I/O pins. When booting from a NAND device, pin-mux for the System Bus must not be set-up because they are exclusive with each other. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/init/init-ld11.c | 4 +++- arch/arm/mach-uniphier/init/init-ld20.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-uniphier/init/init-ld11.c b/arch/arm/mach-uniphier/init/init-ld11.c index e324c94..fdb2838 100644 --- a/arch/arm/mach-uniphier/init/init-ld11.c +++ b/arch/arm/mach-uniphier/init/init-ld11.c @@ -15,7 +15,9 @@ int uniphier_ld11_init(const struct uniphier_board_data *bd) { uniphier_sbc_init_savepin(bd); uniphier_pxs2_sbc_init(bd); - uniphier_pin_init("system_bus_grp"); + /* pins for NAND and System Bus are multiplexed */ + if (spl_boot_device() != BOOT_DEVICE_NAND) + uniphier_pin_init("system_bus_grp"); support_card_reset(); diff --git a/arch/arm/mach-uniphier/init/init-ld20.c b/arch/arm/mach-uniphier/init/init-ld20.c index cb05421..37b860a 100644 --- a/arch/arm/mach-uniphier/init/init-ld20.c +++ b/arch/arm/mach-uniphier/init/init-ld20.c @@ -15,7 +15,9 @@ int uniphier_ld20_init(const struct uniphier_board_data *bd) { uniphier_sbc_init_savepin(bd); uniphier_pxs2_sbc_init(bd); - uniphier_pin_init("system_bus_grp"); + /* pins for NAND and System Bus are multiplexed */ + if (spl_boot_device() != BOOT_DEVICE_NAND) + uniphier_pin_init("system_bus_grp"); support_card_reset(); -- cgit v1.1 From 6c22742d3defa76be00b4d3b5b49911fa63ffa0a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:23 +0900 Subject: ARM: uniphier: enable SSC for DPLL (DRAM PLL) on LD11 SoC For Electro-Magnetic Compatibility test. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/clk/pll-ld11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-uniphier/clk/pll-ld11.c b/arch/arm/mach-uniphier/clk/pll-ld11.c index 8a4a748..7746deb 100644 --- a/arch/arm/mach-uniphier/clk/pll-ld11.c +++ b/arch/arm/mach-uniphier/clk/pll-ld11.c @@ -23,6 +23,7 @@ void uniphier_ld11_pll_init(void) uniphier_ld20_sscpll_ssc_en(SC_CPLLCTRL); uniphier_ld20_sscpll_ssc_en(SC_MPLLCTRL); uniphier_ld20_sscpll_ssc_en(SC_VSPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLLCTRL); uniphier_ld20_vpll27_init(SC_VPLL27FCTRL); uniphier_ld20_vpll27_init(SC_VPLL27ACTRL); -- cgit v1.1 From c89638a02767c295ba368838f21ad1ab4825da96 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:24 +0900 Subject: ARM: uniphier: update DRAM init code for LD20 SoC (2nd) - Do not reference CONFIG_DDR_FREQ; now the DDR frequency is passed from the uniphier_board_data structure - Constify parameter arrays - Tidy up cluttered macros - Lots of code cleanups - Lots of coding style fixes Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/ddrphy-ld20-regs.h | 37 +- arch/arm/mach-uniphier/dram/umc-ld20.c | 652 ++++++++++++------------- 2 files changed, 356 insertions(+), 333 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ld20-regs.h b/arch/arm/mach-uniphier/dram/ddrphy-ld20-regs.h index 02b3aab..0c11b65 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-ld20-regs.h +++ b/arch/arm/mach-uniphier/dram/ddrphy-ld20-regs.h @@ -7,7 +7,12 @@ #ifndef _DDRPHY_LD20_REGS_H #define _DDRPHY_LD20_REGS_H +#include + #define PHY_REG_SHIFT 2 +#define PHY_SLV_DLY_WIDTH 6 +#define PHY_BITLVL_DLY_WIDTH 6 +#define PHY_MAS_DLY_WIDTH 8 #define PHY_SCL_START (0x40 << (PHY_REG_SHIFT)) #define PHY_SCL_DATA_0 (0x41 << (PHY_REG_SHIFT)) @@ -17,8 +22,19 @@ #define PHY_SCL_CONFIG_2 (0x47 << (PHY_REG_SHIFT)) #define PHY_PAD_CTRL (0x48 << (PHY_REG_SHIFT)) #define PHY_DLL_RECALIB (0x49 << (PHY_REG_SHIFT)) +#define PHY_DLL_RECALIB_TRIM_MASK GENMASK(PHY_SLV_DLY_WIDTH - 1, 0) +#define PHY_DLL_RECALIB_INCR BIT(27) #define PHY_DLL_ADRCTRL (0x4A << (PHY_REG_SHIFT)) +#define PHY_DLL_ADRCTRL_TRIM_MASK GENMASK(PHY_SLV_DLY_WIDTH - 1, 0) +#define PHY_DLL_ADRCTRL_INCR BIT(9) +#define PHY_DLL_ADRCTRL_MDL_SHIFT 24 +#define PHY_DLL_ADRCTRL_MDL_MASK (GENMASK(PHY_MAS_DLY_WIDTH - 1, 0) << \ + PHY_DLL_ADRCTRL_MDL_SHIFT) #define PHY_LANE_SEL (0x4B << (PHY_REG_SHIFT)) +#define PHY_LANE_SEL_LANE_SHIFT 0 +#define PHY_LANE_SEL_LANE_WIDTH 8 +#define PHY_LANE_SEL_BIT_SHIFT 8 +#define PHY_LANE_SEL_BIT_WIDTH 4 #define PHY_DLL_TRIM_1 (0x4C << (PHY_REG_SHIFT)) #define PHY_DLL_TRIM_2 (0x4D << (PHY_REG_SHIFT)) #define PHY_DLL_TRIM_3 (0x4E << (PHY_REG_SHIFT)) @@ -34,9 +50,23 @@ #define PHY_UNIQUIFY_TSMC_IO_1 (0x5C << (PHY_REG_SHIFT)) #define PHY_SCL_START_ADDR (0x62 << (PHY_REG_SHIFT)) #define PHY_IP_DQ_DQS_BITWISE_TRIM (0x65 << (PHY_REG_SHIFT)) +#define PHY_IP_DQ_DQS_BITWISE_TRIM_MASK \ + GENMASK(PHY_BITLVL_DLY_WIDTH - 1, 0) +#define PHY_IP_DQ_DQS_BITWISE_TRIM_INC \ + BIT(PHY_BITLVL_DLY_WIDTH) +#define PHY_IP_DQ_DQS_BITWISE_TRIM_OVERRIDE \ + BIT(PHY_BITLVL_DLY_WIDTH + 1) #define PHY_DSCL_CNT (0x67 << (PHY_REG_SHIFT)) #define PHY_OP_DQ_DM_DQS_BITWISE_TRIM (0x68 << (PHY_REG_SHIFT)) +#define PHY_OP_DQ_DM_DQS_BITWISE_TRIM_MASK \ + GENMASK(PHY_BITLVL_DLY_WIDTH - 1, 0) +#define PHY_OP_DQ_DM_DQS_BITWISE_TRIM_INC \ + BIT(PHY_BITLVL_DLY_WIDTH) +#define PHY_OP_DQ_DM_DQS_BITWISE_TRIM_OVERRIDE \ + BIT(PHY_BITLVL_DLY_WIDTH + 1) #define PHY_DLL_TRIM_CLK (0x69 << (PHY_REG_SHIFT)) +#define PHY_DLL_TRIM_CLK_MASK GENMASK(PHY_SLV_DLY_WIDTH, 0) +#define PHY_DLL_TRIM_CLK_INCR BIT(PHY_SLV_DLY_WIDTH + 1) #define PHY_DYNAMIC_BIT_LVL (0x6B << (PHY_REG_SHIFT)) #define PHY_SCL_WINDOW_TRIM (0x6D << (PHY_REG_SHIFT)) #define PHY_DISABLE_GATING_FOR_SCL (0x6E << (PHY_REG_SHIFT)) @@ -45,11 +75,4 @@ #define PHY_VREF_TRAINING (0x72 << (PHY_REG_SHIFT)) #define PHY_SCL_GATE_TIMING (0x78 << (PHY_REG_SHIFT)) -/* MASK */ -#define MSK_OP_DQ_DM_DQS_BITWISE_TRIM 0x0000007F -#define MSK_IP_DQ_DQS_BITWISE_TRIM 0x0000007F -#define MSK_OVERRIDE 0x00000080 - -#define PHY_BITLVL_DLY_WIDTH 6 - #endif /* _DDRPHY_LD20_REGS_H */ diff --git a/arch/arm/mach-uniphier/dram/umc-ld20.c b/arch/arm/mach-uniphier/dram/umc-ld20.c index 1fdd119..4e1fbde 100644 --- a/arch/arm/mach-uniphier/dram/umc-ld20.c +++ b/arch/arm/mach-uniphier/dram/umc-ld20.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2016 Socionext Inc. * - * based on commit a3c28918e86ad57127cf07bf8b32950cab20c03c of Diag + * based on commit 9073035a9860f892f8d1345dfb0ea862b5021145 of Diag * * SPDX-License-Identifier: GPL-2.0+ */ @@ -18,7 +18,6 @@ #include "umc64-regs.h" #define DRAM_CH_NR 3 -#define CONFIG_DDR_FREQ 1866 enum dram_freq { DRAM_FREQ_1866M, @@ -39,311 +38,196 @@ enum dram_board { /* board type */ DRAM_BOARD_NR, }; -#define MSK_PHY_LANE_SEL 0x000000FF -#define MSK_BIT_SEL 0x00000F00 -#define MSK_DLL_MAS_DLY 0xFF000000 -#define MSK_MAS_DLY 0x7F000000 -#define MSK_DLLS_TRIM_CLK 0x000000FF - -#define PHY_DLL_MAS_DLY_WIDTH 8 -#define PHY_SLV_DLY_WIDTH 6 - -static void ddrphy_maskwritel(u32 data, u32 mask, void *addr) -{ - u32 value; - - value = (readl(addr) & ~mask) | (data & mask); - writel(value, addr); -} - -static u32 ddrphy_maskreadl(u32 mask, void *addr) -{ - return readl(addr) & mask; -} - -/* set phy_lane_sel.phy_lane_sel */ -static void ddrphy_set_phy_lane_sel(int val, void __iomem *phy_base) -{ - ddrphy_maskwritel(val, MSK_PHY_LANE_SEL, phy_base + PHY_LANE_SEL); -} - -/* set phy_lane_sel.bit_sel */ -static void ddrphy_set_bit_sel(int bit, void __iomem *phy_base) -{ - ddrphy_maskwritel(bit << 8, MSK_BIT_SEL, phy_base + PHY_LANE_SEL); -} - -/* Calculating step for PUB-byte */ -static int ddrphy_hpstep(int delay, void __iomem *phy_base) -{ - int mdl, freq; - - freq = CONFIG_DDR_FREQ; /* FIXME */ - mdl = ddrphy_maskreadl(MSK_DLL_MAS_DLY, phy_base + PHY_DLL_ADRCTRL) >> 24; - - return DIV_ROUND_CLOSEST(freq * delay * mdl, 2 * 1000000); -} - -static void ddrphy_set_dll_trim_clk(int delay_ckoffset, void __iomem *phy_base) -{ - u8 ck_step; /* ckoffset_step for clock */ - u32 ck_step_all; - - /* CK-Offset */ - if (delay_ckoffset >= 0) { - /* shift + direction */ - ck_step = min(ddrphy_hpstep(delay_ckoffset, phy_base), 127); - ck_step_all = ((0x1<<(PHY_SLV_DLY_WIDTH + 1))|ck_step); - } else{ - /* shift - direction */ - ck_step = min(ddrphy_hpstep(-1*delay_ckoffset, phy_base), 127); - ck_step_all = ck_step; - } - - ddrphy_set_phy_lane_sel(0, phy_base); - ddrphy_maskwritel(ck_step_all, MSK_DLLS_TRIM_CLK, phy_base + PHY_DLL_TRIM_CLK); -} - -static void ddrphy_set_dll_recalib(int delay_qoffset, u32 recalib_cnt, - u8 disable_recalib, u8 ctr_start_val, - void __iomem *phy_base) -{ - u8 dlls_trim_adrctrl_ma, incr_dly_adrctrl_ma; /* qoffset_step and flag for inc/dec */ - u32 recalib_all; /* all fields of register dll_recalib */ - - /* Q-Offset */ - if (delay_qoffset >= 0) { - dlls_trim_adrctrl_ma = min(ddrphy_hpstep(delay_qoffset, phy_base), 63); - incr_dly_adrctrl_ma = 0x1; - } else { - dlls_trim_adrctrl_ma = min(ddrphy_hpstep(-1*delay_qoffset, phy_base), 63); - incr_dly_adrctrl_ma = 0x0; - } - - recalib_all = ((ctr_start_val & 0xf) << 28) | - (incr_dly_adrctrl_ma << 27) | - ((disable_recalib & 0x1) << 26) | - ((recalib_cnt & 0x3ffff) << 8) | - (dlls_trim_adrctrl_ma & 0x3f); - - /* write value for all bits other than bit[7:6] */ - ddrphy_maskwritel(recalib_all, ~0xc0, phy_base + PHY_DLL_RECALIB); -} - -static void ddrphy_set_dll_adrctrl(int delay_qoffset, u8 override_adrctrl, - void __iomem *phy_base) -{ - u8 dlls_trim_adrctrl, incr_dly_adrctrl; /* qoffset_step for clock */ - u32 adrctrl_all; - - if (delay_qoffset >= 0) { - dlls_trim_adrctrl = min(ddrphy_hpstep(delay_qoffset, phy_base), 63); - incr_dly_adrctrl = 0x1; - } else { - dlls_trim_adrctrl = min(ddrphy_hpstep(-delay_qoffset, phy_base), 63); - incr_dly_adrctrl = 0x0; - } - - adrctrl_all = (incr_dly_adrctrl << 9) | - ((override_adrctrl & 0x1) << 8) | - dlls_trim_adrctrl; - - ddrphy_maskwritel(adrctrl_all, 0x33f, phy_base + PHY_DLL_ADRCTRL); -} - -/* dio */ -static int dio_adrctrl_0[DRAM_BOARD_NR][DRAM_CH_NR] = { - {268-262, 268-263, 268-378}, /* LD20 reference */ - {268-262, 268-263, 268-378}, /* LD20 TV */ - {268-212, 268-268, 0}, /* LD21 reference */ - {268-212, 268-268, 0}, /* LD21 TV */ +/* PHY */ +static const int ddrphy_adrctrl[DRAM_BOARD_NR][DRAM_CH_NR] = { + {268 - 262, 268 - 263, 268 - 378}, /* LD20 reference */ + {268 - 262, 268 - 263, 268 - 378}, /* LD20 TV */ + {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 reference */ + {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 TV */ }; -static int dio_dlltrimclk_0[DRAM_BOARD_NR][DRAM_CH_NR] = { + +static const int ddrphy_dlltrimclk[DRAM_BOARD_NR][DRAM_CH_NR] = { {268, 268, 268}, /* LD20 reference */ {268, 268, 268}, /* LD20 TV */ - {268, 268+252, 0}, /* LD21 reference */ - {268, 268+202, 0}, /* LD21 TV */ + {268, 268 + 252, /* No CH2 */}, /* LD21 reference */ + {268, 268 + 202, /* No CH2 */}, /* LD21 TV */ }; -static int dio_dllrecalib_0[DRAM_BOARD_NR][DRAM_CH_NR] = { - {268-378, 268-263, 268-378}, /* LD20 reference */ - {268-378, 268-263, 268-378}, /* LD20 TV */ - {268-212, 268-536, 0}, /* LD21 reference */ - {268-212, 268-536, 0}, /* LD21 TV */ + +static const int ddrphy_dllrecalib[DRAM_BOARD_NR][DRAM_CH_NR] = { + {268 - 378, 268 - 263, 268 - 378}, /* LD20 reference */ + {268 - 378, 268 - 263, 268 - 378}, /* LD20 TV */ + {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 reference */ + {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 TV */ }; -static u32 dio_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = { +static const u32 ddrphy_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = { {0x50B840B1, 0x50B840B1, 0x50B840B1}, /* LD20 reference */ {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV */ - {0x50BB40B4, 0x50B840B1, 0x50BB40B1}, /* LD21 reference */ - {0x50BB40B4, 0x50B840B1, 0x50BB40B1}, /* LD21 TV */ + {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 reference */ + {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 TV */ }; -static u32 dio_scl_gate_timing[DRAM_CH_NR] = {0x00000140, 0x00000180, 0x00000140}; +static const u32 ddrphy_scl_gate_timing[DRAM_CH_NR] = { + 0x00000140, 0x00000180, 0x00000140 +}; -static int dio_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = { +static const int ddrphy_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = { { /* LD20 reference */ { - 2, 1, 0, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 0, 1, 1, 2, 2, 1, + 2, 1, 0, 1, 2, 1, 1, 1, + 2, 1, 1, 2, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 1, 1, + 2, 2, 0, 1, 1, 2, 2, 1, }, { - 1, 1, 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 2, 1, 2, 1, + 1, 1, 0, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 2, 1, 2, 1, }, { - 2, 2, 0, 2, 1, 1, 2, 1, 1, 1, 0, 1, 1, -1, 1, 1, - 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 1, 2, + 2, 2, 0, 2, 1, 1, 2, 1, + 1, 1, 0, 1, 1, -1, 1, 1, + 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 0, 2, 2, 1, 2, }, }, { /* LD20 TV */ { - 2, 1, 0, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 0, 1, 1, 2, 2, 1, + 2, 1, 0, 1, 2, 1, 1, 1, + 2, 1, 1, 2, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 1, 1, + 2, 2, 0, 1, 1, 2, 2, 1, }, { - 1, 1, 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 2, 1, 2, 1, + 1, 1, 0, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 2, 1, 2, 1, }, { - 2, 2, 0, 2, 1, 1, 2, 1, 1, 1, 0, 1, 1, -1, 1, 1, - 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 1, 2, + 2, 2, 0, 2, 1, 1, 2, 1, + 1, 1, 0, 1, 1, -1, 1, 1, + 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 0, 2, 2, 1, 2, }, }, { /* LD21 reference */ { - 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 2, - 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, - }, - { 1, 0, 2, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, - 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 1, 0, 2, + 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 0, 0, 1, }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { 1, 0, 2, 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 0, 0, + 1, 0, 1, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 0, 1, 0, 0, }, + /* No CH2 */ }, { /* LD21 TV */ { - 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 2, - 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, - }, - { 1, 0, 2, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, - 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 1, 0, 2, + 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 0, 0, 1, }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { 1, 0, 2, 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 0, 0, + 1, 0, 1, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 0, 1, 0, 0, }, + /* No CH2 */ }, }; -static int dio_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = { + +static int ddrphy_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = { { /* LD20 reference */ { - 3, 3, 3, 2, 3, 2, 0, 2, 2, 3, 3, 1, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 3, 0, 2, 2, + 3, 3, 3, 2, 3, 2, 0, 2, + 2, 3, 3, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 1, 1, 1, + 2, 2, 2, 2, 3, 0, 2, 2, }, { - 2, 2, 1, 1, -1, 1, 1, 1, 2, 0, 2, 2, 2, 1, 0, 2, - 2, 1, 2, 1, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 1, -1, 1, 1, 1, + 2, 0, 2, 2, 2, 1, 0, 2, + 2, 1, 2, 1, 0, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, }, { - 2, 2, 3, 2, 1, 2, 2, 2, 2, 3, 4, 2, 3, 4, 3, 3, - 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, + 2, 2, 3, 2, 1, 2, 2, 2, + 2, 3, 4, 2, 3, 4, 3, 3, + 2, 2, 1, 2, 1, 1, 1, 1, + 2, 2, 2, 2, 1, 2, 2, 1, }, }, { /* LD20 TV */ { - 3, 3, 3, 2, 3, 2, 0, 2, 2, 3, 3, 1, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 3, 0, 2, 2, + 3, 3, 3, 2, 3, 2, 0, 2, + 2, 3, 3, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 1, 1, 1, + 2, 2, 2, 2, 3, 0, 2, 2, }, { - 2, 2, 1, 1, -1, 1, 1, 1, 2, 0, 2, 2, 2, 1, 0, 2, - 2, 1, 2, 1, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 1, -1, 1, 1, 1, + 2, 0, 2, 2, 2, 1, 0, 2, + 2, 1, 2, 1, 0, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, }, { - 2, 2, 3, 2, 1, 2, 2, 2, 2, 3, 4, 2, 3, 4, 3, 3, - 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, + 2, 2, 3, 2, 1, 2, 2, 2, + 2, 3, 4, 2, 3, 4, 3, 3, + 2, 2, 1, 2, 1, 1, 1, 1, + 2, 2, 2, 2, 1, 2, 2, 1, }, }, { /* LD21 reference */ { - 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, - 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 3, 1, 2, 2, 2, - }, - { - 3, 4, 4, 1, 0, 1, 1, 1, 1, 2, 1, 2, 2, 3, 3, 2, - 1, 0, 2, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, + 2, 2, 2, 2, 1, 2, 2, 2, + 2, 3, 3, 2, 2, 2, 2, 2, + 2, 1, 2, 2, 1, 1, 1, 1, + 2, 2, 2, 3, 1, 2, 2, 2, }, { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 4, 1, 0, 1, 1, 1, + 1, 2, 1, 2, 2, 3, 3, 2, + 1, 0, 2, 1, 1, 0, 1, 0, + 0, 1, 0, 0, 1, 1, 0, 1, }, + /* No CH2 */ }, { /* LD21 TV */ { - 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, - 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 3, 1, 2, 2, 2, - }, - { - 3, 4, 4, 1, 0, 1, 1, 1, 1, 2, 1, 2, 2, 3, 3, 2, - 1, 0, 2, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, + 2, 2, 2, 2, 1, 2, 2, 2, + 2, 3, 3, 2, 2, 2, 2, 2, + 2, 1, 2, 2, 1, 1, 1, 1, + 2, 2, 2, 3, 1, 2, 2, 2, }, { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 4, 1, 0, 1, 1, 1, + 1, 2, 1, 2, 2, 3, 3, 2, + 1, 0, 2, 1, 1, 0, 1, 0, + 0, 1, 0, 0, 1, 1, 0, 1, }, + /* No CH2 */ }, }; -/* umc */ -static u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11}; -static u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC}; -static u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF}; -static u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114}; -static u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0}; - -static u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = { - /* 256MB 512MB */ - {0x00000601, 0x00000801}, /* 1866 MHz */ -}; -static u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = { - /* 256MB 512MB */ - {0x00000120, 0x00000130}, /* 1866 MHz */ -}; -static u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = { - /* 256MB 512MB */ - {0x00033603, 0x00033803}, /* 1866 MHz */ -}; -static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20}; -static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08}; -static u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04}; -static u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = { - /* 256MB 512MB */ - {0x0049071D, 0x0078071D}, /* 1866 MHz */ -}; - -static u32 umc_rdatactl_d0[DRAM_FREQ_NR] = {0x00000610}; -static u32 umc_rdatactl_d1[DRAM_FREQ_NR] = {0x00000610}; -static u32 umc_wdatactl_d0[DRAM_FREQ_NR] = {0x00000204}; -static u32 umc_wdatactl_d1[DRAM_FREQ_NR] = {0x00000204}; -static u32 umc_odtctl_d0[DRAM_FREQ_NR] = {0x02000002}; -static u32 umc_odtctl_d1[DRAM_FREQ_NR] = {0x02000002}; -static u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000}; - -static u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E}; -static u32 umc_directbusctrla[DRAM_CH_NR] = { - 0x00000000, 0x00000001, 0x00000001 -}; - -/* polling function for PHY Init Complete */ -static void ddrphy_init_complete(void __iomem *dc_base) +/* DDR PHY */ +static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane, + unsigned int bit) { - /* Wait for PHY Init Complete */ - while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0))) - cpu_relax(); + WARN_ON(lane >= (1 << PHY_LANE_SEL_LANE_WIDTH)); + WARN_ON(bit >= (1 << PHY_LANE_SEL_BIT_WIDTH)); + + writel((bit << PHY_LANE_SEL_BIT_SHIFT) | + (lane << PHY_LANE_SEL_LANE_SHIFT), + phy_base + PHY_LANE_SEL); } -/* DDR PHY */ -static void ddrphy_init(void __iomem *phy_base, void __iomem *dc_base, - enum dram_freq freq, enum dram_board board, int ch) +static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch) { writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1); while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1))) @@ -352,100 +236,148 @@ static void ddrphy_init(void __iomem *phy_base, void __iomem *dc_base, writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3); writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1); - writel(0x00000000, phy_base + PHY_LANE_SEL); + ddrphy_select_lane(phy_base, 0, 0); writel(0x00000005, phy_base + PHY_DLL_TRIM_1); writel(0x0000000a, phy_base + PHY_DLL_TRIM_3); - writel(0x00000006, phy_base + PHY_LANE_SEL); + ddrphy_select_lane(phy_base, 6, 0); writel(0x00000005, phy_base + PHY_DLL_TRIM_1); writel(0x0000000a, phy_base + PHY_DLL_TRIM_3); - writel(0x0000000c, phy_base + PHY_LANE_SEL); + ddrphy_select_lane(phy_base, 12, 0); writel(0x00000005, phy_base + PHY_DLL_TRIM_1); writel(0x0000000a, phy_base + PHY_DLL_TRIM_3); - writel(0x00000012, phy_base + PHY_LANE_SEL); + ddrphy_select_lane(phy_base, 18, 0); writel(0x00000005, phy_base + PHY_DLL_TRIM_1); writel(0x0000000a, phy_base + PHY_DLL_TRIM_3); writel(0x00000001, phy_base + PHY_SCL_WINDOW_TRIM); writel(0x00000000, phy_base + PHY_UNQ_ANALOG_DLL_1); - writel(dio_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL); + writel(ddrphy_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL); writel(0x00000070, phy_base + PHY_VREF_TRAINING); writel(0x01000075, phy_base + PHY_SCL_CONFIG_1); writel(0x00000501, phy_base + PHY_SCL_CONFIG_2); writel(0x00000000, phy_base + PHY_SCL_CONFIG_3); writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL); writel(0x00000000, phy_base + PHY_SCL_CONFIG_4); - writel(dio_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING); + writel(ddrphy_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING); writel(0x02a000a0, phy_base + PHY_WRLVL_DYN_ODT); writel(0x00840004, phy_base + PHY_WRLVL_ON_OFF); writel(0x0000020d, phy_base + PHY_DLL_ADRCTRL); - writel(0x00000000, phy_base + PHY_LANE_SEL); + ddrphy_select_lane(phy_base, 0, 0); writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK); writel(0xa800100d, phy_base + PHY_DLL_RECALIB); writel(0x00005076, phy_base + PHY_SCL_LATENCY); +} - ddrphy_init_complete(dc_base); +static int ddrphy_to_dly_step(void __iomem *phy_base, unsigned int freq, + int delay) +{ + int mdl; + + mdl = (readl(phy_base + PHY_DLL_ADRCTRL) & PHY_DLL_ADRCTRL_MDL_MASK) >> + PHY_DLL_ADRCTRL_MDL_SHIFT; - ddrphy_set_dll_adrctrl(dio_adrctrl_0[board][ch], 0, phy_base); - ddrphy_set_dll_trim_clk(dio_dlltrimclk_0[board][ch], phy_base); - ddrphy_set_dll_recalib(dio_dllrecalib_0[board][ch], 0x10, 0, 0xa, - phy_base); + return DIV_ROUND_CLOSEST((long)freq * delay * mdl, 2 * 1000000L); } -static void ddrphy_shift_dq(u32 reg_mask, u32 reg_addr, int shift_val, - void __iomem *phy_base) +static void ddrphy_set_delay(void __iomem *phy_base, unsigned int reg, + u32 mask, u32 incr, int dly_step) { - u32 reg_val; - int dq_val; + u32 tmp; - reg_val = ddrphy_maskreadl(reg_mask, phy_base + reg_addr) & 0x7f; - dq_val = reg_val & 0x3f; + tmp = readl(phy_base + reg); + tmp &= ~mask; + tmp |= min_t(u32, abs(dly_step), mask); - if ((reg_val & 0x40) == 0x00) - dq_val = -1 * dq_val; + if (dly_step >= 0) + tmp |= incr; + else + tmp &= ~incr; - /* value shift*/ - dq_val = dq_val + shift_val; + writel(tmp, phy_base + reg); +} - if (dq_val >= 0) - reg_val = 0x40 + (dq_val & 0x3f); - else - reg_val = ((-1 * dq_val) & 0x3f); +static void ddrphy_set_dll_recalib(void __iomem *phy_base, int dly_step) +{ + ddrphy_set_delay(phy_base, PHY_DLL_RECALIB, + PHY_DLL_RECALIB_TRIM_MASK, PHY_DLL_RECALIB_INCR, + dly_step); +} - ddrphy_maskwritel(reg_val, reg_mask, phy_base + reg_addr); +static void ddrphy_set_dll_adrctrl(void __iomem *phy_base, int dly_step) +{ + ddrphy_set_delay(phy_base, PHY_DLL_ADRCTRL, + PHY_DLL_ADRCTRL_TRIM_MASK, PHY_DLL_ADRCTRL_INCR, + dly_step); } -static void ddrphy_shift(void __iomem *phy_base, enum dram_board board, int ch) +static void ddrphy_set_dll_trim_clk(void __iomem *phy_base, int dly_step) { - u32 dx, bit; + ddrphy_select_lane(phy_base, 0, 0); + + ddrphy_set_delay(phy_base, PHY_DLL_TRIM_CLK, + PHY_DLL_TRIM_CLK_MASK, PHY_DLL_TRIM_CLK_INCR, + dly_step); +} - /* set override = 1 */ - ddrphy_maskwritel(MSK_OVERRIDE, MSK_OVERRIDE, - phy_base + PHY_OP_DQ_DM_DQS_BITWISE_TRIM); - ddrphy_maskwritel(MSK_OVERRIDE, MSK_OVERRIDE, - phy_base + PHY_IP_DQ_DQS_BITWISE_TRIM); +static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board, + unsigned int freq, int ch) +{ + int step; - for (dx = 0; dx < 4; dx++) { - /* set byte to PHY_LANE_SEL.phy_lane_sel= dx * (PHY_BITLVL_DLY_WIDTH+1) */ - ddrphy_set_phy_lane_sel(dx * (PHY_BITLVL_DLY_WIDTH + 1), - phy_base); + step = ddrphy_to_dly_step(phy_base, freq, ddrphy_adrctrl[board][ch]); + ddrphy_set_dll_adrctrl(phy_base, step); + step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dlltrimclk[board][ch]); + ddrphy_set_dll_trim_clk(phy_base, step); + + step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dllrecalib[board][ch]); + ddrphy_set_dll_recalib(phy_base, step); +} + +static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg, + u32 mask, u32 incr, int shift_val) +{ + u32 tmp; + int val; + + tmp = readl(phy_base + reg); + + val = tmp & mask; + if (!(tmp & incr)) + val = -val; + + val += shift_val; + + tmp &= ~(incr | mask); + tmp |= min_t(u32, abs(val), mask); + if (val >= 0) + tmp |= incr; + + writel(tmp, phy_base + reg); +} + +static void ddrphy_shift_dq(void __iomem *phy_base, unsigned int reg, + u32 mask, u32 incr, u32 override, + const int *shift_val_array) +{ + u32 tmp; + int dx, bit; + + tmp = readl(phy_base + reg); + tmp |= override; + writel(tmp, phy_base + reg); + + for (dx = 0; dx < 4; dx++) { for (bit = 0; bit < 8; bit++) { - ddrphy_set_bit_sel(bit, phy_base); - - /* shift write reg value*/ - ddrphy_shift_dq(MSK_OP_DQ_DM_DQS_BITWISE_TRIM, - PHY_OP_DQ_DM_DQS_BITWISE_TRIM, - dio_op_dq_shift_val[board][ch][dx * 8 + bit], - phy_base); - /* shift read reg value */ - ddrphy_shift_dq(MSK_IP_DQ_DQS_BITWISE_TRIM, - PHY_IP_DQ_DQS_BITWISE_TRIM, - dio_ip_dq_shift_val[board][ch][dx * 8 + bit], - phy_base); - } + ddrphy_select_lane(phy_base, + (PHY_BITLVL_DLY_WIDTH + 1) * dx, + bit); + ddrphy_shift_one_dq(phy_base, reg, mask, incr, + shift_val_array[dx * 8 + bit]); + } } - ddrphy_set_phy_lane_sel(0, phy_base); - ddrphy_set_bit_sel(0, phy_base); + + ddrphy_select_lane(phy_base, 0, 0); } static int ddrphy_training(void __iomem *phy_base, enum dram_board board, @@ -493,16 +425,90 @@ static int ddrphy_training(void __iomem *phy_base, enum dram_board board, writel(0x00003270, phy_base + PHY_DYNAMIC_BIT_LVL); writel(0x011BD0C4, phy_base + PHY_DSCL_CNT); - /* shift ip_dq, op_dq trim */ - ddrphy_shift(phy_base, board, ch); + /* shift ip_dq trim */ + ddrphy_shift_dq(phy_base, + PHY_IP_DQ_DQS_BITWISE_TRIM, + PHY_IP_DQ_DQS_BITWISE_TRIM_MASK, + PHY_IP_DQ_DQS_BITWISE_TRIM_INC, + PHY_IP_DQ_DQS_BITWISE_TRIM_OVERRIDE, + ddrphy_ip_dq_shift_val[board][ch]); + + /* shift op_dq trim */ + ddrphy_shift_dq(phy_base, + PHY_OP_DQ_DM_DQS_BITWISE_TRIM, + PHY_OP_DQ_DM_DQS_BITWISE_TRIM_MASK, + PHY_OP_DQ_DM_DQS_BITWISE_TRIM_INC, + PHY_OP_DQ_DM_DQS_BITWISE_TRIM_OVERRIDE, + ddrphy_op_dq_shift_val[board][ch]); + return 0; } -static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq, +/* UMC */ +static u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11}; +static u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC}; +static u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF}; +static u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114}; +static u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0}; + +static u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = { + /* 256MB 512MB */ + {0x00000601, 0x00000801}, /* 1866 MHz */ +}; + +static u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = { + /* 256MB 512MB */ + {0x00000120, 0x00000130}, /* 1866 MHz */ +}; + +static u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = { + /* 256MB 512MB */ + {0x00033603, 0x00033803}, /* 1866 MHz */ +}; + +static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20}; +static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08}; +static u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04}; +static u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = { + /* 256MB 512MB */ + {0x0049071D, 0x0078071D}, /* 1866 MHz */ +}; + +static u32 umc_rdatactl_d0[DRAM_FREQ_NR] = {0x00000610}; +static u32 umc_rdatactl_d1[DRAM_FREQ_NR] = {0x00000610}; +static u32 umc_wdatactl_d0[DRAM_FREQ_NR] = {0x00000204}; +static u32 umc_wdatactl_d1[DRAM_FREQ_NR] = {0x00000204}; +static u32 umc_odtctl_d0[DRAM_FREQ_NR] = {0x02000002}; +static u32 umc_odtctl_d1[DRAM_FREQ_NR] = {0x02000002}; +static u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000}; + +static u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E}; +static u32 umc_directbusctrla[DRAM_CH_NR] = { + 0x00000000, 0x00000001, 0x00000001 +}; + +static void umc_poll_phy_init_complete(void __iomem *dc_base) +{ + /* Wait for PHY Init Complete */ + while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0))) + cpu_relax(); +} + +static int umc_dc_init(void __iomem *dc_base, unsigned int freq, unsigned long size, int ch) { + enum dram_freq freq_e; enum dram_size size_e; + switch (freq) { + case 1866: + freq_e = DRAM_FREQ_1866M; + break; + default: + pr_err("unsupported DRAM frequency %ud MHz\n", freq); + return -EINVAL; + } + switch (size) { case 0: return 0; @@ -521,40 +527,40 @@ static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq, writel(0x00000001, dc_base + UMC_DFICSOVRRD); writel(0x00000000, dc_base + UMC_DFITURNOFF); - writel(umc_initctla[freq], dc_base + UMC_INITCTLA); - writel(umc_initctlb[freq], dc_base + UMC_INITCTLB); - writel(umc_initctlc[freq], dc_base + UMC_INITCTLC); + writel(umc_initctla[freq_e], dc_base + UMC_INITCTLA); + writel(umc_initctlb[freq_e], dc_base + UMC_INITCTLB); + writel(umc_initctlc[freq_e], dc_base + UMC_INITCTLC); - writel(umc_drmmr0[freq], dc_base + UMC_DRMMR0); + writel(umc_drmmr0[freq_e], dc_base + UMC_DRMMR0); writel(0x00000004, dc_base + UMC_DRMMR1); - writel(umc_drmmr2[freq], dc_base + UMC_DRMMR2); + writel(umc_drmmr2[freq_e], dc_base + UMC_DRMMR2); writel(0x00000000, dc_base + UMC_DRMMR3); - writel(umc_memconf0a[freq][size_e], dc_base + UMC_MEMCONF0A); - writel(umc_memconf0b[freq][size_e], dc_base + UMC_MEMCONF0B); - writel(umc_memconfch[freq][size_e], dc_base + UMC_MEMCONFCH); + writel(umc_memconf0a[freq_e][size_e], dc_base + UMC_MEMCONF0A); + writel(umc_memconf0b[freq_e][size_e], dc_base + UMC_MEMCONF0B); + writel(umc_memconfch[freq_e][size_e], dc_base + UMC_MEMCONFCH); writel(0x00000008, dc_base + UMC_MEMMAPSET); - writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA); - writel(umc_cmdctlb[freq], dc_base + UMC_CMDCTLB); - writel(umc_cmdctlc[freq], dc_base + UMC_CMDCTLC); - writel(umc_cmdctle[freq][size_e], dc_base + UMC_CMDCTLE); + writel(umc_cmdctla[freq_e], dc_base + UMC_CMDCTLA); + writel(umc_cmdctlb[freq_e], dc_base + UMC_CMDCTLB); + writel(umc_cmdctlc[freq_e], dc_base + UMC_CMDCTLC); + writel(umc_cmdctle[freq_e][size_e], dc_base + UMC_CMDCTLE); - writel(umc_rdatactl_d0[freq], dc_base + UMC_RDATACTL_D0); - writel(umc_rdatactl_d1[freq], dc_base + UMC_RDATACTL_D1); + writel(umc_rdatactl_d0[freq_e], dc_base + UMC_RDATACTL_D0); + writel(umc_rdatactl_d1[freq_e], dc_base + UMC_RDATACTL_D1); - writel(umc_wdatactl_d0[freq], dc_base + UMC_WDATACTL_D0); - writel(umc_wdatactl_d1[freq], dc_base + UMC_WDATACTL_D1); - writel(umc_odtctl_d0[freq], dc_base + UMC_ODTCTL_D0); - writel(umc_odtctl_d1[freq], dc_base + UMC_ODTCTL_D1); - writel(umc_dataset[freq], dc_base + UMC_DATASET); + writel(umc_wdatactl_d0[freq_e], dc_base + UMC_WDATACTL_D0); + writel(umc_wdatactl_d1[freq_e], dc_base + UMC_WDATACTL_D1); + writel(umc_odtctl_d0[freq_e], dc_base + UMC_ODTCTL_D0); + writel(umc_odtctl_d1[freq_e], dc_base + UMC_ODTCTL_D1); + writel(umc_dataset[freq_e], dc_base + UMC_DATASET); writel(0x00400020, dc_base + UMC_DCCGCTL); writel(0x00000003, dc_base + UMC_ACSSETA); writel(0x00000103, dc_base + UMC_FLOWCTLG); writel(0x00010200, dc_base + UMC_ACSSETB); - writel(umc_flowctla[freq], dc_base + UMC_FLOWCTLA); + writel(umc_flowctla[freq_e], dc_base + UMC_FLOWCTLA); writel(0x00004444, dc_base + UMC_FLOWCTLC); writel(0x00000000, dc_base + UMC_DFICUPDCTLA); @@ -577,7 +583,7 @@ static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq, } static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base, - enum dram_freq freq, enum dram_board board, + enum dram_board board, unsigned int freq, unsigned long size, int ch) { void __iomem *dc_base = umc_ch_base + 0x00011000; @@ -591,7 +597,11 @@ static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base, writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST, dc_base + UMC_DIOCTLA); - ddrphy_init(phy_base, dc_base, freq, board, ch); + ddrphy_init(phy_base, board, ch); + + umc_poll_phy_init_complete(dc_base); + + ddrphy_init_tail(phy_base, board, freq, ch); ret = umc_dc_init(dc_base, freq, size, ch); if (ret) @@ -624,19 +634,9 @@ int uniphier_ld20_umc_init(const struct uniphier_board_data *bd) void __iomem *um_base = (void __iomem *)0x5b600000; void __iomem *umc_ch_base = (void __iomem *)0x5b800000; void __iomem *phy_ch_base = (void __iomem *)0x6e200000; - enum dram_freq freq; enum dram_board board; int ch, ret; - switch (bd->dram_freq) { - case 1866: - freq = DRAM_FREQ_1866M; - break; - default: - pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq); - return -EINVAL; - } - switch (UNIPHIER_BD_BOARD_GET_TYPE(bd->flags)) { case UNIPHIER_BD_BOARD_LD20_REF: board = DRAM_BOARD_LD20_REF; @@ -660,8 +660,8 @@ int uniphier_ld20_umc_init(const struct uniphier_board_data *bd) unsigned long size = bd->dram_ch[ch].size; unsigned int width = bd->dram_ch[ch].width; - ret = umc_ch_init(umc_ch_base, phy_ch_base, freq, board, - size / (width / 16), ch); + ret = umc_ch_init(umc_ch_base, phy_ch_base, board, + bd->dram_freq, size / (width / 16), ch); if (ret) { pr_err("failed to initialize UMC ch%d\n", ch); return ret; -- cgit v1.1 From baaafaaad3d53706e3d02aa4e0bba75f535ebd18 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:25 +0900 Subject: ARM: uniphier: add work-around for VBO noise problem Raise the VDD09 voltage line to 1.0V to suppress VBO noise. This errata work-around code is needed only for ES1. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/board_init.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-uniphier/board_init.c b/arch/arm/mach-uniphier/board_init.c index b9be52f..8c7864c 100644 --- a/arch/arm/mach-uniphier/board_init.c +++ b/arch/arm/mach-uniphier/board_init.c @@ -134,6 +134,13 @@ int board_init(void) #endif #if defined(CONFIG_ARCH_UNIPHIER_LD20) case SOC_UNIPHIER_LD20: + /* ES1 errata: increase VDD09 supply to suppress VBO noise */ + if (uniphier_get_soc_revision() == 1) { + writel(0x00000003, 0x6184e004); + writel(0x00000100, 0x6184e040); + writel(0x0000b500, 0x6184e024); + writel(0x00000001, 0x6184e000); + } uniphier_nand_pin_init(false); sg_set_pinsel(149, 14, 8, 4); /* XIRQ0 -> XIRQ0 */ sg_set_iectrl(149); -- cgit v1.1 From 66deb91ec0113d545ece62130e0823a74edc10e6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:26 +0900 Subject: ARM: uniphier: fix typos in a comment block Signed-off-by: Masahiro Yamada --- include/configs/uniphier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index 29be00a..bb873a4 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -54,7 +54,7 @@ #define CONFIG_SYS_FLASH_BASE 0 /* - * flash_toggle does not work for out supoort card. + * flash_toggle does not work for our support card. * We need to use flash_status_poll. */ #define CONFIG_SYS_CFI_FLASH_STATUS_POLL -- cgit v1.1 From f4c93a4f4d73a838954a2b546799fb18e48eab56 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:27 +0900 Subject: ARM: uniphier: enable CONFIG_SYS_NO_FLASH if no CONFIG_MICRO_SUPPORT_CARD NOR flash devices are seldom used on UniPhier platforms these days. The only use case I see is the Micro Support Card is connected. Otherwise, define CONFIG_SYS_NO_FLASH to disable NOR FLASH. Signed-off-by: Masahiro Yamada --- include/configs/uniphier.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index bb873a4..2cd7dce 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -40,10 +40,9 @@ /* FLASH related */ #define CONFIG_MTD_DEVICE -/* - * uncomment the following to disable FLASH related code. - */ -/* #define CONFIG_SYS_NO_FLASH */ +#ifndef CONFIG_MICRO_SUPPORT_CARD +#define CONFIG_SYS_NO_FLASH +#endif #define CONFIG_FLASH_CFI_DRIVER #define CONFIG_SYS_FLASH_CFI -- cgit v1.1 From f1d9a9edb94989a1dd6cb4e2e3ce626bc08b5d96 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:28 +0900 Subject: ARM: uniphier: define CONFIG_SMC911X along with CONFIG_MICRO_SUPPORT_CARD This is an on-board Ethernet device. It has no point if the Micro Support Card is not available. Signed-off-by: Masahiro Yamada --- include/configs/uniphier.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index 2cd7dce..3b78eff 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -15,12 +15,6 @@ #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10 -#define CONFIG_SMC911X - -/* dummy: referenced by examples/standalone/smc911x_eeprom.c */ -#define CONFIG_SMC911X_BASE 0 -#define CONFIG_SMC911X_32_BIT - /*----------------------------------------------------------------------- * MMU and Cache Setting *----------------------------------------------------------------------*/ @@ -40,7 +34,13 @@ /* FLASH related */ #define CONFIG_MTD_DEVICE -#ifndef CONFIG_MICRO_SUPPORT_CARD +#define CONFIG_SMC911X_32_BIT +/* dummy: referenced by examples/standalone/smc911x_eeprom.c */ +#define CONFIG_SMC911X_BASE 0 + +#ifdef CONFIG_MICRO_SUPPORT_CARD +#define CONFIG_SMC911X +#else #define CONFIG_SYS_NO_FLASH #endif -- cgit v1.1 From 66e3efebbcfe2627154d81d6a3c172b337396daf Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:29 +0900 Subject: ARM: uniphier: insert udelay() just before support_card_reset_deassert() As for LD11/LD20, we can no longer rely on the udelay() in the PLL init functions. udelay(200) is needed here to keep the ethernet device in the reset state for enough time. Anyway, 200 usec is quite short for humans, so nobody cares it. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/micro-support-card.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-uniphier/micro-support-card.c b/arch/arm/mach-uniphier/micro-support-card.c index 04e6558..e53bcdf 100644 --- a/arch/arm/mach-uniphier/micro-support-card.c +++ b/arch/arm/mach-uniphier/micro-support-card.c @@ -60,9 +60,8 @@ void support_card_init(void) /* * After power on, we need to keep the LAN controller in reset state * for a while. (200 usec) - * Fortunately, enough wait time is already inserted in pll_init() - * function. So we do not have to wait here. */ + udelay(200); support_card_reset_deassert(); } -- cgit v1.1 From d9f5d99245a32d95ae6aeb89a4ed258f7d1cea97 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:30 +0900 Subject: reset: declare fdtdec_phandle_args as struct to fix warning The of_xlate() callback needs to know fdtdec_phandle_args is struct. Otherwise, the following warning is displayed. include/reset-uclass.h:40:11: warning: 'struct fdtdec_phandle_args' declared inside parameter list struct fdtdec_phandle_args *args); ^ include/reset-uclass.h:40:11: warning: its scope is only this definition or declaration, which is probably not what you want Signed-off-by: Masahiro Yamada --- include/reset-uclass.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/reset-uclass.h b/include/reset-uclass.h index 50adeca..38c716ff 100644 --- a/include/reset-uclass.h +++ b/include/reset-uclass.h @@ -11,6 +11,7 @@ #include +struct fdtdec_phandle_args; struct udevice; /** -- cgit v1.1 From 4fb96c48c183128c00b21c7858bb05897a1b80de Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 8 Oct 2016 13:25:31 +0900 Subject: reset: uniphier: add reset controller driver for UniPhier SoCs This is the initial commit for UniPhier reset controller driver. Most code was ported from Linux. Signed-off-by: Masahiro Yamada --- arch/arm/Kconfig | 1 + drivers/reset/Kconfig | 9 + drivers/reset/Makefile | 1 + drivers/reset/reset-uniphier.c | 376 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 387 insertions(+) create mode 100644 drivers/reset/reset-uniphier.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2d3303b..b64f6d8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -817,6 +817,7 @@ config ARCH_UNIPHIER select DM_GPIO select DM_I2C select DM_MMC + select DM_RESET select DM_SERIAL select DM_USB select OF_CONTROL diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 4fcc0d9..c42b0bc 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -34,4 +34,13 @@ config TEGRA186_RESET Enable support for manipulating Tegra's on-SoC reset signals via IPC requests to the BPMP (Boot and Power Management Processor). +config RESET_UNIPHIER + bool "Reset controller driver for UniPhier SoCs" + depends on ARCH_UNIPHIER + default y + help + Support for reset controllers on UniPhier SoCs. + Say Y if you want to control reset signals provided by System Control + block, Media I/O block, Peripheral Block. + endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 5d4ea3d..5c4305c 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o +obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c new file mode 100644 index 0000000..29c4d4d --- /dev/null +++ b/drivers/reset/reset-uniphier.c @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +struct uniphier_reset_data { + unsigned int id; + unsigned int reg; + unsigned int bit; + unsigned int flags; +#define UNIPHIER_RESET_ACTIVE_LOW BIT(0) +}; + +#define UNIPHIER_RESET_ID_END (unsigned int)(-1) + +#define UNIPHIER_RESET_END \ + { .id = UNIPHIER_RESET_ID_END } + +#define UNIPHIER_RESET(_id, _reg, _bit) \ + { \ + .id = (_id), \ + .reg = (_reg), \ + .bit = (_bit), \ + } + +#define UNIPHIER_RESETX(_id, _reg, _bit) \ + { \ + .id = (_id), \ + .reg = (_reg), \ + .bit = (_bit), \ + .flags = UNIPHIER_RESET_ACTIVE_LOW, \ + } + +/* System reset data */ +#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \ + UNIPHIER_RESETX((id), 0x2000, 10) + +#define UNIPHIER_LD11_SYS_RESET_STDMAC(id) \ + UNIPHIER_RESETX((id), 0x200c, 8) + +#define UNIPHIER_PRO4_SYS_RESET_GIO(id) \ + UNIPHIER_RESETX((id), 0x2000, 6) + +#define UNIPHIER_LD20_SYS_RESET_GIO(id) \ + UNIPHIER_RESETX((id), 0x200c, 5) + +#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \ + UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17) + +const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */ + UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */ + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */ + UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */ + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */ + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */ + UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */ + UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */ + UNIPHIER_RESETX(20, 0x2014, 5), /* USB31-PHY0 */ + UNIPHIER_RESETX(21, 0x2014, 1), /* USB31-PHY1 */ + UNIPHIER_RESETX(28, 0x2014, 12), /* SATA */ + UNIPHIER_RESET(29, 0x2014, 8), /* SATA-PHY (active high) */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */ + UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */ + UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */ + UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */ + UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */ + UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */ + UNIPHIER_RESET_END, +}; + +/* Media I/O reset data */ +#define UNIPHIER_MIO_RESET_SD(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26) + +#define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch) \ + UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_USB2(id, ch) \ + UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24) + +#define UNIPHIER_MIO_RESET_DMAC(id) \ + UNIPHIER_RESETX((id), 0x110, 17) + +const struct uniphier_reset_data uniphier_mio_reset_data[] = { + UNIPHIER_MIO_RESET_SD(0, 0), + UNIPHIER_MIO_RESET_SD(1, 1), + UNIPHIER_MIO_RESET_SD(2, 2), + UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0), + UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1), + UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2), + UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), + UNIPHIER_MIO_RESET_DMAC(7), + UNIPHIER_MIO_RESET_USB2(8, 0), + UNIPHIER_MIO_RESET_USB2(9, 1), + UNIPHIER_MIO_RESET_USB2(10, 2), + UNIPHIER_MIO_RESET_USB2(11, 3), + UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0), + UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1), + UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2), + UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3), + UNIPHIER_RESET_END, +}; + +/* Peripheral reset data */ +#define UNIPHIER_PERI_RESET_UART(id, ch) \ + UNIPHIER_RESETX((id), 0x114, 19 + (ch)) + +#define UNIPHIER_PERI_RESET_I2C(id, ch) \ + UNIPHIER_RESETX((id), 0x114, 5 + (ch)) + +#define UNIPHIER_PERI_RESET_FI2C(id, ch) \ + UNIPHIER_RESETX((id), 0x114, 24 + (ch)) + +const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = { + UNIPHIER_PERI_RESET_UART(0, 0), + UNIPHIER_PERI_RESET_UART(1, 1), + UNIPHIER_PERI_RESET_UART(2, 2), + UNIPHIER_PERI_RESET_UART(3, 3), + UNIPHIER_PERI_RESET_I2C(4, 0), + UNIPHIER_PERI_RESET_I2C(5, 1), + UNIPHIER_PERI_RESET_I2C(6, 2), + UNIPHIER_PERI_RESET_I2C(7, 3), + UNIPHIER_PERI_RESET_I2C(8, 4), + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { + UNIPHIER_PERI_RESET_UART(0, 0), + UNIPHIER_PERI_RESET_UART(1, 1), + UNIPHIER_PERI_RESET_UART(2, 2), + UNIPHIER_PERI_RESET_UART(3, 3), + UNIPHIER_PERI_RESET_FI2C(4, 0), + UNIPHIER_PERI_RESET_FI2C(5, 1), + UNIPHIER_PERI_RESET_FI2C(6, 2), + UNIPHIER_PERI_RESET_FI2C(7, 3), + UNIPHIER_PERI_RESET_FI2C(8, 4), + UNIPHIER_PERI_RESET_FI2C(9, 5), + UNIPHIER_PERI_RESET_FI2C(10, 6), + UNIPHIER_RESET_END, +}; + +/* core implementaton */ +struct uniphier_reset_priv { + void __iomem *base; + const struct uniphier_reset_data *data; +}; + +static int uniphier_reset_request(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int uniphier_reset_free(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert) +{ + struct uniphier_reset_priv *priv = dev_get_priv(reset_ctl->dev); + unsigned long id = reset_ctl->id; + const struct uniphier_reset_data *p; + + for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) { + u32 mask, val; + + if (p->id != id) + continue; + + val = readl(priv->base + p->reg); + + if (p->flags & UNIPHIER_RESET_ACTIVE_LOW) + assert = !assert; + + mask = BIT(p->bit); + + if (assert) + val |= mask; + else + val &= ~mask; + + writel(val, priv->base + p->reg); + + return 0; + } + + dev_err(priv->dev, "reset_id=%lu was not handled\n", id); + return -EINVAL; +} + +static int uniphier_reset_assert(struct reset_ctl *reset_ctl) +{ + return uniphier_reset_update(reset_ctl, 1); +} + +static int uniphier_reset_deassert(struct reset_ctl *reset_ctl) +{ + return uniphier_reset_update(reset_ctl, 0); +} + +static const struct reset_ops uniphier_reset_ops = { + .request = uniphier_reset_request, + .free = uniphier_reset_free, + .rst_assert = uniphier_reset_assert, + .rst_deassert = uniphier_reset_deassert, +}; + +static int uniphier_reset_probe(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_get_addr(dev->parent); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = devm_ioremap(dev, addr, SZ_4K); + if (!priv->base) + return -ENOMEM; + + priv->data = (void *)dev_get_driver_data(dev); + + return 0; +} + +static const struct udevice_id uniphier_reset_match[] = { + /* System reset */ + { + .compatible = "socionext,uniphier-sld3-reset", + .data = (ulong)uniphier_sld3_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-ld4-reset", + .data = (ulong)uniphier_sld3_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-pro4-reset", + .data = (ulong)uniphier_pro4_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-sld8-reset", + .data = (ulong)uniphier_sld3_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-reset", + .data = (ulong)uniphier_pro5_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-reset", + .data = (ulong)uniphier_pxs2_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-ld11-reset", + .data = (ulong)uniphier_ld11_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-reset", + .data = (ulong)uniphier_ld20_sys_reset_data, + }, + /* Media I/O reset */ + { + .compatible = "socionext,uniphier-sld3-mio-clock", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-ld4-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-pro4-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-sld8-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-ld11-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + /* Peripheral reset */ + { + .compatible = "socionext,uniphier-ld4-peri-reset", + .data = (ulong)uniphier_ld4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-pro4-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-sld8-peri-reset", + .data = (ulong)uniphier_ld4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-ld11-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(uniphier_reset) = { + .name = "uniphier-reset", + .id = UCLASS_RESET, + .of_match = uniphier_reset_match, + .probe = uniphier_reset_probe, + .priv_auto_alloc_size = sizeof(struct uniphier_reset_priv), + .ops = &uniphier_reset_ops, +}; -- cgit v1.1