Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull ARM SoC-related driver updates from Olof Johansson:
 "Various driver updates for platforms and a couple of the small driver
  subsystems we merge through our tree:

   - A driver for SCU (system control) on NXP i.MX8QXP

   - Qualcomm Always-on Subsystem messaging driver (AOSS QMP)

   - Qualcomm PM support for MSM8998

   - Support for a newer version of DRAM PHY driver for Broadcom (DPFE)

   - Reset controller support for Bitmain BM1880

   - TI SCI (System Control Interface) support for CPU control on AM654
     processors

   - More TI sysc refactoring and rework"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (84 commits)
  reset: remove redundant null check on pointer dev
  soc: rockchip: work around clang warning
  dt-bindings: reset: imx7: Fix the spelling of 'indices'
  soc: imx: Add i.MX8MN SoC driver support
  soc: aspeed: lpc-ctrl: Fix probe error handling
  soc: qcom: geni: Add support for ACPI
  firmware: ti_sci: Fix gcc unused-but-set-variable warning
  firmware: ti_sci: Use the correct style for SPDX License Identifier
  soc: imx8: Use existing of_root directly
  soc: imx8: Fix potential kernel dump in error path
  firmware/psci: psci_checker: Park kthreads before stopping them
  memory: move jedec_ddr.h from include/memory to drivers/memory/
  memory: move jedec_ddr_data.c from lib/ to drivers/memory/
  MAINTAINERS: Remove myself as qcom maintainer
  soc: aspeed: lpc-ctrl: make parameter optional
  soc: qcom: apr: Don't use reg for domain id
  soc: qcom: fix QCOM_AOSS_QMP dependency and build errors
  memory: tegra: Fix -Wunused-const-variable
  firmware: tegra: Early resume BPMP
  soc/tegra: Select pinctrl for Tegra194
  ...
This commit is contained in:
Linus Torvalds
2019-07-19 17:13:56 -07:00
70 changed files with 4622 additions and 497 deletions

View File

@@ -8,6 +8,14 @@ menuconfig MEMORY
if MEMORY
config DDR
bool
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_PL172_MPMC
tristate "ARM PL172 MPMC driver"
depends on ARM_AMBA && OF

View File

@@ -3,6 +3,7 @@
# Makefile for memory devices
#
obj-$(CONFIG_DDR) += jedec_ddr_data.o
ifeq ($(CONFIG_DDR),y)
obj-$(CONFIG_OF) += of_memory.o
endif

View File

