This pull request adds two new drivers for better
support for LCD found on DaVinci DA8xx devices. They allow configuration of memory interface and bus priorities on the SoC to allow sufficient bandwidth for the LCD and prevent underruns. The DT bindings have been reviewed by Rob and patches have been reviewed by Kevin. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYKaa4AAoJEGFBu2jqvgRNYRMQAIxGiChNTE4MlA8N00dJkhSc e1v3BQRRS3JwdUo/dsq1NhIUny49fBC+EMPUcfuEag63jmhLA2mjwqt93Ikxl3T/ FWvw+o+am7h9SCPtF24z6+qn+9DoICwvqcGO+YYWnNTIsX2KL6Y5ZpwDDhZqWcFC PlZ0itx+BBnhISUFwSlTBWRpmKmmYECknBByUeVNJKRVykdc/Je1P96e5JW8JqRz QK/2E3y1j/KU6TlKzi7tM3GH/w4vxpceAPnyrZ4pqPBcHJVVcaYxm5GiZhaITwOq ccQovRWu+LBS81XGUvMNO68QFB61A4ktBOHlckpHPpxnUtXkj9HmjnxT8b7vO4Jj 7phO3su40P5j4Embn5R4r43QNGoztsshtAZghawMhDsNkqxhYKVzItqUHLnUqSQO SHgTcUrdICczMjm1npFBfXV4Hw2027zJo9g99PvhEkOVLf1OtSIzmkDcDNsAIQdc 0oeAz7k6hQhqivKrPHsPv1mrB4MhtkAbe1FByrB0XhdJY09U+u8o3d+3ishvA7cj ihk57EXEbs9ajsQHszO8GHT8/xLVyO/fc/sMWvjszBGvj+MLAvyrvuYfsQmSqgcL DDb4JsL2STFaeaeJnrtAscrMs4Wem8K0Sel+SFKRwZeMM9JZcMssGiiRQobcMNIM ash8y8D39v7To1vsTdw0 =ye/f -----END PGP SIGNATURE----- Merge tag 'davinci-for-v4.10/drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into next/drivers This pull request adds two new drivers for better support for LCD found on DaVinci DA8xx devices. They allow configuration of memory interface and bus priorities on the SoC to allow sufficient bandwidth for the LCD and prevent underruns. The DT bindings have been reviewed by Rob and patches have been reviewed by Kevin. * tag 'davinci-for-v4.10/drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci: bus: davinci: add support for da8xx bus master priority control memory: davinci: add support for da8xx DDR2/mDDR controller Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
b9bccf35ac
|
@ -0,0 +1,20 @@
|
|||
* Device tree bindings for Texas Instruments da8xx master peripheral
|
||||
priority driver
|
||||
|
||||
DA8XX SoCs feature a set of registers allowing to change the priority of all
|
||||
peripherals classified as masters.
|
||||
|
||||
Documentation:
|
||||
OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh82c/spruh82c.pdf
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "ti,da850-mstpri" - for da850 based boards
|
||||
- reg: offset and length of the mstpri registers
|
||||
|
||||
Example for da850-lcdk is shown below.
|
||||
|
||||
mstpri {
|
||||
compatible = "ti,da850-mstpri";
|
||||
reg = <0x14110 0x0c>;
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
* Device tree bindings for Texas Instruments da8xx DDR2/mDDR memory controller
|
||||
|
||||
The DDR2/mDDR memory controller present on Texas Instruments da8xx SoCs features
|
||||
a set of registers which allow to tweak the controller's behavior.
|
||||
|
||||
Documentation:
|
||||
OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh82c/spruh82c.pdf
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "ti,da850-ddr-controller" - for da850 SoC based boards
|
||||
- reg: a tuple containing the base address of the memory
|
||||
controller and the size of the memory area to map
|
||||
|
||||
Example for da850 shown below.
|
||||
|
||||
ddrctl {
|
||||
compatible = "ti,da850-ddr-controller";
|
||||
reg = <0xb0000000 0xe8>;
|
||||
};
|
|
@ -166,4 +166,13 @@ config VEXPRESS_CONFIG
|
|||
help
|
||||
Platform configuration infrastructure for the ARM Ltd.
|
||||
Versatile Express.
|
||||
|
||||
config DA8XX_MSTPRI
|
||||
bool "TI da8xx master peripheral priority driver"
|
||||
depends on ARCH_DAVINCI_DA8XX
|
||||
help
|
||||
Driver for Texas Instruments da8xx master peripheral priority
|
||||
configuration. Allows to adjust the priorities of all master
|
||||
peripherals.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -21,3 +21,5 @@ obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
|
|||
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
|
||||
obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
|
||||
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
|
||||
|
||||
obj-$(CONFIG_DA8XX_MSTPRI) += da8xx-mstpri.o
|
||||
|
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* TI da8xx master peripheral priority driver
|
||||
*
|
||||
* Copyright (C) 2016 BayLibre SAS
|
||||
*
|
||||
* Author:
|
||||
* Bartosz Golaszewski <bgolaszewski@baylibre.com.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/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of_fdt.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.
|
||||
*/
|
||||
|
||||
#define DA8XX_MSTPRI0_OFFSET 0
|
||||
#define DA8XX_MSTPRI1_OFFSET 4
|
||||
#define DA8XX_MSTPRI2_OFFSET 8
|
||||
|
||||
enum {
|
||||
DA8XX_MSTPRI_ARM_I = 0,
|
||||
DA8XX_MSTPRI_ARM_D,
|
||||
DA8XX_MSTPRI_UPP,
|
||||
DA8XX_MSTPRI_SATA,
|
||||
DA8XX_MSTPRI_PRU0,
|
||||
DA8XX_MSTPRI_PRU1,
|
||||
DA8XX_MSTPRI_EDMA30TC0,
|
||||
DA8XX_MSTPRI_EDMA30TC1,
|
||||
DA8XX_MSTPRI_EDMA31TC0,
|
||||
DA8XX_MSTPRI_VPIF_DMA_0,
|
||||
DA8XX_MSTPRI_VPIF_DMA_1,
|
||||
DA8XX_MSTPRI_EMAC,
|
||||
DA8XX_MSTPRI_USB0CFG,
|
||||
DA8XX_MSTPRI_USB0CDMA,
|
||||
DA8XX_MSTPRI_UHPI,
|
||||
DA8XX_MSTPRI_USB1,
|
||||
DA8XX_MSTPRI_LCDC,
|
||||
};
|
||||
|
||||
struct da8xx_mstpri_descr {
|
||||
int reg;
|
||||
int shift;
|
||||
int mask;
|
||||
};
|
||||
|
||||
static const struct da8xx_mstpri_descr da8xx_mstpri_priority_list[] = {
|
||||
[DA8XX_MSTPRI_ARM_I] = {
|
||||
.reg = DA8XX_MSTPRI0_OFFSET,
|
||||
.shift = 0,
|
||||
.mask = 0x0000000f,
|
||||
},
|
||||
[DA8XX_MSTPRI_ARM_D] = {
|
||||
.reg = DA8XX_MSTPRI0_OFFSET,
|
||||
.shift = 4,
|
||||
.mask = 0x000000f0,
|
||||
},
|
||||
[DA8XX_MSTPRI_UPP] = {
|
||||
.reg = DA8XX_MSTPRI0_OFFSET,
|
||||
.shift = 16,
|
||||
.mask = 0x000f0000,
|
||||
},
|
||||
[DA8XX_MSTPRI_SATA] = {
|
||||
.reg = DA8XX_MSTPRI0_OFFSET,
|
||||
.shift = 20,
|
||||
.mask = 0x00f00000,
|
||||
},
|
||||
[DA8XX_MSTPRI_PRU0] = {
|
||||
.reg = DA8XX_MSTPRI1_OFFSET,
|
||||
.shift = 0,
|
||||
.mask = 0x0000000f,
|
||||
},
|
||||
[DA8XX_MSTPRI_PRU1] = {
|
||||
.reg = DA8XX_MSTPRI1_OFFSET,
|
||||
.shift = 4,
|
||||
.mask = 0x000000f0,
|
||||
},
|
||||
[DA8XX_MSTPRI_EDMA30TC0] = {
|
||||
.reg = DA8XX_MSTPRI1_OFFSET,
|
||||
.shift = 8,
|
||||
.mask = 0x00000f00,
|
||||
},
|
||||
[DA8XX_MSTPRI_EDMA30TC1] = {
|
||||
.reg = DA8XX_MSTPRI1_OFFSET,
|
||||
.shift = 12,
|
||||
.mask = 0x0000f000,
|
||||
},
|
||||
[DA8XX_MSTPRI_EDMA31TC0] = {
|
||||
.reg = DA8XX_MSTPRI1_OFFSET,
|
||||
.shift = 16,
|
||||
.mask = 0x000f0000,
|
||||
},
|
||||
[DA8XX_MSTPRI_VPIF_DMA_0] = {
|
||||
.reg = DA8XX_MSTPRI1_OFFSET,
|
||||
.shift = 24,
|
||||
.mask = 0x0f000000,
|
||||
},
|
||||
[DA8XX_MSTPRI_VPIF_DMA_1] = {
|
||||
.reg = DA8XX_MSTPRI1_OFFSET,
|
||||
.shift = 28,
|
||||
.mask = 0xf0000000,
|
||||
},
|
||||
[DA8XX_MSTPRI_EMAC] = {
|
||||
.reg = DA8XX_MSTPRI2_OFFSET,
|
||||
.shift = 0,
|
||||
.mask = 0x0000000f,
|
||||
},
|
||||
[DA8XX_MSTPRI_USB0CFG] = {
|
||||
.reg = DA8XX_MSTPRI2_OFFSET,
|
||||
.shift = 8,
|
||||
.mask = 0x00000f00,
|
||||
},
|
||||
[DA8XX_MSTPRI_USB0CDMA] = {
|
||||
.reg = DA8XX_MSTPRI2_OFFSET,
|
||||
.shift = 12,
|
||||
.mask = 0x0000f000,
|
||||
},
|
||||
[DA8XX_MSTPRI_UHPI] = {
|
||||
.reg = DA8XX_MSTPRI2_OFFSET,
|
||||
.shift = 20,
|
||||
.mask = 0x00f00000,
|
||||
},
|
||||
[DA8XX_MSTPRI_USB1] = {
|
||||
.reg = DA8XX_MSTPRI2_OFFSET,
|
||||
.shift = 24,
|
||||
.mask = 0x0f000000,
|
||||
},
|
||||
[DA8XX_MSTPRI_LCDC] = {
|
||||
.reg = DA8XX_MSTPRI2_OFFSET,
|
||||
.shift = 28,
|
||||
.mask = 0xf0000000,
|
||||
},
|
||||
};
|
||||
|
||||
struct da8xx_mstpri_priority {
|
||||
int which;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct da8xx_mstpri_board_priorities {
|
||||
const char *board;
|
||||
const struct da8xx_mstpri_priority *priorities;
|
||||
size_t numprio;
|
||||
};
|
||||
|
||||
/*
|
||||
* Default memory settings of da850 do not meet the throughput/latency
|
||||
* requirements of tilcdc. This results in the image displayed being
|
||||
* incorrect and the following warning being displayed by the LCDC
|
||||
* drm driver:
|
||||
*
|
||||
* tilcdc da8xx_lcdc.0: tilcdc_crtc_irq(0x00000020): FIFO underfow
|
||||
*/
|
||||
static const struct da8xx_mstpri_priority da850_lcdk_priorities[] = {
|
||||
{
|
||||
.which = DA8XX_MSTPRI_LCDC,
|
||||
.val = 0,
|
||||
},
|
||||
{
|
||||
.which = DA8XX_MSTPRI_EDMA30TC1,
|
||||
.val = 0,
|
||||
},
|
||||
{
|
||||
.which = DA8XX_MSTPRI_EDMA30TC0,
|
||||
.val = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct da8xx_mstpri_board_priorities da8xx_mstpri_board_confs[] = {
|
||||
{
|
||||
.board = "ti,da850-lcdk",
|
||||
.priorities = da850_lcdk_priorities,
|
||||
.numprio = ARRAY_SIZE(da850_lcdk_priorities),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct da8xx_mstpri_board_priorities *
|
||||
da8xx_mstpri_get_board_prio(void)
|
||||
{
|
||||
const struct da8xx_mstpri_board_priorities *board_prio;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(da8xx_mstpri_board_confs); i++) {
|
||||
board_prio = &da8xx_mstpri_board_confs[i];
|
||||
|
||||
if (of_machine_is_compatible(board_prio->board))
|
||||
return board_prio;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int da8xx_mstpri_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct da8xx_mstpri_board_priorities *prio_list;
|
||||
const struct da8xx_mstpri_descr *prio_descr;
|
||||
const struct da8xx_mstpri_priority *prio;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
void __iomem *mstpri;
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mstpri = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(mstpri)) {
|
||||
dev_err(dev, "unable to map MSTPRI registers\n");
|
||||
return PTR_ERR(mstpri);
|
||||
}
|
||||
|
||||
prio_list = da8xx_mstpri_get_board_prio();
|
||||
if (!prio_list) {
|
||||
dev_err(dev, "no master priotities defined for board '%s'\n",
|
||||
of_flat_dt_get_machine_name());
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < prio_list->numprio; i++) {
|
||||
prio = &prio_list->priorities[i];
|
||||
prio_descr = &da8xx_mstpri_priority_list[prio->which];
|
||||
|
||||
if (prio_descr->reg + sizeof(u32) > resource_size(res)) {
|
||||
dev_warn(dev, "register offset out of range\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
reg = readl(mstpri + prio_descr->reg);
|
||||
reg &= ~prio_descr->mask;
|
||||
reg |= prio->val << prio_descr->shift;
|
||||
|
||||
writel(reg, mstpri + prio_descr->reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id da8xx_mstpri_of_match[] = {
|
||||
{ .compatible = "ti,da850-mstpri", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver da8xx_mstpri_driver = {
|
||||
.probe = da8xx_mstpri_probe,
|
||||
.driver = {
|
||||
.name = "da8xx-mstpri",
|
||||
.of_match_table = da8xx_mstpri_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(da8xx_mstpri_driver);
|
||||
|
||||
MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
|
||||
MODULE_DESCRIPTION("TI da8xx master peripheral priority driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* 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/of_fdt.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 for board '%s'\n",
|
||||
of_flat_dt_get_machine_name());
|
||||
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");
|
Loading…
Reference in New Issue