diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-15 16:03:25 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-15 16:03:25 -0800 |
commit | 991688bfc63550b8c7ab9fb1de2feb44e3071d29 (patch) | |
tree | 1566341d55e1cc56bf9153bc9accc01976b7c87a /drivers/memory | |
parent | 482c3e8835e9e9b325aad295c21bd9e965a11006 (diff) | |
parent | 2ada9593224ccc0f6a9368778dc55a59b92aff10 (diff) | |
download | linux-991688bfc63550b8c7ab9fb1de2feb44e3071d29.tar.bz2 |
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Arnd Bergmann:
"Driver updates for ARM SoCs, including a couple of newly added
drivers:
- A new driver for the power management controller on TI Keystone
- Support for the prerelease "SCPI" firmware protocol that ended up
being shipped by Amlogic in their GXBB SoC.
- A soc_device can now be matched using a glob from inside the
kernel, when another driver wants to know the specific chip it is
running on and cannot find out from DT, firmware or hardware.
- Renesas SoCs now support identification through the soc_device
interface, both in user space and kernel.
- Renesas r8a7743 and r8a7745 gain support for their system
controller
- A new checking module for the ARM "PSCI" (not to be confused with
"SCPI" mentioned above) firmware interface.
- A new driver for the Tegra GMI memory interface
- Support for the Tegra firmware interfaces with their power
management controllers
As usual, the updates for the reset controller framework are merged
here, as they tend to touch multiple SoCs as well, including a new
driver for the Oxford (now Broadcom) OX820 chip and the Tegra bpmp
interface.
The existing drivers for Atmel, Qualcomm, NVIDIA, TI Davinci, and
Rockchips SoCs see some further updates"
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (76 commits)
misc: sram: remove useless #ifdef
drivers: psci: Allow PSCI node to be disabled
drivers: psci: PSCI checker module
soc: renesas: Identify SoC and register with the SoC bus
firmware: qcom: scm: Return PTR_ERR when devm_clk_get fails
firmware: qcom: scm: Remove core, iface and bus clocks dependency
dt-bindings: firmware: scm: Add MSM8996 DT bindings
memory: da8xx-ddrctl: drop the call to of_flat_dt_get_machine_name()
bus: da8xx-mstpri: drop the call to of_flat_dt_get_machine_name()
ARM: shmobile: Document DT bindings for Product Register
soc: renesas: rcar-sysc: add R8A7745 support
reset: Add Tegra BPMP reset driver
dt-bindings: firmware: Allow child nodes inside the Tegra BPMP
dt-bindings: Add power domains to Tegra BPMP firmware
firmware: tegra: Add BPMP support
firmware: tegra: Add IVC library
dt-bindings: firmware: Add bindings for Tegra BPMP
mailbox: tegra-hsp: Use after free in tegra_hsp_remove_doorbells()
mailbox: Add Tegra HSP driver
firmware: arm_scpi: add support for pre-v1.0 SCPI compatible
...
Diffstat (limited to 'drivers/memory')
-rw-r--r-- | drivers/memory/Kconfig | 8 | ||||
-rw-r--r-- | drivers/memory/Makefile | 1 | ||||
-rw-r--r-- | drivers/memory/atmel-ebi.c | 2 | ||||
-rw-r--r-- | drivers/memory/atmel-sdramc.c | 6 | ||||
-rw-r--r-- | drivers/memory/da8xx-ddrctl.c | 173 |
5 files changed, 184 insertions, 6 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 4b4c0c3c3d2f..ec80e35c8dfe 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -134,6 +134,14 @@ config MTK_SMI mainly help enable/disable iommu and control the power domain and clocks for each local arbiter. +config DA8XX_DDRCTL + bool "Texas Instruments da8xx DDR2/mDDR driver" + depends on ARCH_DAVINCI_DA8XX + help + This driver is for the DDR2/mDDR Memory Controller present on + Texas Instruments da8xx SoCs. It's used to tweak various memory + controller configuration options. + source "drivers/memory/samsung/Kconfig" source "drivers/memory/tegra/Kconfig" diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index b20ae38b5bfb..e88097fbc085 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o obj-$(CONFIG_MTK_SMI) += mtk-smi.o +obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o obj-$(CONFIG_SAMSUNG_MC) += samsung/ obj-$(CONFIG_TEGRA_MC) += tegra/ diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index b5ed3bd082b5..047d6fcdcec2 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c @@ -657,7 +657,7 @@ static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np) return -ENOMEM; newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL); - if (!newprop->name) + if (!newprop->value) return -ENOMEM; newprop->length = sizeof("disabled"); diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c index 12080b05e3e6..b418b39af180 100644 --- a/drivers/memory/atmel-sdramc.c +++ b/drivers/memory/atmel-sdramc.c @@ -85,8 +85,4 @@ static struct platform_driver atmel_ramc_driver = { }, }; -static int __init atmel_ramc_init(void) -{ - return platform_driver_register(&atmel_ramc_driver); -} -device_initcall(atmel_ramc_init); +builtin_platform_driver(atmel_ramc_driver); diff --git a/drivers/memory/da8xx-ddrctl.c b/drivers/memory/da8xx-ddrctl.c new file mode 100644 index 000000000000..030afbe29d0c --- /dev/null +++ b/drivers/memory/da8xx-ddrctl.c @@ -0,0 +1,173 @@ +/* + * TI da8xx DDR2/mDDR controller driver + * + * Copyright (C) 2016 BayLibre SAS + * + * Author: + * Bartosz Golaszewski <bgolaszewski@baylibre.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/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +/* + * REVISIT: Linux doesn't have a good framework for the kind of performance + * knobs this driver controls. We can't use device tree properties as it deals + * with hardware configuration rather than description. We also don't want to + * commit to maintaining some random sysfs attributes. + * + * For now we just hardcode the register values for the boards that need + * some changes (as is the case for the LCD controller on da850-lcdk - the + * first board we support here). When linux gets an appropriate framework, + * we'll easily convert the driver to it. + */ + +struct da8xx_ddrctl_config_knob { + const char *name; + u32 reg; + u32 mask; + u32 shift; +}; + +static const struct da8xx_ddrctl_config_knob da8xx_ddrctl_knobs[] = { + { + .name = "da850-pbbpr", + .reg = 0x20, + .mask = 0xffffff00, + .shift = 0, + }, +}; + +struct da8xx_ddrctl_setting { + const char *name; + u32 val; +}; + +struct da8xx_ddrctl_board_settings { + const char *board; + const struct da8xx_ddrctl_setting *settings; +}; + +static const struct da8xx_ddrctl_setting da850_lcdk_ddrctl_settings[] = { + { + .name = "da850-pbbpr", + .val = 0x20, + }, + { } +}; + +static const struct da8xx_ddrctl_board_settings da8xx_ddrctl_board_confs[] = { + { + .board = "ti,da850-lcdk", + .settings = da850_lcdk_ddrctl_settings, + }, +}; + +static const struct da8xx_ddrctl_config_knob * +da8xx_ddrctl_match_knob(const struct da8xx_ddrctl_setting *setting) +{ + const struct da8xx_ddrctl_config_knob *knob; + int i; + + for (i = 0; i < ARRAY_SIZE(da8xx_ddrctl_knobs); i++) { + knob = &da8xx_ddrctl_knobs[i]; + + if (strcmp(knob->name, setting->name) == 0) + return knob; + } + + return NULL; +} + +static const struct da8xx_ddrctl_setting *da8xx_ddrctl_get_board_settings(void) +{ + const struct da8xx_ddrctl_board_settings *board_settings; + int i; + + for (i = 0; i < ARRAY_SIZE(da8xx_ddrctl_board_confs); i++) { + board_settings = &da8xx_ddrctl_board_confs[i]; + + if (of_machine_is_compatible(board_settings->board)) + return board_settings->settings; + } + + return NULL; +} + +static int da8xx_ddrctl_probe(struct platform_device *pdev) +{ + const struct da8xx_ddrctl_config_knob *knob; + const struct da8xx_ddrctl_setting *setting; + struct device_node *node; + struct resource *res; + void __iomem *ddrctl; + struct device *dev; + u32 reg; + + dev = &pdev->dev; + node = dev->of_node; + + setting = da8xx_ddrctl_get_board_settings(); + if (!setting) { + dev_err(dev, "no settings defined for this board\n"); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ddrctl = devm_ioremap_resource(dev, res); + if (IS_ERR(ddrctl)) { + dev_err(dev, "unable to map memory controller registers\n"); + return PTR_ERR(ddrctl); + } + + for (; setting->name; setting++) { + knob = da8xx_ddrctl_match_knob(setting); + if (!knob) { + dev_warn(dev, + "no such config option: %s\n", setting->name); + continue; + } + + if (knob->reg + sizeof(u32) > resource_size(res)) { + dev_warn(dev, + "register offset of '%s' exceeds mapped memory size\n", + knob->name); + continue; + } + + reg = readl(ddrctl + knob->reg); + reg &= knob->mask; + reg |= setting->val << knob->shift; + + dev_dbg(dev, "writing 0x%08x to %s\n", reg, setting->name); + + writel(reg, ddrctl + knob->reg); + } + + return 0; +} + +static const struct of_device_id da8xx_ddrctl_of_match[] = { + { .compatible = "ti,da850-ddr-controller", }, + { }, +}; + +static struct platform_driver da8xx_ddrctl_driver = { + .probe = da8xx_ddrctl_probe, + .driver = { + .name = "da850-ddr-controller", + .of_match_table = da8xx_ddrctl_of_match, + }, +}; +module_platform_driver(da8xx_ddrctl_driver); + +MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); +MODULE_DESCRIPTION("TI da8xx DDR2/mDDR controller driver"); +MODULE_LICENSE("GPL v2"); |