@@ -33,10 +33,10 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#define DRVNAME "brcmstb-dpfe"
#define FIRMWARE_NAME "dpfe.bin"
/* DCPU register offsets */
#define REG_DCPU_RESET 0x0
@@ -59,6 +59,7 @@
#define DRAM_INFO_MR4 0x4
#define DRAM_INFO_ERROR 0x8
#define DRAM_INFO_MR4_MASK 0xff
#define DRAM_INFO_MR4_SHIFT 24 /* We need to look at byte 3 */
/* DRAM MR4 Offsets & Masks */
#define DRAM_MR4_REFRESH 0x0 /* Refresh rate */
@@ -73,13 +74,23 @@
#define DRAM_MR4_TH_OFFS_MASK 0x3
#define DRAM_MR4_TUF_MASK 0x1
/* DRAM Vendor Offsets & Masks */
/* DRAM Vendor Offsets & Masks (API v2) */
#define DRAM_VENDOR_MR5 0x0
#define DRAM_VENDOR_MR6 0x4
#define DRAM_VENDOR_MR7 0x8
#define DRAM_VENDOR_MR8 0xc
#define DRAM_VENDOR_ERROR 0x10
#define DRAM_VENDOR_MASK 0xff
#define DRAM_VENDOR_SHIFT 24 /* We need to look at byte 3 */
/* DRAM Information Offsets & Masks (API v3) */
#define DRAM_DDR_INFO_MR4 0x0
#define DRAM_DDR_INFO_MR5 0x4
#define DRAM_DDR_INFO_MR6 0x8
#define DRAM_DDR_INFO_MR7 0xc
#define DRAM_DDR_INFO_MR8 0x10
#define DRAM_DDR_INFO_ERROR 0x14
#define DRAM_DDR_INFO_MASK 0xff
/* Reset register bits & masks */
#define DCPU_RESET_SHIFT 0x0
@@ -109,7 +120,7 @@
#define DPFE_MSG_TYPE_COMMAND 1
#define DPFE_MSG_TYPE_RESPONSE 2
#define DELAY_LOOP_MAX 200000
#define DELAY_LOOP_MAX 1000
enum dpfe_msg_fields {
MSG_HEADER,
@@ -117,7 +128,7 @@ enum dpfe_msg_fields {
MSG_ARG_COUNT,
MSG_ARG0,
MSG_CHKSUM,
MSG_FIELD_MAX /* Last entry */
MSG_FIELD_MAX = 16 /* Max number of arguments */
};
enum dpfe_commands {
@@ -127,14 +138,6 @@ enum dpfe_commands {
DPFE_CMD_MAX /* Last entry */
};
struct dpfe_msg {
u32 header;
u32 command;
u32 arg_count;
u32 arg0;
u32 chksum; /* This is the sum of all other entries. */
};
/*
* Format of the binary firmware file:
*
@@ -168,12 +171,21 @@ struct init_data {
bool is_big_endian;
};
/* API version and corresponding commands */
struct dpfe_api {
int version;
const char *fw_name;
const struct attribute_group **sysfs_attrs;
u32 command[DPFE_CMD_MAX][MSG_FIELD_MAX];
};
/* Things we need for as long as we are active. */
struct private_data {
void __iomem *regs;
void __iomem *dmem;
void __iomem *imem;
struct device *dev;
const struct dpfe_api *dpfe_api;
struct mutex lock;
};
@@ -182,28 +194,99 @@ static const char *error_text[] = {
"Incorrect checksum", "Malformed command", "Timed out",
};
/* List of supported firmware commands */
static const u32 dpfe_commands[DPFE_CMD_MAX][MSG_FIELD_MAX] = {
[DPFE_CMD_GET_INFO] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 1,
[MSG_ARG_COUNT] = 1,
[MSG_ARG0] = 1,
[MSG_CHKSUM] = 4,
},
[DPFE_CMD_GET_REFRESH] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 2,
[MSG_ARG_COUNT] = 1,
[MSG_ARG0] = 1,
[MSG_CHKSUM] = 5,
},
[DPFE_CMD_GET_VENDOR] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 2,
[MSG_ARG_COUNT] = 1,
[MSG_ARG0] = 2,
[MSG_CHKSUM] = 6,
/*
* Forward declaration of our sysfs attribute functions, so we can declare the
* attribute data structures early.
*/
static ssize_t show_info(struct device *, struct device_attribute *, char *);
static ssize_t show_refresh(struct device *, struct device_attribute *, char *);
static ssize_t store_refresh(struct device *, struct device_attribute *,
const char *, size_t);
static ssize_t show_vendor(struct device *, struct device_attribute *, char *);
static ssize_t show_dram(struct device *, struct device_attribute *, char *);
/*
* Declare our attributes early, so they can be referenced in the API data
* structure. We need to do this, because the attributes depend on the API
* version.
*/
static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL);
static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh);
static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL);
static DEVICE_ATTR(dpfe_dram, 0444, show_dram, NULL);
/* API v2 sysfs attributes */
static struct attribute *dpfe_v2_attrs[] = {
&dev_attr_dpfe_info.attr,
&dev_attr_dpfe_refresh.attr,
&dev_attr_dpfe_vendor.attr,
NULL
};
ATTRIBUTE_GROUPS(dpfe_v2);
/* API v3 sysfs attributes */
static struct attribute *dpfe_v3_attrs[] = {
&dev_attr_dpfe_info.attr,
&dev_attr_dpfe_dram.attr,
NULL
};
ATTRIBUTE_GROUPS(dpfe_v3);
/* API v2 firmware commands */
static const struct dpfe_api dpfe_api_v2 = {
.version = 2,
.fw_name = "dpfe.bin",
.sysfs_attrs = dpfe_v2_groups,
.command = {
[DPFE_CMD_GET_INFO] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 1,
[MSG_ARG_COUNT] = 1,
[MSG_ARG0] = 1,
[MSG_CHKSUM] = 4,
},
[DPFE_CMD_GET_REFRESH] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 2,
[MSG_ARG_COUNT] = 1,
[MSG_ARG0] = 1,
[MSG_CHKSUM] = 5,
},
[DPFE_CMD_GET_VENDOR] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 2,
[MSG_ARG_COUNT] = 1,
[MSG_ARG0] = 2,
[MSG_CHKSUM] = 6,
},
}
};
/* API v3 firmware commands */
static const struct dpfe_api dpfe_api_v3 = {
.version = 3,
.fw_name = NULL, /* We expect the firmware to have been downloaded! */
.sysfs_attrs = dpfe_v3_groups,
.command = {
[DPFE_CMD_GET_INFO] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 0x0101,
[MSG_ARG_COUNT] = 1,
[MSG_ARG0] = 1,
[MSG_CHKSUM] = 0x104,
},
[DPFE_CMD_GET_REFRESH] = {
[MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
[MSG_COMMAND] = 0x0202,
[MSG_ARG_COUNT] = 0,
/*
* This is a bit ugly. Without arguments, the checksum
* follows right after the argument count and not at
* offset MSG_CHKSUM.
*/
[MSG_ARG0] = 0x203,
},
/* There's no GET_VENDOR command in API v3. */
},
};
@@ -248,13 +331,13 @@ static void __enable_dcpu(void __iomem *regs)
writel_relaxed(val, regs + REG_DCPU_RESET);
}
static unsigned int get_msg_chksum(const u32 msg[])
static unsigned int get_msg_chksum(const u32 msg[], unsigned int max)
{
unsigned int sum = 0;
unsigned int i;
/* Don't include the last field in the checksum. */
for (i = 0; i < MSG_FIELD_MAX - 1; i++)
for (i = 0; i < max; i++)
sum += msg[i];
return sum;
@@ -267,6 +350,11 @@ static void __iomem *get_msg_ptr(struct private_data *priv, u32 response,
unsigned int offset;
void __iomem *ptr = NULL;
/* There is no need to use this function for API v3 or later. */
if (unlikely(priv->dpfe_api->version >= 3)) {
return NULL;
}
msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
@@ -294,12 +382,25 @@ static void __iomem *get_msg_ptr(struct private_data *priv, u32 response,
return ptr;
}
static void __finalize_command(struct private_data *priv)
{
unsigned int release_mbox;
/*
* It depends on the API version which MBOX register we have to write to
* to signal we are done.
*/
release_mbox = (priv->dpfe_api->version < 3)
? REG_TO_HOST_MBOX : REG_TO_DCPU_MBOX;
writel_relaxed(0, priv->regs + release_mbox);
}
static int __send_command(struct private_data *priv, unsigned int cmd,
u32 result[])
{
const u32 *msg = dpfe_commands[cmd];
const u32 *msg = priv->dpfe_api->command[cmd];
void __iomem *regs = priv->regs;
unsigned int i, chksum;
unsigned int i, chksum, chksum_idx;
int ret = 0;
u32 resp;
@@ -308,6 +409,18 @@ static int __send_command(struct private_data *priv, unsigned int cmd,
mutex_lock(&priv->lock);
/* Wait for DCPU to become ready */
for (i = 0; i < DELAY_LOOP_MAX; i++) {
resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
if (resp == 0)
break;
msleep(1);
}
if (resp != 0) {
mutex_unlock(&priv->lock);
return -ETIMEDOUT;
}
/* Write command and arguments to message area */
for (i = 0; i < MSG_FIELD_MAX; i++)
writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i));
@@ -321,7 +434,7 @@ static int __send_command(struct private_data *priv, unsigned int cmd,
resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
if (resp > 0)
break;
udelay(5);
msleep(1);
}
if (i == DELAY_LOOP_MAX) {
@@ -331,10 +444,11 @@ static int __send_command(struct private_data *priv, unsigned int cmd,
/* Read response data */
for (i = 0; i < MSG_FIELD_MAX; i++)
result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i));
chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
}
/* Tell DCPU we are done */
writel_relaxed(0, regs + REG_TO_HOST_MBOX);
__finalize_command(priv);
mutex_unlock(&priv->lock);
@@ -342,8 +456,8 @@ static int __send_command(struct private_data *priv, unsigned int cmd,
return ret;
/* Verify response */
chksum = get_msg_chksum(result);
if (chksum != result[MSG_CHKSUM])
chksum = get_msg_chksum(result, chksum_idx);
if (chksum != result[chksum_idx])
resp = DCPU_RET_ERR_CHKSUM;
if (resp != DCPU_RET_SUCCESS) {
@@ -484,7 +598,15 @@ static int brcmstb_dpfe_download_firmware(struct platform_device *pdev,
return 0;
}
ret = request_firmware(&fw, FIRMWARE_NAME, dev);
/*
* If the firmware filename is NULL it means the boot firmware has to
* download the DCPU firmware for us. If that didn't work, we have to
* bail, since downloading it ourselves wouldn't work either.
*/
if (!priv->dpfe_api->fw_name)
return -ENODEV;
ret = request_firmware(&fw, priv->dpfe_api->fw_name, dev);
/* request_firmware() prints its own error messages. */
if (ret)
return ret;
@@ -525,12 +647,10 @@ static int brcmstb_dpfe_download_firmware(struct platform_device *pdev,
}
static ssize_t generic_show(unsigned int command, u32 response[],
struct device *dev, char *buf)
struct private_data *priv, char *buf)
{
struct private_data *priv;
int ret;
priv = dev_get_drvdata(dev);
if (!priv)
return sprintf(buf, "ERROR: driver private data not set\n");
@@ -545,10 +665,12 @@ static ssize_t show_info(struct device *dev, struct device_attribute *devattr,
char *buf)
{
u32 response[MSG_FIELD_MAX];
struct private_data *priv;
unsigned int info;
ssize_t ret;
ret = generic_show(DPFE_CMD_GET_INFO, response, dev, buf);
priv = dev_get_drvdata(dev);
ret = generic_show(DPFE_CMD_GET_INFO, response, priv, buf);
if (ret)
return ret;
@@ -571,17 +693,17 @@ static ssize_t show_refresh(struct device *dev,
u32 mr4;
ssize_t ret;
ret = generic_show(DPFE_CMD_GET_REFRESH, response, dev, buf);
priv = dev_get_drvdata(dev);
ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
if (ret)
return ret;
priv = dev_get_drvdata(dev);
info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
if (!info)
return ret;
mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK;
mr4 = (readl_relaxed(info + DRAM_INFO_MR4) >> DRAM_INFO_MR4_SHIFT) &
DRAM_INFO_MR4_MASK;
refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK;
sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK;
@@ -608,7 +730,6 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
return -EINVAL;
priv = dev_get_drvdata(dev);
ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response);
if (ret)
return ret;
@@ -623,30 +744,58 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
}
static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr,
char *buf)
char *buf)
{
u32 response[MSG_FIELD_MAX];
struct private_data *priv;
void __iomem *info;
ssize_t ret;
ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf);
if (ret)
return ret;
u32 mr5, mr6, mr7, mr8, err;
priv = dev_get_drvdata(dev);
ret = generic_show(DPFE_CMD_GET_VENDOR, response, priv, buf);
if (ret)
return ret;
info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
if (!info)
return ret;
return sprintf(buf, "%#x %#x %#x %#x %#x\n",
readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK,
readl_relaxed(info + DRAM_VENDOR_MR6) & DRAM_VENDOR_MASK,
readl_relaxed(info + DRAM_VENDOR_MR7) & DRAM_VENDOR_MASK,
readl_relaxed(info + DRAM_VENDOR_MR8) & DRAM_VENDOR_MASK,
readl_relaxed(info + DRAM_VENDOR_ERROR) &
DRAM_VENDOR_MASK);
mr5 = (readl_relaxed(info + DRAM_VENDOR_MR5) >> DRAM_VENDOR_SHIFT) &
DRAM_VENDOR_MASK;
mr6 = (readl_relaxed(info + DRAM_VENDOR_MR6) >> DRAM_VENDOR_SHIFT) &
DRAM_VENDOR_MASK;
mr7 = (readl_relaxed(info + DRAM_VENDOR_MR7) >> DRAM_VENDOR_SHIFT) &
DRAM_VENDOR_MASK;
mr8 = (readl_relaxed(info + DRAM_VENDOR_MR8) >> DRAM_VENDOR_SHIFT) &
DRAM_VENDOR_MASK;
err = readl_relaxed(info + DRAM_VENDOR_ERROR) & DRAM_VENDOR_MASK;
return sprintf(buf, "%#x %#x %#x %#x %#x\n", mr5, mr6, mr7, mr8, err);
}
static ssize_t show_dram(struct device *dev, struct device_attribute *devattr,
char *buf)
{
u32 response[MSG_FIELD_MAX];
struct private_data *priv;
ssize_t ret;
u32 mr4, mr5, mr6, mr7, mr8, err;
priv = dev_get_drvdata(dev);
ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
if (ret)
return ret;
mr4 = response[MSG_ARG0 + 0] & DRAM_INFO_MR4_MASK;
mr5 = response[MSG_ARG0 + 1] & DRAM_DDR_INFO_MASK;
mr6 = response[MSG_ARG0 + 2] & DRAM_DDR_INFO_MASK;
mr7 = response[MSG_ARG0 + 3] & DRAM_DDR_INFO_MASK;
mr8 = response[MSG_ARG0 + 4] & DRAM_DDR_INFO_MASK;
err = response[MSG_ARG0 + 5] & DRAM_DDR_INFO_MASK;
return sprintf(buf, "%#x %#x %#x %#x %#x %#x\n", mr4, mr5, mr6, mr7,
mr8, err);
}
static int brcmstb_dpfe_resume(struct platform_device *pdev)
@@ -656,17 +805,6 @@ static int brcmstb_dpfe_resume(struct platform_device *pdev)
return brcmstb_dpfe_download_firmware(pdev, &init);
}
static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL);
static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh);
static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL);
static struct attribute *dpfe_attrs[] = {
&dev_attr_dpfe_info.attr,
&dev_attr_dpfe_refresh.attr,
&dev_attr_dpfe_vendor.attr,
NULL
};
ATTRIBUTE_GROUPS(dpfe);
static int brcmstb_dpfe_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -703,26 +841,47 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
return -ENOENT;
}
ret = brcmstb_dpfe_download_firmware(pdev, &init);
if (ret)
return ret;
priv->dpfe_api = of_device_get_match_data(dev);
if (unlikely(!priv->dpfe_api)) {
/*
* It should be impossible to end up here, but to be safe we
* check anyway.
*/
dev_err(dev, "Couldn't determine API\n");
return -ENOENT;
}
ret = sysfs_create_groups(&pdev->dev.kobj, dpfe_groups);
ret = brcmstb_dpfe_download_firmware(pdev, &init);
if (ret) {
dev_err(dev, "Couldn't download firmware -- %d\n", ret);
return ret;
}
ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
if (!ret)
dev_info(dev, "registered.\n");
dev_info(dev, "registered with API v%d.\n",
priv->dpfe_api->version);
return ret;
}
static int brcmstb_dpfe_remove(struct platform_device *pdev)
{
sysfs_remove_groups(&pdev->dev.kobj, dpfe_groups);
struct private_data *priv = dev_get_drvdata(&pdev->dev);
sysfs_remove_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
return 0;
}
static const struct of_device_id brcmstb_dpfe_of_match[] = {
{ .compatible = "brcm,dpfe-cpu", },
/* Use legacy API v2 for a select number of chips */
{ .compatible = "brcm,bcm7268-dpfe-cpu", .data = &dpfe_api_v2 },
{ .compatible = "brcm,bcm7271-dpfe-cpu", .data = &dpfe_api_v2 },
{ .compatible = "brcm,bcm7278-dpfe-cpu", .data = &dpfe_api_v2 },
{ .compatible = "brcm,bcm7211-dpfe-cpu", .data = &dpfe_api_v2 },
/* API v3 is the default going forward */
{ .compatible = "brcm,dpfe-cpu", .data = &dpfe_api_v3 },
{}
};
MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match);

