mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-09-29 10:52:09 +00:00
e3e2470fdd
When using OF_PLATDATA, the bind process between devices and drivers is performed trying to match compatible string with driver names. However driver names are not strictly defined, and also there are different names used when declaring a driver with U_BOOT_DRIVER, the name of the symbol used in the linker list and the used in the struct driver_info. In order to make things a bit more clear, rename the drivers names. This will also help for further OF_PLATDATA improvements, such as checking for valid driver names. Signed-off-by: Walter Lozano <walter.lozano@collabora.com> Reviewed-by: Simon Glass <sjg@chromium.org> Add a fix for sandbox of-platdata to avoid using an invalid ANSI colour: Signed-off-by: Simon Glass <sjg@chromium.org>
193 lines
4.1 KiB
C
193 lines
4.1 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2019 DENX Software Engineering
|
|
* Lukasz Majewski, DENX Software Engineering, lukma@denx.de
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <log.h>
|
|
#include <dm/device_compat.h>
|
|
#include <dm/devres.h>
|
|
#include <linux/io.h>
|
|
#include <linux/err.h>
|
|
#include <dm.h>
|
|
#include <dm/pinctrl.h>
|
|
#include <dm/read.h>
|
|
#include "pinctrl-mxs.h"
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
struct mxs_pinctrl_priv {
|
|
void __iomem *base;
|
|
const struct mxs_regs *regs;
|
|
};
|
|
|
|
static unsigned long mxs_dt_node_to_map(struct udevice *conf)
|
|
{
|
|
unsigned long config = 0;
|
|
int ret;
|
|
u32 val;
|
|
|
|
ret = dev_read_u32(conf, "fsl,drive-strength", &val);
|
|
if (!ret)
|
|
config = val | MA_PRESENT;
|
|
|
|
ret = dev_read_u32(conf, "fsl,voltage", &val);
|
|
if (!ret)
|
|
config |= val << VOL_SHIFT | VOL_PRESENT;
|
|
|
|
ret = dev_read_u32(conf, "fsl,pull-up", &val);
|
|
if (!ret)
|
|
config |= val << PULL_SHIFT | PULL_PRESENT;
|
|
|
|
return config;
|
|
}
|
|
|
|
static int mxs_pinctrl_set_mux(struct udevice *dev, u32 val, int bank, int pin)
|
|
{
|
|
struct mxs_pinctrl_priv *iomux = dev_get_priv(dev);
|
|
int muxsel = MUXID_TO_MUXSEL(val), shift;
|
|
void __iomem *reg;
|
|
|
|
reg = iomux->base + iomux->regs->muxsel;
|
|
reg += bank * 0x20 + pin / 16 * 0x10;
|
|
shift = pin % 16 * 2;
|
|
|
|
mxs_pinctrl_rmwl(muxsel, 0x3, shift, reg);
|
|
debug(" mux %d,", muxsel);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mxs_pinctrl_set_state(struct udevice *dev, struct udevice *conf)
|
|
{
|
|
struct mxs_pinctrl_priv *iomux = dev_get_priv(dev);
|
|
u32 *pin_data, val, ma, vol, pull;
|
|
int npins, size, i, ret;
|
|
unsigned long config;
|
|
|
|
debug("\n%s: set state: %s\n", __func__, conf->name);
|
|
|
|
size = dev_read_size(conf, "fsl,pinmux-ids");
|
|
if (size < 0)
|
|
return size;
|
|
|
|
if (!size || size % sizeof(int)) {
|
|
dev_err(dev, "Invalid fsl,pinmux-ids property in %s\n",
|
|
conf->name);
|
|
return -EINVAL;
|
|
}
|
|
|
|
npins = size / sizeof(int);
|
|
|
|
pin_data = devm_kzalloc(dev, size, 0);
|
|
if (!pin_data)
|
|
return -ENOMEM;
|
|
|
|
ret = dev_read_u32_array(conf, "fsl,pinmux-ids", pin_data, npins);
|
|
if (ret) {
|
|
dev_err(dev, "Error reading pin data.\n");
|
|
devm_kfree(dev, pin_data);
|
|
return -EINVAL;
|
|
}
|
|
|
|
config = mxs_dt_node_to_map(conf);
|
|
|
|
ma = CONFIG_TO_MA(config);
|
|
vol = CONFIG_TO_VOL(config);
|
|
pull = CONFIG_TO_PULL(config);
|
|
|
|
for (i = 0; i < npins; i++) {
|
|
int pinid, bank, pin, shift;
|
|
void __iomem *reg;
|
|
|
|
val = pin_data[i];
|
|
|
|
pinid = MUXID_TO_PINID(val);
|
|
bank = PINID_TO_BANK(pinid);
|
|
pin = PINID_TO_PIN(pinid);
|
|
|
|
debug("(val: 0x%x) pin %d,", val, pinid);
|
|
/* Setup pinmux */
|
|
mxs_pinctrl_set_mux(dev, val, bank, pin);
|
|
|
|
debug(" ma: %d, vol: %d, pull: %d\n", ma, vol, pull);
|
|
|
|
/* drive */
|
|
reg = iomux->base + iomux->regs->drive;
|
|
reg += bank * 0x40 + pin / 8 * 0x10;
|
|
|
|
/* mA */
|
|
if (config & MA_PRESENT) {
|
|
shift = pin % 8 * 4;
|
|
mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
|
|
}
|
|
|
|
/* vol */
|
|
if (config & VOL_PRESENT) {
|
|
shift = pin % 8 * 4 + 2;
|
|
if (vol)
|
|
writel(1 << shift, reg + SET);
|
|
else
|
|
writel(1 << shift, reg + CLR);
|
|
}
|
|
|
|
/* pull */
|
|
if (config & PULL_PRESENT) {
|
|
reg = iomux->base + iomux->regs->pull;
|
|
reg += bank * 0x10;
|
|
shift = pin;
|
|
if (pull)
|
|
writel(1 << shift, reg + SET);
|
|
else
|
|
writel(1 << shift, reg + CLR);
|
|
}
|
|
}
|
|
|
|
devm_kfree(dev, pin_data);
|
|
return 0;
|
|
}
|
|
|
|
static struct pinctrl_ops mxs_pinctrl_ops = {
|
|
.set_state = mxs_pinctrl_set_state,
|
|
};
|
|
|
|
static int mxs_pinctrl_probe(struct udevice *dev)
|
|
{
|
|
struct mxs_pinctrl_priv *iomux = dev_get_priv(dev);
|
|
|
|
iomux->base = dev_read_addr_ptr(dev);
|
|
iomux->regs = (struct mxs_regs *)dev_get_driver_data(dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct mxs_regs imx23_regs = {
|
|
.muxsel = 0x100,
|
|
.drive = 0x200,
|
|
.pull = 0x400,
|
|
};
|
|
|
|
static const struct mxs_regs imx28_regs = {
|
|
.muxsel = 0x100,
|
|
.drive = 0x300,
|
|
.pull = 0x600,
|
|
};
|
|
|
|
static const struct udevice_id mxs_pinctrl_match[] = {
|
|
{ .compatible = "fsl,imx23-pinctrl", .data = (ulong)&imx23_regs },
|
|
{ .compatible = "fsl,imx28-pinctrl", .data = (ulong)&imx28_regs },
|
|
{ /* sentinel */ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(fsl_imx23_pinctrl) = {
|
|
.name = "fsl_imx23_pinctrl",
|
|
.id = UCLASS_PINCTRL,
|
|
.of_match = of_match_ptr(mxs_pinctrl_match),
|
|
.probe = mxs_pinctrl_probe,
|
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
|
.bind = dm_scan_fdt_dev,
|
|
#endif
|
|
.priv_auto_alloc_size = sizeof(struct mxs_pinctrl_priv),
|
|
.ops = &mxs_pinctrl_ops,
|
|
};
|