Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
Hi Paul, On 04/11/2012 07:44 PM, Paul Walmsley wrote: Cc Mark Greer, Mark Salter Hi Greg, Aneesh, On Sat, 17 Mar 2012, Aneesh V wrote: Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. Just checking to see what the current state of this series is. Greg, are you considering this for merging, or are there remaining issues? Aneesh, do you have any remaining issues to resolve with this set? No. I don't have anything remaining. It's just that I was on vacation for a while and couldn't find time for this after that. If Greg is fine with this, I can rebase it and send one final version with Reviewed-By's from Santosh and Benoit. thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] misc: ddr: add LPDDR2 data from JESD209-2
add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v3: - Converted EXPORT_SYMBOL to EXPORT_SYMBOL_GPL - Removed un-necessary newline v1: - Moved to /lib from /drivers/misc - Corrected Copyright year --- include/misc/jedec_ddr.h | 177 ++ lib/Kconfig |8 ++ lib/Makefile |2 + lib/jedec_ddr_data.c | 135 +++ 4 files changed, 322 insertions(+), 0 deletions(-) create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c diff --git a/include/misc/jedec_ddr.h b/include/misc/jedec_ddr.h new file mode 100644 index 000..93ffd4a --- /dev/null +++ b/include/misc/jedec_ddr.h @@ -0,0 +1,177 @@ +/* + * Definitions for DDR memories based on JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh V ane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __LINUX_JEDEC_DDR_H +#define __LINUX_JEDEC_DDR_H + +#ifndef __ASSEMBLY__ +#include linux/types.h + +/* DDR Densities */ +#define DDR_DENSITY_64Mb 1 +#define DDR_DENSITY_128Mb 2 +#define DDR_DENSITY_256Mb 3 +#define DDR_DENSITY_512Mb 4 +#define DDR_DENSITY_1Gb5 +#define DDR_DENSITY_2Gb6 +#define DDR_DENSITY_4Gb7 +#define DDR_DENSITY_8Gb8 +#define DDR_DENSITY_16Gb 9 +#define DDR_DENSITY_32Gb 10 + +/* DDR type */ +#define DDR_TYPE_DDR2 1 +#define DDR_TYPE_DDR3 2 +#define DDR_TYPE_LPDDR2_S4 3 +#define DDR_TYPE_LPDDR2_S2 4 +#define DDR_TYPE_LPDDR2_NVM5 + +/* DDR IO width */ +#define DDR_IO_WIDTH_4 1 +#define DDR_IO_WIDTH_8 2 +#define DDR_IO_WIDTH_163 +#define DDR_IO_WIDTH_324 + +/* Number of Row bits */ +#define R9 9 +#define R1010 +#define R1111 +#define R1212 +#define R1313 +#define R1414 +#define R1515 +#define R1616 + +/* Number of Column bits */ +#define C7 7 +#define C8 8 +#define C9 9 +#define C1010 +#define C1111 +#define C1212 + +/* Number of Banks */ +#define B1 0 +#define B2 1 +#define B4 2 +#define B8 3 + +/* Refresh rate in nano-seconds */ +#define T_REFI_15_615600 +#define T_REFI_7_8 7800 +#define T_REFI_3_9 3900 + +/* tRFC values */ +#define T_RFC_90 9 +#define T_RFC_110 11 +#define T_RFC_130 13 +#define T_RFC_160 16 +#define T_RFC_210 21 +#define T_RFC_300 30 +#define T_RFC_350 35 + +/* Mode register numbers */ +#define DDR_MR00 +#define DDR_MR11 +#define DDR_MR22 +#define DDR_MR33 +#define DDR_MR44 +#define DDR_MR55 +#define DDR_MR66 +#define DDR_MR77 +#define DDR_MR88 +#define DDR_MR99 +#define DDR_MR10 10 +#define DDR_MR11 11 +#define DDR_MR16 16 +#define DDR_MR17 17 +#define DDR_MR18 18 + +/* + * LPDDR2 related defines + */ + +/* MR4 register fields */ +#define MR4_SDRAM_REF_RATE_SHIFT 0 +#define MR4_SDRAM_REF_RATE_MASK7 +#define MR4_TUF_SHIFT 7 +#define MR4_TUF_MASK (1 7) + +/* MR4 SDRAM Refresh Rate field values */ +#define SDRAM_TEMP_NOMINAL 0x3 +#define SDRAM_TEMP_RESERVED_4 0x4 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 +#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 + +#define NUM_DDR_ADDR_TABLE_ENTRIES 11 +#define NUM_DDR_TIMING_TABLE_ENTRIES 4 + +/* Structure for DDR addressing info from the JEDEC spec */ +struct lpddr2_addressing { + u32 num_banks; + u32 tREFI_ns; + u32 tRFCab_ps; +}; + +/* + * Structure for timings from the LPDDR2 datasheet + * All parameters are in pico
[PATCH v4] misc: ddr: add LPDDR2 data from JESD209-2
add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers. Right now this is used by the TI EMIF SDRAM controller driver. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v4: - Removed 'ifndef __ASSEMBLY__' from jedec_ddr.h - Updated commit log to be more specific on where this patch is used currently v3: - Converted EXPORT_SYMBOL to EXPORT_SYMBOL_GPL - Removed un-necessary newline v1: - Moved to /lib from /drivers/misc - Corrected Copyright year --- include/misc/jedec_ddr.h | 175 ++ lib/Kconfig |8 ++ lib/Makefile |2 + lib/jedec_ddr_data.c | 135 +++ 4 files changed, 320 insertions(+), 0 deletions(-) create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c diff --git a/include/misc/jedec_ddr.h b/include/misc/jedec_ddr.h new file mode 100644 index 000..ddad0f8 --- /dev/null +++ b/include/misc/jedec_ddr.h @@ -0,0 +1,175 @@ +/* + * Definitions for DDR memories based on JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh V ane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __LINUX_JEDEC_DDR_H +#define __LINUX_JEDEC_DDR_H + +#include linux/types.h + +/* DDR Densities */ +#define DDR_DENSITY_64Mb 1 +#define DDR_DENSITY_128Mb 2 +#define DDR_DENSITY_256Mb 3 +#define DDR_DENSITY_512Mb 4 +#define DDR_DENSITY_1Gb5 +#define DDR_DENSITY_2Gb6 +#define DDR_DENSITY_4Gb7 +#define DDR_DENSITY_8Gb8 +#define DDR_DENSITY_16Gb 9 +#define DDR_DENSITY_32Gb 10 + +/* DDR type */ +#define DDR_TYPE_DDR2 1 +#define DDR_TYPE_DDR3 2 +#define DDR_TYPE_LPDDR2_S4 3 +#define DDR_TYPE_LPDDR2_S2 4 +#define DDR_TYPE_LPDDR2_NVM5 + +/* DDR IO width */ +#define DDR_IO_WIDTH_4 1 +#define DDR_IO_WIDTH_8 2 +#define DDR_IO_WIDTH_163 +#define DDR_IO_WIDTH_324 + +/* Number of Row bits */ +#define R9 9 +#define R1010 +#define R1111 +#define R1212 +#define R1313 +#define R1414 +#define R1515 +#define R1616 + +/* Number of Column bits */ +#define C7 7 +#define C8 8 +#define C9 9 +#define C1010 +#define C1111 +#define C1212 + +/* Number of Banks */ +#define B1 0 +#define B2 1 +#define B4 2 +#define B8 3 + +/* Refresh rate in nano-seconds */ +#define T_REFI_15_615600 +#define T_REFI_7_8 7800 +#define T_REFI_3_9 3900 + +/* tRFC values */ +#define T_RFC_90 9 +#define T_RFC_110 11 +#define T_RFC_130 13 +#define T_RFC_160 16 +#define T_RFC_210 21 +#define T_RFC_300 30 +#define T_RFC_350 35 + +/* Mode register numbers */ +#define DDR_MR00 +#define DDR_MR11 +#define DDR_MR22 +#define DDR_MR33 +#define DDR_MR44 +#define DDR_MR55 +#define DDR_MR66 +#define DDR_MR77 +#define DDR_MR88 +#define DDR_MR99 +#define DDR_MR10 10 +#define DDR_MR11 11 +#define DDR_MR16 16 +#define DDR_MR17 17 +#define DDR_MR18 18 + +/* + * LPDDR2 related defines + */ + +/* MR4 register fields */ +#define MR4_SDRAM_REF_RATE_SHIFT 0 +#define MR4_SDRAM_REF_RATE_MASK7 +#define MR4_TUF_SHIFT 7 +#define MR4_TUF_MASK (1 7) + +/* MR4 SDRAM Refresh Rate field values */ +#define SDRAM_TEMP_NOMINAL 0x3 +#define SDRAM_TEMP_RESERVED_4 0x4 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 +#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 + +#define NUM_DDR_ADDR_TABLE_ENTRIES 11 +#define NUM_DDR_TIMING_TABLE_ENTRIES 4 + +/* Structure for DDR addressing info from the JEDEC spec */ +struct
Re: [PATCH v2 1/7] misc: ddr: add LPDDR2 data from JESD209-2
Hi Greg, On Friday 16 March 2012 12:32 AM, Greg KH wrote: On Thu, Mar 15, 2012 at 11:47:31PM +0530, Aneesh V wrote: add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers Right now, only one driver, right? +#ifndef __ASSEMBLY__ Why is this needed? +/* Structure for DDR addressing info from the JEDEC spec */ +struct lpddr2_addressing { + u32 num_banks; + u32 tREFI_ns; + u32 tRFCab_ps; +}; Do these structures cross the user/kernel boundry somehow? If so, please use the proper kernel types for this. --- a/lib/Makefile +++ b/lib/Makefile @@ -123,6 +123,9 @@ obj-$(CONFIG_SIGNATURE) += digsig.o obj-$(CONFIG_CLZ_TAB) += clz_tab.o +obj-$(CONFIG_DDR) += jedec_ddr_data.o + + Why the extra line? hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/jedec_ddr_data.c b/lib/jedec_ddr_data.c new file mode 100644 index 000..fc223d6 --- /dev/null +++ b/lib/jedec_ddr_data.c @@ -0,0 +1,135 @@ +/* + * DDR addressing details and AC timing parameters from JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh Vane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#includemisc/jedec_ddr.h +#includelinux/module.h + +/* LPDDR2 addressing details from JESD209-2 section 2.4 */ +const struct lpddr2_addressing + lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES] = { + {B4, T_REFI_15_6, T_RFC_90}, /* 64M */ + {B4, T_REFI_15_6, T_RFC_90}, /* 128M */ + {B4, T_REFI_7_8, T_RFC_90}, /* 256M */ + {B4, T_REFI_7_8, T_RFC_90}, /* 512M */ + {B8, T_REFI_7_8, T_RFC_130}, /* 1GS4 */ + {B8, T_REFI_3_9, T_RFC_130}, /* 2GS4 */ + {B8, T_REFI_3_9, T_RFC_130}, /* 4G */ + {B8, T_REFI_3_9, T_RFC_210}, /* 8G */ + {B4, T_REFI_7_8, T_RFC_130}, /* 1GS2 */ + {B4, T_REFI_3_9, T_RFC_130}, /* 2GS2 */ +}; +EXPORT_SYMBOL(lpddr2_jedec_addressing_table); EXPORT_SYMBOL_GPL for these and the others? I have fixed these comments and pushed my latest patches at: git://github.com/aneeshv/linux.git branch: emif-upstream-v4 thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4] misc: ddr: add LPDDR2 data from JESD209-2
On Saturday 17 March 2012 03:13 AM, Greg KH wrote: On Sat, Mar 17, 2012 at 02:20:07AM +0530, Aneesh V wrote: add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers. Right now this is used by the TI EMIF SDRAM controller driver. Cc: Greg KHg...@kroah.com Signed-off-by: Aneesh Vane...@ti.com What happened to the other patches that depended on this one? I was not sure what was the convention regarding re-submitting just one patch in a series. I realize that you prefer having the whole series again. I will send it shortly. thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 0/7] Add TI EMIF SDRAM controller driver
Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. The driver supports the following features: - Calculates the DDR AC timing parameters to be set in EMIF registers using data from the device data-sheets and based on the DDR frequency. If data from data-sheets is not available default timing values from the JEDEC spec are used. These will be safe, but not necessarily optimal - API for changing timings during DVFS or at boot-up - Temperature alert configuration and handling of temperature alerts, if any for LPDDR2 devices * temperature alert is based on periodic polling of MR4 mode register in DDR devices automatically performed by hardware * timings are de-rated and brought back to nominal when temperature raises and falls respectively - Cache of calculated register values to avoid re-calculating them The driver will need some minor updates when it is eventually integrated with Dynamic Voltage and Frequency Scaling (DVFS). This can not be done now as DVFS support is not available in the mainline yet. Discussions with Santosh Shilimkar santosh.shilim...@ti.com were immensely helpful in shaping up the interfaces. Vibhore Vardhan vvard...@gmail.com did the initial code snippet for thermal handling. Testing: - The driver is tested on OMAP4430 SDP. - The driver in a slightly adapted form is also tested on OMAP5. - Since mainline kernel doesn't have DVFS support yet, testing was done using a test module. - Temperature alert handling was tested with simulated interrupts and faked temperature values as testing all cases in real-life scenarios is difficult. - Tested the driver as a module Cc: Greg KH g...@kroah.com v4: - Converted instances of EXPORT_SYMBOL to EXPORT_SYMBOL_GPL - Removed un-necessary #ifndef __ASSEMBLY__' - Minor formatting fix v2: - Fixed a bug found in the implementation of errata i728 workaround - Fixed the value of frequency printed in debugfs - Dropped the hwmod patch as Paul has already posted a a hwmod series [1] that adds hwmod for EMIF - Converted instances of __init to __init_or_module [1] http://thread.gmane.org/gmane.linux.ports.arm.omap/72855 Aneesh V (7): misc: ddr: add LPDDR2 data from JESD209-2 misc: emif: add register definitions for EMIF misc: emif: add basic infrastructure for EMIF driver misc: emif: handle frequency and voltage change events misc: emif: add interrupt and temperature handling misc: emif: add one-time settings misc: emif: add debugfs entries for emif Documentation/misc-devices/ti-emif.txt | 58 ++ drivers/misc/Kconfig| 12 + drivers/misc/Makefile |1 + drivers/misc/emif.c | 1670 +++ drivers/misc/emif.h | 589 +++ include/linux/platform_data/emif_plat.h | 128 +++ include/misc/jedec_ddr.h| 175 lib/Kconfig |8 + lib/Makefile|2 + lib/jedec_ddr_data.c| 135 +++ 10 files changed, 2778 insertions(+), 0 deletions(-) create mode 100644 Documentation/misc-devices/ti-emif.txt create mode 100644 drivers/misc/emif.c create mode 100644 drivers/misc/emif.h create mode 100644 include/linux/platform_data/emif_plat.h create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 1/7] misc: ddr: add LPDDR2 data from JESD209-2
add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers. Right now this is used by the TI EMIF SDRAM controller driver. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v4: - Removed 'ifndef __ASSEMBLY__' from jedec_ddr.h - Updated commit log to be more specific on where this patch is used currently - Converted EXPORT_SYMBOL to EXPORT_SYMBOL_GPL - Removed un-necessary newline v1: - Moved to /lib from /drivers/misc - Corrected Copyright year --- include/misc/jedec_ddr.h | 175 ++ lib/Kconfig |8 ++ lib/Makefile |2 + lib/jedec_ddr_data.c | 135 +++ 4 files changed, 320 insertions(+), 0 deletions(-) create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c diff --git a/include/misc/jedec_ddr.h b/include/misc/jedec_ddr.h new file mode 100644 index 000..ddad0f8 --- /dev/null +++ b/include/misc/jedec_ddr.h @@ -0,0 +1,175 @@ +/* + * Definitions for DDR memories based on JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh V ane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __LINUX_JEDEC_DDR_H +#define __LINUX_JEDEC_DDR_H + +#include linux/types.h + +/* DDR Densities */ +#define DDR_DENSITY_64Mb 1 +#define DDR_DENSITY_128Mb 2 +#define DDR_DENSITY_256Mb 3 +#define DDR_DENSITY_512Mb 4 +#define DDR_DENSITY_1Gb5 +#define DDR_DENSITY_2Gb6 +#define DDR_DENSITY_4Gb7 +#define DDR_DENSITY_8Gb8 +#define DDR_DENSITY_16Gb 9 +#define DDR_DENSITY_32Gb 10 + +/* DDR type */ +#define DDR_TYPE_DDR2 1 +#define DDR_TYPE_DDR3 2 +#define DDR_TYPE_LPDDR2_S4 3 +#define DDR_TYPE_LPDDR2_S2 4 +#define DDR_TYPE_LPDDR2_NVM5 + +/* DDR IO width */ +#define DDR_IO_WIDTH_4 1 +#define DDR_IO_WIDTH_8 2 +#define DDR_IO_WIDTH_163 +#define DDR_IO_WIDTH_324 + +/* Number of Row bits */ +#define R9 9 +#define R1010 +#define R1111 +#define R1212 +#define R1313 +#define R1414 +#define R1515 +#define R1616 + +/* Number of Column bits */ +#define C7 7 +#define C8 8 +#define C9 9 +#define C1010 +#define C1111 +#define C1212 + +/* Number of Banks */ +#define B1 0 +#define B2 1 +#define B4 2 +#define B8 3 + +/* Refresh rate in nano-seconds */ +#define T_REFI_15_615600 +#define T_REFI_7_8 7800 +#define T_REFI_3_9 3900 + +/* tRFC values */ +#define T_RFC_90 9 +#define T_RFC_110 11 +#define T_RFC_130 13 +#define T_RFC_160 16 +#define T_RFC_210 21 +#define T_RFC_300 30 +#define T_RFC_350 35 + +/* Mode register numbers */ +#define DDR_MR00 +#define DDR_MR11 +#define DDR_MR22 +#define DDR_MR33 +#define DDR_MR44 +#define DDR_MR55 +#define DDR_MR66 +#define DDR_MR77 +#define DDR_MR88 +#define DDR_MR99 +#define DDR_MR10 10 +#define DDR_MR11 11 +#define DDR_MR16 16 +#define DDR_MR17 17 +#define DDR_MR18 18 + +/* + * LPDDR2 related defines + */ + +/* MR4 register fields */ +#define MR4_SDRAM_REF_RATE_SHIFT 0 +#define MR4_SDRAM_REF_RATE_MASK7 +#define MR4_TUF_SHIFT 7 +#define MR4_TUF_MASK (1 7) + +/* MR4 SDRAM Refresh Rate field values */ +#define SDRAM_TEMP_NOMINAL 0x3 +#define SDRAM_TEMP_RESERVED_4 0x4 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 +#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 + +#define NUM_DDR_ADDR_TABLE_ENTRIES 11 +#define NUM_DDR_TIMING_TABLE_ENTRIES 4 + +/* Structure for DDR addressing info from the JEDEC spec */ +struct
[PATCH v4 2/7] misc: emif: add register definitions for EMIF
Add register offsets and bit field definitions for EMIF module in TI SoCs Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v1: - Improved commit log - Corrected copyright year - Changed file name in order to add other defines needed by the driver in the same file in subsequent patches --- drivers/misc/emif.h | 454 +++ 1 files changed, 454 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif.h diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h new file mode 100644 index 000..44b97df --- /dev/null +++ b/drivers/misc/emif.h @@ -0,0 +1,454 @@ +/* + * Defines for the EMIF driver + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Benoit Cousson (b-cous...@ti.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __EMIF_H +#define __EMIF_H + +/* Registers offset */ +#define EMIF_MODULE_ID_AND_REVISION0x +#define EMIF_STATUS0x0004 +#define EMIF_SDRAM_CONFIG 0x0008 +#define EMIF_SDRAM_CONFIG_20x000c +#define EMIF_SDRAM_REFRESH_CONTROL 0x0010 +#define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 +#define EMIF_SDRAM_TIMING_10x0018 +#define EMIF_SDRAM_TIMING_1_SHDW 0x001c +#define EMIF_SDRAM_TIMING_20x0020 +#define EMIF_SDRAM_TIMING_2_SHDW 0x0024 +#define EMIF_SDRAM_TIMING_30x0028 +#define EMIF_SDRAM_TIMING_3_SHDW 0x002c +#define EMIF_LPDDR2_NVM_TIMING 0x0030 +#define EMIF_LPDDR2_NVM_TIMING_SHDW0x0034 +#define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW0x003c +#define EMIF_LPDDR2_MODE_REG_DATA 0x0040 +#define EMIF_LPDDR2_MODE_REG_CONFIG0x0050 +#define EMIF_OCP_CONFIG0x0054 +#define EMIF_OCP_CONFIG_VALUE_10x0058 +#define EMIF_OCP_CONFIG_VALUE_20x005c +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 +#define EMIF_PERFORMANCE_COUNTER_1 0x0080 +#define EMIF_PERFORMANCE_COUNTER_2 0x0084 +#define EMIF_PERFORMANCE_COUNTER_CONFIG0x0088 +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c +#define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 +#define EMIF_MISC_REG 0x0094 +#define EMIF_DLL_CALIB_CTRL0x0098 +#define EMIF_DLL_CALIB_CTRL_SHDW 0x009c +#define EMIF_END_OF_INTERRUPT 0x00a0 +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac +#define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 +#define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc +#define EMIF_OCP_ERROR_LOG 0x00d0 +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 +#define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc +#define EMIF_DDR_PHY_CTRL_10x00e4 +#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 +#define EMIF_DDR_PHY_CTRL_20x00ec +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100 +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104 +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108 +#define EMIF_READ_WRITE_EXECUTION_THRESHOLD0x0120 +#define EMIF_COS_CONFIG0x0124 +#define EMIF_PHY_STATUS_1 0x0140 +#define EMIF_PHY_STATUS_2 0x0144 +#define EMIF_PHY_STATUS_3 0x0148 +#define EMIF_PHY_STATUS_4 0x014c
[PATCH v4 4/7] misc: emif: handle frequency and voltage change events
Change SDRAM timings and other settings as necessary on voltage and frequency changes. We calculate these register settings based on data from the device data sheet and inputs such a frequency, voltage state(stable or ramping), temperature level etc. TODO: frequency and voltage change handling needs to be integrated with clock framework and regulator framework respectively. This is not done today due to missing pieces in the kernel. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v1: - Added comment in commit log as well as code about missing integration part that needs to be done in future - Removed some settings that were relevant only for DDR3 - Correction in temperature derated value of tim3 - Added errata i735 and i728 workarounds. As part of this we need to now maintain a list of all devices in the driver and iterate through them in some cases - Improved synchronization. Added protection for newly identified cases of potential race conditions. - Minor changes in patch organization. struct members needed by this patch now defined here. --- drivers/misc/emif.c | 894 ++- drivers/misc/emif.h | 130 - 2 files changed, 1020 insertions(+), 4 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index f864640..1ca8165 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -21,6 +21,7 @@ #include linux/seq_file.h #include linux/module.h #include linux/list.h +#include linux/spinlock.h #include misc/jedec_ddr.h #include emif.h @@ -37,20 +38,595 @@ * @node: node in the device list * @base: base address of memory-mapped IO registers. * @dev: device pointer. + * @addressing table with addressing information from the spec + * @regs_cache:An array of 'struct emif_regs' that stores + * calculated register values for different + * frequencies, to avoid re-calculating them on + * each DVFS transition. + * @curr_regs: The set of register values used in the last + * frequency change (i.e. corresponding to the + * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. */ struct emif_data { u8 duplicate; u8 temperature_level; + u8 lpmode; struct list_headnode; + unsigned long irq_state; void __iomem*base; struct device *dev; + const struct lpddr2_addressing *addressing; + struct emif_regs*regs_cache[EMIF_MAX_NUM_FREQUENCIES]; + struct emif_regs*curr_regs; struct emif_platform_data *plat_data; }; static struct emif_data *emif1; +static spinlock_t emif_lock; +static unsigned long irq_state; +static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); +/* + * Calculate the period of DDR clock from frequency value + */ +static void set_ddr_clk_period(u32 freq) +{ + /* Divide 10^12 by frequency to get period in ps */ + t_ck = (u32)DIV_ROUND_UP_ULL(1ull, freq); +} + +/* + * Get the CL from SDRAM_CONFIG register + */ +static u32 get_cl(struct emif_data *emif) +{ + u32 cl; + void __iomem*base = emif-base; + + cl = (readl(base + EMIF_SDRAM_CONFIG) CL_MASK) CL_SHIFT; + + return cl; +} + +static void set_lpmode(struct emif_data *emif, u8 lpmode) +{ + u32 temp; + void __iomem *base = emif-base; + + temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); + temp = ~LP_MODE_MASK; + temp |= (lpmode LP_MODE_SHIFT); + writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL); +} + +static void do_freq_update(void) +{ + struct emif_data *emif; + + /* +* Workaround for errata i728: Disable LPMODE during FREQ_UPDATE +* +* i728 DESCRIPTION: +* The EMIF automatically puts the SDRAM into self-refresh mode +* after the EMIF has not performed accesses during +* EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles +* and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set +* to 0x2. If during a small window the following three events +* occur: +* - The SR_TIMING counter expires +* - And frequency change is requested +* - And OCP access is requested +* Then it causes instable clock on the DDR interface. +* +* WORKAROUND +* To avoid the occurrence of the three events, the workaround +* is to disable the self-refresh when requesting a frequency
[PATCH v4 5/7] misc: emif: add interrupt and temperature handling
Add an ISR for EMIF that: 1. reports details of access errors 2. takes action on thermal events Also clear all interrupts on shut-down. Pending IRQs may casue problems during warm-reset. Temperature handling: EMIF can be configured to poll the temperature level of an LPDDR2 device from the MR4 mode register in the device. EMIF generates an interrupt whenever it identifies a temperature level change between two consecutive pollings. Some of the timing parameters need to be de-rated at high temperatures. The interrupt handler takes care of doing this and also takes care of going back to nominal settings when temperature falls back to nominal levels. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - replaced __init with __init_or_module v1: - Improved commit log - Improved synchronization with thread context --- drivers/misc/emif.c | 211 ++- 1 files changed, 209 insertions(+), 2 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 1ca8165..52048f4 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -545,6 +545,42 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) } /* + * Get the temperature level of the EMIF instance: + * Reads the MR4 register of attached SDRAM parts to find out the temperature + * level. If there are two parts attached(one on each CS), then the temperature + * level for the EMIF instance is the higher of the two temperatures. + */ +static void get_temperature_level(struct emif_data *emif) +{ + u32 temp, temperature_level; + void __iomem*base; + + base = emif-base; + + /* Read mode register 4 */ + writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temperature_level = (temperature_level MR4_SDRAM_REF_RATE_MASK) + MR4_SDRAM_REF_RATE_SHIFT; + + if (emif-plat_data-device_info-cs1_used) { + writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temp = (temp MR4_SDRAM_REF_RATE_MASK) +MR4_SDRAM_REF_RATE_SHIFT; + temperature_level = max(temp, temperature_level); + } + + /* treat everything less than nominal(3) in MR4 as nominal */ + if (unlikely(temperature_level SDRAM_TEMP_NOMINAL)) + temperature_level = SDRAM_TEMP_NOMINAL; + + /* if we get reserved value in MR4 persist with the existing value */ + if (likely(temperature_level != SDRAM_TEMP_RESERVED_4)) + emif-temperature_level = temperature_level; +} + +/* * Program EMIF shadow registers that are not dependent on temperature * or voltage */ @@ -627,6 +663,158 @@ out: writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW); } +static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) +{ + u32 old_temp_level; + irqreturn_t ret = IRQ_HANDLED; + + spin_lock_irqsave(emif_lock, irq_state); + old_temp_level = emif-temperature_level; + get_temperature_level(emif); + + if (unlikely(emif-temperature_level == old_temp_level)) { + goto out; + } else if (!emif-curr_regs) { + dev_err(emif-dev, temperature alert before registers are calculated, not de-rating timings\n); + goto out; + } + + if (emif-temperature_level old_temp_level || + emif-temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { + /* +* Temperature coming down - defer handling to thread OR +* Temperature far too high - do kernel_power_off() from +* thread context +*/ + ret = IRQ_WAKE_THREAD; + } else { + /* Temperature is going up - handle immediately */ + setup_temperature_sensitive_regs(emif, emif-curr_regs); + do_freq_update(); + } + +out: + spin_unlock_irqrestore(emif_lock, irq_state); + return ret; +} + +static irqreturn_t emif_interrupt_handler(int irq, void *dev_id) +{ + u32 interrupts; + struct emif_data*emif = dev_id; + void __iomem*base = emif-base; + struct device *dev = emif-dev; + irqreturn_t ret = IRQ_HANDLED; + + /* Save the status and clear it */ + interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); + writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); + + /* +* Handle temperature alert +* Temperature alert should be same for all ports +* So, it's enough to process it only for one of the ports +*/ + if (interrupts TA_SYS_MASK) + ret = handle_temp_alert
[PATCH v4 7/7] misc: emif: add debugfs entries for emif
Add debug entries for: 1. calculated registers per frequency 2. last polled value of MR4(temperature level of LPDDR2 memory) Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - Corrected the frequency value shown in register cache dump - replaced __init with __init_or_module --- drivers/misc/emif.c | 138 +++ 1 files changed, 138 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 270a0e4..6d2f776 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #include linux/platform_device.h #include linux/interrupt.h #include linux/slab.h +#include linux/debugfs.h #include linux/seq_file.h #include linux/module.h #include linux/list.h @@ -47,6 +48,7 @@ * frequency change (i.e. corresponding to the * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. + * @debugfs_root: dentry to the root folder for EMIF in debugfs */ struct emif_data { u8 duplicate; @@ -60,6 +62,7 @@ struct emif_data { struct emif_regs*regs_cache[EMIF_MAX_NUM_FREQUENCIES]; struct emif_regs*curr_regs; struct emif_platform_data *plat_data; + struct dentry *debugfs_root; }; static struct emif_data *emif1; @@ -68,6 +71,130 @@ static unsigned longirq_state; static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); +static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, + struct emif_regs *regs) +{ + u32 type = emif-plat_data-device_info-type; + u32 ip_rev = emif-plat_data-ip_rev; + + seq_printf(s, EMIF register cache dump for %dMHz\n, + regs-freq/100); + + seq_printf(s, ref_ctrl_shdw\t: 0x%08x\n, regs-ref_ctrl_shdw); + seq_printf(s, sdram_tim1_shdw\t: 0x%08x\n, regs-sdram_tim1_shdw); + seq_printf(s, sdram_tim2_shdw\t: 0x%08x\n, regs-sdram_tim2_shdw); + seq_printf(s, sdram_tim3_shdw\t: 0x%08x\n, regs-sdram_tim3_shdw); + + if (ip_rev == EMIF_4D) { + seq_printf(s, read_idle_ctrl_shdw_normal\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_normal); + seq_printf(s, read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_volt_ramp); + } else if (ip_rev == EMIF_4D5) { + seq_printf(s, dll_calib_ctrl_shdw_normal\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_normal); + seq_printf(s, dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_volt_ramp); + } + + if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { + seq_printf(s, ref_ctrl_shdw_derated\t: 0x%08x\n, + regs-ref_ctrl_shdw_derated); + seq_printf(s, sdram_tim1_shdw_derated\t: 0x%08x\n, + regs-sdram_tim1_shdw_derated); + seq_printf(s, sdram_tim3_shdw_derated\t: 0x%08x\n, + regs-sdram_tim3_shdw_derated); + } +} + +static int emif_regdump_show(struct seq_file *s, void *unused) +{ + struct emif_data*emif = s-private; + struct emif_regs**regs_cache; + int i; + + if (emif-duplicate) + regs_cache = emif1-regs_cache; + else + regs_cache = emif-regs_cache; + + for (i = 0; i EMIF_MAX_NUM_FREQUENCIES regs_cache[i]; i++) { + do_emif_regdump_show(s, emif, regs_cache[i]); + seq_printf(s, \n); + } + + return 0; +} + +static int emif_regdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_regdump_show, inode-i_private); +} + +static const struct file_operations emif_regdump_fops = { + .open = emif_regdump_open, + .read = seq_read, + .release= single_release, +}; + +static int emif_mr4_show(struct seq_file *s, void *unused) +{ + struct emif_data *emif = s-private; + + seq_printf(s, MR4=%d\n, emif-temperature_level); + return 0; +} + +static int emif_mr4_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_mr4_show, inode-i_private); +} + +static const struct file_operations emif_mr4_fops = { + .open = emif_mr4_open, + .read = seq_read, + .release= single_release, +}; + +static int __init_or_module emif_debugfs_init(struct emif_data *emif) +{ + struct dentry *dentry; + int ret; + + dentry = debugfs_create_dir(dev_name(emif-dev), NULL); + if (IS_ERR(dentry
Re: [PATCH v2 1/7] misc: ddr: add LPDDR2 data from JESD209-2
On Saturday 17 March 2012 03:03 AM, Greg KH wrote: On Sat, Mar 17, 2012 at 02:28:47AM +0530, Aneesh V wrote: Hi Greg, [...] I have fixed these comments and pushed my latest patches at: git://github.com/aneeshv/linux.git branch: emif-upstream-v4 Sorry, but I don't take git pulls for stuff like this, please send all of the patches in email so it can be reviewed properly. I had sent the updated version of the affected patch. Anyway, I will send the whole series again. thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 6/7] misc: emif: add one-time settings
Add settings that are not dependent on frequency or any other transient parameters. This includes - power managment control init - impedence calibration control - frequency independent phy configuration registers - initialization of temperature polling Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - replaced __init with __init_or_module - fixed bug in the implementation of i728 errata workaround v1: - Improved commit log - Changes for errata i728 workaround --- drivers/misc/emif.c | 148 +++ 1 files changed, 148 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 52048f4..270a0e4 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -78,6 +78,24 @@ static void set_ddr_clk_period(u32 freq) } /* + * Get bus width used by EMIF. Note that this may be different from the + * bus width of the DDR devices used. For instance two 16-bit DDR devices + * may be connected to a given CS of EMIF. In this case bus width as far + * as EMIF is concerned is 32, where as the DDR bus width is 16 bits. + */ +static u32 get_emif_bus_width(struct emif_data *emif) +{ + u32 width; + void __iomem*base = emif-base; + + width = (readl(base + EMIF_SDRAM_CONFIG) NARROW_MODE_MASK) +NARROW_MODE_SHIFT; + width = width == 0 ? 32 : 16; + + return width; +} + +/* * Get the CL from SDRAM_CONFIG register */ static u32 get_cl(struct emif_data *emif) @@ -372,6 +390,70 @@ static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings, return tim3; } +static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing, + bool cs1_used, bool cal_resistors_per_cs) +{ + u32 zq = 0, val = 0; + + val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing-tREFI_ns; + zq |= val ZQ_REFINTERVAL_SHIFT; + + val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1; + zq |= val ZQ_ZQCL_MULT_SHIFT; + + val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1; + zq |= val ZQ_ZQINIT_MULT_SHIFT; + + zq |= ZQ_SFEXITEN_ENABLE ZQ_SFEXITEN_SHIFT; + + if (cal_resistors_per_cs) + zq |= ZQ_DUALCALEN_ENABLE ZQ_DUALCALEN_SHIFT; + else + zq |= ZQ_DUALCALEN_DISABLE ZQ_DUALCALEN_SHIFT; + + zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */ + + val = cs1_used ? 1 : 0; + zq |= val ZQ_CS1EN_SHIFT; + + return zq; +} + +static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing, + const struct emif_custom_configs *custom_configs, bool cs1_used, + u32 sdram_io_width, u32 emif_bus_width) +{ + u32 alert = 0, interval, devcnt; + + if (custom_configs (custom_configs-mask + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)) + interval = custom_configs-temp_alert_poll_interval_ms; + else + interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS; + + interval *= 100;/* Convert to ns */ + interval /= addressing-tREFI_ns; /* Convert to refresh cycles */ + alert |= (interval TA_REFINTERVAL_SHIFT); + + /* +* sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width +* also to this form and subtract to get TA_DEVCNT, which is +* in log2(x) form. +*/ + emif_bus_width = __fls(emif_bus_width) - 1; + devcnt = emif_bus_width - sdram_io_width; + alert |= devcnt TA_DEVCNT_SHIFT; + + /* DEVWDT is in 'log2(x) - 3' form */ + alert |= (sdram_io_width - 2) TA_DEVWDT_SHIFT; + + alert |= 1 TA_SFEXITEN_SHIFT; + alert |= 1 TA_CS0EN_SHIFT; + alert |= (cs1_used ? 1 : 0) TA_CS1EN_SHIFT; + + return alert; +} + static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) { u32 idle = 0, val = 0; @@ -815,6 +897,71 @@ static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq) } +static void __init_or_module emif_onetime_settings(struct emif_data *emif) +{ + u32 pwr_mgmt_ctrl, zq, temp_alert_cfg; + void __iomem*base = emif-base; + const struct lpddr2_addressing *addressing; + const struct ddr_device_info*device_info; + + device_info = emif-plat_data-device_info; + addressing = get_addressing_table(device_info); + + /* +* Init power management settings +* We don't know the frequency yet. Use a high frequency +* value for a conservative timeout setting +*/ + pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(10, emif, + emif-plat_data-ip_rev); + emif-lpmode = (pwr_mgmt_ctrl LP_MODE_MASK) LP_MODE_SHIFT; + writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL); + + /* Init ZQ calibration settings */ + zq
[PATCH v4 3/7] misc: emif: add basic infrastructure for EMIF driver
EMIF is an SDRAM controller used in various Texas Instruments SoCs. EMIF supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols. Add the basic infrastructure for EMIF driver that includes driver registration, probe, parsing of platform data etc. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - replaced __init with __init_or_module v1: - Removed emif_cleanup() function and instead used devm_* variant of APIs for resource allocations - Split include/linux/emif.h into two parts. The first part now becomes include/linux/platform_data/emif_plat.h and the other part is now merged in drivers/misc/emif.h - Made error messages more verbose - Corrected copyright year - Fixed other coding style comments - Minor adjustments to patch organization. Moved some definitions to a subsequent patch that uses them - Added a list a of devices. This is needed for errata i728 workaround and for the new locking scheme - Added documentation for driver --- Documentation/misc-devices/ti-emif.txt | 58 ++ drivers/misc/Kconfig| 12 ++ drivers/misc/Makefile |1 + drivers/misc/emif.c | 289 +++ drivers/misc/emif.h |7 + include/linux/platform_data/emif_plat.h | 128 ++ 6 files changed, 495 insertions(+), 0 deletions(-) create mode 100644 Documentation/misc-devices/ti-emif.txt create mode 100644 drivers/misc/emif.c create mode 100644 include/linux/platform_data/emif_plat.h diff --git a/Documentation/misc-devices/ti-emif.txt b/Documentation/misc-devices/ti-emif.txt new file mode 100644 index 000..a9238c1 --- /dev/null +++ b/Documentation/misc-devices/ti-emif.txt @@ -0,0 +1,58 @@ +TI EMIF SDRAM Controller Driver: + +Author + +Aneesh V ane...@ti.com + +Location + +driver/misc/emif.c + +Supported SoCs: +=== +TI OMAP44xx +TI OMAP54xx + +Menuconfig option: +== +Device Drivers + Misc devices + Texas Instruments EMIF driver + +Description +=== +This driver is for the EMIF module available in Texas Instruments +SoCs. EMIF is an SDRAM controller that, based on its revision, +supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. +This driver takes care of only LPDDR2 memories presently. The +functions of the driver includes re-configuring AC timing +parameters and other settings during frequency, voltage and +temperature changes + +Platform Data (see include/linux/platform_data/emif_plat.h): += +DDR device details and other board dependent and SoC dependent +information can be passed through platform data (struct emif_platform_data) +- DDR device details: 'struct ddr_device_info' +- Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck' +- Custom configurations: customizable policy options through + 'struct emif_custom_configs' +- IP revision +- PHY type + +Interface to the external world: + +EMIF driver registers notifiers for voltage and frequency changes +affecting EMIF and takes appropriate actions when these are invoked. +- freq_pre_notify_handling() +- freq_post_notify_handling() +- volt_notify_handling() + +Debugfs + +The driver creates two debugfs entries per device. +- regcache_dump : dump of register values calculated and saved for all + frequencies used so far. +- mr4 : last polled value of MR4 register in the LPDDR2 device. MR4 + indicates the current temperature level of the device. + diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index c779509..847a936 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -441,6 +441,18 @@ config VMWARE_BALLOON To compile this driver as a module, choose M here: the module will be called vmw_balloon. +config TI_EMIF + tristate Texas Instruments EMIF driver + select DDR + help + This driver is for the EMIF module available in Texas Instruments + SoCs. EMIF is an SDRAM controller that, based on its revision, + supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. + This driver takes care of only LPDDR2 memories presently. The + functions of the driver includes re-configuring AC timing + parameters and other settings during frequency, voltage and + temperature changes + config ARM_CHARLCD bool ARM Ltd. Character LCD Driver depends on PLAT_VERSATILE diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 3e1d801..75ab920 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o +obj-$(CONFIG_TI_EMIF) += emif.o obj-y
[PATCH v2 0/7] Add TI EMIF SDRAM controller driver
Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. The driver supports the following features: - Calculates the DDR AC timing parameters to be set in EMIF registers using data from the device data-sheets and based on the DDR frequency. If data from data-sheets is not available default timing values from the JEDEC spec are used. These will be safe, but not necessarily optimal - API for changing timings during DVFS or at boot-up - Temperature alert configuration and handling of temperature alerts, if any for LPDDR2 devices * temperature alert is based on periodic polling of MR4 mode register in DDR devices automatically performed by hardware * timings are de-rated and brought back to nominal when temperature raises and falls respectively - Cache of calculated register values to avoid re-calculating them The driver will need some minor updates when it is eventually integrated with Dynamic Voltage and Frequency Scaling (DVFS). This can not be done now as DVFS support is not available in the mainline yet. Discussions with Santosh Shilimkar santosh.shilim...@ti.com were immensely helpful in shaping up the interfaces. Vibhore Vardhan vvard...@gmail.com did the initial code snippet for thermal handling. Testing: - The driver is tested on OMAP4430 SDP. - The driver in a slightly adapted form is also tested on OMAP5. - Since mainline kernel doesn't have DVFS support yet, testing was done using a test module. - Temperature alert handling was tested with simulated interrupts and faked temperature values as testing all cases in real-life scenarios is difficult. - Tested the driver as a module Cc: Greg KH g...@kroah.com v2: - Fixed a bug found in the implementation of errata i728 workaround - Fixed the value of frequency printed in debugfs - Dropped the hwmod patch as Paul has already posted a a hwmod series [1] that adds hwmod for EMIF - Converted instances of __init to __init_or_module [1] http://thread.gmane.org/gmane.linux.ports.arm.omap/72855 Aneesh V (7): misc: ddr: add LPDDR2 data from JESD209-2 misc: emif: add register definitions for EMIF misc: emif: add basic infrastructure for EMIF driver misc: emif: handle frequency and voltage change events misc: emif: add interrupt and temperature handling misc: emif: add one-time settings misc: emif: add debugfs entries for emif Documentation/misc-devices/ti-emif.txt | 58 ++ drivers/misc/Kconfig| 12 + drivers/misc/Makefile |1 + drivers/misc/emif.c | 1670 +++ drivers/misc/emif.h | 589 +++ include/linux/platform_data/emif_plat.h | 128 +++ include/misc/jedec_ddr.h| 177 lib/Kconfig |8 + lib/Makefile|3 + lib/jedec_ddr_data.c| 135 +++ 10 files changed, 2781 insertions(+), 0 deletions(-) create mode 100644 Documentation/misc-devices/ti-emif.txt create mode 100644 drivers/misc/emif.c create mode 100644 drivers/misc/emif.h create mode 100644 include/linux/platform_data/emif_plat.h create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/7] misc: ddr: add LPDDR2 data from JESD209-2
add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v1: - Moved to /lib from /drivers/misc - Corrected Copyright year --- include/misc/jedec_ddr.h | 177 ++ lib/Kconfig |8 ++ lib/Makefile |3 + lib/jedec_ddr_data.c | 135 +++ 4 files changed, 323 insertions(+), 0 deletions(-) create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c diff --git a/include/misc/jedec_ddr.h b/include/misc/jedec_ddr.h new file mode 100644 index 000..93ffd4a --- /dev/null +++ b/include/misc/jedec_ddr.h @@ -0,0 +1,177 @@ +/* + * Definitions for DDR memories based on JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh V ane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __LINUX_JEDEC_DDR_H +#define __LINUX_JEDEC_DDR_H + +#ifndef __ASSEMBLY__ +#include linux/types.h + +/* DDR Densities */ +#define DDR_DENSITY_64Mb 1 +#define DDR_DENSITY_128Mb 2 +#define DDR_DENSITY_256Mb 3 +#define DDR_DENSITY_512Mb 4 +#define DDR_DENSITY_1Gb5 +#define DDR_DENSITY_2Gb6 +#define DDR_DENSITY_4Gb7 +#define DDR_DENSITY_8Gb8 +#define DDR_DENSITY_16Gb 9 +#define DDR_DENSITY_32Gb 10 + +/* DDR type */ +#define DDR_TYPE_DDR2 1 +#define DDR_TYPE_DDR3 2 +#define DDR_TYPE_LPDDR2_S4 3 +#define DDR_TYPE_LPDDR2_S2 4 +#define DDR_TYPE_LPDDR2_NVM5 + +/* DDR IO width */ +#define DDR_IO_WIDTH_4 1 +#define DDR_IO_WIDTH_8 2 +#define DDR_IO_WIDTH_163 +#define DDR_IO_WIDTH_324 + +/* Number of Row bits */ +#define R9 9 +#define R1010 +#define R1111 +#define R1212 +#define R1313 +#define R1414 +#define R1515 +#define R1616 + +/* Number of Column bits */ +#define C7 7 +#define C8 8 +#define C9 9 +#define C1010 +#define C1111 +#define C1212 + +/* Number of Banks */ +#define B1 0 +#define B2 1 +#define B4 2 +#define B8 3 + +/* Refresh rate in nano-seconds */ +#define T_REFI_15_615600 +#define T_REFI_7_8 7800 +#define T_REFI_3_9 3900 + +/* tRFC values */ +#define T_RFC_90 9 +#define T_RFC_110 11 +#define T_RFC_130 13 +#define T_RFC_160 16 +#define T_RFC_210 21 +#define T_RFC_300 30 +#define T_RFC_350 35 + +/* Mode register numbers */ +#define DDR_MR00 +#define DDR_MR11 +#define DDR_MR22 +#define DDR_MR33 +#define DDR_MR44 +#define DDR_MR55 +#define DDR_MR66 +#define DDR_MR77 +#define DDR_MR88 +#define DDR_MR99 +#define DDR_MR10 10 +#define DDR_MR11 11 +#define DDR_MR16 16 +#define DDR_MR17 17 +#define DDR_MR18 18 + +/* + * LPDDR2 related defines + */ + +/* MR4 register fields */ +#define MR4_SDRAM_REF_RATE_SHIFT 0 +#define MR4_SDRAM_REF_RATE_MASK7 +#define MR4_TUF_SHIFT 7 +#define MR4_TUF_MASK (1 7) + +/* MR4 SDRAM Refresh Rate field values */ +#define SDRAM_TEMP_NOMINAL 0x3 +#define SDRAM_TEMP_RESERVED_4 0x4 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 +#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 + +#define NUM_DDR_ADDR_TABLE_ENTRIES 11 +#define NUM_DDR_TIMING_TABLE_ENTRIES 4 + +/* Structure for DDR addressing info from the JEDEC spec */ +struct lpddr2_addressing { + u32 num_banks; + u32 tREFI_ns; + u32 tRFCab_ps; +}; + +/* + * Structure for timings from the LPDDR2 datasheet + * All parameters are in pico seconds(ps) unless explicitly indicated + * with a suffix like tRAS_max_ns below
[PATCH v2 3/7] misc: emif: add basic infrastructure for EMIF driver
EMIF is an SDRAM controller used in various Texas Instruments SoCs. EMIF supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols. Add the basic infrastructure for EMIF driver that includes driver registration, probe, parsing of platform data etc. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - replaced __init with __init_or_module v1: - Removed emif_cleanup() function and instead used devm_* variant of APIs for resource allocations - Split include/linux/emif.h into two parts. The first part now becomes include/linux/platform_data/emif_plat.h and the other part is now merged in drivers/misc/emif.h - Made error messages more verbose - Corrected copyright year - Fixed other coding style comments - Minor adjustments to patch organization. Moved some definitions to a subsequent patch that uses them - Added a list a of devices. This is needed for errata i728 workaround and for the new locking scheme - Added documentation for driver --- Documentation/misc-devices/ti-emif.txt | 58 ++ drivers/misc/Kconfig| 12 ++ drivers/misc/Makefile |1 + drivers/misc/emif.c | 289 +++ drivers/misc/emif.h |7 + include/linux/platform_data/emif_plat.h | 128 ++ 6 files changed, 495 insertions(+), 0 deletions(-) create mode 100644 Documentation/misc-devices/ti-emif.txt create mode 100644 drivers/misc/emif.c create mode 100644 include/linux/platform_data/emif_plat.h diff --git a/Documentation/misc-devices/ti-emif.txt b/Documentation/misc-devices/ti-emif.txt new file mode 100644 index 000..a9238c1 --- /dev/null +++ b/Documentation/misc-devices/ti-emif.txt @@ -0,0 +1,58 @@ +TI EMIF SDRAM Controller Driver: + +Author + +Aneesh V ane...@ti.com + +Location + +driver/misc/emif.c + +Supported SoCs: +=== +TI OMAP44xx +TI OMAP54xx + +Menuconfig option: +== +Device Drivers + Misc devices + Texas Instruments EMIF driver + +Description +=== +This driver is for the EMIF module available in Texas Instruments +SoCs. EMIF is an SDRAM controller that, based on its revision, +supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. +This driver takes care of only LPDDR2 memories presently. The +functions of the driver includes re-configuring AC timing +parameters and other settings during frequency, voltage and +temperature changes + +Platform Data (see include/linux/platform_data/emif_plat.h): += +DDR device details and other board dependent and SoC dependent +information can be passed through platform data (struct emif_platform_data) +- DDR device details: 'struct ddr_device_info' +- Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck' +- Custom configurations: customizable policy options through + 'struct emif_custom_configs' +- IP revision +- PHY type + +Interface to the external world: + +EMIF driver registers notifiers for voltage and frequency changes +affecting EMIF and takes appropriate actions when these are invoked. +- freq_pre_notify_handling() +- freq_post_notify_handling() +- volt_notify_handling() + +Debugfs + +The driver creates two debugfs entries per device. +- regcache_dump : dump of register values calculated and saved for all + frequencies used so far. +- mr4 : last polled value of MR4 register in the LPDDR2 device. MR4 + indicates the current temperature level of the device. + diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index c779509..847a936 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -441,6 +441,18 @@ config VMWARE_BALLOON To compile this driver as a module, choose M here: the module will be called vmw_balloon. +config TI_EMIF + tristate Texas Instruments EMIF driver + select DDR + help + This driver is for the EMIF module available in Texas Instruments + SoCs. EMIF is an SDRAM controller that, based on its revision, + supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. + This driver takes care of only LPDDR2 memories presently. The + functions of the driver includes re-configuring AC timing + parameters and other settings during frequency, voltage and + temperature changes + config ARM_CHARLCD bool ARM Ltd. Character LCD Driver depends on PLAT_VERSATILE diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 3e1d801..75ab920 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o +obj-$(CONFIG_TI_EMIF) += emif.o obj-y
[PATCH v2 2/7] misc: emif: add register definitions for EMIF
Add register offsets and bit field definitions for EMIF module in TI SoCs Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v1: - Improved commit log - Corrected copyright year - Changed file name in order to add other defines needed by the driver in the same file in subsequent patches --- drivers/misc/emif.h | 454 +++ 1 files changed, 454 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif.h diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h new file mode 100644 index 000..44b97df --- /dev/null +++ b/drivers/misc/emif.h @@ -0,0 +1,454 @@ +/* + * Defines for the EMIF driver + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Benoit Cousson (b-cous...@ti.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __EMIF_H +#define __EMIF_H + +/* Registers offset */ +#define EMIF_MODULE_ID_AND_REVISION0x +#define EMIF_STATUS0x0004 +#define EMIF_SDRAM_CONFIG 0x0008 +#define EMIF_SDRAM_CONFIG_20x000c +#define EMIF_SDRAM_REFRESH_CONTROL 0x0010 +#define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 +#define EMIF_SDRAM_TIMING_10x0018 +#define EMIF_SDRAM_TIMING_1_SHDW 0x001c +#define EMIF_SDRAM_TIMING_20x0020 +#define EMIF_SDRAM_TIMING_2_SHDW 0x0024 +#define EMIF_SDRAM_TIMING_30x0028 +#define EMIF_SDRAM_TIMING_3_SHDW 0x002c +#define EMIF_LPDDR2_NVM_TIMING 0x0030 +#define EMIF_LPDDR2_NVM_TIMING_SHDW0x0034 +#define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW0x003c +#define EMIF_LPDDR2_MODE_REG_DATA 0x0040 +#define EMIF_LPDDR2_MODE_REG_CONFIG0x0050 +#define EMIF_OCP_CONFIG0x0054 +#define EMIF_OCP_CONFIG_VALUE_10x0058 +#define EMIF_OCP_CONFIG_VALUE_20x005c +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 +#define EMIF_PERFORMANCE_COUNTER_1 0x0080 +#define EMIF_PERFORMANCE_COUNTER_2 0x0084 +#define EMIF_PERFORMANCE_COUNTER_CONFIG0x0088 +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c +#define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 +#define EMIF_MISC_REG 0x0094 +#define EMIF_DLL_CALIB_CTRL0x0098 +#define EMIF_DLL_CALIB_CTRL_SHDW 0x009c +#define EMIF_END_OF_INTERRUPT 0x00a0 +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac +#define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 +#define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc +#define EMIF_OCP_ERROR_LOG 0x00d0 +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 +#define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc +#define EMIF_DDR_PHY_CTRL_10x00e4 +#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 +#define EMIF_DDR_PHY_CTRL_20x00ec +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100 +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104 +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108 +#define EMIF_READ_WRITE_EXECUTION_THRESHOLD0x0120 +#define EMIF_COS_CONFIG0x0124 +#define EMIF_PHY_STATUS_1 0x0140 +#define EMIF_PHY_STATUS_2 0x0144 +#define EMIF_PHY_STATUS_3 0x0148 +#define EMIF_PHY_STATUS_4 0x014c
[PATCH v2 4/7] misc: emif: handle frequency and voltage change events
Change SDRAM timings and other settings as necessary on voltage and frequency changes. We calculate these register settings based on data from the device data sheet and inputs such a frequency, voltage state(stable or ramping), temperature level etc. TODO: frequency and voltage change handling needs to be integrated with clock framework and regulator framework respectively. This is not done today due to missing pieces in the kernel. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v1: - Added comment in commit log as well as code about missing integration part that needs to be done in future - Removed some settings that were relevant only for DDR3 - Correction in temperature derated value of tim3 - Added errata i735 and i728 workarounds. As part of this we need to now maintain a list of all devices in the driver and iterate through them in some cases - Improved synchronization. Added protection for newly identified cases of potential race conditions. - Minor changes in patch organization. struct members needed by this patch now defined here. --- drivers/misc/emif.c | 894 ++- drivers/misc/emif.h | 130 - 2 files changed, 1020 insertions(+), 4 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index f864640..1ca8165 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -21,6 +21,7 @@ #include linux/seq_file.h #include linux/module.h #include linux/list.h +#include linux/spinlock.h #include misc/jedec_ddr.h #include emif.h @@ -37,20 +38,595 @@ * @node: node in the device list * @base: base address of memory-mapped IO registers. * @dev: device pointer. + * @addressing table with addressing information from the spec + * @regs_cache:An array of 'struct emif_regs' that stores + * calculated register values for different + * frequencies, to avoid re-calculating them on + * each DVFS transition. + * @curr_regs: The set of register values used in the last + * frequency change (i.e. corresponding to the + * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. */ struct emif_data { u8 duplicate; u8 temperature_level; + u8 lpmode; struct list_headnode; + unsigned long irq_state; void __iomem*base; struct device *dev; + const struct lpddr2_addressing *addressing; + struct emif_regs*regs_cache[EMIF_MAX_NUM_FREQUENCIES]; + struct emif_regs*curr_regs; struct emif_platform_data *plat_data; }; static struct emif_data *emif1; +static spinlock_t emif_lock; +static unsigned long irq_state; +static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); +/* + * Calculate the period of DDR clock from frequency value + */ +static void set_ddr_clk_period(u32 freq) +{ + /* Divide 10^12 by frequency to get period in ps */ + t_ck = (u32)DIV_ROUND_UP_ULL(1ull, freq); +} + +/* + * Get the CL from SDRAM_CONFIG register + */ +static u32 get_cl(struct emif_data *emif) +{ + u32 cl; + void __iomem*base = emif-base; + + cl = (readl(base + EMIF_SDRAM_CONFIG) CL_MASK) CL_SHIFT; + + return cl; +} + +static void set_lpmode(struct emif_data *emif, u8 lpmode) +{ + u32 temp; + void __iomem *base = emif-base; + + temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); + temp = ~LP_MODE_MASK; + temp |= (lpmode LP_MODE_SHIFT); + writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL); +} + +static void do_freq_update(void) +{ + struct emif_data *emif; + + /* +* Workaround for errata i728: Disable LPMODE during FREQ_UPDATE +* +* i728 DESCRIPTION: +* The EMIF automatically puts the SDRAM into self-refresh mode +* after the EMIF has not performed accesses during +* EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles +* and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set +* to 0x2. If during a small window the following three events +* occur: +* - The SR_TIMING counter expires +* - And frequency change is requested +* - And OCP access is requested +* Then it causes instable clock on the DDR interface. +* +* WORKAROUND +* To avoid the occurrence of the three events, the workaround +* is to disable the self-refresh when requesting a frequency
[PATCH v2 5/7] misc: emif: add interrupt and temperature handling
Add an ISR for EMIF that: 1. reports details of access errors 2. takes action on thermal events Also clear all interrupts on shut-down. Pending IRQs may casue problems during warm-reset. Temperature handling: EMIF can be configured to poll the temperature level of an LPDDR2 device from the MR4 mode register in the device. EMIF generates an interrupt whenever it identifies a temperature level change between two consecutive pollings. Some of the timing parameters need to be de-rated at high temperatures. The interrupt handler takes care of doing this and also takes care of going back to nominal settings when temperature falls back to nominal levels. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - replaced __init with __init_or_module v1: - Improved commit log - Improved synchronization with thread context --- drivers/misc/emif.c | 211 ++- 1 files changed, 209 insertions(+), 2 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 1ca8165..52048f4 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -545,6 +545,42 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) } /* + * Get the temperature level of the EMIF instance: + * Reads the MR4 register of attached SDRAM parts to find out the temperature + * level. If there are two parts attached(one on each CS), then the temperature + * level for the EMIF instance is the higher of the two temperatures. + */ +static void get_temperature_level(struct emif_data *emif) +{ + u32 temp, temperature_level; + void __iomem*base; + + base = emif-base; + + /* Read mode register 4 */ + writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temperature_level = (temperature_level MR4_SDRAM_REF_RATE_MASK) + MR4_SDRAM_REF_RATE_SHIFT; + + if (emif-plat_data-device_info-cs1_used) { + writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temp = (temp MR4_SDRAM_REF_RATE_MASK) +MR4_SDRAM_REF_RATE_SHIFT; + temperature_level = max(temp, temperature_level); + } + + /* treat everything less than nominal(3) in MR4 as nominal */ + if (unlikely(temperature_level SDRAM_TEMP_NOMINAL)) + temperature_level = SDRAM_TEMP_NOMINAL; + + /* if we get reserved value in MR4 persist with the existing value */ + if (likely(temperature_level != SDRAM_TEMP_RESERVED_4)) + emif-temperature_level = temperature_level; +} + +/* * Program EMIF shadow registers that are not dependent on temperature * or voltage */ @@ -627,6 +663,158 @@ out: writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW); } +static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) +{ + u32 old_temp_level; + irqreturn_t ret = IRQ_HANDLED; + + spin_lock_irqsave(emif_lock, irq_state); + old_temp_level = emif-temperature_level; + get_temperature_level(emif); + + if (unlikely(emif-temperature_level == old_temp_level)) { + goto out; + } else if (!emif-curr_regs) { + dev_err(emif-dev, temperature alert before registers are calculated, not de-rating timings\n); + goto out; + } + + if (emif-temperature_level old_temp_level || + emif-temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { + /* +* Temperature coming down - defer handling to thread OR +* Temperature far too high - do kernel_power_off() from +* thread context +*/ + ret = IRQ_WAKE_THREAD; + } else { + /* Temperature is going up - handle immediately */ + setup_temperature_sensitive_regs(emif, emif-curr_regs); + do_freq_update(); + } + +out: + spin_unlock_irqrestore(emif_lock, irq_state); + return ret; +} + +static irqreturn_t emif_interrupt_handler(int irq, void *dev_id) +{ + u32 interrupts; + struct emif_data*emif = dev_id; + void __iomem*base = emif-base; + struct device *dev = emif-dev; + irqreturn_t ret = IRQ_HANDLED; + + /* Save the status and clear it */ + interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); + writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); + + /* +* Handle temperature alert +* Temperature alert should be same for all ports +* So, it's enough to process it only for one of the ports +*/ + if (interrupts TA_SYS_MASK) + ret = handle_temp_alert
[PATCH v2 7/7] misc: emif: add debugfs entries for emif
Add debug entries for: 1. calculated registers per frequency 2. last polled value of MR4(temperature level of LPDDR2 memory) Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - Corrected the frequency value shown in register cache dump - replaced __init with __init_or_module --- drivers/misc/emif.c | 138 +++ 1 files changed, 138 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 270a0e4..6d2f776 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #include linux/platform_device.h #include linux/interrupt.h #include linux/slab.h +#include linux/debugfs.h #include linux/seq_file.h #include linux/module.h #include linux/list.h @@ -47,6 +48,7 @@ * frequency change (i.e. corresponding to the * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. + * @debugfs_root: dentry to the root folder for EMIF in debugfs */ struct emif_data { u8 duplicate; @@ -60,6 +62,7 @@ struct emif_data { struct emif_regs*regs_cache[EMIF_MAX_NUM_FREQUENCIES]; struct emif_regs*curr_regs; struct emif_platform_data *plat_data; + struct dentry *debugfs_root; }; static struct emif_data *emif1; @@ -68,6 +71,130 @@ static unsigned longirq_state; static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); +static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, + struct emif_regs *regs) +{ + u32 type = emif-plat_data-device_info-type; + u32 ip_rev = emif-plat_data-ip_rev; + + seq_printf(s, EMIF register cache dump for %dMHz\n, + regs-freq/100); + + seq_printf(s, ref_ctrl_shdw\t: 0x%08x\n, regs-ref_ctrl_shdw); + seq_printf(s, sdram_tim1_shdw\t: 0x%08x\n, regs-sdram_tim1_shdw); + seq_printf(s, sdram_tim2_shdw\t: 0x%08x\n, regs-sdram_tim2_shdw); + seq_printf(s, sdram_tim3_shdw\t: 0x%08x\n, regs-sdram_tim3_shdw); + + if (ip_rev == EMIF_4D) { + seq_printf(s, read_idle_ctrl_shdw_normal\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_normal); + seq_printf(s, read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_volt_ramp); + } else if (ip_rev == EMIF_4D5) { + seq_printf(s, dll_calib_ctrl_shdw_normal\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_normal); + seq_printf(s, dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_volt_ramp); + } + + if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { + seq_printf(s, ref_ctrl_shdw_derated\t: 0x%08x\n, + regs-ref_ctrl_shdw_derated); + seq_printf(s, sdram_tim1_shdw_derated\t: 0x%08x\n, + regs-sdram_tim1_shdw_derated); + seq_printf(s, sdram_tim3_shdw_derated\t: 0x%08x\n, + regs-sdram_tim3_shdw_derated); + } +} + +static int emif_regdump_show(struct seq_file *s, void *unused) +{ + struct emif_data*emif = s-private; + struct emif_regs**regs_cache; + int i; + + if (emif-duplicate) + regs_cache = emif1-regs_cache; + else + regs_cache = emif-regs_cache; + + for (i = 0; i EMIF_MAX_NUM_FREQUENCIES regs_cache[i]; i++) { + do_emif_regdump_show(s, emif, regs_cache[i]); + seq_printf(s, \n); + } + + return 0; +} + +static int emif_regdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_regdump_show, inode-i_private); +} + +static const struct file_operations emif_regdump_fops = { + .open = emif_regdump_open, + .read = seq_read, + .release= single_release, +}; + +static int emif_mr4_show(struct seq_file *s, void *unused) +{ + struct emif_data *emif = s-private; + + seq_printf(s, MR4=%d\n, emif-temperature_level); + return 0; +} + +static int emif_mr4_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_mr4_show, inode-i_private); +} + +static const struct file_operations emif_mr4_fops = { + .open = emif_mr4_open, + .read = seq_read, + .release= single_release, +}; + +static int __init_or_module emif_debugfs_init(struct emif_data *emif) +{ + struct dentry *dentry; + int ret; + + dentry = debugfs_create_dir(dev_name(emif-dev), NULL); + if (IS_ERR(dentry
[PATCH v2 6/7] misc: emif: add one-time settings
Add settings that are not dependent on frequency or any other transient parameters. This includes - power managment control init - impedence calibration control - frequency independent phy configuration registers - initialization of temperature polling Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- v2: - replaced __init with __init_or_module - fixed bug in the implementation of i728 errata workaround v1: - Improved commit log - Changes for errata i728 workaround --- drivers/misc/emif.c | 148 +++ 1 files changed, 148 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 52048f4..270a0e4 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -78,6 +78,24 @@ static void set_ddr_clk_period(u32 freq) } /* + * Get bus width used by EMIF. Note that this may be different from the + * bus width of the DDR devices used. For instance two 16-bit DDR devices + * may be connected to a given CS of EMIF. In this case bus width as far + * as EMIF is concerned is 32, where as the DDR bus width is 16 bits. + */ +static u32 get_emif_bus_width(struct emif_data *emif) +{ + u32 width; + void __iomem*base = emif-base; + + width = (readl(base + EMIF_SDRAM_CONFIG) NARROW_MODE_MASK) +NARROW_MODE_SHIFT; + width = width == 0 ? 32 : 16; + + return width; +} + +/* * Get the CL from SDRAM_CONFIG register */ static u32 get_cl(struct emif_data *emif) @@ -372,6 +390,70 @@ static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings, return tim3; } +static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing, + bool cs1_used, bool cal_resistors_per_cs) +{ + u32 zq = 0, val = 0; + + val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing-tREFI_ns; + zq |= val ZQ_REFINTERVAL_SHIFT; + + val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1; + zq |= val ZQ_ZQCL_MULT_SHIFT; + + val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1; + zq |= val ZQ_ZQINIT_MULT_SHIFT; + + zq |= ZQ_SFEXITEN_ENABLE ZQ_SFEXITEN_SHIFT; + + if (cal_resistors_per_cs) + zq |= ZQ_DUALCALEN_ENABLE ZQ_DUALCALEN_SHIFT; + else + zq |= ZQ_DUALCALEN_DISABLE ZQ_DUALCALEN_SHIFT; + + zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */ + + val = cs1_used ? 1 : 0; + zq |= val ZQ_CS1EN_SHIFT; + + return zq; +} + +static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing, + const struct emif_custom_configs *custom_configs, bool cs1_used, + u32 sdram_io_width, u32 emif_bus_width) +{ + u32 alert = 0, interval, devcnt; + + if (custom_configs (custom_configs-mask + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)) + interval = custom_configs-temp_alert_poll_interval_ms; + else + interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS; + + interval *= 100;/* Convert to ns */ + interval /= addressing-tREFI_ns; /* Convert to refresh cycles */ + alert |= (interval TA_REFINTERVAL_SHIFT); + + /* +* sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width +* also to this form and subtract to get TA_DEVCNT, which is +* in log2(x) form. +*/ + emif_bus_width = __fls(emif_bus_width) - 1; + devcnt = emif_bus_width - sdram_io_width; + alert |= devcnt TA_DEVCNT_SHIFT; + + /* DEVWDT is in 'log2(x) - 3' form */ + alert |= (sdram_io_width - 2) TA_DEVWDT_SHIFT; + + alert |= 1 TA_SFEXITEN_SHIFT; + alert |= 1 TA_CS0EN_SHIFT; + alert |= (cs1_used ? 1 : 0) TA_CS1EN_SHIFT; + + return alert; +} + static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) { u32 idle = 0, val = 0; @@ -815,6 +897,71 @@ static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq) } +static void __init_or_module emif_onetime_settings(struct emif_data *emif) +{ + u32 pwr_mgmt_ctrl, zq, temp_alert_cfg; + void __iomem*base = emif-base; + const struct lpddr2_addressing *addressing; + const struct ddr_device_info*device_info; + + device_info = emif-plat_data-device_info; + addressing = get_addressing_table(device_info); + + /* +* Init power management settings +* We don't know the frequency yet. Use a high frequency +* value for a conservative timeout setting +*/ + pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(10, emif, + emif-plat_data-ip_rev); + emif-lpmode = (pwr_mgmt_ctrl LP_MODE_MASK) LP_MODE_SHIFT; + writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL); + + /* Init ZQ calibration settings */ + zq
[PATCH v2 0/4] dt: device tree support for TI EMIF driver
This series adds device tree support for TI EMIF SDRAM controller driver. For this, a binding has been added for representing AC timing parameters and other details of LPDDR2 memories. This series depends v2 of my series for adding EMIF driver [1] [1] http://marc.info/?l=linux-omapm=133183554007498w=2 Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Grant Likely grant.lik...@secretlab.ca Aneesh V (4): dt: device tree bindings for LPDDR2 memories dt: emif: device tree bindings for TI's EMIF sdram controller arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards misc: emif: add device tree support to emif driver .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 52 .../devicetree/bindings/lpddr2/lpddr2.txt | 102 +++ .../bindings/memory-controllers/ti/emif.txt| 55 arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 67 + arch/arm/boot/dts/omap4-panda.dts | 13 + arch/arm/boot/dts/omap4-sdp.dts| 13 + arch/arm/boot/dts/omap4.dtsi | 18 ++ drivers/misc/emif.c| 285 +++- 8 files changed, 604 insertions(+), 1 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/4] dt: device tree bindings for LPDDR2 memories
device tree bindings for LPDDR2 SDRAM memories compliant to JESD209-2 standard. The 'lpddr2' binding in-turn uses another binding 'lpddr2-timings' for specifying the AC timing parameters of the memory device at different speed-bins. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Grant Likely grant.lik...@secretlab.ca Signed-off-by: Aneesh V ane...@ti.com --- v1: - Removed two DDR3 only timing parameters that were inadvertently added in the binding --- .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 52 ++ .../devicetree/bindings/lpddr2/lpddr2.txt | 102 2 files changed, 154 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt new file mode 100644 index 000..a48f698 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt @@ -0,0 +1,52 @@ +* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin + +Required properties: +- compatible : Should be jedec,lpddr2-timings +- min-freq : minimum DDR clock frequency for the speed-bin. Type is u32 +- max-freq : maximum DDR clock frequency for the speed-bin. Type is u32 + +Optional properties: + +The following properties represent AC timing parameters from the memory +data-sheet of the device for a given speed-bin. All these properties are +of type u32 and the default unit is ps (pico seconds). Parameters with +a different unit have a suffix indicating the unit such as 'tRAS-max-ns' +- tRCD +- tWR +- tRAS-min +- tRRD +- tWTR +- tXP +- tRTP +- tDQSCK-max +- tFAW +- tZQCS +- tZQinit +- tRPab +- tZQCL +- tCKESR +- tRAS-max-ns +- tDQSCK-max-derated + +Example: + +timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; +}; diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt new file mode 100644 index 000..a2ab203 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt @@ -0,0 +1,102 @@ +* LPDDR2 SDRAM memories compliant to JEDEC JESD209-2 + +Required properties: +- compatible : Should be one of - jedec,lpddr2-nvm, jedec,lpddr2-s2, + jedec,lpddr2-s4 + + ti,jedec-lpddr2-s2 should be listed if the memory part is LPDDR2-S2 type + + ti,jedec-lpddr2-s4 should be listed if the memory part is LPDDR2-S4 type + + ti,jedec-lpddr2-nvm should be listed if the memory part is LPDDR2-NVM type + +- density : u32 representing density in Mb (Mega bits) + +- io-width : u32 representing bus width. Possible values are 8, 16, and 32 + +Optional properties: + +The following optional properties represent the minimum value of some AC +timing parameters of the DDR device in terms of number of clock cycles. +These values shall be obtained from the device data-sheet. +- tRRD-min-tck +- tWTR-min-tck +- tXP-min-tck +- tRTP-min-tck +- tCKE-min-tck +- tRPab-min-tck +- tRCD-min-tck +- tWR-min-tck +- tRASmin-min-tck +- tCKESR-min-tck +- tFAW-min-tck + +Child nodes: +- The lpddr2 node may have one or more child nodes of type lpddr2-timings. + lpddr2-timings provides AC timing parameters of the device for + a given speed-bin. The user may provide the timings for as many + speed-bins as is required. Please see Documentation/devicetree/ + bindings/lpddr2/lpddr2-timings.txt for more information on lpddr2-timings + +Example: + +elpida_ECB240ABACN : lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000
[PATCH v2 2/4] dt: emif: device tree bindings for TI's EMIF sdram controller
EMIF - External Memory Interface - is an SDRAM controller used in TI SoCs. EMIF supports, based on the IP revision, one or more of DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance of the EMIF IP and memory parts attached to it. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Grant Likely grant.lik...@secretlab.ca Signed-off-by: Aneesh V ane...@ti.com --- --- .../bindings/memory-controllers/ti/emif.txt| 55 1 files changed, 55 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt new file mode 100644 index 000..938f8e1 --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt @@ -0,0 +1,55 @@ +* EMIF family of TI SDRAM controllers + +EMIF - External Memory Interface - is an SDRAM controller used in +TI SoCs. EMIF supports, based on the IP revision, one or more of +DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance +of the EMIF IP and memory parts attached to it. + +Required properties: +- compatible : Should be of the form ti,emif-ip-rev where ip-rev + is the IP revision of the specific EMIF instance. + +- phy-type : u32 indicating the DDR phy type. Following are the + allowed values + 1 : Attila PHY + 2 : Intelli PHY + +- device-handle: phandle to a lpddr2 node representing the memory part + +- ti,hwmods: For TI hwmods processing and omap device creation + the value shall be emifn where n is the number of the EMIF + instance with base 1. + +Optional properties: +- cs1-used : Have this property if CS1 of this EMIF + instance has a memory part attached to it. If there is a memory + part attached to CS1, it should be the same type as the one on CS0, + so there is no need to give the details of this memory part. + +- cal-resistor-per-cs : Have this property if the board has one + calibration resistor per chip-select. + +- hw-caps-read-idle-ctrl: Have this property if the controller + supports read idle window programming + +- hw-caps-dll-calib-ctrl: Have this property if the controller + supports dll calibration control + +- hw-caps-ll-interface : Have this property if the controller + has a low latency interface and corresponding interrupt events + +- hw-caps-temp-alert : Have this property if the controller + has capability for generating SDRAM temperature alerts + +Example: + +emif1: emif@0x4c00 { + compatible = ti,emif-4d; + ti,hwmods = emif2; + phy-type= 1; + device-handle = elpida_ECB240ABACN; + cs1-used; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; + hw-caps-temp-alert; +}; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/4] arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards
Device tree data for the EMIF sdram controllers in OMAP4 and LPDDR2 memory devices attached to OMAP4 boards. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Grant Likely grant.lik...@secretlab.ca Signed-off-by: Aneesh V ane...@ti.com --- v1: - Removed DDR3 only parameters from elpida_ecb240abacn.dtsi --- arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 67 + arch/arm/boot/dts/omap4-panda.dts | 13 ++ arch/arm/boot/dts/omap4-sdp.dts | 13 ++ arch/arm/boot/dts/omap4.dtsi | 18 4 files changed, 111 insertions(+), 0 deletions(-) create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi new file mode 100644 index 000..34b9f72 --- /dev/null +++ b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi @@ -0,0 +1,67 @@ +/* + * Common devices used in different OMAP boards + */ + +/ { + elpida_ECB240ABACN: lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + tDQSCK-max-derated = 6000; + }; + + timings_elpida_ECB240ABACN_200mhz: lpddr2-timings@1 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 2; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 1; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + tDQSCK-max-derated = 6000; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index 9755ad5..f548523 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 PandaBoard; @@ -17,4 +18,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 63c6b2b..6dc08bc 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 SDP board; @@ -17,4 +18,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00
[PATCH v2 4/4] misc: emif: add device tree support to emif driver
Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Grant Likely grant.lik...@secretlab.ca Signed-off-by: Aneesh V ane...@ti.com --- v2: - Addressed comments from Grant Likely: Converted occurences of __init to __init_or_module Removed un-necessary instances of #ifdef CONFIG_OF - Rebased to v2 of EMIF driver series v1: - Rebased to the latest version of EMIF series - Replace kzalloc()/kfree() with devm_* variants --- drivers/misc/emif.c | 285 ++- 1 files changed, 284 insertions(+), 1 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 6d2f776..75f21d2 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #include linux/platform_device.h #include linux/interrupt.h #include linux/slab.h +#include linux/of.h #include linux/debugfs.h #include linux/seq_file.h #include linux/module.h @@ -49,6 +50,7 @@ * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. * @debugfs_root: dentry to the root folder for EMIF in debugfs + * @np_ddr:Pointer to ddr device tree node */ struct emif_data { u8 duplicate; @@ -63,6 +65,7 @@ struct emif_data { struct emif_regs*curr_regs; struct emif_platform_data *plat_data; struct dentry *debugfs_root; + struct device_node *np_ddr; }; static struct emif_data *emif1; @@ -1148,6 +1151,270 @@ static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, return valid; } +#if defined(CONFIG_OF) +static void __init_or_module of_get_custom_configs(struct device_node *np_emif, + struct emif_data *emif) +{ + struct emif_custom_configs *cust_cfgs = NULL; + int len; + const int *lpmode, *poll_intvl; + + lpmode = of_get_property(np_emif, low-power-mode, len); + poll_intvl = of_get_property(np_emif, temp-alert-poll-interval, len); + + if (lpmode || poll_intvl) + cust_cfgs = devm_kzalloc(emif-dev, sizeof(*cust_cfgs), + GFP_KERNEL); + + if (!cust_cfgs) + return; + + if (lpmode) { + cust_cfgs-mask |= EMIF_CUSTOM_CONFIG_LPMODE; + cust_cfgs-lpmode = *lpmode; + of_property_read_u32(np_emif, + low-power-mode-timeout-performance, + cust_cfgs-lpmode_timeout_performance); + of_property_read_u32(np_emif, + low-power-mode-timeout-power, + cust_cfgs-lpmode_timeout_power); + of_property_read_u32(np_emif, + low-power-mode-freq-threshold, + cust_cfgs-lpmode_freq_threshold); + } + + if (poll_intvl) { + cust_cfgs-mask |= + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL; + cust_cfgs-temp_alert_poll_interval_ms = *poll_intvl; + } + + if (!is_custom_config_valid(cust_cfgs, emif-dev)) { + devm_kfree(emif-dev, cust_cfgs); + return; + } + + emif-plat_data-custom_configs = cust_cfgs; +} + +static void __init_or_module of_get_min_tck(struct device_node *np, + struct emif_data *emif) +{ + int ret = 0; + struct lpddr2_min_tck *min; + + min = devm_kzalloc(emif-dev, sizeof(*min), GFP_KERNEL); + if (!min) + goto default_min_tck; + + ret |= of_property_read_u32(np, tRPab-min-tck, min-tRPab); + ret |= of_property_read_u32(np, tRCD-min-tck, min-tRCD); + ret |= of_property_read_u32(np, tWR-min-tck, min-tWR); + ret |= of_property_read_u32(np, tRASmin-min-tck, min-tRASmin); + ret |= of_property_read_u32(np, tRRD-min-tck, min-tRRD); + ret |= of_property_read_u32(np, tWTR-min-tck, min-tWTR); + ret |= of_property_read_u32(np, tXP-min-tck, min-tXP); + ret |= of_property_read_u32(np, tRTP-min-tck, min-tRTP); + ret |= of_property_read_u32(np, tCKE-min-tck, min-tCKE); + ret |= of_property_read_u32(np, tCKESR-min-tck, min-tCKESR); + ret |= of_property_read_u32(np, tFAW-min-tck, min-tFAW); + + if (ret) { + devm_kfree(emif-dev, min); + goto default_min_tck; + } + + emif-plat_data-min_tck = min; + return; + +default_min_tck: + dev_warn(emif-dev, %s: using default min-tck values\n, __func__); + emif-plat_data-min_tck = lpddr2_jedec_min_tck; +} + +static int __init_or_module of_do_get_timings(struct device_node *np, + struct lpddr2_timings *tim) +{ + int ret; + + ret = of_property_read_u32(np, max-freq, tim-max_freq
Re: [PATCH v2 1/7] misc: ddr: add LPDDR2 data from JESD209-2
On Friday 16 March 2012 12:32 AM, Greg KH wrote: On Thu, Mar 15, 2012 at 11:47:31PM +0530, Aneesh V wrote: add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers Right now, only one driver, right? Yes, should that be documented? +#ifndef __ASSEMBLY__ Why is this needed? IIRC, this header file was getting included in an omap specific header file that was in turn included from an assembly file. I will check if this is still the case. If not, I will remove it. +/* Structure for DDR addressing info from the JEDEC spec */ +struct lpddr2_addressing { + u32 num_banks; + u32 tREFI_ns; + u32 tRFCab_ps; +}; Do these structures cross the user/kernel boundry somehow? If so, please use the proper kernel types for this. No. These structures are meant for use by device drivers. --- a/lib/Makefile +++ b/lib/Makefile @@ -123,6 +123,9 @@ obj-$(CONFIG_SIGNATURE) += digsig.o obj-$(CONFIG_CLZ_TAB) += clz_tab.o +obj-$(CONFIG_DDR) += jedec_ddr_data.o + + Why the extra line? Un-intentional. Will remove. hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/jedec_ddr_data.c b/lib/jedec_ddr_data.c new file mode 100644 index 000..fc223d6 --- /dev/null +++ b/lib/jedec_ddr_data.c @@ -0,0 +1,135 @@ +/* + * DDR addressing details and AC timing parameters from JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh Vane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#includemisc/jedec_ddr.h +#includelinux/module.h + +/* LPDDR2 addressing details from JESD209-2 section 2.4 */ +const struct lpddr2_addressing + lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES] = { + {B4, T_REFI_15_6, T_RFC_90}, /* 64M */ + {B4, T_REFI_15_6, T_RFC_90}, /* 128M */ + {B4, T_REFI_7_8, T_RFC_90}, /* 256M */ + {B4, T_REFI_7_8, T_RFC_90}, /* 512M */ + {B8, T_REFI_7_8, T_RFC_130}, /* 1GS4 */ + {B8, T_REFI_3_9, T_RFC_130}, /* 2GS4 */ + {B8, T_REFI_3_9, T_RFC_130}, /* 4G */ + {B8, T_REFI_3_9, T_RFC_210}, /* 8G */ + {B4, T_REFI_7_8, T_RFC_130}, /* 1GS2 */ + {B4, T_REFI_3_9, T_RFC_130}, /* 2GS2 */ +}; +EXPORT_SYMBOL(lpddr2_jedec_addressing_table); EXPORT_SYMBOL_GPL for these and the others? Will fix all. Thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/7] Add TI EMIF SDRAM controller driver
On Friday 16 March 2012 12:34 AM, Greg KH wrote: On Thu, Mar 15, 2012 at 11:47:30PM +0530, Aneesh V wrote: Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. The driver supports the following features: - Calculates the DDR AC timing parameters to be set in EMIF registers using data from the device data-sheets and based on the DDR frequency. If data from data-sheets is not available default timing values from the JEDEC spec are used. These will be safe, but not necessarily optimal - API for changing timings during DVFS or at boot-up Is this a kernel/user API, or just an in-kernel API? That's just an in-kernel API or more precisely callbacks to be registered for DDR frequency change events. thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/4] misc: emif: add device tree support to emif driver
Hi Grant, On Friday 09 March 2012 11:07 AM, Grant Likely wrote: On Thu, 8 Mar 2012 22:03:57 +0530, Aneesh Vane...@ti.com wrote: Cc: Rajendra Nayakrna...@ti.com Cc: Benoit Coussonb-cous...@ti.com Signed-off-by: Aneesh Vane...@ti.com --- Changes since RFC v4: - Rebased to the latest version of EMIF series - Replace kzalloc()/kfree() with devm_* variants --- drivers/misc/emif.c | 289 ++- 1 files changed, 288 insertions(+), 1 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 79fb161..0aaa61e 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #includelinux/platform_device.h #includelinux/interrupt.h #includelinux/slab.h +#includelinux/of.h #includelinux/debugfs.h #includelinux/seq_file.h #includelinux/module.h @@ -49,6 +50,7 @@ *frequency in effect at the moment) * @plat_data:Pointer to saved platform data. * @debugfs_root: dentry to the root folder for EMIF in debugfs + * @np_ddr:Pointer to ddr device tree node */ struct emif_data { u8 duplicate; @@ -63,6 +65,9 @@ struct emif_data { struct emif_regs*curr_regs; struct emif_platform_data *plat_data; struct dentry *debugfs_root; +#if defined(CONFIG_OF) + struct device_node *np_ddr; +#endif Don't bother with the #if/#endif wrapper here. Ok. }; static struct emif_data *emif1; @@ -1147,6 +1152,270 @@ static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, return valid; } +#if defined(CONFIG_OF) +static void __init of_get_custom_configs(struct device_node *np_emif, __devinit. Same through the rest of the file. I am not sure if we need __devinit. I see that __devinit will not have any effect if CONFIG_HOTPLUG is enabled and CONFIG_HOTPLUG is always enabled in our configuration. EMIF devices are not hot-pluggable devices and are always added at boot-time from the board file. They are on-chip IP modules and dynamic discovery and addition doesn't make sense for them. So, can't we save some memory by making them __init. AFAIU, __init doesn't have any effect in a module. However, I can make that more explicit by using '__init_or_module'. Is that ok? [...] + return NULL; +out: + return emif; +} +#endif + static struct emif_data * __init get_device_details( This function also must be __devinit struct platform_device *pdev) { @@ -1266,7 +1535,13 @@ static int __init emif_probe(struct platform_device *pdev) struct resource *res; int irq; - emif = get_device_details(pdev); +#if defined(CONFIG_OF) + if (pdev-dev.of_node) + emif = of_get_device_details(pdev-dev.of_node,pdev-dev); + else +#endif + emif = get_device_details(pdev); + if (!emif) { pr_err(%s: error getting device data\n, __func__); goto error; @@ -1643,11 +1918,23 @@ static void __attribute__((unused)) freq_post_notify_handling(void) spin_unlock_irqrestore(emif_lock, irq_state); } +#if defined(CONFIG_OF) +static const struct of_device_id emif_of_match[] = { + { .compatible = ti,emif-4d }, + { .compatible = ti,emif-4d5 }, + {}, +}; +MODULE_DEVICE_TABLE(of, emif_of_match); +#endif + static struct platform_driver emif_driver = { .remove = __exit_p(emif_remove), Not part of this patch I realize, but this is a bug. .remove must be in the __devexit section and the __devexit_p() wrapper must be used. Similarly, emif_probe must be in the __devinit section. Again, in our case remove() is not needed unless the driver is built as a module because the devices will never be un-registered. When it is built as a module the effect is same for both: #if defined(MODULE) || defined(CONFIG_HOTPLUG) #define __devexit_p(x) x #else #define __devexit_p(x) NULL #endif #ifdef MODULE #define __exit_p(x) x #else #define __exit_p(x) NULL #endif .shutdown = emif_shutdown, .driver = { .name = emif, +#if defined(CONFIG_OF) + .of_match_table = of_match_ptr(emif_of_match), +#endif The of_match_ptr() macro makes the #if/#endif wrapper redundant. Ok. I will remove it. Otherwise, on brief review this patch looks right. Thanks for the review. Are you ok with the bindings too? br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/8] OMAP4: hwmod: add EMIF hw mod data
From: Benoit Cousson b-cous...@ti.com Add hwmod data for EMIF IP instances in OMAP4. Signed-off-by: Benoit Cousson b-cous...@ti.com --- Changes since RFC: - Improved commit log --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 110 1 files changed, 110 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index f9f1510..2b107c7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -5480,6 +5480,111 @@ static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves), }; +/* + * 'emif' class + * external memory interface no1 + */ + +static struct omap_hwmod_class omap44xx_emif_hwmod_class = { + .name = emif, +}; + +/* emif1 */ +static struct omap_hwmod omap44xx_emif1_hwmod; +static struct omap_hwmod_irq_info omap44xx_emif1_irqs[] = { + { .irq = 110 + OMAP44XX_IRQ_GIC_START }, + { .irq = -1 } +}; + +static struct omap_hwmod_addr_space omap44xx_emif1_addrs[] = { + { + .pa_start = 0x4c00, + .pa_end = 0x4cff, + .flags = ADDR_TYPE_RT + }, + { } +}; + +/* emif_fw - emif1 */ +static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif1 = { + .master = omap44xx_emif_fw_hwmod, + .slave = omap44xx_emif1_hwmod, + .clk= l3_div_ck, + .addr = omap44xx_emif1_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* emif1 slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_emif1_slaves[] = { + omap44xx_emif_fw__emif1, +}; + +static struct omap_hwmod omap44xx_emif1_hwmod = { + .name = emif1, + .class = omap44xx_emif_hwmod_class, + .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, + .mpu_irqs = omap44xx_emif1_irqs, + .main_clk = emif1_fck, + .clkdm_name = l3_emif_clkdm, + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET, + .context_offs = OMAP4_RM_MEMIF_EMIF_1_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, + .slaves = omap44xx_emif1_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_emif1_slaves), +}; + +/* emif2 */ +static struct omap_hwmod omap44xx_emif2_hwmod; +static struct omap_hwmod_irq_info omap44xx_emif2_irqs[] = { + { .irq = 111 + OMAP44XX_IRQ_GIC_START }, + { .irq = -1 } +}; + +static struct omap_hwmod_addr_space omap44xx_emif2_addrs[] = { + { + .pa_start = 0x4d00, + .pa_end = 0x4dff, + .flags = ADDR_TYPE_RT + }, + { } +}; + +/* emif_fw - emif2 */ +static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif2 = { + .master = omap44xx_emif_fw_hwmod, + .slave = omap44xx_emif2_hwmod, + .clk= l3_div_ck, + .addr = omap44xx_emif2_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* emif2 slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_emif2_slaves[] = { + omap44xx_emif_fw__emif2, +}; + +static struct omap_hwmod omap44xx_emif2_hwmod = { + .name = emif2, + .class = omap44xx_emif_hwmod_class, + .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, + .mpu_irqs = omap44xx_emif2_irqs, + .main_clk = emif2_fck, + .clkdm_name = l3_emif_clkdm, + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET, + .context_offs = OMAP4_RM_MEMIF_EMIF_1_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + } + }, + .slaves = omap44xx_emif2_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_emif2_slaves), +}; + static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* dmm class */ @@ -5629,6 +5734,11 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* wd_timer class */ omap44xx_wd_timer2_hwmod, omap44xx_wd_timer3_hwmod, + + /* emif class */ + omap44xx_emif1_hwmod, + omap44xx_emif2_hwmod, + NULL, }; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/8] misc: ddr: add LPDDR2 data from JESD209-2
add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC: - Moved to /lib from /drivers/misc - Corrected Copyright year --- include/misc/jedec_ddr.h | 177 ++ lib/Kconfig |8 ++ lib/Makefile |3 + lib/jedec_ddr_data.c | 135 +++ 4 files changed, 323 insertions(+), 0 deletions(-) create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c diff --git a/include/misc/jedec_ddr.h b/include/misc/jedec_ddr.h new file mode 100644 index 000..93ffd4a --- /dev/null +++ b/include/misc/jedec_ddr.h @@ -0,0 +1,177 @@ +/* + * Definitions for DDR memories based on JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh V ane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __LINUX_JEDEC_DDR_H +#define __LINUX_JEDEC_DDR_H + +#ifndef __ASSEMBLY__ +#include linux/types.h + +/* DDR Densities */ +#define DDR_DENSITY_64Mb 1 +#define DDR_DENSITY_128Mb 2 +#define DDR_DENSITY_256Mb 3 +#define DDR_DENSITY_512Mb 4 +#define DDR_DENSITY_1Gb5 +#define DDR_DENSITY_2Gb6 +#define DDR_DENSITY_4Gb7 +#define DDR_DENSITY_8Gb8 +#define DDR_DENSITY_16Gb 9 +#define DDR_DENSITY_32Gb 10 + +/* DDR type */ +#define DDR_TYPE_DDR2 1 +#define DDR_TYPE_DDR3 2 +#define DDR_TYPE_LPDDR2_S4 3 +#define DDR_TYPE_LPDDR2_S2 4 +#define DDR_TYPE_LPDDR2_NVM5 + +/* DDR IO width */ +#define DDR_IO_WIDTH_4 1 +#define DDR_IO_WIDTH_8 2 +#define DDR_IO_WIDTH_163 +#define DDR_IO_WIDTH_324 + +/* Number of Row bits */ +#define R9 9 +#define R1010 +#define R1111 +#define R1212 +#define R1313 +#define R1414 +#define R1515 +#define R1616 + +/* Number of Column bits */ +#define C7 7 +#define C8 8 +#define C9 9 +#define C1010 +#define C1111 +#define C1212 + +/* Number of Banks */ +#define B1 0 +#define B2 1 +#define B4 2 +#define B8 3 + +/* Refresh rate in nano-seconds */ +#define T_REFI_15_615600 +#define T_REFI_7_8 7800 +#define T_REFI_3_9 3900 + +/* tRFC values */ +#define T_RFC_90 9 +#define T_RFC_110 11 +#define T_RFC_130 13 +#define T_RFC_160 16 +#define T_RFC_210 21 +#define T_RFC_300 30 +#define T_RFC_350 35 + +/* Mode register numbers */ +#define DDR_MR00 +#define DDR_MR11 +#define DDR_MR22 +#define DDR_MR33 +#define DDR_MR44 +#define DDR_MR55 +#define DDR_MR66 +#define DDR_MR77 +#define DDR_MR88 +#define DDR_MR99 +#define DDR_MR10 10 +#define DDR_MR11 11 +#define DDR_MR16 16 +#define DDR_MR17 17 +#define DDR_MR18 18 + +/* + * LPDDR2 related defines + */ + +/* MR4 register fields */ +#define MR4_SDRAM_REF_RATE_SHIFT 0 +#define MR4_SDRAM_REF_RATE_MASK7 +#define MR4_TUF_SHIFT 7 +#define MR4_TUF_MASK (1 7) + +/* MR4 SDRAM Refresh Rate field values */ +#define SDRAM_TEMP_NOMINAL 0x3 +#define SDRAM_TEMP_RESERVED_4 0x4 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 +#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 + +#define NUM_DDR_ADDR_TABLE_ENTRIES 11 +#define NUM_DDR_TIMING_TABLE_ENTRIES 4 + +/* Structure for DDR addressing info from the JEDEC spec */ +struct lpddr2_addressing { + u32 num_banks; + u32 tREFI_ns; + u32 tRFCab_ps; +}; + +/* + * Structure for timings from the LPDDR2 datasheet + * All parameters are in pico seconds(ps) unless explicitly indicated + * with a suffix like
[PATCH 3/8] misc: emif: add register definitions for EMIF
Add register offsets and bit field definitions for EMIF module in TI SoCs Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC: - Improved commit log - Corrected copyright year - Changed file name in order to add other defines needed by the driver in the same file in subsequent patches --- drivers/misc/emif.h | 454 +++ 1 files changed, 454 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif.h diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h new file mode 100644 index 000..44b97df --- /dev/null +++ b/drivers/misc/emif.h @@ -0,0 +1,454 @@ +/* + * Defines for the EMIF driver + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Benoit Cousson (b-cous...@ti.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __EMIF_H +#define __EMIF_H + +/* Registers offset */ +#define EMIF_MODULE_ID_AND_REVISION0x +#define EMIF_STATUS0x0004 +#define EMIF_SDRAM_CONFIG 0x0008 +#define EMIF_SDRAM_CONFIG_20x000c +#define EMIF_SDRAM_REFRESH_CONTROL 0x0010 +#define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 +#define EMIF_SDRAM_TIMING_10x0018 +#define EMIF_SDRAM_TIMING_1_SHDW 0x001c +#define EMIF_SDRAM_TIMING_20x0020 +#define EMIF_SDRAM_TIMING_2_SHDW 0x0024 +#define EMIF_SDRAM_TIMING_30x0028 +#define EMIF_SDRAM_TIMING_3_SHDW 0x002c +#define EMIF_LPDDR2_NVM_TIMING 0x0030 +#define EMIF_LPDDR2_NVM_TIMING_SHDW0x0034 +#define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW0x003c +#define EMIF_LPDDR2_MODE_REG_DATA 0x0040 +#define EMIF_LPDDR2_MODE_REG_CONFIG0x0050 +#define EMIF_OCP_CONFIG0x0054 +#define EMIF_OCP_CONFIG_VALUE_10x0058 +#define EMIF_OCP_CONFIG_VALUE_20x005c +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 +#define EMIF_PERFORMANCE_COUNTER_1 0x0080 +#define EMIF_PERFORMANCE_COUNTER_2 0x0084 +#define EMIF_PERFORMANCE_COUNTER_CONFIG0x0088 +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c +#define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 +#define EMIF_MISC_REG 0x0094 +#define EMIF_DLL_CALIB_CTRL0x0098 +#define EMIF_DLL_CALIB_CTRL_SHDW 0x009c +#define EMIF_END_OF_INTERRUPT 0x00a0 +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac +#define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 +#define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc +#define EMIF_OCP_ERROR_LOG 0x00d0 +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 +#define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc +#define EMIF_DDR_PHY_CTRL_10x00e4 +#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 +#define EMIF_DDR_PHY_CTRL_20x00ec +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100 +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104 +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108 +#define EMIF_READ_WRITE_EXECUTION_THRESHOLD0x0120 +#define EMIF_COS_CONFIG0x0124 +#define EMIF_PHY_STATUS_1 0x0140 +#define EMIF_PHY_STATUS_2 0x0144 +#define EMIF_PHY_STATUS_3 0x0148 +#define EMIF_PHY_STATUS_4
[PATCH 4/8] misc: emif: add basic infrastructure for EMIF driver
EMIF is an SDRAM controller used in various Texas Instruments SoCs. EMIF supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols. Add the basic infrastructure for EMIF driver that includes driver registration, probe, parsing of platform data etc. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC: - Removed emif_cleanup() function and instead used devm_* variant of APIs for resource allocations - Split include/linux/emif.h into two parts. The first part now becomes include/linux/platform_data/emif_plat.h and the other part is now merged in drivers/misc/emif.h - Made error messages more verbose - Corrected copyright year - Fixed other coding style comments - Minor adjustments to patch organization. Moved some definitions to a subsequent patch that uses them - Added a list a of devices. This is needed for errata i728 workaround and for the new locking scheme - Added documentation for driver --- Documentation/misc-devices/ti-emif.txt | 58 ++ drivers/misc/Kconfig| 12 ++ drivers/misc/Makefile |1 + drivers/misc/emif.c | 289 +++ drivers/misc/emif.h |7 + include/linux/platform_data/emif_plat.h | 128 ++ 6 files changed, 495 insertions(+), 0 deletions(-) create mode 100644 Documentation/misc-devices/ti-emif.txt create mode 100644 drivers/misc/emif.c create mode 100644 include/linux/platform_data/emif_plat.h diff --git a/Documentation/misc-devices/ti-emif.txt b/Documentation/misc-devices/ti-emif.txt new file mode 100644 index 000..a9238c1 --- /dev/null +++ b/Documentation/misc-devices/ti-emif.txt @@ -0,0 +1,58 @@ +TI EMIF SDRAM Controller Driver: + +Author + +Aneesh V ane...@ti.com + +Location + +driver/misc/emif.c + +Supported SoCs: +=== +TI OMAP44xx +TI OMAP54xx + +Menuconfig option: +== +Device Drivers + Misc devices + Texas Instruments EMIF driver + +Description +=== +This driver is for the EMIF module available in Texas Instruments +SoCs. EMIF is an SDRAM controller that, based on its revision, +supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. +This driver takes care of only LPDDR2 memories presently. The +functions of the driver includes re-configuring AC timing +parameters and other settings during frequency, voltage and +temperature changes + +Platform Data (see include/linux/platform_data/emif_plat.h): += +DDR device details and other board dependent and SoC dependent +information can be passed through platform data (struct emif_platform_data) +- DDR device details: 'struct ddr_device_info' +- Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck' +- Custom configurations: customizable policy options through + 'struct emif_custom_configs' +- IP revision +- PHY type + +Interface to the external world: + +EMIF driver registers notifiers for voltage and frequency changes +affecting EMIF and takes appropriate actions when these are invoked. +- freq_pre_notify_handling() +- freq_post_notify_handling() +- volt_notify_handling() + +Debugfs + +The driver creates two debugfs entries per device. +- regcache_dump : dump of register values calculated and saved for all + frequencies used so far. +- mr4 : last polled value of MR4 register in the LPDDR2 device. MR4 + indicates the current temperature level of the device. + diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 6a1a092..732b38a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -451,6 +451,18 @@ config VMWARE_BALLOON To compile this driver as a module, choose M here: the module will be called vmw_balloon. +config TI_EMIF + tristate Texas Instruments EMIF driver + select DDR + help + This driver is for the EMIF module available in Texas Instruments + SoCs. EMIF is an SDRAM controller that, based on its revision, + supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. + This driver takes care of only LPDDR2 memories presently. The + functions of the driver includes re-configuring AC timing + parameters and other settings during frequency, voltage and + temperature changes + config ARM_CHARLCD bool ARM Ltd. Character LCD Driver depends on PLAT_VERSATILE diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 3e1d801..75ab920 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o +obj-$(CONFIG_TI_EMIF) += emif.o obj-y += eeprom
[PATCH 5/8] misc: emif: handle frequency and voltage change events
Change SDRAM timings and other settings as necessary on voltage and frequency changes. We calculate these register settings based on data from the device data sheet and inputs such a frequency, voltage state(stable or ramping), temperature level etc. TODO: frequency and voltage change handling needs to be integrated with clock framework and regulator framework respectively. This is not done today due to missing pieces in the kernel. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC: - Added comment in commit log as well as code about missing integration part that needs to be done in future - Removed some settings that were relevant only for DDR3 - Correction in temperature derated value of tim3 - Added errata i735 and i728 workarounds. As part of this we need to now maintain a list of all devices in the driver and iterate through them in some cases - Improved synchronization. Added protection for newly identified cases of potential race conditions. - Minor changes in patch organization. struct members needed by this patch now defined here. --- drivers/misc/emif.c | 894 ++- drivers/misc/emif.h | 130 - 2 files changed, 1020 insertions(+), 4 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 4a7048a..5ab130b 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -21,6 +21,7 @@ #include linux/seq_file.h #include linux/module.h #include linux/list.h +#include linux/spinlock.h #include misc/jedec_ddr.h #include emif.h @@ -37,20 +38,595 @@ * @node: node in the device list * @base: base address of memory-mapped IO registers. * @dev: device pointer. + * @addressing table with addressing information from the spec + * @regs_cache:An array of 'struct emif_regs' that stores + * calculated register values for different + * frequencies, to avoid re-calculating them on + * each DVFS transition. + * @curr_regs: The set of register values used in the last + * frequency change (i.e. corresponding to the + * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. */ struct emif_data { u8 duplicate; u8 temperature_level; + u8 lpmode; struct list_headnode; + unsigned long irq_state; void __iomem*base; struct device *dev; + const struct lpddr2_addressing *addressing; + struct emif_regs*regs_cache[EMIF_MAX_NUM_FREQUENCIES]; + struct emif_regs*curr_regs; struct emif_platform_data *plat_data; }; static struct emif_data *emif1; +static spinlock_t emif_lock; +static unsigned long irq_state; +static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); +/* + * Calculate the period of DDR clock from frequency value + */ +static void set_ddr_clk_period(u32 freq) +{ + /* Divide 10^12 by frequency to get period in ps */ + t_ck = (u32)DIV_ROUND_UP_ULL(1ull, freq); +} + +/* + * Get the CL from SDRAM_CONFIG register + */ +static u32 get_cl(struct emif_data *emif) +{ + u32 cl; + void __iomem*base = emif-base; + + cl = (readl(base + EMIF_SDRAM_CONFIG) CL_MASK) CL_SHIFT; + + return cl; +} + +static void set_lpmode(struct emif_data *emif, u8 lpmode) +{ + u32 temp; + void __iomem *base = emif-base; + + temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); + temp = ~LP_MODE_MASK; + temp |= (lpmode LP_MODE_SHIFT); + writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL); +} + +static void do_freq_update(void) +{ + struct emif_data *emif; + + /* +* Workaround for errata i728: Disable LPMODE during FREQ_UPDATE +* +* i728 DESCRIPTION: +* The EMIF automatically puts the SDRAM into self-refresh mode +* after the EMIF has not performed accesses during +* EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles +* and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set +* to 0x2. If during a small window the following three events +* occur: +* - The SR_TIMING counter expires +* - And frequency change is requested +* - And OCP access is requested +* Then it causes instable clock on the DDR interface. +* +* WORKAROUND +* To avoid the occurrence of the three events, the workaround +* is to disable the self-refresh when requesting
[PATCH 6/8] misc: emif: add interrupt and temperature handling
Add an ISR for EMIF that: 1. reports details of access errors 2. takes action on thermal events Also clear all interrupts on shut-down. Pending IRQs may casue problems during warm-reset. Temperature handling: EMIF can be configured to poll the temperature level of an LPDDR2 device from the MR4 mode register in the device. EMIF generates an interrupt whenever it identifies a temperature level change between two consecutive pollings. Some of the timing parameters need to be de-rated at high temperatures. The interrupt handler takes care of doing this and also takes care of going back to nominal settings when temperature falls back to nominal levels. Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC: - Improved commit log - Improved synchronization with thread context --- drivers/misc/emif.c | 211 ++- 1 files changed, 209 insertions(+), 2 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 5ab130b..09d0e68 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -545,6 +545,42 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) } /* + * Get the temperature level of the EMIF instance: + * Reads the MR4 register of attached SDRAM parts to find out the temperature + * level. If there are two parts attached(one on each CS), then the temperature + * level for the EMIF instance is the higher of the two temperatures. + */ +static void get_temperature_level(struct emif_data *emif) +{ + u32 temp, temperature_level; + void __iomem*base; + + base = emif-base; + + /* Read mode register 4 */ + writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temperature_level = (temperature_level MR4_SDRAM_REF_RATE_MASK) + MR4_SDRAM_REF_RATE_SHIFT; + + if (emif-plat_data-device_info-cs1_used) { + writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temp = (temp MR4_SDRAM_REF_RATE_MASK) +MR4_SDRAM_REF_RATE_SHIFT; + temperature_level = max(temp, temperature_level); + } + + /* treat everything less than nominal(3) in MR4 as nominal */ + if (unlikely(temperature_level SDRAM_TEMP_NOMINAL)) + temperature_level = SDRAM_TEMP_NOMINAL; + + /* if we get reserved value in MR4 persist with the existing value */ + if (likely(temperature_level != SDRAM_TEMP_RESERVED_4)) + emif-temperature_level = temperature_level; +} + +/* * Program EMIF shadow registers that are not dependent on temperature * or voltage */ @@ -627,6 +663,158 @@ out: writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW); } +static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) +{ + u32 old_temp_level; + irqreturn_t ret = IRQ_HANDLED; + + spin_lock_irqsave(emif_lock, irq_state); + old_temp_level = emif-temperature_level; + get_temperature_level(emif); + + if (unlikely(emif-temperature_level == old_temp_level)) { + goto out; + } else if (!emif-curr_regs) { + dev_err(emif-dev, temperature alert before registers are calculated, not de-rating timings\n); + goto out; + } + + if (emif-temperature_level old_temp_level || + emif-temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { + /* +* Temperature coming down - defer handling to thread OR +* Temperature far too high - do kernel_power_off() from +* thread context +*/ + ret = IRQ_WAKE_THREAD; + } else { + /* Temperature is going up - handle immediately */ + setup_temperature_sensitive_regs(emif, emif-curr_regs); + do_freq_update(); + } + +out: + spin_unlock_irqrestore(emif_lock, irq_state); + return ret; +} + +static irqreturn_t emif_interrupt_handler(int irq, void *dev_id) +{ + u32 interrupts; + struct emif_data*emif = dev_id; + void __iomem*base = emif-base; + struct device *dev = emif-dev; + irqreturn_t ret = IRQ_HANDLED; + + /* Save the status and clear it */ + interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); + writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); + + /* +* Handle temperature alert +* Temperature alert should be same for all ports +* So, it's enough to process it only for one of the ports +*/ + if (interrupts TA_SYS_MASK) + ret = handle_temp_alert(base, emif
[PATCH 7/8] misc: emif: add one-time settings
Add settings that are not dependent on frequency or any other transient parameters. This includes - power managment control init - impedence calibration control - frequency independent phy configuration registers - initialization of temperature polling Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC: - Improved commit log - Changes for errata i728 workaround --- drivers/misc/emif.c | 147 +++ 1 files changed, 147 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 09d0e68..da79dd6 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -78,6 +78,24 @@ static void set_ddr_clk_period(u32 freq) } /* + * Get bus width used by EMIF. Note that this may be different from the + * bus width of the DDR devices used. For instance two 16-bit DDR devices + * may be connected to a given CS of EMIF. In this case bus width as far + * as EMIF is concerned is 32, where as the DDR bus width is 16 bits. + */ +static u32 get_emif_bus_width(struct emif_data *emif) +{ + u32 width; + void __iomem*base = emif-base; + + width = (readl(base + EMIF_SDRAM_CONFIG) NARROW_MODE_MASK) +NARROW_MODE_SHIFT; + width = width == 0 ? 32 : 16; + + return width; +} + +/* * Get the CL from SDRAM_CONFIG register */ static u32 get_cl(struct emif_data *emif) @@ -372,6 +390,70 @@ static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings, return tim3; } +static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing, + bool cs1_used, bool cal_resistors_per_cs) +{ + u32 zq = 0, val = 0; + + val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing-tREFI_ns; + zq |= val ZQ_REFINTERVAL_SHIFT; + + val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1; + zq |= val ZQ_ZQCL_MULT_SHIFT; + + val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1; + zq |= val ZQ_ZQINIT_MULT_SHIFT; + + zq |= ZQ_SFEXITEN_ENABLE ZQ_SFEXITEN_SHIFT; + + if (cal_resistors_per_cs) + zq |= ZQ_DUALCALEN_ENABLE ZQ_DUALCALEN_SHIFT; + else + zq |= ZQ_DUALCALEN_DISABLE ZQ_DUALCALEN_SHIFT; + + zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */ + + val = cs1_used ? 1 : 0; + zq |= val ZQ_CS1EN_SHIFT; + + return zq; +} + +static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing, + const struct emif_custom_configs *custom_configs, bool cs1_used, + u32 sdram_io_width, u32 emif_bus_width) +{ + u32 alert = 0, interval, devcnt; + + if (custom_configs (custom_configs-mask + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)) + interval = custom_configs-temp_alert_poll_interval_ms; + else + interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS; + + interval *= 100;/* Convert to ns */ + interval /= addressing-tREFI_ns; /* Convert to refresh cycles */ + alert |= (interval TA_REFINTERVAL_SHIFT); + + /* +* sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width +* also to this form and subtract to get TA_DEVCNT, which is +* in log2(x) form. +*/ + emif_bus_width = __fls(emif_bus_width) - 1; + devcnt = emif_bus_width - sdram_io_width; + alert |= devcnt TA_DEVCNT_SHIFT; + + /* DEVWDT is in 'log2(x) - 3' form */ + alert |= (sdram_io_width - 2) TA_DEVWDT_SHIFT; + + alert |= 1 TA_SFEXITEN_SHIFT; + alert |= 1 TA_CS0EN_SHIFT; + alert |= (cs1_used ? 1 : 0) TA_CS1EN_SHIFT; + + return alert; +} + static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) { u32 idle = 0, val = 0; @@ -815,6 +897,70 @@ static int __init setup_interrupts(struct emif_data *emif, u32 irq) } +static void __init emif_onetime_settings(struct emif_data *emif) +{ + u32 pwr_mgmt_ctrl, zq, temp_alert_cfg; + void __iomem*base = emif-base; + const struct lpddr2_addressing *addressing; + const struct ddr_device_info*device_info; + + device_info = emif-plat_data-device_info; + addressing = get_addressing_table(device_info); + + /* +* Init power management settings +* We don't know the frequency yet. Use a high frequency +* value for a conservative timeout setting +*/ + pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(10, emif, + emif-plat_data-ip_rev); + writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL); + + /* Init ZQ calibration settings */ + zq = get_zq_config_reg(addressing, device_info-cs1_used, + device_info-cal_resistors_per_cs); + writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG
[PATCH 0/8] Add TI EMIF SDRAM controller driver
Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. The driver supports the following features: - Calculates the DDR AC timing parameters to be set in EMIF registers using data from the device data-sheets and based on the DDR frequency. If data from data-sheets is not available default timing values from the JEDEC spec are used. These will be safe, but not necessarily optimal - API for changing timings during DVFS or at boot-up - Temperature alert configuration and handling of temperature alerts, if any for LPDDR2 devices * temperature alert is based on periodic polling of MR4 mode register in DDR devices automatically performed by hardware * timings are de-rated and brought back to nominal when temperature raises and falls respectively - Cache of calculated register values to avoid re-calculating them The driver will need some minor updates when it is eventually integrated with Dynamic Voltage and Frequency Scaling (DVFS). This can not be done now as DVFS support is not available in the mainline yet. Discussions with Santosh Shilimkar santosh.shilim...@ti.com were immensely helpful in shaping up the interfaces. Vibhore Vardhan vvard...@gmail.com did the initial code snippet for thermal handling. Testing: - The driver is tested on OMAP4430 SDP. - The driver in a slightly adapted form is also tested on OMAP5. - Since mainline kernel doesn't have DVFS support yet, testing was done using a test module. - Temperature alert handling was tested with simulated interrupts and faked temperature values as testing all cases in real-life scenarios is difficult. - Tested the driver as a module Cc: Greg KH g...@kroah.com Aneesh V (7): misc: ddr: add LPDDR2 data from JESD209-2 misc: emif: add register definitions for EMIF misc: emif: add basic infrastructure for EMIF driver misc: emif: handle frequency and voltage change events misc: emif: add interrupt and temperature handling misc: emif: add one-time settings misc: emif: add debugfs entries for emif Benoit Cousson (1): OMAP4: hwmod: add EMIF hw mod data Documentation/misc-devices/ti-emif.txt | 58 + arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 110 ++ drivers/misc/Kconfig | 12 + drivers/misc/Makefile |1 + drivers/misc/emif.c| 1669 drivers/misc/emif.h| 589 ++ include/linux/platform_data/emif_plat.h| 128 +++ include/misc/jedec_ddr.h | 177 +++ lib/Kconfig|8 + lib/Makefile |3 + lib/jedec_ddr_data.c | 135 +++ 11 files changed, 2890 insertions(+), 0 deletions(-) create mode 100644 Documentation/misc-devices/ti-emif.txt create mode 100644 drivers/misc/emif.c create mode 100644 drivers/misc/emif.h create mode 100644 include/linux/platform_data/emif_plat.h create mode 100644 include/misc/jedec_ddr.h create mode 100644 lib/jedec_ddr_data.c -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 8/8] misc: emif: add debugfs entries for emif
Add debug entries for: 1. calculated registers per frequency 2. last polled value of MR4(temperature level of LPDDR2 memory) Cc: Greg KH g...@kroah.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC: - None --- drivers/misc/emif.c | 138 +++ 1 files changed, 138 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index da79dd6..79fb161 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #include linux/platform_device.h #include linux/interrupt.h #include linux/slab.h +#include linux/debugfs.h #include linux/seq_file.h #include linux/module.h #include linux/list.h @@ -47,6 +48,7 @@ * frequency change (i.e. corresponding to the * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. + * @debugfs_root: dentry to the root folder for EMIF in debugfs */ struct emif_data { u8 duplicate; @@ -60,6 +62,7 @@ struct emif_data { struct emif_regs*regs_cache[EMIF_MAX_NUM_FREQUENCIES]; struct emif_regs*curr_regs; struct emif_platform_data *plat_data; + struct dentry *debugfs_root; }; static struct emif_data *emif1; @@ -68,6 +71,130 @@ static unsigned longirq_state; static u32 t_ck; /* DDR clock period in ps */ static LIST_HEAD(device_list); +static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, + struct emif_regs *regs) +{ + u32 type = emif-plat_data-device_info-type; + u32 ip_rev = emif-plat_data-ip_rev; + + seq_printf(s, EMIF register cache dump for %dMHz\n, + regs-freq/10); + + seq_printf(s, ref_ctrl_shdw\t: 0x%08x\n, regs-ref_ctrl_shdw); + seq_printf(s, sdram_tim1_shdw\t: 0x%08x\n, regs-sdram_tim1_shdw); + seq_printf(s, sdram_tim2_shdw\t: 0x%08x\n, regs-sdram_tim2_shdw); + seq_printf(s, sdram_tim3_shdw\t: 0x%08x\n, regs-sdram_tim3_shdw); + + if (ip_rev == EMIF_4D) { + seq_printf(s, read_idle_ctrl_shdw_normal\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_normal); + seq_printf(s, read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_volt_ramp); + } else if (ip_rev == EMIF_4D5) { + seq_printf(s, dll_calib_ctrl_shdw_normal\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_normal); + seq_printf(s, dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_volt_ramp); + } + + if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { + seq_printf(s, ref_ctrl_shdw_derated\t: 0x%08x\n, + regs-ref_ctrl_shdw_derated); + seq_printf(s, sdram_tim1_shdw_derated\t: 0x%08x\n, + regs-sdram_tim1_shdw_derated); + seq_printf(s, sdram_tim3_shdw_derated\t: 0x%08x\n, + regs-sdram_tim3_shdw_derated); + } +} + +static int emif_regdump_show(struct seq_file *s, void *unused) +{ + struct emif_data*emif = s-private; + struct emif_regs**regs_cache; + int i; + + if (emif-duplicate) + regs_cache = emif1-regs_cache; + else + regs_cache = emif-regs_cache; + + for (i = 0; i EMIF_MAX_NUM_FREQUENCIES regs_cache[i]; i++) { + do_emif_regdump_show(s, emif, regs_cache[i]); + seq_printf(s, \n); + } + + return 0; +} + +static int emif_regdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_regdump_show, inode-i_private); +} + +static const struct file_operations emif_regdump_fops = { + .open = emif_regdump_open, + .read = seq_read, + .release= single_release, +}; + +static int emif_mr4_show(struct seq_file *s, void *unused) +{ + struct emif_data *emif = s-private; + + seq_printf(s, MR4=%d\n, emif-temperature_level); + return 0; +} + +static int emif_mr4_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_mr4_show, inode-i_private); +} + +static const struct file_operations emif_mr4_fops = { + .open = emif_mr4_open, + .read = seq_read, + .release= single_release, +}; + +static int __init emif_debugfs_init(struct emif_data *emif) +{ + struct dentry *dentry; + int ret; + + dentry = debugfs_create_dir(dev_name(emif-dev), NULL); + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); + goto err0; + } + emif-debugfs_root = dentry
[PATCH 0/4] dt: device tree support for TI EMIF driver
This series adds device tree support for TI EMIF SDRAM controller driver. For this, a binding has been added for representing AC timing parameters and other details of LPDDR2 memories. This series depends my series for adding EMIF driver [1] [1] http://marc.info/?l=linux-omapm=133122243430942w=2 Aneesh V (4): dt: device tree bindings for LPDDR2 memories dt: emif: device tree bindings for TI's EMIF sdram controller arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards misc: emif: add device tree support to emif driver .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 52 .../devicetree/bindings/lpddr2/lpddr2.txt | 102 +++ .../bindings/memory-controllers/ti/emif.txt| 55 arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 67 + arch/arm/boot/dts/omap4-panda.dts | 13 + arch/arm/boot/dts/omap4-sdp.dts| 13 + arch/arm/boot/dts/omap4.dtsi | 18 ++ drivers/misc/emif.c| 289 +++- 8 files changed, 608 insertions(+), 1 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/4] dt: device tree bindings for LPDDR2 memories
device tree bindings for LPDDR2 SDRAM memories compliant to JESD209-2 standard. The 'lpddr2' binding in-turn uses another binding 'lpddr2-timings' for specifying the AC timing parameters of the memory device at different speed-bins. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC v4: - Removed two DDR3 only timing parameters that were inadvertently added in the binding --- .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 52 ++ .../devicetree/bindings/lpddr2/lpddr2.txt | 102 2 files changed, 154 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt new file mode 100644 index 000..a48f698 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt @@ -0,0 +1,52 @@ +* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin + +Required properties: +- compatible : Should be jedec,lpddr2-timings +- min-freq : minimum DDR clock frequency for the speed-bin. Type is u32 +- max-freq : maximum DDR clock frequency for the speed-bin. Type is u32 + +Optional properties: + +The following properties represent AC timing parameters from the memory +data-sheet of the device for a given speed-bin. All these properties are +of type u32 and the default unit is ps (pico seconds). Parameters with +a different unit have a suffix indicating the unit such as 'tRAS-max-ns' +- tRCD +- tWR +- tRAS-min +- tRRD +- tWTR +- tXP +- tRTP +- tDQSCK-max +- tFAW +- tZQCS +- tZQinit +- tRPab +- tZQCL +- tCKESR +- tRAS-max-ns +- tDQSCK-max-derated + +Example: + +timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; +}; diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt new file mode 100644 index 000..a2ab203 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt @@ -0,0 +1,102 @@ +* LPDDR2 SDRAM memories compliant to JEDEC JESD209-2 + +Required properties: +- compatible : Should be one of - jedec,lpddr2-nvm, jedec,lpddr2-s2, + jedec,lpddr2-s4 + + ti,jedec-lpddr2-s2 should be listed if the memory part is LPDDR2-S2 type + + ti,jedec-lpddr2-s4 should be listed if the memory part is LPDDR2-S4 type + + ti,jedec-lpddr2-nvm should be listed if the memory part is LPDDR2-NVM type + +- density : u32 representing density in Mb (Mega bits) + +- io-width : u32 representing bus width. Possible values are 8, 16, and 32 + +Optional properties: + +The following optional properties represent the minimum value of some AC +timing parameters of the DDR device in terms of number of clock cycles. +These values shall be obtained from the device data-sheet. +- tRRD-min-tck +- tWTR-min-tck +- tXP-min-tck +- tRTP-min-tck +- tCKE-min-tck +- tRPab-min-tck +- tRCD-min-tck +- tWR-min-tck +- tRASmin-min-tck +- tCKESR-min-tck +- tFAW-min-tck + +Child nodes: +- The lpddr2 node may have one or more child nodes of type lpddr2-timings. + lpddr2-timings provides AC timing parameters of the device for + a given speed-bin. The user may provide the timings for as many + speed-bins as is required. Please see Documentation/devicetree/ + bindings/lpddr2/lpddr2-timings.txt for more information on lpddr2-timings + +Example: + +elpida_ECB240ABACN : lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000
[PATCH 2/4] dt: emif: device tree bindings for TI's EMIF sdram controller
EMIF - External Memory Interface - is an SDRAM controller used in TI SoCs. EMIF supports, based on the IP revision, one or more of DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance of the EMIF IP and memory parts attached to it. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- Changes sice RFC v4: - None --- .../bindings/memory-controllers/ti/emif.txt| 55 1 files changed, 55 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt new file mode 100644 index 000..938f8e1 --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt @@ -0,0 +1,55 @@ +* EMIF family of TI SDRAM controllers + +EMIF - External Memory Interface - is an SDRAM controller used in +TI SoCs. EMIF supports, based on the IP revision, one or more of +DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance +of the EMIF IP and memory parts attached to it. + +Required properties: +- compatible : Should be of the form ti,emif-ip-rev where ip-rev + is the IP revision of the specific EMIF instance. + +- phy-type : u32 indicating the DDR phy type. Following are the + allowed values + 1 : Attila PHY + 2 : Intelli PHY + +- device-handle: phandle to a lpddr2 node representing the memory part + +- ti,hwmods: For TI hwmods processing and omap device creation + the value shall be emifn where n is the number of the EMIF + instance with base 1. + +Optional properties: +- cs1-used : Have this property if CS1 of this EMIF + instance has a memory part attached to it. If there is a memory + part attached to CS1, it should be the same type as the one on CS0, + so there is no need to give the details of this memory part. + +- cal-resistor-per-cs : Have this property if the board has one + calibration resistor per chip-select. + +- hw-caps-read-idle-ctrl: Have this property if the controller + supports read idle window programming + +- hw-caps-dll-calib-ctrl: Have this property if the controller + supports dll calibration control + +- hw-caps-ll-interface : Have this property if the controller + has a low latency interface and corresponding interrupt events + +- hw-caps-temp-alert : Have this property if the controller + has capability for generating SDRAM temperature alerts + +Example: + +emif1: emif@0x4c00 { + compatible = ti,emif-4d; + ti,hwmods = emif2; + phy-type= 1; + device-handle = elpida_ECB240ABACN; + cs1-used; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; + hw-caps-temp-alert; +}; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards
Device tree data for the EMIF sdram controllers in OMAP4 and LPDDR2 memory devices attached to OMAP4 boards. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC v4: - Removed DDR3 only parameters from elpida_ecb240abacn.dtsi --- arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 67 + arch/arm/boot/dts/omap4-panda.dts | 13 ++ arch/arm/boot/dts/omap4-sdp.dts | 13 ++ arch/arm/boot/dts/omap4.dtsi | 18 4 files changed, 111 insertions(+), 0 deletions(-) create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi new file mode 100644 index 000..34b9f72 --- /dev/null +++ b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi @@ -0,0 +1,67 @@ +/* + * Common devices used in different OMAP boards + */ + +/ { + elpida_ECB240ABACN: lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + tDQSCK-max-derated = 6000; + }; + + timings_elpida_ECB240ABACN_200mhz: lpddr2-timings@1 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 2; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 1; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + tDQSCK-max-derated = 6000; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index 9755ad5..f548523 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 PandaBoard; @@ -17,4 +18,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 63c6b2b..6dc08bc 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 SDP board; @@ -17,4 +18,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used
[PATCH 4/4] misc: emif: add device tree support to emif driver
Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- Changes since RFC v4: - Rebased to the latest version of EMIF series - Replace kzalloc()/kfree() with devm_* variants --- drivers/misc/emif.c | 289 ++- 1 files changed, 288 insertions(+), 1 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 79fb161..0aaa61e 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #include linux/platform_device.h #include linux/interrupt.h #include linux/slab.h +#include linux/of.h #include linux/debugfs.h #include linux/seq_file.h #include linux/module.h @@ -49,6 +50,7 @@ * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. * @debugfs_root: dentry to the root folder for EMIF in debugfs + * @np_ddr:Pointer to ddr device tree node */ struct emif_data { u8 duplicate; @@ -63,6 +65,9 @@ struct emif_data { struct emif_regs*curr_regs; struct emif_platform_data *plat_data; struct dentry *debugfs_root; +#if defined(CONFIG_OF) + struct device_node *np_ddr; +#endif }; static struct emif_data *emif1; @@ -1147,6 +1152,270 @@ static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, return valid; } +#if defined(CONFIG_OF) +static void __init of_get_custom_configs(struct device_node *np_emif, + struct emif_data *emif) +{ + struct emif_custom_configs *cust_cfgs = NULL; + int len; + const int *lpmode, *poll_intvl; + + lpmode = of_get_property(np_emif, low-power-mode, len); + poll_intvl = of_get_property(np_emif, temp-alert-poll-interval, len); + + if (lpmode || poll_intvl) + cust_cfgs = devm_kzalloc(emif-dev, sizeof(*cust_cfgs), + GFP_KERNEL); + + if (!cust_cfgs) + return; + + if (lpmode) { + cust_cfgs-mask |= EMIF_CUSTOM_CONFIG_LPMODE; + cust_cfgs-lpmode = *lpmode; + of_property_read_u32(np_emif, + low-power-mode-timeout-performance, + cust_cfgs-lpmode_timeout_performance); + of_property_read_u32(np_emif, + low-power-mode-timeout-power, + cust_cfgs-lpmode_timeout_power); + of_property_read_u32(np_emif, + low-power-mode-freq-threshold, + cust_cfgs-lpmode_freq_threshold); + } + + if (poll_intvl) { + cust_cfgs-mask |= + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL; + cust_cfgs-temp_alert_poll_interval_ms = *poll_intvl; + } + + if (!is_custom_config_valid(cust_cfgs, emif-dev)) { + devm_kfree(emif-dev, cust_cfgs); + return; + } + + emif-plat_data-custom_configs = cust_cfgs; +} + +static void __init of_get_min_tck(struct device_node *np, + struct emif_data *emif) +{ + int ret = 0; + struct lpddr2_min_tck *min; + + min = devm_kzalloc(emif-dev, sizeof(*min), GFP_KERNEL); + if (!min) + goto default_min_tck; + + ret |= of_property_read_u32(np, tRPab-min-tck, min-tRPab); + ret |= of_property_read_u32(np, tRCD-min-tck, min-tRCD); + ret |= of_property_read_u32(np, tWR-min-tck, min-tWR); + ret |= of_property_read_u32(np, tRASmin-min-tck, min-tRASmin); + ret |= of_property_read_u32(np, tRRD-min-tck, min-tRRD); + ret |= of_property_read_u32(np, tWTR-min-tck, min-tWTR); + ret |= of_property_read_u32(np, tXP-min-tck, min-tXP); + ret |= of_property_read_u32(np, tRTP-min-tck, min-tRTP); + ret |= of_property_read_u32(np, tCKE-min-tck, min-tCKE); + ret |= of_property_read_u32(np, tCKESR-min-tck, min-tCKESR); + ret |= of_property_read_u32(np, tFAW-min-tck, min-tFAW); + + if (ret) { + devm_kfree(emif-dev, min); + goto default_min_tck; + } + + emif-plat_data-min_tck = min; + return; + +default_min_tck: + dev_warn(emif-dev, %s: using default min-tck values\n, __func__); + emif-plat_data-min_tck = lpddr2_min_tck; +} + +static int __init of_do_get_timings(struct device_node *np, + struct lpddr2_timings *tim) +{ + int ret; + + ret = of_property_read_u32(np, max-freq, tim-max_freq); + ret |= of_property_read_u32(np, min-freq, tim-min_freq); + ret |= of_property_read_u32(np, tRPab, tim-tRPab); + ret |= of_property_read_u32(np, tRCD, tim-tRCD); + ret
Re: [PATCH 1/8] OMAP4: hwmod: add EMIF hw mod data
On Thursday 08 March 2012 10:11 PM, Cousson, Benoit wrote: Hi Aneesh On 3/8/2012 4:54 PM, Aneesh V wrote: From: Benoit Coussonb-cous...@ti.com Add hwmod data for EMIF IP instances in OMAP4. Paul has just posted an OMAP4 hwmod series (ARM: OMAP4: hwmod data: add almost all remaining IP blocks) that does contain the EMIF hwmods, so assuming that you are not adding some custom dev_attr here, it should work for you. Ok. I will test with that tomorrow and drop this patch. Thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/8] Add TI EMIF SDRAM controller driver
On Friday 09 March 2012 02:29 AM, Greg KH wrote: On Thu, Mar 08, 2012 at 09:24:17PM +0530, Aneesh V wrote: Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. The driver supports the following features: - Calculates the DDR AC timing parameters to be set in EMIF registers using data from the device data-sheets and based on the DDR frequency. If data from data-sheets is not available default timing values from the JEDEC spec are used. These will be safe, but not necessarily optimal - API for changing timings during DVFS or at boot-up - Temperature alert configuration and handling of temperature alerts, if any for LPDDR2 devices * temperature alert is based on periodic polling of MR4 mode register in DDR devices automatically performed by hardware * timings are de-rated and brought back to nominal when temperature raises and falls respectively - Cache of calculated register values to avoid re-calculating them The driver will need some minor updates when it is eventually integrated with Dynamic Voltage and Frequency Scaling (DVFS). This can not be done now as DVFS support is not available in the mainline yet. What will need to be updated in it? The userspace interface or something else? The driver will need to register notifiers with regulator framework and clock framework respectively for voltage and frequency notifications. Also a hook will be needed for initiating the hardware sequence for updating the AC timings. This process is under the control of Power Reset and Clock Management(PRCM) module of OMAP. Why not wait until that code is accepted, it should be going into 3.4, right? As Paul mentioned Core DVFS may take longer time. Besides, EMIF driver is a pre-requisite for correct functioning of Core DVFS. thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 4/8] misc: emif: add basic infrastructure for EMIF driver
On Thursday 16 February 2012 10:00 PM, Cousson, Benoit wrote: Hi Aneesh, [...] +struct emif_data { + u8 duplicate; + u8 temperature_level; + u32 irq; + spinlock_t lock; /* lock to prevent races */ Nit: That comment is useless, since you already have the kerneldoc comment before. Now I remember why I did that. Without that comment checkpatch gives this check. CHECK: spinlock_t definition without comment #124: FILE: drivers/misc/emif.c:54: + spinlock_t lock; br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v4 PATCH 0/4] dt: device tree support for TI EMIF driver
On Saturday 04 February 2012 06:12 PM, Aneesh V wrote: This series adds device tree support for TI EMIF SDRAM controller driver. For this, a binding has been added for representing AC timing parameters and other details of LPDDR2 memories. Ping! Any comments on this series? br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 0/8] Add TI EMIF SDRAM controller driver
On Friday 17 February 2012 11:20 PM, Greg KH wrote: On Fri, Feb 17, 2012 at 07:26:29PM +0530, Aneesh V wrote: [...] I don't know what any of those TLA words mean, so I really can't suggest This is a driver for TI's memory controller(called EMIF). The driver is needed for adjusting the controller settings on frequency, voltage, and temperature changes. Any suggestion as to where this should go? For those type of things, don't the iio framework provide what you need and what? Or perhaps the cpufreq layer? I don't think this driver fits into the iio framework. This is not a sensor or IO kind of device. Neither does it generate events. The primary responsibility of this driver is to re-configure the SDRAM controller settings on all transient events affecting it after the bootloader has set it up at boot-time. These are typically events generated by other sub-systems in the kernel such as the clock framework (DDR frequency change) regulator framework (voltage transitions) etc. Temperature events are generated (by polling the SDRAM device) and handled within the driver. Neither do I think it will fit into cpufreq layer because DDR frequency can be triggered by clock framework independent of cpufreq. Moreover handling DDR frequency change is only one of the functions of the driver. where this code should go. But just from this diffstat, it looks like you are creating a new user/kernel interface, without documenting it anywhere, which isn't ok. I think you are referring to the header files added in include/linux/ They are not creating new user/kernel interface per se. Then why are they in include/linux/ ? My mistake. I will move them to more appropriate places. include/linux/jedec_ddr.h is the interface to a library that contains data from the DDR specs. include/linux/emif.h has definitions for platform data needed by the driver. Maybe these should go to some other sub-directory within include/ or include/linux/ ? Who needs these files? If it's only the drivers themselves, then put it in the same directory as the driver. If it's platform data, then put it, and only it, in the include/linux/platform_data/ directory. The above work has two components: 1. The driver 2. A small library with data from the SDRAM specs that the driver uses. Alan Cox has suggested to move the library part to lib/ so the corresponding header file jedec_ddr.h has to be in some common place. Can this be in include/misc or do you have a better place to suggest? The other one emif.h can be split into two parts, one for platform data that can go under include/linux/platform_data/ and the rest in the same directory as the driver, as you suggested. I shall add documentation for the driver in the next revision. That would be good. Please also cc: me on the next revision if you wish me to take the patches (hint, get_maintainer.pl should have told you this...) Sure. Thanks. - Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 4/8] misc: emif: add basic infrastructure for EMIF driver
Hi Benoit, On Thursday 16 February 2012 10:00 PM, Cousson, Benoit wrote: Hi Aneesh, On 2/4/2012 1:16 PM, Aneesh V wrote: EMIF is an SDRAM controller used in various Texas Instruments SoCs. EMIF supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols. Add the basic infrastructure for EMIF driver that includes driver registration, probe, parsing of platform data etc. Signed-off-by: Aneesh Vane...@ti.com --- drivers/misc/Kconfig | 12 ++ drivers/misc/Makefile |1 + drivers/misc/emif.c | 300 + include/linux/emif.h | 160 ++ 4 files changed, 473 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif.c create mode 100644 include/linux/emif.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8337bf6..d68184a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -459,6 +459,18 @@ config DDR information. This data is useful for drivers handling DDR SDRAM controllers. +config EMIF + tristate Texas Instruments EMIF driver + select DDR + help + This driver is for the EMIF module available in Texas Instruments + SoCs. EMIF is an SDRAM controller that, based on its revision, + supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. + This driver takes care of only LPDDR2 memories presently. The + functions of the driver includes re-configuring AC timing + parameters and other settings during frequency, voltage and + temperature changes + config ARM_CHARLCD bool ARM Ltd. Character LCD Driver depends on PLAT_VERSATILE diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 4759166..076db0f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352)+= hmc6352.o obj-$(CONFIG_DDR)+= jedec_ddr_data.o +obj-$(CONFIG_EMIF) += emif.o obj-y+= eeprom/ obj-y+= cb710/ obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c new file mode 100644 index 000..ba1e3f9 --- /dev/null +++ b/drivers/misc/emif.c @@ -0,0 +1,300 @@ +/* + * EMIF driver + * + * Copyright (C) 2010 Texas Instruments, Inc. Nit: 2012? Will fix it. + * + * Aneesh Vane...@ti.com + * Santosh Shilimkarsantosh.shilim...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#includelinux/kernel.h +#includelinux/reboot.h +#includelinux/emif.h +#includelinux/io.h +#includelinux/device.h +#includelinux/platform_device.h +#includelinux/interrupt.h +#includelinux/slab.h +#includelinux/seq_file.h +#includelinux/module.h +#includelinux/spinlock.h +#include emif_regs.h + +/** + * struct emif_data - Per device static data for driver's use + * @duplicate: Whether the DDR devices attached to this EMIF + * instance are exactly same as that on EMIF1. In + * this case we can save some memory and processing + * @temperature_level: Maximum temperature of LPDDR2 devices attached + * to this EMIF - read from MR4 register. If there + * are two devices attached to this EMIF, this + * value is the maximum of the two temperature + * levels. + * @irq: IRQ number Do you really need to store the IRQ number? Yes, I need it right now because setup_interrupts() is called later, after the first frequency notification, because that's when I have the registers to be programmed on a temperature event. But I am re-thinking on this strategy. I will move it back to probe() because other interrupts can/should be enabled at probe() time. When I do that I won't have to store it anymore and I will remove it. + * @lock: lock for protecting temperature_level and + * associated actions from race conditions + * @base: base address of memory-mapped IO registers. + * @dev: device pointer. + * @addressing table with addressing information from the spec + * @regs_cache:An array of 'struct emif_regs' that stores + * calculated register values for different + * frequencies, to avoid re-calculating them on + * each DVFS transition. + * @curr_regs: The set of register values used in the last
Re: [RFC PATCH 0/8] Add TI EMIF SDRAM controller driver
Greg, On Thursday 16 February 2012 09:53 PM, Greg KH wrote: On Thu, Feb 16, 2012 at 04:21:11PM +0530, Santosh Shilimkar wrote: Andrew, Greg, On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. The driver supports the following features: - Calculates the DDR AC timing parameters to be set in EMIF registers using data from the device data-sheets and based on the DDR frequency. If data from data-sheets is not available default timing values from the JEDEC spec are used. These will be safe, but not necessarily optimal - API for changing timings during DVFS or at boot-up - Temperature alert configuration and handling of temperature alerts, if any for LPDDR2 devices * temperature alert is based on periodic polling of MR4 mode register in DDR devices automatically performed by hardware * timings are de-rated and brought back to nominal when temperature raises and falls respectively - Cache of calculated register values to avoid re-calculating them The driver will need some minor updates when it is eventually integrated with DVFS. This can not be done now as DVFS support is not available yet in mainline. Discussions with Santosh Shilimkarsantosh.shilim...@ti.com were immensely helpful in shaping up the interfaces. Vibhore Vardhan vvard...@gmail.com did the initial code snippet for thermal handling. Testing: - The driver is tested on OMAP4430 SDP. - The driver in a slightly adapted form is also tested on OMAP5. - Since mainline kernel doesn't have DVFS support yet, testing was done using a test module. - Temperature alert handling was tested with simulated interrupts and faked temperature values as testing all cases in real-life scenarios is difficult. [...] arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 110 ++ drivers/misc/Kconfig | 20 + drivers/misc/Makefile |2 + drivers/misc/emif.c| 1522 drivers/misc/emif_regs.h | 461 + drivers/misc/jedec_ddr_data.c | 141 +++ include/linux/emif.h | 257 + include/linux/jedec_ddr.h | 174 Any suggestion on where this driver can reside. It's a memory controller driver which supports standard DDR functionality as per JDEC specs including thermal alert. On top of that it does support DVFS using the TI PRCM IP block. I don't know what any of those TLA words mean, so I really can't suggest This is a driver for TI's memory controller(called EMIF). The driver is needed for adjusting the controller settings on frequency, voltage, and temperature changes. Any suggestion as to where this should go? where this code should go. But just from this diffstat, it looks like you are creating a new user/kernel interface, without documenting it anywhere, which isn't ok. I think you are referring to the header files added in include/linux/ They are not creating new user/kernel interface per se. include/linux/jedec_ddr.h is the interface to a library that contains data from the DDR specs. include/linux/emif.h has definitions for platform data needed by the driver. Maybe these should go to some other sub-directory within include/ or include/linux/ ? I shall add documentation for the driver in the next revision. Thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 4/8] misc: emif: add basic infrastructure for EMIF driver
On Friday 17 February 2012 07:14 PM, Cousson, Benoit wrote: Hi Aneesh, [...] + emif = kzalloc(sizeof(struct emif_data), GFP_KERNEL); You should use the devm_* version of this API to get the simplify the error handling / removal. Please note that most of my allocations are happening through kmemdup(). kmemdup() doesn't have a devm_* equivalent. So, I have a cleanup() function and in the interest of uniformity decided to avoid devm_* variants altogether. I think it still worth using devm_kzalloc + memcopy here instead of kmemdup to avoid the cleanup() and simplify as well the error handling. I will do that. You might even propose a new devm_kmemdup API if you want. Ok. I will attempt that, maybe both devm_kmalloc() and devm_kmemdup(). But I would like to de-couple that from this series. That is, I will do the patch separately and if that gets up-streamed I will update EMIF driver to use them. Until then I will go with what you suggested above. br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 1/8] OMAP4: hwmod: add EMIF hw mod data
Santosh, Thanks for the review. On Thursday 16 February 2012 03:32 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: From: Benoit Coussonb-cous...@ti.com One line of change log will do here. Ok. Will add. br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 2/8] misc: ddr: add LPDDR2 data from JESD209-2
On Thursday 16 February 2012 03:37 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers Signed-off-by: Aneesh Vane...@ti.com Sorry.. Missed one minor comment. --- drivers/misc/Kconfig |8 ++ drivers/misc/Makefile |1 + drivers/misc/jedec_ddr_data.c | 141 + include/linux/jedec_ddr.h | 174 + 4 files changed, 324 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/jedec_ddr_data.c create mode 100644 include/linux/jedec_ddr.h [...] diff --git a/drivers/misc/jedec_ddr_data.c b/drivers/misc/jedec_ddr_data.c new file mode 100644 index 000..299c056 --- /dev/null +++ b/drivers/misc/jedec_ddr_data.c @@ -0,0 +1,141 @@ +/* + * DDR addressing details and AC timing parameters from JEDEC specs + * + * Copyright (C) 2010 Texas Instruments, Inc. Fix the year please. Should be 2012 Ok. Will do. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 3/8] misc: emif: add register definitions for EMIF
On Thursday 16 February 2012 03:40 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: Signed-off-by: Aneesh Vane...@ti.com --- drivers/misc/emif_regs.h | 461 ++ 1 files changed, 461 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif_regs.h Changelog please. O.w looks fine to me. Ok. Will add. thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 4/8] misc: emif: add basic infrastructure for EMIF driver
On Thursday 16 February 2012 04:03 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: EMIF is an SDRAM controller used in various Texas Instruments SoCs. EMIF supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols. Add the basic infrastructure for EMIF driver that includes driver registration, probe, parsing of platform data etc. Signed-off-by: Aneesh Vane...@ti.com --- drivers/misc/Kconfig | 12 ++ drivers/misc/Makefile |1 + drivers/misc/emif.c | 300 + include/linux/emif.h | 160 ++ 4 files changed, 473 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif.c create mode 100644 include/linux/emif.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8337bf6..d68184a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -459,6 +459,18 @@ config DDR information. This data is useful for drivers handling DDR SDRAM controllers. +config EMIF Add TI prefix here since it's TI IP and not a generic one. Ok. + tristate Texas Instruments EMIF driver + select DDR + help + This driver is for the EMIF module available in Texas Instruments + SoCs. EMIF is an SDRAM controller that, based on its revision, + supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. + This driver takes care of only LPDDR2 memories presently. The + functions of the driver includes re-configuring AC timing + parameters and other settings during frequency, voltage and + temperature changes + config ARM_CHARLCD bool ARM Ltd. Character LCD Driver depends on PLAT_VERSATILE diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 4759166..076db0f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o obj-$(CONFIG_DDR) += jedec_ddr_data.o +obj-$(CONFIG_EMIF) += emif.o obj-y += eeprom/ obj-y += cb710/ obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c new file mode 100644 index 000..ba1e3f9 --- /dev/null +++ b/drivers/misc/emif.c @@ -0,0 +1,300 @@ +/* + * EMIF driver + * + * Copyright (C) 2010 Texas Instruments, Inc. Fix year. 2012 + * + * Aneesh Vane...@ti.com + * Santosh Shilimkarsantosh.shilim...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#includelinux/kernel.h +#includelinux/reboot.h +#includelinux/emif.h +#includelinux/io.h +#includelinux/device.h +#includelinux/platform_device.h +#includelinux/interrupt.h +#includelinux/slab.h +#includelinux/seq_file.h +#includelinux/module.h +#includelinux/spinlock.h +#include emif_regs.h + +/** + * struct emif_data - Per device static data for driver's use + * @duplicate: Whether the DDR devices attached to this EMIF + * instance are exactly same as that on EMIF1. In + * this case we can save some memory and processing + * @temperature_level: Maximum temperature of LPDDR2 devices attached + * to this EMIF - read from MR4 register. If there + * are two devices attached to this EMIF, this + * value is the maximum of the two temperature + * levels. + * @irq: IRQ number + * @lock: lock for protecting temperature_level and + * associated actions from race conditions + * @base: base address of memory-mapped IO registers. + * @dev: device pointer. + * @addressing table with addressing information from the spec + * @regs_cache:An array of 'struct emif_regs' that stores + * calculated register values for different + * frequencies, to avoid re-calculating them on + * each DVFS transition. + * @curr_regs: The set of register values used in the last + * frequency change (i.e. corresponding to the + * frequency in effect at the moment) + * @plat_data: Pointer to saved platform data. + */ +struct emif_data { + u8 duplicate; + u8 temperature_level; + u32 irq; + spinlock_t lock; /* lock to prevent
Re: [RFC PATCH 5/8] misc: emif: handle frequency and voltage change events
On Thursday 16 February 2012 04:08 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: Change SDRAM timings and other settings as necessary on voltage and frequency changes. We calculate these register settings based on data from the device data sheet and inputs such a frequency, voltage state(stable or ramping), temperature level etc. May be you want add TBD or FIXME for notifiers when they are available. Do that in commit log as well as in the code so that we don't forget about it. Will do. Signed-off-by: Aneesh Vane...@ti.com --- Rest of the patch looks fine. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 6/8] misc: emif: add interrupt and temperature handling
On Thursday 16 February 2012 04:11 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: Add an ISR for EMIF that: 1. reports details of access errors 2. takes action on thermal events On thermal events SDRAM timing parameters are adjusted to ensure safe operation Also clear all interrupts on shut-down. Pending IRQs may casue problems during warm-reset. Add some more details like MR4, EMIF polling frequency etc for better understanding. Will do. Signed-off-by: Aneesh Vane...@ti.com --- drivers/misc/emif.c | 209 ++- 1 files changed, 207 insertions(+), 2 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 36ba6f4..5c2b0ae 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -500,6 +500,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) } /* + * Get the temperature level of the EMIF instance: + * Reads the MR4 register of attached SDRAM parts to find out the temperature + * level. If there are two parts attached(one on each CS), then the temperature + * level for the EMIF instance is the higher of the two temperatures. + */ +static void get_temperature_level(struct emif_data *emif) +{ + u32 temp, temperature_level; + unsigned long irqs; + void __iomem*base; + + base = emif-base; + + /* Read mode register 4 */ + writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temperature_level = (temperature_level MR4_SDRAM_REF_RATE_MASK) + MR4_SDRAM_REF_RATE_SHIFT; + + if (emif-plat_data-device_info-cs1_used) { + writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temp = (temp MR4_SDRAM_REF_RATE_MASK) + MR4_SDRAM_REF_RATE_SHIFT; + temperature_level = max(temp, temperature_level); + } + + spin_lock_irqsave(emif-lock, irqs); Add a line here. Will do. + /* treat everything less than nominal(3) in MR4 as nominal */ + if (unlikely(temperature_level SDRAM_TEMP_NOMINAL)) + temperature_level = SDRAM_TEMP_NOMINAL; + + /* if we get reserved value in MR4 persist with the existing value */ + if (likely(temperature_level != SDRAM_TEMP_RESERVED_4)) + emif-temperature_level = temperature_level; + spin_unlock_irqrestore(emif-lock, irqs); +} + rest of the patch looks fine to me Thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 2/8] misc: ddr: add LPDDR2 data from JESD209-2
On Thursday 16 February 2012 04:40 PM, Alan Cox wrote: On Thu, 16 Feb 2012 15:57:57 +0530 Aneesh Vane...@ti.com wrote: On Thursday 16 February 2012 03:37 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers I don't think it belongs in drivers/misc. It's not a driver but a library. lib/ might be a better place for it perhaps ? Agree. I shall move it to lib/ br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 7/8] misc: emif: add one-time settings
On Thursday 16 February 2012 04:14 PM, Santosh Shilimkar wrote: On Saturday 04 February 2012 05:46 PM, Aneesh V wrote: Add settings that are not dependent on frequency or any other transient parameters Expand the changelog a bit. One time settings like SDRAM_CONFIG, PHY_CONTROL, TEMP alert etc. Will do. Signed-off-by: Aneesh Vane...@ti.com --- Patch looks fine. Thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 3/8] misc: emif: add register definitions for EMIF
On Thursday 09 February 2012 04:55 PM, Bedia, Vaibhav wrote: -Original Message- From: linux-omap-ow...@vger.kernel.org [mailto:linux-omap-ow...@vger.kernel.org] On Behalf Of V, Aneesh Sent: Saturday, February 04, 2012 5:46 PM To: linux-omap@vger.kernel.org Cc: linux-ker...@vger.kernel.org; a...@linux-foundation.org; V, Aneesh Subject: [RFC PATCH 3/8] misc: emif: add register definitions for EMIF Sorry for the delayed response. Can these register definitions be put in a place where the code from the arch/arm/mach-omap2/* can also access it? I don't have any issues with it as long as everybody is in agreement. Devices like AM335x and TI814x will need to reconfigure the EMIF when coming out of low power states and putting these register definitions in a common place will help us avoid some code duplication. Can you elaborate on that. Does EMIF lose its settings in low-power mode? If so, are you going to do the re-initialization from internal RAM or something? For us EMIF doesn't lose its state in low power modes. br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 0/8] Add TI EMIF SDRAM controller driver
Add a driver for the EMIF SDRAM controller used in TI SoCs EMIF is an SDRAM controller that supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support for LPDDR2. The driver supports the following features: - Calculates the DDR AC timing parameters to be set in EMIF registers using data from the device data-sheets and based on the DDR frequency. If data from data-sheets is not available default timing values from the JEDEC spec are used. These will be safe, but not necessarily optimal - API for changing timings during DVFS or at boot-up - Temperature alert configuration and handling of temperature alerts, if any for LPDDR2 devices * temperature alert is based on periodic polling of MR4 mode register in DDR devices automatically performed by hardware * timings are de-rated and brought back to nominal when temperature raises and falls respectively - Cache of calculated register values to avoid re-calculating them The driver will need some minor updates when it is eventually integrated with DVFS. This can not be done now as DVFS support is not available yet in mainline. Discussions with Santosh Shilimkar santosh.shilim...@ti.com were immensely helpful in shaping up the interfaces. Vibhore Vardhan vvard...@gmail.com did the initial code snippet for thermal handling. Testing: - The driver is tested on OMAP4430 SDP. - The driver in a slightly adapted form is also tested on OMAP5. - Since mainline kernel doesn't have DVFS support yet, testing was done using a test module. - Temperature alert handling was tested with simulated interrupts and faked temperature values as testing all cases in real-life scenarios is difficult. Aneesh V (7): misc: ddr: add LPDDR2 data from JESD209-2 misc: emif: add register definitions for EMIF misc: emif: add basic infrastructure for EMIF driver misc: emif: handle frequency and voltage change events misc: emif: add interrupt and temperature handling misc: emif: add one-time settings misc: emif: add debugfs entries for emif Benoit Cousson (1): OMAP4: hwmod: add EMIF hw mod data arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 110 ++ drivers/misc/Kconfig | 20 + drivers/misc/Makefile |2 + drivers/misc/emif.c| 1522 drivers/misc/emif_regs.h | 461 + drivers/misc/jedec_ddr_data.c | 141 +++ include/linux/emif.h | 257 + include/linux/jedec_ddr.h | 174 8 files changed, 2687 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif.c create mode 100644 drivers/misc/emif_regs.h create mode 100644 drivers/misc/jedec_ddr_data.c create mode 100644 include/linux/emif.h create mode 100644 include/linux/jedec_ddr.h -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 1/8] OMAP4: hwmod: add EMIF hw mod data
From: Benoit Cousson b-cous...@ti.com Signed-off-by: Benoit Cousson b-cous...@ti.com --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 110 1 files changed, 110 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index f9f1510..2b107c7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -5480,6 +5480,111 @@ static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves), }; +/* + * 'emif' class + * external memory interface no1 + */ + +static struct omap_hwmod_class omap44xx_emif_hwmod_class = { + .name = emif, +}; + +/* emif1 */ +static struct omap_hwmod omap44xx_emif1_hwmod; +static struct omap_hwmod_irq_info omap44xx_emif1_irqs[] = { + { .irq = 110 + OMAP44XX_IRQ_GIC_START }, + { .irq = -1 } +}; + +static struct omap_hwmod_addr_space omap44xx_emif1_addrs[] = { + { + .pa_start = 0x4c00, + .pa_end = 0x4cff, + .flags = ADDR_TYPE_RT + }, + { } +}; + +/* emif_fw - emif1 */ +static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif1 = { + .master = omap44xx_emif_fw_hwmod, + .slave = omap44xx_emif1_hwmod, + .clk= l3_div_ck, + .addr = omap44xx_emif1_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* emif1 slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_emif1_slaves[] = { + omap44xx_emif_fw__emif1, +}; + +static struct omap_hwmod omap44xx_emif1_hwmod = { + .name = emif1, + .class = omap44xx_emif_hwmod_class, + .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, + .mpu_irqs = omap44xx_emif1_irqs, + .main_clk = emif1_fck, + .clkdm_name = l3_emif_clkdm, + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET, + .context_offs = OMAP4_RM_MEMIF_EMIF_1_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, + .slaves = omap44xx_emif1_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_emif1_slaves), +}; + +/* emif2 */ +static struct omap_hwmod omap44xx_emif2_hwmod; +static struct omap_hwmod_irq_info omap44xx_emif2_irqs[] = { + { .irq = 111 + OMAP44XX_IRQ_GIC_START }, + { .irq = -1 } +}; + +static struct omap_hwmod_addr_space omap44xx_emif2_addrs[] = { + { + .pa_start = 0x4d00, + .pa_end = 0x4dff, + .flags = ADDR_TYPE_RT + }, + { } +}; + +/* emif_fw - emif2 */ +static struct omap_hwmod_ocp_if omap44xx_emif_fw__emif2 = { + .master = omap44xx_emif_fw_hwmod, + .slave = omap44xx_emif2_hwmod, + .clk= l3_div_ck, + .addr = omap44xx_emif2_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* emif2 slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_emif2_slaves[] = { + omap44xx_emif_fw__emif2, +}; + +static struct omap_hwmod omap44xx_emif2_hwmod = { + .name = emif2, + .class = omap44xx_emif_hwmod_class, + .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, + .mpu_irqs = omap44xx_emif2_irqs, + .main_clk = emif2_fck, + .clkdm_name = l3_emif_clkdm, + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET, + .context_offs = OMAP4_RM_MEMIF_EMIF_1_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + } + }, + .slaves = omap44xx_emif2_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_emif2_slaves), +}; + static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* dmm class */ @@ -5629,6 +5734,11 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* wd_timer class */ omap44xx_wd_timer2_hwmod, omap44xx_wd_timer3_hwmod, + + /* emif class */ + omap44xx_emif1_hwmod, + omap44xx_emif2_hwmod, + NULL, }; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH 2/8] misc: ddr: add LPDDR2 data from JESD209-2
add LPDDR2 data from the JEDEC spec JESD209-2. The data includes: 1. Addressing information for LPDDR2 memories of different densities and types(S2/S4) 2. AC timing data. This data will useful for memory controller device drivers Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/Kconfig |8 ++ drivers/misc/Makefile |1 + drivers/misc/jedec_ddr_data.c | 141 + include/linux/jedec_ddr.h | 174 + 4 files changed, 324 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/jedec_ddr_data.c create mode 100644 include/linux/jedec_ddr.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 6a1a092..8337bf6 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -451,6 +451,14 @@ config VMWARE_BALLOON To compile this driver as a module, choose M here: the module will be called vmw_balloon. +config DDR + bool JEDEC DDR data + help + Data from JEDEC specs for DDR SDRAM memories, + particularly the AC timing parameters and addressing + information. This data is useful for drivers handling + DDR SDRAM controllers. + config ARM_CHARLCD bool ARM Ltd. Character LCD Driver depends on PLAT_VERSATILE diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 3e1d801..4759166 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o +obj-$(CONFIG_DDR) += jedec_ddr_data.o obj-y += eeprom/ obj-y += cb710/ obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)+= spear13xx_pcie_gadget.o diff --git a/drivers/misc/jedec_ddr_data.c b/drivers/misc/jedec_ddr_data.c new file mode 100644 index 000..299c056 --- /dev/null +++ b/drivers/misc/jedec_ddr_data.c @@ -0,0 +1,141 @@ +/* + * DDR addressing details and AC timing parameters from JEDEC specs + * + * Copyright (C) 2010 Texas Instruments, Inc. + * + * Aneesh V ane...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/jedec_ddr.h +#include linux/module.h + +/* LPDDR2 addressing details from JESD209-2 section 2.4 */ +const struct lpddr2_addressing lpddr2_jedec_addressing_table[] = { + {B4, T_REFI_15_6, T_RFC_90}, /* 64M */ + {B4, T_REFI_15_6, T_RFC_90}, /* 128M */ + {B4, T_REFI_7_8, T_RFC_90}, /* 256M */ + {B4, T_REFI_7_8, T_RFC_90}, /* 512M */ + {B8, T_REFI_7_8, T_RFC_130}, /* 1GS4 */ + {B8, T_REFI_3_9, T_RFC_130}, /* 2GS4 */ + {B8, T_REFI_3_9, T_RFC_130}, /* 4G */ + {B8, T_REFI_3_9, T_RFC_210}, /* 8G */ + {B4, T_REFI_7_8, T_RFC_130}, /* 1GS2 */ + {B4, T_REFI_3_9, T_RFC_130}, /* 2GS2 */ +}; +EXPORT_SYMBOL(lpddr2_jedec_addressing_table); + +/* LPDDR2 AC timing parameters from JESD209-2 section 12 */ +const struct lpddr2_timings lpddr2_jedec_timings[] = { + /* Speed bin 400(200 MHz) */ + [0] = { + .max_freq = 2, + .min_freq = 1000, + .tRPab = 21000, + .tRCD = 18000, + .tWR= 15000, + .tRAS_min = 42000, + .tRRD = 1, + .tWTR = 1, + .tXP= 7500, + .tRTP = 7500, + .tCKESR = 15000, + .tDQSCK_max = 5500, + .tFAW = 5, + .tZQCS = 9, + .tZQCL = 36, + .tZQinit= 100, + .tRAS_max_ns= 7, + .tRTW = 7500, + .tAONPD = 1000, + .tDQSCK_max_derated = 6000, + }, + /* Speed bin 533(266 MHz) */ + [1] = { + .max_freq = 2, + .min_freq = 1000, + .tRPab = 21000, + .tRCD = 18000, + .tWR= 15000, + .tRAS_min = 42000, + .tRRD = 1, + .tWTR = 7500, + .tXP= 7500, + .tRTP = 7500, + .tCKESR = 15000, + .tDQSCK_max = 5500, + .tFAW = 5, + .tZQCS = 9, + .tZQCL = 36, + .tZQinit= 100, + .tRAS_max_ns= 7, + .tRTW = 7500, + .tAONPD = 1000
[RFC PATCH 3/8] misc: emif: add register definitions for EMIF
Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/emif_regs.h | 461 ++ 1 files changed, 461 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif_regs.h diff --git a/drivers/misc/emif_regs.h b/drivers/misc/emif_regs.h new file mode 100644 index 000..6ec818a --- /dev/null +++ b/drivers/misc/emif_regs.h @@ -0,0 +1,461 @@ +/* + * EMIF registers and bitfields + * + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Benoit Cousson (b-cous...@ti.com) + * + * This file is automatically generated from the OMAP hardware databases. + * We respectfully ask that any modifications to this file be coordinated + * with the public linux-omap@vger.kernel.org mailing list and the + * authors above to ensure that the autogeneration scripts are kept + * up-to-date with the file contents. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __EMIF_REGS_H +#define __EMIF_REGS_H + +/* Registers offset */ +#define EMIF_MODULE_ID_AND_REVISION0x +#define EMIF_STATUS0x0004 +#define EMIF_SDRAM_CONFIG 0x0008 +#define EMIF_SDRAM_CONFIG_20x000c +#define EMIF_SDRAM_REFRESH_CONTROL 0x0010 +#define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 +#define EMIF_SDRAM_TIMING_10x0018 +#define EMIF_SDRAM_TIMING_1_SHDW 0x001c +#define EMIF_SDRAM_TIMING_20x0020 +#define EMIF_SDRAM_TIMING_2_SHDW 0x0024 +#define EMIF_SDRAM_TIMING_30x0028 +#define EMIF_SDRAM_TIMING_3_SHDW 0x002c +#define EMIF_LPDDR2_NVM_TIMING 0x0030 +#define EMIF_LPDDR2_NVM_TIMING_SHDW0x0034 +#define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW0x003c +#define EMIF_LPDDR2_MODE_REG_DATA 0x0040 +#define EMIF_LPDDR2_MODE_REG_CONFIG0x0050 +#define EMIF_OCP_CONFIG0x0054 +#define EMIF_OCP_CONFIG_VALUE_10x0058 +#define EMIF_OCP_CONFIG_VALUE_20x005c +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 +#define EMIF_PERFORMANCE_COUNTER_1 0x0080 +#define EMIF_PERFORMANCE_COUNTER_2 0x0084 +#define EMIF_PERFORMANCE_COUNTER_CONFIG0x0088 +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c +#define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 +#define EMIF_MISC_REG 0x0094 +#define EMIF_DLL_CALIB_CTRL0x0098 +#define EMIF_DLL_CALIB_CTRL_SHDW 0x009c +#define EMIF_END_OF_INTERRUPT 0x00a0 +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac +#define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 +#define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc +#define EMIF_OCP_ERROR_LOG 0x00d0 +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 +#define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc +#define EMIF_DDR_PHY_CTRL_10x00e4 +#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 +#define EMIF_DDR_PHY_CTRL_20x00ec +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING
[RFC PATCH 4/8] misc: emif: add basic infrastructure for EMIF driver
EMIF is an SDRAM controller used in various Texas Instruments SoCs. EMIF supports, based on its revision, one or more of LPDDR2/DDR2/DDR3 protocols. Add the basic infrastructure for EMIF driver that includes driver registration, probe, parsing of platform data etc. Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/Kconfig | 12 ++ drivers/misc/Makefile |1 + drivers/misc/emif.c | 300 + include/linux/emif.h | 160 ++ 4 files changed, 473 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/emif.c create mode 100644 include/linux/emif.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8337bf6..d68184a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -459,6 +459,18 @@ config DDR information. This data is useful for drivers handling DDR SDRAM controllers. +config EMIF + tristate Texas Instruments EMIF driver + select DDR + help + This driver is for the EMIF module available in Texas Instruments + SoCs. EMIF is an SDRAM controller that, based on its revision, + supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. + This driver takes care of only LPDDR2 memories presently. The + functions of the driver includes re-configuring AC timing + parameters and other settings during frequency, voltage and + temperature changes + config ARM_CHARLCD bool ARM Ltd. Character LCD Driver depends on PLAT_VERSATILE diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 4759166..076db0f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o obj-$(CONFIG_DDR) += jedec_ddr_data.o +obj-$(CONFIG_EMIF) += emif.o obj-y += eeprom/ obj-y += cb710/ obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)+= spear13xx_pcie_gadget.o diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c new file mode 100644 index 000..ba1e3f9 --- /dev/null +++ b/drivers/misc/emif.c @@ -0,0 +1,300 @@ +/* + * EMIF driver + * + * Copyright (C) 2010 Texas Instruments, Inc. + * + * Aneesh V ane...@ti.com + * Santosh Shilimkar santosh.shilim...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include linux/kernel.h +#include linux/reboot.h +#include linux/emif.h +#include linux/io.h +#include linux/device.h +#include linux/platform_device.h +#include linux/interrupt.h +#include linux/slab.h +#include linux/seq_file.h +#include linux/module.h +#include linux/spinlock.h +#include emif_regs.h + +/** + * struct emif_data - Per device static data for driver's use + * @duplicate: Whether the DDR devices attached to this EMIF + * instance are exactly same as that on EMIF1. In + * this case we can save some memory and processing + * @temperature_level: Maximum temperature of LPDDR2 devices attached + * to this EMIF - read from MR4 register. If there + * are two devices attached to this EMIF, this + * value is the maximum of the two temperature + * levels. + * @irq: IRQ number + * @lock: lock for protecting temperature_level and + * associated actions from race conditions + * @base: base address of memory-mapped IO registers. + * @dev: device pointer. + * @addressing table with addressing information from the spec + * @regs_cache:An array of 'struct emif_regs' that stores + * calculated register values for different + * frequencies, to avoid re-calculating them on + * each DVFS transition. + * @curr_regs: The set of register values used in the last + * frequency change (i.e. corresponding to the + * frequency in effect at the moment) + * @plat_data: Pointer to saved platform data. + */ +struct emif_data { + u8 duplicate; + u8 temperature_level; + u32 irq; + spinlock_t lock; /* lock to prevent races */ + void __iomem*base; + struct device *dev; + const struct lpddr2_addressing *addressing; + struct emif_regs
[RFC PATCH 5/8] misc: emif: handle frequency and voltage change events
Change SDRAM timings and other settings as necessary on voltage and frequency changes. We calculate these register settings based on data from the device data sheet and inputs such a frequency, voltage state(stable or ramping), temperature level etc. Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/emif.c | 741 ++ include/linux/emif.h | 97 +++ 2 files changed, 838 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index ba1e3f9..36ba6f4 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -62,6 +62,527 @@ struct emif_data { }; static struct emif_data *emif1; +static u32 t_ck; /* DDR clock period in ps */ + +/* + * Calculate the period of DDR clock from frequency value + */ +static void set_ddr_clk_period(u32 freq) +{ + /* Divide 10^12 by frequency to get period in ps */ + t_ck = (u32)DIV_ROUND_UP_ULL(1ull, freq); +} + +/* + * Get the CL from SDRAM_CONFIG register + */ +static u32 get_cl(struct emif_data *emif) +{ + u32 cl; + void __iomem*base = emif-base; + + cl = (readl(base + EMIF_SDRAM_CONFIG) CL_MASK) CL_SHIFT; + + return cl; +} + +static void do_freq_update(void) +{ + /* TODO: Add an implementation when DVFS framework is available */ +} + +/* Find addressing table entry based on the device's type and density */ +static const struct lpddr2_addressing *get_addressing_table( + const struct ddr_device_info *device_info) +{ + u32 index, type, density; + + type = device_info-type; + density = device_info-density; + + switch (type) { + case DDR_TYPE_LPDDR2_S4: + index = density - 1; + break; + case DDR_TYPE_LPDDR2_S2: + switch (density) { + case DDR_DENSITY_1Gb: + case DDR_DENSITY_2Gb: + index = density + 3; + break; + default: + index = density - 1; + } + break; + default: + return NULL; + } + + return lpddr2_jedec_addressing_table[index]; +} + +/* + * Find the the right timing table from the array of timing + * tables of the device using DDR clock frequency + */ +static const struct lpddr2_timings *get_timings_table(struct emif_data *emif, + u32 freq) +{ + u32 i, min, max, freq_nearest; + const struct lpddr2_timings *timings = NULL; + const struct lpddr2_timings *timings_arr = emif-plat_data-timings; + struct device *dev = emif-dev; + + /* Start with a very high frequency - 1GHz */ + freq_nearest = 10; + + /* +* Find the timings table such that: +* 1. the frequency range covers the required frequency(safe) AND +* 2. the max_freq is closest to the required frequency(optimal) +*/ + for (i = 0; i emif-plat_data-timings_arr_size; i++) { + max = timings_arr[i].max_freq; + min = timings_arr[i].min_freq; + if ((freq = min) (freq = max) (max freq_nearest)) { + freq_nearest = max; + timings = timings_arr[i]; + } + } + + if (!timings) + dev_err(dev, Couldn't find timings for - %dHz\n, freq); + + dev_dbg(dev, timings table: freq %d, speed bin freq %d\n, + freq, freq_nearest); + + return timings; +} + +static u32 get_sdram_ref_ctrl_shdw(u32 freq, + const struct lpddr2_addressing *addressing) +{ + u32 ref_ctrl_shdw = 0, val = 0, freq_khz, t_refi; + + /* Scale down frequency and t_refi to avoid overflow */ + freq_khz = freq / 1000; + t_refi = addressing-tREFI_ns / 100; + + /* +* refresh rate to be set is 'tREFI(in us) * freq in MHz +* division by 1 to account for change in units +*/ + val = t_refi * freq_khz / 1; + ref_ctrl_shdw |= val REFRESH_RATE_SHIFT; + + return ref_ctrl_shdw; +} + +static u32 get_sdram_tim_1_shdw(const struct lpddr2_timings *timings, + const struct lpddr2_min_tck *min_tck, + const struct lpddr2_addressing *addressing, + u32 ip_rev) +{ + u32 tim1 = 0, val = 0; + + val = max(min_tck-tWTR, DIV_ROUND_UP(timings-tWTR, t_ck)) - 1; + tim1 |= val T_WTR_SHIFT; + + if (addressing-num_banks == B8) + val = DIV_ROUND_UP(timings-tFAW, t_ck*4); + else + val = max(min_tck-tRRD, DIV_ROUND_UP(timings-tRRD, t_ck)); + tim1 |= (val - 1) T_RRD_SHIFT; + + val = DIV_ROUND_UP(timings-tRAS_min + timings-tRPab, t_ck) - 1; + tim1 |= val T_RC_SHIFT; + + val = max(min_tck-tRASmin, DIV_ROUND_UP(timings-tRAS_min, t_ck)); + tim1 |= (val - 1
[RFC PATCH 6/8] misc: emif: add interrupt and temperature handling
Add an ISR for EMIF that: 1. reports details of access errors 2. takes action on thermal events On thermal events SDRAM timing parameters are adjusted to ensure safe operation Also clear all interrupts on shut-down. Pending IRQs may casue problems during warm-reset. Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/emif.c | 209 ++- 1 files changed, 207 insertions(+), 2 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 36ba6f4..5c2b0ae 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -500,6 +500,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) } /* + * Get the temperature level of the EMIF instance: + * Reads the MR4 register of attached SDRAM parts to find out the temperature + * level. If there are two parts attached(one on each CS), then the temperature + * level for the EMIF instance is the higher of the two temperatures. + */ +static void get_temperature_level(struct emif_data *emif) +{ + u32 temp, temperature_level; + unsigned long irqs; + void __iomem*base; + + base = emif-base; + + /* Read mode register 4 */ + writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temperature_level = (temperature_level MR4_SDRAM_REF_RATE_MASK) + MR4_SDRAM_REF_RATE_SHIFT; + + if (emif-plat_data-device_info-cs1_used) { + writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG); + temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA); + temp = (temp MR4_SDRAM_REF_RATE_MASK) +MR4_SDRAM_REF_RATE_SHIFT; + temperature_level = max(temp, temperature_level); + } + + spin_lock_irqsave(emif-lock, irqs); + /* treat everything less than nominal(3) in MR4 as nominal */ + if (unlikely(temperature_level SDRAM_TEMP_NOMINAL)) + temperature_level = SDRAM_TEMP_NOMINAL; + + /* if we get reserved value in MR4 persist with the existing value */ + if (likely(temperature_level != SDRAM_TEMP_RESERVED_4)) + emif-temperature_level = temperature_level; + spin_unlock_irqrestore(emif-lock, irqs); +} + +/* * Program EMIF shadow registers that are not dependent on temperature * or voltage */ @@ -553,7 +592,8 @@ static void setup_volt_sensitive_regs(struct emif_data *emif, static void setup_temperature_sensitive_regs(struct emif_data *emif, struct emif_regs *regs) { - u32 tim1, tim3, ref_ctrl, type, irqs; + u32 tim1, tim3, ref_ctrl, type; + unsigned long irqs; void __iomem*base = emif-base; u32 temperature; @@ -568,7 +608,7 @@ static void setup_temperature_sensitive_regs(struct emif_data *emif, if (type != DDR_TYPE_LPDDR2_S2 type != DDR_TYPE_LPDDR2_S4) goto out; - temperature_level = emif-temperature_level; + temperature = emif-temperature_level; if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH) { ref_ctrl = regs-ref_ctrl_shdw_derated; } else if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS) { @@ -584,6 +624,153 @@ out: spin_unlock_irqrestore(emif-lock, irqs); } +static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) +{ + u32 old_temp_level; + + old_temp_level = emif-temperature_level; + get_temperature_level(emif); + + if (unlikely(emif-temperature_level == old_temp_level)) + goto handled; + + if (emif-temperature_level old_temp_level || + emif-temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { + /* +* Temperature coming down - defer handling to thread OR +* Temperature far too high - do kernel_power_off() from +* thread context +*/ + goto thread; + } else { + /* Temperature is going up - handle immediately */ + if (!emif-curr_regs) { + dev_err(emif-dev, temperature alert before registers are calculated, not de-rating timings\n); + goto handled; + } + setup_temperature_sensitive_regs(emif, emif-curr_regs); + do_freq_update(); + } + +handled: + return IRQ_HANDLED; +thread: + return IRQ_WAKE_THREAD; +} + +static irqreturn_t emif_interrupt_handler(int irq, void *dev_id) +{ + u32 interrupts; + struct emif_data*emif = dev_id; + void __iomem*base = emif-base; + struct device *dev = emif-dev; + irqreturn_t ret = IRQ_HANDLED; + + /* Save the status and clear
[RFC PATCH 7/8] misc: emif: add one-time settings
Add settings that are not dependent on frequency or any other transient parameters Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/emif.c | 147 +++ 1 files changed, 147 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 5c2b0ae..9d24cc7 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -74,6 +74,24 @@ static void set_ddr_clk_period(u32 freq) } /* + * Get bus width used by EMIF. Note that this may be different from the + * bus width of the DDR devices used. For instance two 16-bit DDR devices + * may be connected to a given CS of EMIF. In this case bus width as far + * as EMIF is concerned is 32, where as the DDR bus width is 16 bits. + */ +static u32 get_emif_bus_width(struct emif_data *emif) +{ + u32 width; + void __iomem*base = emif-base; + + width = (readl(base + EMIF_SDRAM_CONFIG) NARROW_MODE_MASK) +NARROW_MODE_SHIFT; + width = width == 0 ? 32 : 16; + + return width; +} + +/* * Get the CL from SDRAM_CONFIG register */ static u32 get_cl(struct emif_data *emif) @@ -331,6 +349,70 @@ static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings, return tim3; } +static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing, + bool cs1_used, bool cal_resistors_per_cs) +{ + u32 zq = 0, val = 0; + + val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing-tREFI_ns; + zq |= val ZQ_REFINTERVAL_SHIFT; + + val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1; + zq |= val ZQ_ZQCL_MULT_SHIFT; + + val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1; + zq |= val ZQ_ZQINIT_MULT_SHIFT; + + zq |= ZQ_SFEXITEN_ENABLE ZQ_SFEXITEN_SHIFT; + + if (cal_resistors_per_cs) + zq |= ZQ_DUALCALEN_ENABLE ZQ_DUALCALEN_SHIFT; + else + zq |= ZQ_DUALCALEN_DISABLE ZQ_DUALCALEN_SHIFT; + + zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */ + + val = cs1_used ? 1 : 0; + zq |= val ZQ_CS1EN_SHIFT; + + return zq; +} + +static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing, + const struct emif_custom_configs *custom_configs, bool cs1_used, + u32 sdram_io_width, u32 emif_bus_width) +{ + u32 alert = 0, interval, devcnt; + + if (custom_configs (custom_configs-mask + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)) + interval = custom_configs-temp_alert_poll_interval_ms; + else + interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS; + + interval *= 100;/* Convert to ns */ + interval /= addressing-tREFI_ns; /* Convert to refresh cycles */ + alert |= (interval TA_REFINTERVAL_SHIFT); + + /* +* sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width +* also to this form and subtract to get TA_DEVCNT, which is +* in log2(x) form. +*/ + emif_bus_width = __fls(emif_bus_width) - 1; + devcnt = emif_bus_width - sdram_io_width; + alert |= devcnt TA_DEVCNT_SHIFT; + + /* DEVWDT is in 'log2(x) - 3' form */ + alert |= (sdram_io_width - 2) TA_DEVWDT_SHIFT; + + alert |= 1 TA_SFEXITEN_SHIFT; + alert |= 1 TA_CS0EN_SHIFT; + alert |= (cs1_used ? 1 : 0) TA_CS1EN_SHIFT; + + return alert; +} + static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) { u32 idle = 0, val = 0; @@ -771,6 +853,70 @@ static int __init setup_interrupts(struct emif_data *emif) } +static void __init emif_onetime_settings(struct emif_data *emif) +{ + u32 pwr_mgmt_ctrl, zq, temp_alert_cfg; + void __iomem*base = emif-base; + const struct lpddr2_addressing *addressing; + const struct ddr_device_info*device_info; + + device_info = emif-plat_data-device_info; + addressing = get_addressing_table(device_info); + + /* +* Init power management settings +* We don't know the frequency yet. Use a high frequency +* value for a conservative timeout setting +*/ + pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(10, emif, + emif-plat_data-ip_rev); + writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL); + + /* Init ZQ calibration settings */ + zq = get_zq_config_reg(addressing, device_info-cs1_used, + device_info-cal_resistors_per_cs); + writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG); + + /* Check temperature level temperature level*/ + get_temperature_level(emif); + if (emif-temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) + dev_emerg(emif-dev, SDRAM temperature exceeds operating limit.. Needs shut down!!!\n); + + /* Init temperature
[RFC PATCH 8/8] misc: emif: add debugfs entries for emif
Add debug entries for: 1. calculated registers per frequency 2. last polled value of MR4(temperature level of LPDDR2 memory) Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/emif.c | 129 +++ 1 files changed, 129 insertions(+), 0 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index 9d24cc7..f67a9e7 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #include linux/platform_device.h #include linux/interrupt.h #include linux/slab.h +#include linux/debugfs.h #include linux/seq_file.h #include linux/module.h #include linux/spinlock.h @@ -47,6 +48,7 @@ * frequency change (i.e. corresponding to the * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. + * @debugfs_root: dentry to the root folder for EMIF in debugfs */ struct emif_data { u8 duplicate; @@ -59,11 +61,136 @@ struct emif_data { struct emif_regs*regs_cache[EMIF_MAX_NUM_FREQUENCIES]; struct emif_regs*curr_regs; struct emif_platform_data *plat_data; + struct dentry *debugfs_root; }; static struct emif_data *emif1; static u32 t_ck; /* DDR clock period in ps */ +static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, + struct emif_regs *regs) +{ + u32 type = emif-plat_data-device_info-type; + u32 ip_rev = emif-plat_data-ip_rev; + + seq_printf(s, EMIF register cache dump for %dMHz\n, + regs-freq/10); + + seq_printf(s, ref_ctrl_shdw\t: 0x%08x\n, regs-ref_ctrl_shdw); + seq_printf(s, sdram_tim1_shdw\t: 0x%08x\n, regs-sdram_tim1_shdw); + seq_printf(s, sdram_tim2_shdw\t: 0x%08x\n, regs-sdram_tim2_shdw); + seq_printf(s, sdram_tim3_shdw\t: 0x%08x\n, regs-sdram_tim3_shdw); + + if (ip_rev == EMIF_4D) { + seq_printf(s, read_idle_ctrl_shdw_normal\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_normal); + seq_printf(s, read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-read_idle_ctrl_shdw_volt_ramp); + } else if (ip_rev == EMIF_4D5) { + seq_printf(s, dll_calib_ctrl_shdw_normal\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_normal); + seq_printf(s, dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n, + regs-dll_calib_ctrl_shdw_volt_ramp); + } + + if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { + seq_printf(s, ref_ctrl_shdw_derated\t: 0x%08x\n, + regs-ref_ctrl_shdw_derated); + seq_printf(s, sdram_tim1_shdw_derated\t: 0x%08x\n, + regs-sdram_tim1_shdw_derated); + seq_printf(s, sdram_tim3_shdw_derated\t: 0x%08x\n, + regs-sdram_tim3_shdw_derated); + } +} + +static int emif_regdump_show(struct seq_file *s, void *unused) +{ + struct emif_data*emif = s-private; + struct emif_regs**regs_cache; + int i; + + if (emif-duplicate) + regs_cache = emif1-regs_cache; + else + regs_cache = emif-regs_cache; + + for (i = 0; i EMIF_MAX_NUM_FREQUENCIES regs_cache[i]; i++) { + do_emif_regdump_show(s, emif, regs_cache[i]); + seq_printf(s, \n); + } + + return 0; +} + +static int emif_regdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_regdump_show, inode-i_private); +} + +static const struct file_operations emif_regdump_fops = { + .open = emif_regdump_open, + .read = seq_read, + .release= single_release, +}; + +static int emif_mr4_show(struct seq_file *s, void *unused) +{ + struct emif_data *emif = s-private; + + seq_printf(s, MR4=%d\n, emif-temperature_level); + return 0; +} + +static int emif_mr4_open(struct inode *inode, struct file *file) +{ + return single_open(file, emif_mr4_show, inode-i_private); +} + +static const struct file_operations emif_mr4_fops = { + .open = emif_mr4_open, + .read = seq_read, + .release= single_release, +}; + +static int __init emif_debugfs_init(struct emif_data *emif) +{ + struct dentry *dentry; + int ret; + + dentry = debugfs_create_dir(dev_name(emif-dev), NULL); + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); + goto err0; + } + emif-debugfs_root = dentry; + + dentry = debugfs_create_file(regcache_dump, S_IRUGO, + emif-debugfs_root, emif, emif_regdump_fops); + if (IS_ERR
[RFC v4 PATCH 0/4] dt: device tree support for TI EMIF driver
This series adds device tree support for TI EMIF SDRAM controller driver. For this, a binding has been added for representing AC timing parameters and other details of LPDDR2 memories. This series depends on the series for adding EMIF driver [1] Changes in RFC v3: * Removed support for DDR3 * Incorporated review comments from Olof Changes from RFC v3 to RFC v4: * Added a new patch to add DT support in the EMIF driver [1] http://marc.info/?l=linux-omapm=132835811606125w=2 Aneesh V (4): dt: device tree bindings for LPDDR2 memories dt: emif: device tree bindings for TI's EMIF sdram controller arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards misc: emif: add device tree support to emif driver .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 54 .../devicetree/bindings/lpddr2/lpddr2.txt | 102 +++ .../bindings/memory-controllers/ti/emif.txt| 55 arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 71 + arch/arm/boot/dts/omap4-panda.dts | 13 + arch/arm/boot/dts/omap4-sdp.dts| 13 + arch/arm/boot/dts/omap4.dtsi | 18 ++ drivers/misc/emif.c| 281 +++- 8 files changed, 606 insertions(+), 1 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v4 PATCH 1/4] dt: device tree bindings for LPDDR2 memories
device tree bindings for LPDDR2 SDRAM memories compliant to JESD209-2 standard. The 'lpddr2' binding in-turn uses another binding 'lpddr2-timings' for specifying the AC timing parameters of the memory device at different speed-bins. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- --- .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 54 ++ .../devicetree/bindings/lpddr2/lpddr2.txt | 102 2 files changed, 156 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt new file mode 100644 index 000..c405e44 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt @@ -0,0 +1,54 @@ +* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin + +Required properties: +- compatible : Should be jedec,lpddr2-timings +- min-freq : minimum DDR clock frequency for the speed-bin. Type is u32 +- max-freq : maximum DDR clock frequency for the speed-bin. Type is u32 + +Optional properties: + +The following properties represent AC timing parameters from the memory +data-sheet of the device for a given speed-bin. All these properties are +of type u32 and the default unit is ps (pico seconds). Parameters with +a different unit have a suffix indicating the unit such as 'tRAS-max-ns' +- tRCD +- tWR +- tRAS-min +- tRRD +- tWTR +- tXP +- tRTP +- tDQSCK-max +- tFAW +- tZQCS +- tZQinit +- tRPab +- tZQCL +- tCKESR +- tRAS-max-ns +- tRTW +- tAONPD +- tDQSCK-max-derated + +Example: + +timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; +}; diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt new file mode 100644 index 000..a2ab203 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt @@ -0,0 +1,102 @@ +* LPDDR2 SDRAM memories compliant to JEDEC JESD209-2 + +Required properties: +- compatible : Should be one of - jedec,lpddr2-nvm, jedec,lpddr2-s2, + jedec,lpddr2-s4 + + ti,jedec-lpddr2-s2 should be listed if the memory part is LPDDR2-S2 type + + ti,jedec-lpddr2-s4 should be listed if the memory part is LPDDR2-S4 type + + ti,jedec-lpddr2-nvm should be listed if the memory part is LPDDR2-NVM type + +- density : u32 representing density in Mb (Mega bits) + +- io-width : u32 representing bus width. Possible values are 8, 16, and 32 + +Optional properties: + +The following optional properties represent the minimum value of some AC +timing parameters of the DDR device in terms of number of clock cycles. +These values shall be obtained from the device data-sheet. +- tRRD-min-tck +- tWTR-min-tck +- tXP-min-tck +- tRTP-min-tck +- tCKE-min-tck +- tRPab-min-tck +- tRCD-min-tck +- tWR-min-tck +- tRASmin-min-tck +- tCKESR-min-tck +- tFAW-min-tck + +Child nodes: +- The lpddr2 node may have one or more child nodes of type lpddr2-timings. + lpddr2-timings provides AC timing parameters of the device for + a given speed-bin. The user may provide the timings for as many + speed-bins as is required. Please see Documentation/devicetree/ + bindings/lpddr2/lpddr2-timings.txt for more information on lpddr2-timings + +Example: + +elpida_ECB240ABACN : lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500
[RFC v4 PATCH 2/4] dt: emif: device tree bindings for TI's EMIF sdram controller
EMIF - External Memory Interface - is an SDRAM controller used in TI SoCs. EMIF supports, based on the IP revision, one or more of DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance of the EMIF IP and memory parts attached to it. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- --- .../bindings/memory-controllers/ti/emif.txt| 55 1 files changed, 55 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt new file mode 100644 index 000..938f8e1 --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt @@ -0,0 +1,55 @@ +* EMIF family of TI SDRAM controllers + +EMIF - External Memory Interface - is an SDRAM controller used in +TI SoCs. EMIF supports, based on the IP revision, one or more of +DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance +of the EMIF IP and memory parts attached to it. + +Required properties: +- compatible : Should be of the form ti,emif-ip-rev where ip-rev + is the IP revision of the specific EMIF instance. + +- phy-type : u32 indicating the DDR phy type. Following are the + allowed values + 1 : Attila PHY + 2 : Intelli PHY + +- device-handle: phandle to a lpddr2 node representing the memory part + +- ti,hwmods: For TI hwmods processing and omap device creation + the value shall be emifn where n is the number of the EMIF + instance with base 1. + +Optional properties: +- cs1-used : Have this property if CS1 of this EMIF + instance has a memory part attached to it. If there is a memory + part attached to CS1, it should be the same type as the one on CS0, + so there is no need to give the details of this memory part. + +- cal-resistor-per-cs : Have this property if the board has one + calibration resistor per chip-select. + +- hw-caps-read-idle-ctrl: Have this property if the controller + supports read idle window programming + +- hw-caps-dll-calib-ctrl: Have this property if the controller + supports dll calibration control + +- hw-caps-ll-interface : Have this property if the controller + has a low latency interface and corresponding interrupt events + +- hw-caps-temp-alert : Have this property if the controller + has capability for generating SDRAM temperature alerts + +Example: + +emif1: emif@0x4c00 { + compatible = ti,emif-4d; + ti,hwmods = emif2; + phy-type= 1; + device-handle = elpida_ECB240ABACN; + cs1-used; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; + hw-caps-temp-alert; +}; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v4 PATCH 3/4] arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards
Device tree data for the EMIF sdram controllers in OMAP4 and LPDDR2 memory devices attached to OMAP4 boards. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 71 + arch/arm/boot/dts/omap4-panda.dts | 13 + arch/arm/boot/dts/omap4-sdp.dts | 13 + arch/arm/boot/dts/omap4.dtsi | 18 +++ 4 files changed, 115 insertions(+), 0 deletions(-) create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi new file mode 100644 index 000..b384861 --- /dev/null +++ b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi @@ -0,0 +1,71 @@ +/* + * Common devices used in different OMAP boards + */ + +/ { + elpida_ECB240ABACN: lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + tRTW= 7500; + tAONPD = 1000; + tDQSCK-max-derated = 6000; + }; + + timings_elpida_ECB240ABACN_200mhz: lpddr2-timings@1 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 2; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 1; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + tRTW= 7500; + tAONPD = 1000; + tDQSCK-max-derated = 6000; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index 9755ad5..f548523 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 PandaBoard; @@ -17,4 +18,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 63c6b2b..6dc08bc 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 SDP board; @@ -17,4 +18,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB
[RFC v4 PATCH 4/4] misc: emif: add device tree support to emif driver
Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- drivers/misc/emif.c | 281 ++- 1 files changed, 280 insertions(+), 1 deletions(-) diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c index f67a9e7..2fc0813 100644 --- a/drivers/misc/emif.c +++ b/drivers/misc/emif.c @@ -18,6 +18,7 @@ #include linux/platform_device.h #include linux/interrupt.h #include linux/slab.h +#include linux/of.h #include linux/debugfs.h #include linux/seq_file.h #include linux/module.h @@ -49,6 +50,7 @@ * frequency in effect at the moment) * @plat_data: Pointer to saved platform data. * @debugfs_root: dentry to the root folder for EMIF in debugfs + * @np_ddr:Pointer to ddr device tree node */ struct emif_data { u8 duplicate; @@ -62,6 +64,9 @@ struct emif_data { struct emif_regs*curr_regs; struct emif_platform_data *plat_data; struct dentry *debugfs_root; +#if defined(CONFIG_OF) + struct device_node *np_ddr; +#endif }; static struct emif_data *emif1; @@ -1117,6 +1122,263 @@ static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, return valid; } +#if defined(CONFIG_OF) +static void __init of_get_custom_configs(struct device_node *np_emif, + struct emif_data *emif) +{ + struct emif_custom_configs *cust_cfgs = NULL; + int len; + const int *lpmode, *poll_intvl; + + lpmode = of_get_property(np_emif, low-power-mode, len); + poll_intvl = of_get_property(np_emif, temp-alert-poll-interval, len); + + if (lpmode || poll_intvl) + cust_cfgs = kzalloc(sizeof(*cust_cfgs), GFP_KERNEL); + + if (!cust_cfgs) + return; + + if (lpmode) { + cust_cfgs-mask |= EMIF_CUSTOM_CONFIG_LPMODE; + cust_cfgs-lpmode = *lpmode; + of_property_read_u32(np_emif, + low-power-mode-timeout-performance, + cust_cfgs-lpmode_timeout_performance); + of_property_read_u32(np_emif, + low-power-mode-timeout-power, + cust_cfgs-lpmode_timeout_power); + of_property_read_u32(np_emif, + low-power-mode-freq-threshold, + cust_cfgs-lpmode_freq_threshold); + } + + if (poll_intvl) { + cust_cfgs-mask |= + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL; + cust_cfgs-temp_alert_poll_interval_ms = *poll_intvl; + } + + if (!is_custom_config_valid(cust_cfgs, emif-dev)) { + kfree(cust_cfgs); + return; + } + + emif-plat_data-custom_configs = cust_cfgs; +} + +static void __init of_get_min_tck(struct device_node *np, + struct emif_data *emif) +{ + int ret = 0; + struct lpddr2_min_tck *min; + + min = kzalloc(sizeof(*min), GFP_KERNEL); + if (!min) + goto default_min_tck; + + ret |= of_property_read_u32(np, tRPab-min-tck, min-tRPab); + ret |= of_property_read_u32(np, tRCD-min-tck, min-tRCD); + ret |= of_property_read_u32(np, tWR-min-tck, min-tWR); + ret |= of_property_read_u32(np, tRASmin-min-tck, min-tRASmin); + ret |= of_property_read_u32(np, tRRD-min-tck, min-tRRD); + ret |= of_property_read_u32(np, tWTR-min-tck, min-tWTR); + ret |= of_property_read_u32(np, tXP-min-tck, min-tXP); + ret |= of_property_read_u32(np, tRTP-min-tck, min-tRTP); + ret |= of_property_read_u32(np, tCKE-min-tck, min-tCKE); + ret |= of_property_read_u32(np, tCKESR-min-tck, min-tCKESR); + ret |= of_property_read_u32(np, tFAW-min-tck, min-tFAW); + + if (ret) { + kfree(min); + goto default_min_tck; + } + + emif-plat_data-min_tck = min; + return; + +default_min_tck: + dev_warn(emif-dev, Using default min-tck values\n); + emif-plat_data-min_tck = lpddr2_min_tck; +} + +static int __init of_do_get_timings(struct device_node *np, + struct lpddr2_timings *tim) +{ + int ret; + + ret = of_property_read_u32(np, max-freq, tim-max_freq); + ret |= of_property_read_u32(np, min-freq, tim-min_freq); + ret |= of_property_read_u32(np, tRPab, tim-tRPab); + ret |= of_property_read_u32(np, tRCD, tim-tRCD); + ret |= of_property_read_u32(np, tWR, tim-tWR); + ret |= of_property_read_u32(np, tRAS-min, tim-tRAS_min); + ret |= of_property_read_u32(np, tRRD, tim-tRRD); + ret |= of_property_read_u32(np, tWTR, tim-tWTR); + ret
Re: OMAP3 L2/outer cache enabled in kernel (after being disabled by uBoot)?
Hi Catalin, On Friday 27 January 2012 11:00 PM, Catalin Marinas wrote: On Fri, Jan 20, 2012 at 08:57:11AM +, Joe Woodward wrote: So I re-iterate that we need to have solution to this problem. ... I don't want to be a pain, but it seems to me that this dicussion didn't reach a full conclussion? Probably not, because it depends on many variables. See below my take on this. I think it was left with the open options being: 1) Leave the L2/outer cache enabled in the bootloader (not ideal and may cause problems with future devices) This depends on whether the L2 is inner or outer: L2 inner - leave it enabled in the boot loader L2 outer - leave it disabled in the boot loader 2) Turn the L2/outer cache on for OMAP3 later in the kernel boot when the device is known Same as above: L2 inner - don't do anything, it gets used when SCTLR.M is enabled L2 outer - enabled at boot time via the platform code (later, after MMU was enabled). What is the reasoning behind this recommendation? Why the distinction between L2 being inner or outer. I don't see anything to this effect in the Cortex-A8 TRM? In fact the only recommendation I could find(section 8.3) is asking to set L2EN to 1 before setting C bit to 1 irrespective of inner/outer? br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v3 PATCH 1/3] dt: device tree bindings for DDR memories
On Saturday 21 January 2012 12:58 PM, Olof Johansson wrote: On Thu, Jan 19, 2012 at 12:56 PM, Aneesh Vane...@ti.com wrote: Hi Olof, On Friday 20 January 2012 01:01 AM, Olof Johansson wrote: Hi, Sorry for the delay in responding, I know you pinged me about it yesterday. On Thu, Jan 19, 2012 at 6:31 AM, Aneesh Vane...@ti.comwrote: device tree bindings for LPDDR2 SDRAM memories compliant to JESD209-2 standard. The 'lpddr2' binding in-turn uses another binding 'lpddr2-timings' for specifying the AC timing parameters of the memory device at different speed-bins. As I just commented on the thread with Mike, I think we would be better off sticking to embedding a standard JEDEC SPD structure in the device tree. It's not large (128-256 bytes depending on memory type), and it's clearly defined and used all over the industry. It also has the benefit of reusing parsing code if you ever end up with a system that uses DIMMs for memory, thus needing to parse the SPD on said modules. I did mention in the previous thread why SPD doesn't work for us ([1] and [2]). Let me repeat the key points here. Ah, sorry. Missed it in the chain of replies. 1. I couldn't find an SPD addendum for LPDDR2 from the JEDEC website. 2. This seems to indicate that SPD is not used for LPDDR2 devices. Bummer. I'm guessing most applications where LPDDR* is used won't be suitable for modular memory, so there's not the same need for SPD. 3. I tried to see if I can fit the DDR3 or DDR2 SPD for our needs. But some of the AC timing parameters needed by our controller are not available in those layouts. Are those properties of the memory, or a combination of memory and board properties? I think it still makes sense for the memories that do have it to use the SPD format and extend with additional properties, at least if it's only a few additional properties needed. They are AC timing parameters defined by the spec such as tCKESR, tFAW etc, nothing specific to OMAP. As for other memories, we do not intend to support any at the moment. In my initial version I had bindings for DDR3, because we intended to have DDR3 support in the driver. But we have since decided to drop DDR3 support for the following reasons: 1. According to the DDR3 spec, the operating frequency range for the speed-bins is limited (unlike LPDDR2). Scaling DDR frequency in this small range doesn't make sense for us (this may be the case for other platforms too). 2. Unlike LPDDR2, DDR3 doesn't have a mechanism for polling the temperature from the device and derate timings. If DVFS and thermal handling are not relevant for DDR3, having a kernel driver doesn't make sense. One-time settings in the bootloader are good enough. So, I have made my binding only for LPDDR2 and removed DDR3 parts from it. I don't see any option other than defining a new binding for LPDDR2. Yeah, agreed. Thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v2 PATCH 1/3] dt: device tree bindings for DDR memories
Hi Olof, On Tuesday 20 December 2011 12:39 PM, Aneesh V wrote: Hi Olof, On Monday 19 December 2011 10:22 PM, Olof Johansson wrote: Hi, Some comments below, but also a more general question: How much of this generic data makes sense to encode in the device tree? Final hardware configuration usually has to take into consideration board layout/signal delays, etc, and that's not part of this binding. When I was looking at your comments again for fixing them, I just realized that I hadn't answered part of this question. In the recent OMAPs, memory chips are stacked on to the OMAP, hence board layout etc doesn't figure in the equation. The only board level details that we need to program the memory controller are the details about the memory device itself, which is what this binding is targeting. The JEDEC specifies base values for all timing parameters. But Vendors can improve on these timings and provide better values. Using device specific timing values therefore provides scope for optimization. Everything that I have encoded here is needed by our driver to re-configure our SDRAM controller during DVFS. In fact, I have not listed all AC timing parameters in the spec in this binding, leaving the rest for future users to add if they need them. br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
This is an RFC to add new device tree bindings for DDR memories and EMIF - TI's DDR SDRAM controller. The first patch adds bindings for DDR memories. Currently, we have added properties for only DDR3 and LPDDR2 memories. However, the binding can be easily extended to describe other types such as DDR2 in the future. The second patch provides the bindings for the EMIF controller. The final patch provides DT data for EMIF controller instances in OMAP4 and LPDDR2 memories attached to them on various boards. Thanks to Rajendra for answering my numerous queries on device tree. This is a re-post of the RFC that was posted to devicetree-discuss ml, now sent to a larger audience and looping out an internal list. Please ignore the previous version. Aneesh V (3): dt: device tree bindings for DDR memories dt: device tree bindings for TI's EMIF sdram controller arm/dts: EMIF and lpddr2 device tree data for OMAP4 boards Documentation/devicetree/bindings/ddr/ddr.txt | 114 .../devicetree/bindings/ddr/ddr_timings.txt| 62 +++ .../bindings/memory-controllers/ti/emif.txt| 64 +++ arch/arm/boot/dts/omap-common-devices.dtsi | 63 +++ arch/arm/boot/dts/omap4-panda.dts | 13 +++ arch/arm/boot/dts/omap4-sdp.dts| 13 +++ arch/arm/boot/dts/omap4.dtsi | 19 7 files changed, 348 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/ddr/ddr.txt create mode 100644 Documentation/devicetree/bindings/ddr/ddr_timings.txt create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt create mode 100644 arch/arm/boot/dts/omap-common-devices.dtsi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] dt: device tree bindings for DDR memories
device tree bindings for DDR SDRAM memories compliant to JEDEC standards. Currently only DDR3 and LPDDR2 have been considered for this binding. Properties for other memory types(DDR2 etc) could be added to this binding on a need-basis. The 'ddr' binding in-turn uses another binding 'ddr-timings' for specifying the AC timing parameters of the memory device at different speed-bins. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com Changes in RFC v2: * Removed the manufacturer property and added it in compatible property instead * Changed the DDR device names in example to indicate the part number --- .../devicetree/bindings/ddr/lpddr2-timings.txt | 50 + Documentation/devicetree/bindings/ddr/lpddr2.txt | 106 2 files changed, 156 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/ddr/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/ddr/lpddr2.txt diff --git a/Documentation/devicetree/bindings/ddr/lpddr2-timings.txt b/Documentation/devicetree/bindings/ddr/lpddr2-timings.txt new file mode 100644 index 000..d4c1bff --- /dev/null +++ b/Documentation/devicetree/bindings/ddr/lpddr2-timings.txt @@ -0,0 +1,50 @@ +* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin + +Required properties: +- compatible : Should be jedec,lpddr2-timings +- min-freq : minimum DDR clock frequency for the speed-bin +- max-freq : maximum DDR clock frequency for the speed-bin + +Optional properties: + +The following properties represent AC timing parameters from the memory +data-sheet of the device for a given speed-bin. All these properties are +of type u32 and the default unit is ps (pico seconds). +- tRCD +- tWR +- tRAS-min +- tRRD +- tWTR +- tXP +- tRTP +- tDQSCK-max +- tFAW +- tZQCS +- tZQinit +- tRPab +- tZQCL +- tCKESR +- tRAS-max-ns + +Example: + +timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; +}; diff --git a/Documentation/devicetree/bindings/ddr/lpddr2.txt b/Documentation/devicetree/bindings/ddr/lpddr2.txt new file mode 100644 index 000..c03c62d --- /dev/null +++ b/Documentation/devicetree/bindings/ddr/lpddr2.txt @@ -0,0 +1,106 @@ +* LPDDR2 SDRAM memories compliant to JEDEC JESD209-2 + +Required properties: +- compatible : Should be one of - jedec,lpddr2-nvm, jedec,lpddr2-s2, + jedec,lpddr2-s4 + + ti,jedec-lpddr2-s2 should be listed if the memory part is LPDDR2-S2 type + + ti,jedec-lpddr2-s4 should be listed if the memory part is LPDDR2-S4 type + + ti,jedec-lpddr2-nvm should be listed if the memory part is LPDDR2-NVM type + +- density : u32 representing density in Mb (Mega bits) + +- io-width : u32 representing bus width. Possible values are 8, 16, and 32 + +Optional properties: + +The following optional properties represent the minimum value of some AC +timing parameters of the DDR device in terms of number of clock cycles. +These values shall be obtained from the device data-sheet. + +The suffix 'tck' indicates that the unit for these parameters is number +of DDR clock cycles. + +- tRRD-min-tck +- tWTR-min-tck +- tXP-min-tck +- tRTP-min-tck +- tCKE-min-tck +- tRPab-min-tck +- tRCD-min-tck +- tWR-min-tck +- tRASmin-min-tck +- tCKESR-min-tck +- tFAW-min-tck + +Child nodes: +- The lpddr2 node may have one or more child nodes of type lpddr2-timings. + lpddr2-timings provides AC timing parameters of the device for + a given speed-bin. The user may provide the timings for as many + speed-bins as is required. Please see Documentation/devicetree/ + bindings/lpddr2/lpddr2-timings.txt for more information on lpddr2-timings + +Example: + +elpida_ECB240ABACN : lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRP
[PATCH 2/3] dt: device tree bindings for TI's EMIF sdram controller
EMIF - External Memory Interface - is an SDRAM controller used in TI SoCs. EMIF supports, based on the IP revision, one or more of DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance of the EMIF IP and memory parts attached to it. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- .../bindings/memory-controllers/ti/emif.txt| 62 1 files changed, 62 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt new file mode 100644 index 000..0b166e0 --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt @@ -0,0 +1,62 @@ +* EMIF family of TI SDRAM controllers + +EMIF - External Memory Interface - is an SDRAM controller used in +TI SoCs. EMIF supports, based on the IP revision, one or more of +DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance +of the EMIF IP and memory parts attached to it. + +Required properties: +- compatible : One or more of ti,emif-lpddr22, ti,emif-lpddr23, and + ti,emif-lpddr2 + + ti,emif-lpddr22 should be listed of the EMIF controller on this SoC + supports DDR2 memories + + ti,emif-lpddr23 should be listed of the EMIF controller on this SoC + supports DDR3 memories + + ti,emif-lpddr2 should be listed of the EMIF controller on this SoC + supports LPDDR2 memories + +- ti,hwmods: For TI hwmods processing and omap device creation + the value shall be emifn where n is the number of the EMIF + instance with base 1. + +- phy-type : u32 indicating the DDR phy type. Following are the + allowed values + 1 : Attila PHY + 2 : Intelli PHY + +- lpddr2-handle: phandle to a lpddr2 node representing the memory part + attached to this EMIF instance. + +Optional properties: +- cs1-used : Have this property if CS1 of this EMIF + instance has a memory part attached to it. If there is a memory + part attached to CS1, it should be the same type as the one on CS0, + so there is no need to give the details of this memory part. + +- cal-resistor-per-cs : Have this property if the board has one + calibration resistor per chip-select. + +- hw-caps-read-idle-ctrl: Have this property if the controller + supports read idle window programming + +- hw-caps-ll-interface : Have this property if the controller + has a low latency interface and corresponding interrupt events + +- hw-caps-temp-alert : Have this property if the controller + has capability for generating SDRAM temperature alerts + +Example: + +emif1: emif@0x4c00 { + compatible = ti,emif-lpddr2; + ti,hwmods = emif2; + phy-type= 1; + lpddr2-handle = elpida_ECB240ABACN; + cs1-used; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; + hw-caps-temp-alert; +}; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] arm/dts: EMIF and lpddr2 device tree data for OMAP4 boards
Device tree data for the EMIF sdram controllers in OMAP4 and DDR memories attached to OMAP4 boards. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 64 + arch/arm/boot/dts/omap4-panda.dts | 13 ++ arch/arm/boot/dts/omap4-sdp.dts | 13 ++ arch/arm/boot/dts/omap4.dtsi | 19 + 4 files changed, 109 insertions(+), 0 deletions(-) create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi new file mode 100644 index 000..437eaff --- /dev/null +++ b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi @@ -0,0 +1,64 @@ +/* + * Common devices used in different OMAP boards + */ + +/ { + elpida_ECB240ABACN: lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + }; + + timings_elpida_ECB240ABACN_200mhz: lpddr2-timings@1 { + min-freq= 1000; + max-freq= 2; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 1; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index c702657..b4f3904 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 PandaBoard; @@ -26,4 +27,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + lpddr2-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + lpddr2-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 066e28c..7959a02 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 SDP board; @@ -26,4 +27,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + lpddr2-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + lpddr2-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot
Re: [RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
On Thursday 19 January 2012 07:58 PM, Aneesh V wrote: This is an RFC to add new device tree bindings for DDR memories and EMIF - TI's DDR SDRAM controller. The first patch adds bindings for DDR memories. Currently, we have added properties for only DDR3 and LPDDR2 memories. However, the binding can be easily extended to describe other types such as DDR2 in the future. The second patch provides the bindings for the EMIF controller. The final patch provides DT data for EMIF controller instances in OMAP4 and LPDDR2 memories attached to them on various boards. Thanks to Rajendra for answering my numerous queries on device tree. This is a re-post of the RFC that was posted to devicetree-discuss ml, now sent to a larger audience and looping out an internal list. Please ignore the previous version. Please ignore this series. I did git-send-email from wrong directory. Aneesh V (3): dt: device tree bindings for DDR memories dt: device tree bindings for TI's EMIF sdram controller arm/dts: EMIF and lpddr2 device tree data for OMAP4 boards Documentation/devicetree/bindings/ddr/ddr.txt | 114 .../devicetree/bindings/ddr/ddr_timings.txt| 62 +++ .../bindings/memory-controllers/ti/emif.txt| 64 +++ arch/arm/boot/dts/omap-common-devices.dtsi | 63 +++ arch/arm/boot/dts/omap4-panda.dts | 13 +++ arch/arm/boot/dts/omap4-sdp.dts| 13 +++ arch/arm/boot/dts/omap4.dtsi | 19 7 files changed, 348 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/ddr/ddr.txt create mode 100644 Documentation/devicetree/bindings/ddr/ddr_timings.txt create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt create mode 100644 arch/arm/boot/dts/omap-common-devices.dtsi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v3 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
This is an RFC to add new device tree bindings for DDR memories and EMIF - TI's DDR SDRAM controller. The first patch adds bindings for LPDDR2 memories. Second patch provides the bindings for the EMIF controller. The final patch provides DT data for EMIF controller instances in OMAP4 and LPDDR2 memories attached to them on various boards. Thanks to Rajendra for answering my numerous queries on device tree. Changes in RFC v3: * Removed support for DDR3 * Incorporated review comments from Olof Aneesh V (3): dt: device tree bindings for DDR memories dt: device tree bindings for TI's EMIF sdram controller arm/dts: EMIF and lpddr2 device tree data for OMAP4 boards .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 51 ++ .../devicetree/bindings/lpddr2/lpddr2.txt | 102 .../bindings/memory-controllers/ti/emif.txt| 49 ++ arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 65 + arch/arm/boot/dts/omap4-panda.dts | 13 +++ arch/arm/boot/dts/omap4-sdp.dts| 13 +++ arch/arm/boot/dts/omap4.dtsi | 19 7 files changed, 312 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v3 PATCH 1/3] dt: device tree bindings for DDR memories
device tree bindings for LPDDR2 SDRAM memories compliant to JESD209-2 standard. The 'lpddr2' binding in-turn uses another binding 'lpddr2-timings' for specifying the AC timing parameters of the memory device at different speed-bins. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Olof Johansson o...@lixom.net Signed-off-by: Aneesh V ane...@ti.com Changes in RFC v2: * Removed the manufacturer property and added it in compatible property instead * Changed the DDR device names in example to indicate the part number Changes in RFC v3: * Removed DDR3 support * Fixed review comments on RFC v2 --- .../devicetree/bindings/lpddr2/lpddr2-timings.txt | 51 ++ .../devicetree/bindings/lpddr2/lpddr2.txt | 102 2 files changed, 153 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt new file mode 100644 index 000..1483841 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt @@ -0,0 +1,51 @@ +* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin + +Required properties: +- compatible : Should be jedec,lpddr2-timings +- min-freq : minimum DDR clock frequency for the speed-bin. Type is u32 +- max-freq : maximum DDR clock frequency for the speed-bin. Type is u32 + +Optional properties: + +The following properties represent AC timing parameters from the memory +data-sheet of the device for a given speed-bin. All these properties are +of type u32 and the default unit is ps (pico seconds). Parameters with +a different unit have a suffix indicating the unit such as 'tRAS-max-ns' +- tRCD +- tWR +- tRAS-min +- tRRD +- tWTR +- tXP +- tRTP +- tDQSCK-max +- tFAW +- tZQCS +- tZQinit +- tRPab +- tZQCL +- tCKESR +- tRAS-max-ns + +Example: + +timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; +}; diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt new file mode 100644 index 000..9c175f0 --- /dev/null +++ b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt @@ -0,0 +1,102 @@ +* LPDDR2 SDRAM memories compliant to JEDEC JESD209-2 + +Required properties: +- compatible : Should be one of - jedec,lpddr2-nvm, jedec,lpddr2-s2, + jedec,lpddr2-s4 + + ti,jedec-lpddr2-s2 should be listed if the memory part is LPDDR2-S2 type + + ti,jedec-lpddr2-s4 should be listed if the memory part is LPDDR2-S4 type + + ti,jedec-lpddr2-nvm should be listed if the memory part is LPDDR2-NVM type + +- density : u32 representing density in Mb (Mega bits) + +- io-width : u32 representing bus width. Possible values are 8, 16, and 32 + +Optional properties: + +The following optional properties represent the minimum value of some AC +timing parameters of the DDR device in terms of number of clock cycles. +These values shall be obtained from the device data-sheet. +- tRRD-min-tck +- tWTR-min-tck +- tXP-min-tck +- tRTP-min-tck +- tCKE-min-tck +- tRPab-min-tck +- tRCD-min-tck +- tWR-min-tck +- tRASmin-min-tck +- tCKESR-min-tck +- tFAW-min-tck + +Child nodes: +- The lpddr2 node may have one or more child nodes of type lpddr2-timings. + lpddr2-timings provides AC timing parameters of the device for + a given speed-bin. The user may provide the timings for as many + speed-bins as is required. Please see Documentation/devicetree/ + bindings/lpddr2/lpddr2-timings.txt for more information on lpddr2-timings + +Example: + +elpida_ECB240ABACN : lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4
[RFC v3 PATCH 2/3] dt: device tree bindings for TI's EMIF sdram controller
EMIF - External Memory Interface - is an SDRAM controller used in TI SoCs. EMIF supports, based on the IP revision, one or more of DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance of the EMIF IP and memory parts attached to it. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Olof Johansson o...@lixom.net Signed-off-by: Aneesh V ane...@ti.com --- Changes in RFC v3: * Fixed review comments from RFC v2 --- .../bindings/memory-controllers/ti/emif.txt| 49 1 files changed, 49 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt new file mode 100644 index 000..2925add --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt @@ -0,0 +1,49 @@ +* EMIF family of TI SDRAM controllers + +EMIF - External Memory Interface - is an SDRAM controller used in +TI SoCs. EMIF supports, based on the IP revision, one or more of +DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance +of the EMIF IP and memory parts attached to it. + +Required properties: +- compatible : Should be of the form ti,emif-ip-rev where ip-rev + is the IP revision of the specific EMIF instance. + +- phy-type : u32 indicating the DDR phy type. Following are the + allowed values + 1 : Attila PHY + 2 : Intelli PHY + +- device-handle: phandle to a lpddr2 node representing the memory part + attached to this EMIF instance. + +Optional properties: +- cs1-used : Have this property if CS1 of this EMIF + instance has a memory part attached to it. If there is a memory + part attached to CS1, it should be the same type as the one on CS0, + so there is no need to give the details of this memory part. + +- cal-resistor-per-cs : Have this property if the board has one + calibration resistor per chip-select. + +- hw-caps-read-idle-ctrl: Have this property if the controller + supports read idle window programming + +- hw-caps-ll-interface : Have this property if the controller + has a low latency interface and corresponding interrupt events + +- hw-caps-temp-alert : Have this property if the controller + has capability for generating SDRAM temperature alerts + +Example: + +emif1: emif@0x4c00 { + compatible = ti,emif-4d; + ti,hwmods = emif2; + phy-type= 1; + device-handle = elpida_ECB240ABACN; + cs1-used; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; + hw-caps-temp-alert; +}; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v3 PATCH 3/3] arm/dts: EMIF and lpddr2 device tree data for OMAP4 boards
Device tree data for the EMIF sdram controllers in OMAP4 and LPDDR memory devices attached to OMAP4 boards. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Cc: Olof Johansson o...@lixom.net Signed-off-by: Aneesh V ane...@ti.com --- Changes in RFC v3: * Fixed review comments from RFC v2 --- arch/arm/boot/dts/elpida_ecb240abacn.dtsi | 65 + arch/arm/boot/dts/omap4-panda.dts | 13 ++ arch/arm/boot/dts/omap4-sdp.dts | 13 ++ arch/arm/boot/dts/omap4.dtsi | 19 4 files changed, 110 insertions(+), 0 deletions(-) create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi new file mode 100644 index 000..2384233 --- /dev/null +++ b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi @@ -0,0 +1,65 @@ +/* + * Common devices used in different OMAP boards + */ + +/ { + elpida_ECB240ABACN: lpddr2 { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2048; + io-width= 32; + + tRPab-min-tck = 3; + tRCD-min-tck= 3; + tWR-min-tck = 3; + tRASmin-min-tck = 3; + tRRD-min-tck= 2; + tWTR-min-tck= 2; + tXP-min-tck = 2; + tRTP-min-tck= 2; + tCKE-min-tck= 3; + tCKESR-min-tck = 3; + tFAW-min-tck= 8; + + timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 4; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 7500; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + }; + + timings_elpida_ECB240ABACN_200mhz: lpddr2-timings@1 { + compatible = jedec,lpddr2-timings; + min-freq= 1000; + max-freq= 2; + tRPab = 21000; + tRCD= 18000; + tWR = 15000; + tRAS-min= 42000; + tRRD= 1; + tWTR= 1; + tXP = 7500; + tRTP= 7500; + tCKESR = 15000; + tDQSCK-max = 5500; + tFAW= 5; + tZQCS = 9; + tZQCL = 36; + tZQinit = 100; + tRAS-max-ns = 7; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index c702657..9b46802 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 PandaBoard; @@ -26,4 +27,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 066e28c..896d682 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ elpida_ecb240abacn.dtsi / { model = TI OMAP4 SDP board; @@ -26,4 +27,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + device-handle = elpida_ECB240ABACN; + }; + + emif2: emif
Re: [RFC v3 PATCH 1/3] dt: device tree bindings for DDR memories
Hi Olof, On Friday 20 January 2012 01:01 AM, Olof Johansson wrote: Hi, Sorry for the delay in responding, I know you pinged me about it yesterday. On Thu, Jan 19, 2012 at 6:31 AM, Aneesh Vane...@ti.com wrote: device tree bindings for LPDDR2 SDRAM memories compliant to JESD209-2 standard. The 'lpddr2' binding in-turn uses another binding 'lpddr2-timings' for specifying the AC timing parameters of the memory device at different speed-bins. As I just commented on the thread with Mike, I think we would be better off sticking to embedding a standard JEDEC SPD structure in the device tree. It's not large (128-256 bytes depending on memory type), and it's clearly defined and used all over the industry. It also has the benefit of reusing parsing code if you ever end up with a system that uses DIMMs for memory, thus needing to parse the SPD on said modules. I did mention in the previous thread why SPD doesn't work for us ([1] and [2]). Let me repeat the key points here. 1. I couldn't find an SPD addendum for LPDDR2 from the JEDEC website. 2. This seems to indicate that SPD is not used for LPDDR2 devices. 3. I tried to see if I can fit the DDR3 or DDR2 SPD for our needs. But some of the AC timing parameters needed by our controller are not available in those layouts. I don't see any option other than defining a new binding for LPDDR2. br, Aneesh [1] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg61250.html [2] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg60473.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: OMAP3 L2/outer cache enabled in kernel (after being disabled by uBoot)?
Santosh, Russel, On Monday 16 January 2012 06:52 PM, Shilimkar, Santosh wrote: On Mon, Jan 16, 2012 at 2:13 PM, Russell King - ARM Linux li...@arm.linux.org.uk wrote: On Mon, Jan 16, 2012 at 01:43:03PM +0100, Shilimkar, Santosh wrote: This code will be in assembly and that's what I have been using. Not having stack shoudn't be a blocker and can be work-around in this code. And this API has to be anyway called before MMU is enabled. What about SMC on OMAP potentially corrupting most of the integer registers? What if it corrupts an integer register which we depend upon? You don't have a stack here to save those registers. We'd need at least one additional register to save the old 'lr' value. That's right. What about other secure monitors? Some implementations require you to give parameters via memory. How do you obtain that memory that early on in the kernel boot (you haven't parsed anything here.) Not only that but you're asking to make the kernel boot a _lot_ more fragile, when people start stuffing all kinds of utter shite into this hook - and then we're burdened again with the old 'my kernel won't boot and it remains silent, well your debug code is utter shite get rid of it' crap that we used to have in the early 2000s. I really don't want to go anywhere near that situation. Fair point. It will be harder to maintain and won't be consistent. Am not sure what you mean because secure API as such isn't a problem. If you mean one standard interface for all the ARM SOC's then that's something won't be easy to handled because it is tied up the security architecture which can vary across SoCs. The latter. This is exactly the kind of pain I forsaw with this security shite, and when I heard about it I was utterly dismayed at ARM Ltd for coming up with such a brain-dead lack of design here. You're having to struggle with the results of that by having lots of SoC specific hooks all around the place to fiddle with this that and the other. Your need to have something called from the early assembly code is just yet more of that disease caused by ARM Ltd's lack of forsight on this matter. I have no solution for you on this I managed use some secure macro kind of code but as you said it will be really hard to maintain. So we are stuck with this issue then. Can't we delay the L2 initialization a bit and do it when we have a stack, like we do in OMAP4 (early_initcall)? Am I missing something? br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
Hi Olof, On Saturday 14 January 2012 01:06 AM, Aneesh V wrote: Hi Olof, snip We wish to drop the DDR3 support because we have concluded that our platforms with DDR3 memories will not scale DDR frequency due to limitations in DDR3 protocol(operating frequency can vary only in a small range). So, is it ok to persist with my bindings for LPDDR2 (fixing the comments already given by you) and drop the DDR3 part from it? Ping! Forgive my impatience, but I would like to close on this at the earliest to continue my work on the driver. thanks, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: OMAP3 L2/outer cache enabled in kernel (after being disabled by uBoot)?
Hi Catalin, On Tuesday 17 January 2012 05:41 PM, Catalin Marinas wrote: On Tue, Jan 17, 2012 at 08:54:44AM +, Joe Woodward wrote: So, is the upshot of this that the kernel isn't going to be in a position to enable the L2/outer cache on OMAP3 (due to the need for hacky/unmaintainable code)? Hence the bootloader/uBoot had better leave it enabled... It could but the Linux decompressor needs to be aware and either flush the L2 (more difficult as it doesn't have all the device information) or Cortex-A8 is aware of L2$ and can flush it, isn't it? set the page table attributes to outer non-cacheable (TEX[2:0] = 0b100). If the above is right, this is not needed right? The latter may still not work if there are stale L2 cache lines left by U-Boot (and that's always possible unless U-Boot also uses outer non-cacheable memory attributes). U-Boot flushes the caches before disabling it. On top of it, it does an invalidate after the disabling the caches to cover some corner case. So, it's guaranteed that there won't be any stale entries in L2 after U-Boot. So, we could as well leave L2$ enabled (and invalidated) and caches disabled globally after U-Boot. But I thought enabling L2$ again in kernel is the cleaner solution. br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
Hi Olof, On Monday 09 January 2012 11:12 AM, Olof Johansson wrote: Hi, On Sun, Jan 8, 2012 at 9:23 AM, Aneesh Vane...@ti.com wrote: Hi, On Tuesday 20 December 2011 03:08 PM, Aneesh V wrote: Hi Benoit On Tuesday 20 December 2011 06:10 PM, Cousson, Benoit wrote: Hi Aneesh, snip In general, is it really feasible to parse the DTB before DDR is initialized? Changing timings is still needed for DVFS during runtime. But we can boot to userspace with bootloader set timings, so I'm As far as I understand, in the current out-of-tree DVFS implementation for OMAP, DVFS can start even before user-space. Maybe it is the case, but that does not mean it should. We can potentially delay the DVFS init until the user-space is started. This should not be considered as a big constraint. Or at least until ramdisk is available, and store the tables there. It's a matter of seconds, delaying DVFS initialization until then shouldn't be the end of the world. It's not about power savings, here is what I understand from discussion with power management folks. In our current architecture drivers can set frequency constraints with clock framework and this may in turn initiate frequency scaling and this can happen before user space. Perhaps we could forbid this too. But I am not sure if the benefit is worth the trouble. thinking that maybe these timings should be just set by loadable modules. Just the configuration of which timings to select should be passed via DT. Something in compatible like: .compatible = ti,omap3630, sdram-micron-mt46h32m32lf-6; And that should allow the SDRC driver to only accept timings for sdram-micron-mt46h32m32lf-6. Do you mean one module per memory device and have all timing data in the respective module? Wouldn't this clutter the kernel proper with all these tables. By having the timing data in DT, it can be eventually moved out of kernel eventually, right? Yes, that's the theory, but referring to Olof's point, this is not necessarily the goal of DT to store all the information that are not board dependent. In this case, each DDR will have it sets of well known AC timings data that will never depend of the board config. In this case, storing that inside DT might not be the best solution. In fact we always had the same kind of discussion for the pinmux data and for the clock data... The conclusion being that most of the static data does not have to be in the DTS. But since Linus was complaining about the huge amount of data inside the kernel, it is not obvious what the best solution is:-) Hmm.. I get the point now. Linus' complaint is what I had in mind too. My humble opinion is to have such data in DTS but re-use it as much as possible. That is, we could have something like a sdram-micron- mt46h32m32lf-6.dtsi(as you suggested before) that can be included by board level DTS files. I think the fact that dts files are organized at arch level today is limiting such re-use. Please correct me if I am wrong. Gentle reminder on this one. Are we aligned on having the DDR timings in device tree? I didn't revisit the thread until today, unfortunately, but the approach suggested by Tony sounds quite intriguing: Only encode the memory chip id, and have the driver request firmware (not a module) for that model that contains the SPD (if it isn't provided by the memory module itself, which it rarely is on embedded platforms). That data can then be parsed by the kernel like regular SPD. As a second-best option, encoding in SPD format in the device-tree through dtsi files sounds like a reasonable approach: the format is already standardized and drivers who can already deal with i2c-based SPD data can just use it (with some minor changes). I did look for an SPD spec for LPDDR2, but couldn't find one. It appears to me that SPD is not used in LPDDR2 devices and therefore there is no standard governing it. I checked the DDR3 spec too. But that doesn't seem to have some parameters needed by our controller. Even if SPD worked, I wonder if that is the right solution for our need. Don't you think it will be too cryptic for the user to input and verify the data (some of the bytes in the layout are a combination of more than one parameter). It's all fine if it came from the memory device. But when we have to enter it manually, can't we chose a more readable representation? We wish to drop the DDR3 support because we have concluded that our platforms with DDR3 memories will not scale DDR frequency due to limitations in DDR3 protocol(operating frequency can vary only in a small range). So, is it ok to persist with my bindings for LPDDR2 (fixing the comments already given by you) and drop the DDR3 part from it? br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
Hi, On Tuesday 20 December 2011 03:08 PM, Aneesh V wrote: Hi Benoit On Tuesday 20 December 2011 06:10 PM, Cousson, Benoit wrote: Hi Aneesh, snip In general, is it really feasible to parse the DTB before DDR is initialized? Changing timings is still needed for DVFS during runtime. But we can boot to userspace with bootloader set timings, so I'm As far as I understand, in the current out-of-tree DVFS implementation for OMAP, DVFS can start even before user-space. Maybe it is the case, but that does not mean it should. We can potentially delay the DVFS init until the user-space is started. This should not be considered as a big constraint. thinking that maybe these timings should be just set by loadable modules. Just the configuration of which timings to select should be passed via DT. Something in compatible like: .compatible = ti,omap3630, sdram-micron-mt46h32m32lf-6; And that should allow the SDRC driver to only accept timings for sdram-micron-mt46h32m32lf-6. Do you mean one module per memory device and have all timing data in the respective module? Wouldn't this clutter the kernel proper with all these tables. By having the timing data in DT, it can be eventually moved out of kernel eventually, right? Yes, that's the theory, but referring to Olof's point, this is not necessarily the goal of DT to store all the information that are not board dependent. In this case, each DDR will have it sets of well known AC timings data that will never depend of the board config. In this case, storing that inside DT might not be the best solution. In fact we always had the same kind of discussion for the pinmux data and for the clock data... The conclusion being that most of the static data does not have to be in the DTS. But since Linus was complaining about the huge amount of data inside the kernel, it is not obvious what the best solution is:-) Hmm.. I get the point now. Linus' complaint is what I had in mind too. My humble opinion is to have such data in DTS but re-use it as much as possible. That is, we could have something like a sdram-micron- mt46h32m32lf-6.dtsi(as you suggested before) that can be included by board level DTS files. I think the fact that dts files are organized at arch level today is limiting such re-use. Please correct me if I am wrong. Gentle reminder on this one. Are we aligned on having the DDR timings in device tree? br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
On Tuesday 20 December 2011 04:31 AM, Rob Herring wrote: On 12/19/2011 08:05 AM, Aneesh V wrote: This is an RFC to add new device tree bindings for DDR memories and EMIF - TI's DDR SDRAM controller. The first patch adds bindings for DDR memories. Currently, we have added properties for only DDR3 and LPDDR2 memories. However, the binding can be easily extended to describe other types such as DDR2 in the future. The second patch provides the bindings for the EMIF controller. The final patch provides DT data for EMIF controller instances in OMAP4 and LPDDR2 memories attached to them on various boards. Thanks to Rajendra for answering my numerous queries on device tree. This is a re-post of the RFC that was posted to devicetree-discuss ml, now sent to a larger audience and looping out an internal list. Please ignore the previous version. There's already a standard way (i.e. JEDEC standard) to define DDR chip configuration that's called SPD. Why invent something new? While this is normally an i2c eeprom on a DIMM, there's no reason you couldn't get it from somewhere else including perhaps the DT. There's already code in u-boot that can parse SPD data. Thanks for pointing this out. I looked into this a bit. I see some difficulties in adopting SPD for our needs. 1. Our primary target is LPDDR2 and I can't seem to find an SPD standard for LPDDR2. Maybe, because automatic memory detection is not that critical in the embedded world. 2. I did find one for DDR SDRAM memories(Appendix D, Rev 1.0 - maybe for the first generation of PC DDR memories). But many of the AC timing parameters needed to program our controller are not listed in it. 3. We do not really need DDR3 support at the moment because we do not intend to scale DDR frequency in platforms with DDR3 memory. This is due the to limited operating frequency range of DDR3. So, I was wondering whether I should limit the binding to only LPDDR2 and have an SPD based binding for DDR2/DDR3 if that is required later? What do you think? In general, is it really feasible to parse the DTB before DDR is initialized? As pointed out by Tony we rely on bootloader for the initial SDRAM configuration. The kernel SDRAM controller driver is used mainly for DVFS and thermal management. best regards, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
On Tuesday 20 December 2011 05:05 AM, Tony Lindgren wrote: * Rob Herringrobherri...@gmail.com [111219 14:29]: On 12/19/2011 08:05 AM, Aneesh V wrote: This is an RFC to add new device tree bindings for DDR memories and EMIF - TI's DDR SDRAM controller. The first patch adds bindings for DDR memories. Currently, we have added properties for only DDR3 and LPDDR2 memories. However, the binding can be easily extended to describe other types such as DDR2 in the future. The second patch provides the bindings for the EMIF controller. The final patch provides DT data for EMIF controller instances in OMAP4 and LPDDR2 memories attached to them on various boards. Thanks to Rajendra for answering my numerous queries on device tree. This is a re-post of the RFC that was posted to devicetree-discuss ml, now sent to a larger audience and looping out an internal list. Please ignore the previous version. There's already a standard way (i.e. JEDEC standard) to define DDR chip configuration that's called SPD. Why invent something new? While this is normally an i2c eeprom on a DIMM, there's no reason you couldn't get it from somewhere else including perhaps the DT. There's already code in u-boot that can parse SPD data. I agree generic JEDEC standard would be good for the DT. Please see my comments in reply to Rob's mail. SPD doesn't seems to have a standard for LPDDR2. What JEDEC has now is not suitable for our needs. In general, is it really feasible to parse the DTB before DDR is initialized? Changing timings is still needed for DVFS during runtime. But we can boot to userspace with bootloader set timings, so I'm As far as I understand, in the current out-of-tree DVFS implementation for OMAP, DVFS can start even before user-space. thinking that maybe these timings should be just set by loadable modules. Just the configuration of which timings to select should be passed via DT. Something in compatible like: .compatible = ti,omap3630, sdram-micron-mt46h32m32lf-6; And that should allow the SDRC driver to only accept timings for sdram-micron-mt46h32m32lf-6. Do you mean one module per memory device and have all timing data in the respective module? Wouldn't this clutter the kernel proper with all these tables. By having the timing data in DT, it can be eventually moved out of kernel eventually, right? br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
Hi Benoit On Tuesday 20 December 2011 06:10 PM, Cousson, Benoit wrote: Hi Aneesh, snip In general, is it really feasible to parse the DTB before DDR is initialized? Changing timings is still needed for DVFS during runtime. But we can boot to userspace with bootloader set timings, so I'm As far as I understand, in the current out-of-tree DVFS implementation for OMAP, DVFS can start even before user-space. Maybe it is the case, but that does not mean it should. We can potentially delay the DVFS init until the user-space is started. This should not be considered as a big constraint. thinking that maybe these timings should be just set by loadable modules. Just the configuration of which timings to select should be passed via DT. Something in compatible like: .compatible = ti,omap3630, sdram-micron-mt46h32m32lf-6; And that should allow the SDRC driver to only accept timings for sdram-micron-mt46h32m32lf-6. Do you mean one module per memory device and have all timing data in the respective module? Wouldn't this clutter the kernel proper with all these tables. By having the timing data in DT, it can be eventually moved out of kernel eventually, right? Yes, that's the theory, but referring to Olof's point, this is not necessarily the goal of DT to store all the information that are not board dependent. In this case, each DDR will have it sets of well known AC timings data that will never depend of the board config. In this case, storing that inside DT might not be the best solution. In fact we always had the same kind of discussion for the pinmux data and for the clock data... The conclusion being that most of the static data does not have to be in the DTS. But since Linus was complaining about the huge amount of data inside the kernel, it is not obvious what the best solution is:-) Hmm.. I get the point now. Linus' complaint is what I had in mind too. My humble opinion is to have such data in DTS but re-use it as much as possible. That is, we could have something like a sdram-micron- mt46h32m32lf-6.dtsi(as you suggested before) that can be included by board level DTS files. I think the fact that dts files are organized at arch level today is limiting such re-use. Please correct me if I am wrong. br, Aneesh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v2 PATCH 0/3] dt: device tree bindings and data for EMIF and DDR
This is an RFC to add new device tree bindings for DDR memories and EMIF - TI's DDR SDRAM controller. The first patch adds bindings for DDR memories. Currently, we have added properties for only DDR3 and LPDDR2 memories. However, the binding can be easily extended to describe other types such as DDR2 in the future. The second patch provides the bindings for the EMIF controller. The final patch provides DT data for EMIF controller instances in OMAP4 and LPDDR2 memories attached to them on various boards. Thanks to Rajendra for answering my numerous queries on device tree. This is a re-post of the RFC that was posted to devicetree-discuss ml, now sent to a larger audience and looping out an internal list. Please ignore the previous version. Aneesh V (3): dt: device tree bindings for DDR memories dt: device tree bindings for TI's EMIF sdram controller arm/dts: EMIF and lpddr2 device tree data for OMAP4 boards Documentation/devicetree/bindings/ddr/ddr.txt | 114 .../devicetree/bindings/ddr/ddr_timings.txt| 62 +++ .../bindings/memory-controllers/ti/emif.txt| 64 +++ arch/arm/boot/dts/omap-common-devices.dtsi | 63 +++ arch/arm/boot/dts/omap4-panda.dts | 13 +++ arch/arm/boot/dts/omap4-sdp.dts| 13 +++ arch/arm/boot/dts/omap4.dtsi | 19 7 files changed, 348 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/ddr/ddr.txt create mode 100644 Documentation/devicetree/bindings/ddr/ddr_timings.txt create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt create mode 100644 arch/arm/boot/dts/omap-common-devices.dtsi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v2 PATCH 1/3] dt: device tree bindings for DDR memories
device tree bindings for DDR SDRAM memories compliant to JEDEC standards. Currently only DDR3 and LPDDR2 have been considered for this binding. Properties for other memory types(DDR2 etc) could be added to this binding on a need-basis. The 'ddr' binding in-turn uses another binding 'ddr-timings' for specifying the AC timing parameters of the memory device at different speed-bins. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- Documentation/devicetree/bindings/ddr/ddr.txt | 114 .../devicetree/bindings/ddr/ddr_timings.txt| 62 +++ 2 files changed, 176 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/ddr/ddr.txt create mode 100644 Documentation/devicetree/bindings/ddr/ddr_timings.txt diff --git a/Documentation/devicetree/bindings/ddr/ddr.txt b/Documentation/devicetree/bindings/ddr/ddr.txt new file mode 100644 index 000..f15c4dd --- /dev/null +++ b/Documentation/devicetree/bindings/ddr/ddr.txt @@ -0,0 +1,114 @@ +* DDR SDRAM memories compliant to JEDEC specifications JESD209-2(LPDDR2) + or JESD79-3(DDR3). + +Required properties: +- compatible : Should be one of - jedec,ddr3, jedec,lpddr2-nvm, + jedec,lpddr2-s2, jedec,lpddr2-s4 + + ti,jedec-ddr3 should be listed if the memory part is DDR3 type + + ti,jedec-lpddr2-s2 should be listed if the memory part is LPDDR2-S2 type + + ti,jedec-lpddr2-s4 should be listed if the memory part is LPDDR2-S4 type + + ti,jedec-lpddr2-nvm should be listed if the memory part is LPDDR2-NVM type + +- density : string representing the density of the device in terms of + Mb (mega bits). Following are the allowed values: 64Mb, 128Mb, + 256Mb, 512Mb, 1Gb, 2Gb, 4Gb, 8Gb, 16Gb, or 32Gb + +- io-width : string representing the io width: x8, x16 or x32. + +Optional properties: + +The following optional properties represent the minimum value of some AC +timing parameters of the DDR device in terms of number of clock cycles. +These values shall be obtained from the device data-sheet. + +The suffix nCK indicates that the unit for these parameters is number +of DDR clock cycles. Note: In LPDDR2 spec and data-sheets tCK is used +inter-changeably for nCK. Both are equivalent in this context. + +- tRRD-min-nCK +- tWTR-min-nCK +- tXP-min-nCK +- tRTP-min-nCK +- tCKE-min-nCK +- tRPab-min-nCK/* LPDDR2 only */ +- tRCD-min-nCK /* LPDDR2 only */ +- tWR-min-nCK /* LPDDR2 only */ +- tRASmin-min-nCK /* LPDDR2 only */ +- tCKESR-min-nCK /* LPDDR2 only */ +- tFAW-min-nCK /* LPDDR2 only */ +- tZQCS-min-nCK/* DDR3 only */ +- tZQoper-min-nCK /* DDR3 only */ +- tZQinit-min-nCK /* DDR3 only */ +- tXS-min-nCK /* DDR3 only */ + +Child nodes: +- The ddr node may have one or more child nodes of type ddr-timings. + ddr-timings provides AC timing parameters of the device for + a given speed-bin. The user may provide the timings for as many + speed-bins as is required. Please see Documentation/devicetree/ + bindings/ddr/ddr-timings.txt for more information on ddr-timings + +Example: + +elpida_ECB240ABACN : ddr { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2Gb; + io-width= x32; + + tRPab-min-nCK = 3; + tRCD-min-nCK= 3; + tWR-min-nCK = 3; + tRASmin-min-nCK = 3; + tRRD-min-nCK= 2; + tWTR-min-nCK= 2; + tXP-min-nCK = 2; + tRTP-min-nCK= 2; + tCKE-min-nCK= 3; + tCKESR-min-nCK = 3; + tFAW-min-nCK= 8; + + timings_elpida_ECB240ABACN_400mhz: ddr-timings { + min-freq= 1000; + max-freq= 4; + tRP-ps = 21000; + tRCD-ps = 18000; + tWR-ps = 15000; + tRAS-min-ps = 42000:; + tRRD-ps = 1; + tWTR-ps = 7500; + tXP-ps = 7500; + tRTP-ps = 7500; + tCKESR-ps = 15000; + tDQSCK-max-ps = 5500; + tFAW-ps = 5; + tZQCS-ps= 9; + tZQoper-ps = 36; + tZQinit-ps = 100; + tRAS-max-ns = 7; + }; + + timings_elpida_ECB240ABACN_200mhz: ddr-timings { + min-freq= 1000; + max-freq= 2; + tRP-ps = 21000; + tRCD-ps = 18000; + tWR-ps = 15000; + tRAS-min-ps = 42000:; + tRRD-ps = 1; + tWTR-ps = 1; + tXP-ps = 7500; + tRTP-ps = 7500; + tCKESR-ps = 15000; + tDQSCK-max-ps = 5500; + tFAW
[RFC v2 PATCH 2/3] dt: device tree bindings for TI's EMIF sdram controller
EMIF - External Memory Interface - is an SDRAM controller used in TI SoCs. EMIF supports, based on the IP revision, one or more of DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance of the EMIF IP and memory parts attached to it. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- .../bindings/memory-controllers/ti/emif.txt| 64 1 files changed, 64 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt new file mode 100644 index 000..e2f687b --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt @@ -0,0 +1,64 @@ +* EMIF family of TI SDRAM controllers + +EMIF - External Memory Interface - is an SDRAM controller used in +TI SoCs. EMIF supports, based on the IP revision, one or more of +DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance +of the EMIF IP and memory parts attached to it. + +Required properties: +- compatible : One or more of ti,emif-ddr2, ti,emif-ddr3, and + ti,emif-lpddr2 + + ti,emif-ddr2 should be listed of the EMIF controller on this SoC + supports DDR2 memories + + ti,emif-ddr3 should be listed of the EMIF controller on this SoC + supports DDR3 memories + + ti,emif-lpddr2 should be listed of the EMIF controller on this SoC + supports LPDDR2 memories + +- ti,hwmods: For TI hwmods processing and omap device creation + the value shall be emifn where n is the number of the EMIF + instance with base 1. + +- phy-type : string indicating the phy type. Should be one of the + following: + + phy-type-omap4 : PHY used in OMAP4 family of SoCs + + phy-type-dm81xx : PHY used in DM81XX family of SoCs + +- ddr-handle : phandle to a ddr node representing the memory part + attached to this EMIF instance. + +Optional properties: +- cs1-used : Have this property if CS1 of this EMIF + instance has a memory part attached to it. If there is a memory + part attached to CS1, it should be the same type as the one on CS0, + so there is no need to give the details of this memory part. + +- cal-resistor-per-cs : Have this property if the board has one + calibration resistor per chip-select. + +- hw-caps-read-idle-ctrl: Have this property if the controller + supports read idle window programming + +- hw-caps-ll-interface : Have this property if the controller + has a low latency interface and corresponding interrupt events + +- hw-caps-temp-alert : Have this property if the controller + has capability for generating SDRAM temperature alerts + +Example: + +emif1: emif@0x4c00 { + compatible = ti,emif-lpddr2; + ti,hwmods = emif2; + phy-type= phy-type-omap4; + ddr-handle = elpida_ECB240ABACN; + cs1-used; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; + hw-caps-temp-alert; +}; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC v2 PATCH 3/3] arm/dts: EMIF and lpddr2 device tree data for OMAP4 boards
Device tree data for the EMIF sdram controllers in OMAP4 and DDR memories attached to OMAP4 boards. Cc: Rajendra Nayak rna...@ti.com Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Aneesh V ane...@ti.com --- arch/arm/boot/dts/omap-common-devices.dtsi | 63 arch/arm/boot/dts/omap4-panda.dts | 13 ++ arch/arm/boot/dts/omap4-sdp.dts| 13 ++ arch/arm/boot/dts/omap4.dtsi | 19 4 files changed, 108 insertions(+), 0 deletions(-) create mode 100644 arch/arm/boot/dts/omap-common-devices.dtsi diff --git a/arch/arm/boot/dts/omap-common-devices.dtsi b/arch/arm/boot/dts/omap-common-devices.dtsi new file mode 100644 index 000..bac2a40 --- /dev/null +++ b/arch/arm/boot/dts/omap-common-devices.dtsi @@ -0,0 +1,63 @@ +/* + * Common devices used in different OMAP boards + */ + +/ { + elpida_ECB240ABACN: ddr { + compatible = Elpida,ECB240ABACN,jedec,lpddr2-s4; + density = 2Gb; + io-width= x32; + + tRPab-min-nCK = 3; + tRCD-min-nCK= 3; + tWR-min-nCK = 3; + tRASmin-min-nCK = 3; + tRRD-min-nCK= 2; + tWTR-min-nCK= 2; + tXP-min-nCK = 2; + tRTP-min-nCK= 2; + tCKE-min-nCK= 3; + tCKESR-min-nCK = 3; + tFAW-min-nCK= 8; + + timings_elpida_ECB240ABACN_400mhz: ddr-timings@1 { + min-freq= 1000; + max-freq= 4; + tRPab-ps= 21000; + tRCD-ps = 18000; + tWR-ps = 15000; + tRAS-min-ps = 42000; + tRRD-ps = 1; + tWTR-ps = 7500; + tXP-ps = 7500; + tRTP-ps = 7500; + tCKESR-ps = 15000; + tDQSCK-max-ps = 5500; + tFAW-ps = 5; + tZQCS-ps= 9; + tZQCL-ps= 36; + tZQinit-ps = 100; + tRAS-max-ns = 7; + }; + + timings_elpida_ECB240ABACN_200mhz: ddr-timings@ { + min-freq= 1000; + max-freq= 2; + tRPab-ps= 21000; + tRCD-ps = 18000; + tWR-ps = 15000; + tRAS-min-ps = 42000; + tRRD-ps = 1; + tWTR-ps = 1; + tXP-ps = 7500; + tRTP-ps = 7500; + tCKESR-ps = 15000; + tDQSCK-max-ps = 5500; + tFAW-ps = 5; + tZQCS-ps= 9; + tZQCL-ps= 36; + tZQinit-ps = 100; + tRAS-max-ns = 7; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index c702657..3446f4f 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ omap-common-devices.dtsi / { model = TI OMAP4 PandaBoard; @@ -26,4 +27,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + ddr-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + ddr-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 066e28c..799ac0a 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -8,6 +8,7 @@ /dts-v1/; /include/ omap4.dtsi +/include/ omap-common-devices.dtsi / { model = TI OMAP4 SDP board; @@ -26,4 +27,16 @@ device_type = memory; reg = 0x8000 0x4000; /* 1 GB */ }; + + ocp { + emif1: emif@0x4c00 { + cs1-used; + ddr-handle = elpida_ECB240ABACN; + }; + + emif2: emif@0x4d00 { + cs1-used; + ddr-handle = elpida_ECB240ABACN; + }; + }; }; diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 4c61c82..5393ae5 100644