brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 2bf34da Raw
166 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * TI da8xx DDR2/mDDR controller driver4 *5 * Copyright (C) 2016 BayLibre SAS6 *7 * Author:8 *   Bartosz Golaszewski <bgolaszewski@baylibre.com>9 */10 11#include <linux/module.h>12#include <linux/of.h>13#include <linux/platform_device.h>14#include <linux/io.h>15 16/*17 * REVISIT: Linux doesn't have a good framework for the kind of performance18 * knobs this driver controls. We can't use device tree properties as it deals19 * with hardware configuration rather than description. We also don't want to20 * commit to maintaining some random sysfs attributes.21 *22 * For now we just hardcode the register values for the boards that need23 * some changes (as is the case for the LCD controller on da850-lcdk - the24 * first board we support here). When linux gets an appropriate framework,25 * we'll easily convert the driver to it.26 */27 28struct da8xx_ddrctl_config_knob {29	const char *name;30	u32 reg;31	u32 mask;32	u32 shift;33};34 35static const struct da8xx_ddrctl_config_knob da8xx_ddrctl_knobs[] = {36	{37		.name = "da850-pbbpr",38		.reg = 0x20,39		.mask = 0xffffff00,40		.shift = 0,41	},42};43 44struct da8xx_ddrctl_setting {45	const char *name;46	u32 val;47};48 49struct da8xx_ddrctl_board_settings {50	const char *board;51	const struct da8xx_ddrctl_setting *settings;52};53 54static const struct da8xx_ddrctl_setting da850_lcdk_ddrctl_settings[] = {55	{56		.name = "da850-pbbpr",57		.val = 0x20,58	},59	{ }60};61 62static const struct da8xx_ddrctl_board_settings da8xx_ddrctl_board_confs[] = {63	{64		.board = "ti,da850-lcdk",65		.settings = da850_lcdk_ddrctl_settings,66	},67};68 69static const struct da8xx_ddrctl_config_knob *70da8xx_ddrctl_match_knob(const struct da8xx_ddrctl_setting *setting)71{72	const struct da8xx_ddrctl_config_knob *knob;73	int i;74 75	for (i = 0; i < ARRAY_SIZE(da8xx_ddrctl_knobs); i++) {76		knob = &da8xx_ddrctl_knobs[i];77 78		if (strcmp(knob->name, setting->name) == 0)79			return knob;80	}81 82	return NULL;83}84 85static const struct da8xx_ddrctl_setting *da8xx_ddrctl_get_board_settings(void)86{87	const struct da8xx_ddrctl_board_settings *board_settings;88	int i;89 90	for (i = 0; i < ARRAY_SIZE(da8xx_ddrctl_board_confs); i++) {91		board_settings = &da8xx_ddrctl_board_confs[i];92 93		if (of_machine_is_compatible(board_settings->board))94			return board_settings->settings;95	}96 97	return NULL;98}99 100static int da8xx_ddrctl_probe(struct platform_device *pdev)101{102	const struct da8xx_ddrctl_config_knob *knob;103	const struct da8xx_ddrctl_setting *setting;104	struct resource *res;105	void __iomem *ddrctl;106	struct device *dev;107	u32 reg;108 109	dev = &pdev->dev;110 111	setting = da8xx_ddrctl_get_board_settings();112	if (!setting) {113		dev_err(dev, "no settings defined for this board\n");114		return -EINVAL;115	}116 117	ddrctl = devm_platform_get_and_ioremap_resource(pdev, 0, &res);118	if (IS_ERR(ddrctl)) {119		dev_err(dev, "unable to map memory controller registers\n");120		return PTR_ERR(ddrctl);121	}122 123	for (; setting->name; setting++) {124		knob = da8xx_ddrctl_match_knob(setting);125		if (!knob) {126			dev_warn(dev,127				 "no such config option: %s\n", setting->name);128			continue;129		}130 131		if (knob->reg + sizeof(u32) > resource_size(res)) {132			dev_warn(dev,133				 "register offset of '%s' exceeds mapped memory size\n",134				 knob->name);135			continue;136		}137 138		reg = readl(ddrctl + knob->reg);139		reg &= knob->mask;140		reg |= setting->val << knob->shift;141 142		dev_dbg(dev, "writing 0x%08x to %s\n", reg, setting->name);143 144		writel(reg, ddrctl + knob->reg);145	}146 147	return 0;148}149 150static const struct of_device_id da8xx_ddrctl_of_match[] = {151	{ .compatible = "ti,da850-ddr-controller", },152	{ },153};154 155static struct platform_driver da8xx_ddrctl_driver = {156	.probe = da8xx_ddrctl_probe,157	.driver = {158		.name = "da850-ddr-controller",159		.of_match_table = da8xx_ddrctl_of_match,160	},161};162module_platform_driver(da8xx_ddrctl_driver);163 164MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");165MODULE_DESCRIPTION("TI da8xx DDR2/mDDR controller driver");166