View File

@@ -23,8 +23,9 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <memory/jedec_ddr.h>
#include "emif.h"
#include "jedec_ddr.h"
#include "of_memory.h"
/**

172
drivers/memory/jedec_ddr.h Normal file
View File

@@ -0,0 +1,172 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Definitions for DDR memories based on JEDEC specs
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Aneesh V <aneesh@ti.com>
*/
#ifndef __JEDEC_DDR_H
#define __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_1Gb 5
#define DDR_DENSITY_2Gb 6
#define DDR_DENSITY_4Gb 7
#define DDR_DENSITY_8Gb 8
#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_NVM 5
/* DDR IO width */
#define DDR_IO_WIDTH_4 1
#define DDR_IO_WIDTH_8 2
#define DDR_IO_WIDTH_16 3
#define DDR_IO_WIDTH_32 4
/* Number of Row bits */
#define R9 9
#define R10 10
#define R11 11
#define R12 12
#define R13 13
#define R14 14
#define R15 15
#define R16 16
/* Number of Column bits */
#define C7 7
#define C8 8
#define C9 9
#define C10 10
#define C11 11
#define C12 12
/* Number of Banks */
#define B1 0
#define B2 1
#define B4 2
#define B8 3
/* Refresh rate in nano-seconds */
#define T_REFI_15_6 15600
#define T_REFI_7_8 7800
#define T_REFI_3_9 3900
/* tRFC values */
#define T_RFC_90 90000
#define T_RFC_110 110000
#define T_RFC_130 130000
#define T_RFC_160 160000
#define T_RFC_210 210000
#define T_RFC_300 300000
#define T_RFC_350 350000
/* Mode register numbers */
#define DDR_MR0 0
#define DDR_MR1 1
#define DDR_MR2 2
#define DDR_MR3 3
#define DDR_MR4 4
#define DDR_MR5 5
#define DDR_MR6 6
#define DDR_MR7 7
#define DDR_MR8 8
#define DDR_MR9 9
#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_MASK 7
#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
*/
struct lpddr2_timings {
u32 max_freq;
u32 min_freq;
u32 tRPab;
u32 tRCD;
u32 tWR;
u32 tRAS_min;
u32 tRRD;
u32 tWTR;
u32 tXP;
u32 tRTP;
u32 tCKESR;
u32 tDQSCK_max;
u32 tDQSCK_max_derated;
u32 tFAW;
u32 tZQCS;
u32 tZQCL;
u32 tZQinit;
u32 tRAS_max_ns;
};
/*
* Min value for some parameters in terms of number of tCK cycles(nCK)
* Please set to zero parameters that are not valid for a given memory
* type
*/
struct lpddr2_min_tck {
u32 tRPab;
u32 tRCD;
u32 tWR;
u32 tRASmin;
u32 tRRD;
u32 tWTR;
u32 tXP;
u32 tRTP;
u32 tCKE;
u32 tCKESR;
u32 tFAW;
};
extern const struct lpddr2_addressing
lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES];
extern const struct lpddr2_timings
lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES];
extern const struct lpddr2_min_tck lpddr2_jedec_min_tck;
#endif /* __JEDEC_DDR_H */

