// SPDX-License-Identifier: GPL-2.0 /* uio_fsl_elbc_gpcm: UIO driver for eLBC/GPCM peripherals
Copyright (C) 2014 Linutronix GmbH Author: John Ogness <john.ogness@linutronix.de>
This driver provides UIO access to memory of a peripheral connected to the Freescale enhanced local bus controller (eLBC) interface using the general purpose chip-select mode (GPCM).
Only the entries reg (to identify bank) and elbc-gpcm-* (initial BR/OR values) are required. The entries interrupt*, device_type, and uio_name are optional (as well as any type-specific options such as netx5152,init-win0-offset). As long as no interrupt handler is needed, this driver can be used without any type-specific implementation.
The netx5152 type has been tested to work with the netX 51/52 hardware from Hilscher using the Hilscher userspace netX stack.
The netx5152 type should serve as a model to add new type-specific devices as needed.
*/
/* get the memory resource */
ret = of_address_to_resource(node, 0, res); if (ret) {
dev_err(priv->dev, "failed to get resource\n"); return ret;
}
/* get the bank number */
ret = of_property_read_u32(node, "reg", &priv->bank); if (ret) {
dev_err(priv->dev, "failed to get bank number\n"); return ret;
}
/* get BR value to set */
ret = of_property_read_u32(node, "elbc-gpcm-br", reg_br); if (ret) {
dev_err(priv->dev, "missing elbc-gpcm-br value\n"); return ret;
}
/* get OR value to set */
ret = of_property_read_u32(node, "elbc-gpcm-or", reg_or); if (ret) {
dev_err(priv->dev, "missing elbc-gpcm-or value\n"); return ret;
}
/* get optional peripheral type */
priv->name = "generic"; if (of_property_read_string(node, "device_type", &type) == 0)
setup_periph(priv, type);
/* get optional irq value */
*irq = irq_of_parse_and_map(node, 0);
/* sanity check device tree data */
ret = check_of_data(priv, res, *reg_br, *reg_or); if (ret) return ret;
/* get optional uio name */ if (of_property_read_string(node, "uio_name", &dt_name) != 0)
dt_name = "eLBC_GPCM";
*name = devm_kstrdup(priv->dev, dt_name, GFP_KERNEL); if (!*name) return -ENOMEM;
if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) return -ENODEV;
/* allocate private data */
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
priv->dev = &pdev->dev;
priv->lbc = fsl_lbc_ctrl_dev->regs;
/* get device tree data */
ret = get_of_data(priv, node, &res, ®_br_new, ®_or_new,
&irq, &uio_name); if (ret) return ret;
/* allocate UIO structure */
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM;
/* get current BR/OR values */
reg_br_cur = in_be32(&priv->lbc->bank[priv->bank].br);
reg_or_cur = in_be32(&priv->lbc->bank[priv->bank].or);
/* if bank already configured, make sure it matches */ if ((reg_br_cur & BR_V)) { if ((reg_br_cur & BR_MSEL) != BR_MS_GPCM ||
(reg_br_cur & reg_or_cur & BR_BA)
!= fsl_lbc_addr(res.start)) {
dev_err(priv->dev, "bank in use by another peripheral\n"); return -ENODEV;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.