View File

@@ -0,0 +1,133 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* DDR addressing details and AC timing parameters from JEDEC specs
*
* Copyright (C) 2012 Texas Instruments, Inc.
*
* Aneesh V <aneesh@ti.com>
*/
#include <linux/export.h>
#include "jedec_ddr.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_GPL(lpddr2_jedec_addressing_table);
/* LPDDR2 AC timing parameters from JESD209-2 section 12 */
const struct lpddr2_timings
lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES] = {
/* Speed bin 400(200 MHz) */
[0] = {
.max_freq = 200000000,
.min_freq = 10000000,
.tRPab = 21000,
.tRCD = 18000,
.tWR = 15000,
.tRAS_min = 42000,
.tRRD = 10000,
.tWTR = 10000,
.tXP = 7500,
.tRTP = 7500,
.tCKESR = 15000,
.tDQSCK_max = 5500,
.tFAW = 50000,
.tZQCS = 90000,
.tZQCL = 360000,
.tZQinit = 1000000,
.tRAS_max_ns = 70000,
.tDQSCK_max_derated = 6000,
},
/* Speed bin 533(266 MHz) */
[1] = {
.max_freq = 266666666,
.min_freq = 10000000,
.tRPab = 21000,
.tRCD = 18000,
.tWR = 15000,
.tRAS_min = 42000,
.tRRD = 10000,
.tWTR = 7500,
.tXP = 7500,
.tRTP = 7500,
.tCKESR = 15000,
.tDQSCK_max = 5500,
.tFAW = 50000,
.tZQCS = 90000,
.tZQCL = 360000,
.tZQinit = 1000000,
.tRAS_max_ns = 70000,
.tDQSCK_max_derated = 6000,
},
/* Speed bin 800(400 MHz) */
[2] = {
.max_freq = 400000000,
.min_freq = 10000000,
.tRPab = 21000,
.tRCD = 18000,
.tWR = 15000,
.tRAS_min = 42000,
.tRRD = 10000,
.tWTR = 7500,
.tXP = 7500,
.tRTP = 7500,
.tCKESR = 15000,
.tDQSCK_max = 5500,
.tFAW = 50000,
.tZQCS = 90000,
.tZQCL = 360000,
.tZQinit = 1000000,
.tRAS_max_ns = 70000,
.tDQSCK_max_derated = 6000,
},
/* Speed bin 1066(533 MHz) */
[3] = {
.max_freq = 533333333,
.min_freq = 10000000,
.tRPab = 21000,
.tRCD = 18000,
.tWR = 15000,
.tRAS_min = 42000,
.tRRD = 10000,
.tWTR = 7500,
.tXP = 7500,
.tRTP = 7500,
.tCKESR = 15000,
.tDQSCK_max = 5500,
.tFAW = 50000,
.tZQCS = 90000,
.tZQCL = 360000,
.tZQinit = 1000000,
.tRAS_max_ns = 70000,
.tDQSCK_max_derated = 5620,
},
};
EXPORT_SYMBOL_GPL(lpddr2_jedec_timings);
const struct lpddr2_min_tck lpddr2_jedec_min_tck = {
.tRPab = 3,
.tRCD = 3,
.tWR = 3,
.tRASmin = 3,
.tRRD = 2,
.tWTR = 2,
.tXP = 2,
.tRTP = 2,
.tCKE = 3,
.tCKESR = 3,
.tFAW = 8
};
EXPORT_SYMBOL_GPL(lpddr2_jedec_min_tck);

View File

@@ -10,8 +10,9 @@
#include <linux/list.h>
#include <linux/of.h>
#include <linux/gfp.h>
#include <memory/jedec_ddr.h>
#include <linux/export.h>
#include "jedec_ddr.h"
#include "of_memory.h"
/**

View File

@@ -30,28 +30,6 @@
#define MC_EMEM_ARB_MISC1 0xdc
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
static const unsigned long tegra124_mc_emem_regs[] = {
MC_EMEM_ARB_CFG,
MC_EMEM_ARB_OUTSTANDING_REQ,
MC_EMEM_ARB_TIMING_RCD,
MC_EMEM_ARB_TIMING_RP,
MC_EMEM_ARB_TIMING_RC,
MC_EMEM_ARB_TIMING_RAS,
MC_EMEM_ARB_TIMING_FAW,
MC_EMEM_ARB_TIMING_RRD,
MC_EMEM_ARB_TIMING_RAP2PRE,
MC_EMEM_ARB_TIMING_WAP2PRE,
MC_EMEM_ARB_TIMING_R2R,
MC_EMEM_ARB_TIMING_W2W,
MC_EMEM_ARB_TIMING_R2W,
MC_EMEM_ARB_TIMING_W2R,
MC_EMEM_ARB_DA_TURNS,
MC_EMEM_ARB_DA_COVERS,
MC_EMEM_ARB_MISC0,
MC_EMEM_ARB_MISC1,
MC_EMEM_ARB_RING1_THROTTLE
};
static const struct tegra_mc_client tegra124_mc_clients[] = {
{
.id = 0x00,
@@ -1046,6 +1024,28 @@ static const struct tegra_mc_reset tegra124_mc_resets[] = {
};
#ifdef CONFIG_ARCH_TEGRA_124_SOC
static const unsigned long tegra124_mc_emem_regs[] = {
MC_EMEM_ARB_CFG,
MC_EMEM_ARB_OUTSTANDING_REQ,
MC_EMEM_ARB_TIMING_RCD,
MC_EMEM_ARB_TIMING_RP,
MC_EMEM_ARB_TIMING_RC,
MC_EMEM_ARB_TIMING_RAS,
MC_EMEM_ARB_TIMING_FAW,
MC_EMEM_ARB_TIMING_RRD,
MC_EMEM_ARB_TIMING_RAP2PRE,
MC_EMEM_ARB_TIMING_WAP2PRE,
MC_EMEM_ARB_TIMING_R2R,
MC_EMEM_ARB_TIMING_W2W,
MC_EMEM_ARB_TIMING_R2W,
MC_EMEM_ARB_TIMING_W2R,
MC_EMEM_ARB_DA_TURNS,
MC_EMEM_ARB_DA_COVERS,
MC_EMEM_ARB_MISC0,
MC_EMEM_ARB_MISC1,
MC_EMEM_ARB_RING1_THROTTLE
};
static const struct tegra_smmu_soc tegra124_smmu_soc = {
.clients = tegra124_mc_clients,
.num_clients = ARRAY_SIZE(tegra124_mc_clients),