示例#1
0
static struct syscon *of_syscon_register(struct device_node *np)
{
	int ret;
	struct syscon *syscon;
	struct resource res;

	if (!of_device_is_compatible(np, "syscon"))
		return ERR_PTR(-EINVAL);

	syscon = xzalloc(sizeof(*syscon));

	if (of_address_to_resource(np, 0, &res)) {
		ret = -ENOMEM;
		goto err_map;
	}

	syscon->base = IOMEM(res.start);
	syscon->np   = np;

	list_add_tail(&syscon->list, &syscon_list);

	syscon->regmap = regmap_init(NULL,
				     &syscon_regmap_bus,
				     syscon,
				     &syscon_regmap_config);
	return syscon;

err_map:
	kfree(syscon);
	return ERR_PTR(ret);
}
示例#2
0
文件: ocotp.c 项目: gazoo74/barebox
static int imx_ocotp_probe(struct device_d *dev)
{
	struct resource *iores;
	void __iomem *base;
	struct ocotp_priv *priv;
	int ret = 0;
	struct imx_ocotp_data *data;

	ret = dev_get_drvdata(dev, (const void **)&data);
	if (ret)
		return ret;

	iores = dev_request_mem_resource(dev, 0);
	if (IS_ERR(iores))
		return PTR_ERR(iores);
	base = IOMEM(iores->start);

	imx_ocotp_init_dt(dev, base);

	priv = xzalloc(sizeof(*priv));

	priv->base	= base;
	priv->clk	= clk_get(dev, NULL);
	if (IS_ERR(priv->clk))
		return PTR_ERR(priv->clk);

	strcpy(priv->dev.name, "ocotp");
	priv->dev.parent = dev;
	register_device(&priv->dev);

	priv->map_config.reg_bits = 32;
	priv->map_config.val_bits = 32;
	priv->map_config.reg_stride = 4;
	priv->map_config.max_register = data->num_regs - 1;

	priv->map = regmap_init(dev, &imx_ocotp_regmap_bus, priv, &priv->map_config);
	if (IS_ERR(priv->map))
		return PTR_ERR(priv->map);

	ret = regmap_register_cdev(priv->map, "imx-ocotp");
	if (ret)
		return ret;

	if (IS_ENABLED(CONFIG_IMX_OCOTP_WRITE)) {
		dev_add_param_bool(&(priv->dev), "permanent_write_enable",
				NULL, NULL, &priv->permanent_write_enable, NULL);
	}

	if (IS_ENABLED(CONFIG_NET))
		dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac,
				imx_ocotp_get_mac, priv->ethaddr, priv);

	dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv);

	return 0;
}
示例#3
0
/**
 * regmap_init_i2c(): Initialise register map
 *
 * @i2c: Device that will be interacted with
 * @config: Configuration for register map
 *
 * The return value will be an ERR_PTR() on error or a valid pointer to
 * a struct regmap.
 */
struct regmap *regmap_init_i2c(struct i2c_client *i2c,
			       const struct regmap_config *config)
{
	const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);

	if (IS_ERR(bus))
		return ERR_CAST(bus);

	return regmap_init(&i2c->dev, bus, &i2c->dev, config);
}
示例#4
0
/**
 * regmap_init_mcuio(): Initialise mcuio register map
 *
 * @dev: Device that will be interacted with
 * @hc: mcuio system controller
 * @config: Configuration for register map
 *
 * The return value will be an ERR_PTR() on error or a valid pointer to
 * a struct regmap.
 */
struct regmap *regmap_init_mcuio(struct mcuio_device *mdev,
				 const struct regmap_config *config)
{
	struct regmap_mcuio_context *ctx;
	ctx = regmap_mcuio_setup_context(mdev, config);
	if (IS_ERR(ctx))
		return ERR_CAST(ctx);

	return regmap_init(&mdev->dev, &regmap_mcuio, ctx, config);
}
/**
 * regmap_init_mmio(): Initialise register map
 *
 * @dev: Device that will be interacted with
 * @regs: Pointer to memory-mapped IO region
 * @config: Configuration for register map
 *
 * The return value will be an ERR_PTR() on error or a valid pointer to
 * a struct regmap.
 */
struct regmap *regmap_init_mmio(struct device *dev,
				void __iomem *regs,
				const struct regmap_config *config)
{
	struct regmap_mmio_context *ctx;

	ctx = regmap_mmio_gen_context(regs, config);
	if (IS_ERR(ctx))
		return ERR_CAST(ctx);

	return regmap_init(dev, &regmap_mmio, ctx, config);
}
示例#6
0
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
				   u16 opcode_write)
{
	struct regmap_ibt_context *ctx;

	bt_dev_info(hdev, "regmap: Init R%x-W%x region", opcode_read,
		    opcode_write);

	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return ERR_PTR(-ENOMEM);

	ctx->op_read = opcode_read;
	ctx->op_write = opcode_write;
	ctx->hdev = hdev;

	return regmap_init(&hdev->dev, &regmap_ibt, ctx, &regmap_ibt_cfg);
}
示例#7
0
static struct regmap *
mcuio_soft_hc_setup_regmap(struct device *dev,
			   void *__plat)
{
	struct mcuio_hc_platform_data *plat = __plat;
	struct regmap_config *map_cfg = mcuio_soft_hc_setup_regmap_config();
	struct mcuio_soft_hc *shc;
	struct regmap *out = ERR_PTR(-ENOMEM);
	if (!map_cfg) {
		dev_err(dev, "%s: cannot setup regmap config\n", __func__);
		return ERR_PTR(-ENOMEM);
	}
	shc = plat->data;
	if (!shc) {
		dev_err(dev, "%s: no platform data\n", __func__);
		return out;
	}
	/*
	  no_bus regmap with reg_read and reg_write, use soft controller
	  structure as regmap context
	*/
	return regmap_init(dev, NULL, shc, map_cfg);
}
示例#8
0
/**
 * regmap_init_ac97(): Initialise AC'97 register map
 *
 * @ac97: Device that will be interacted with
 * @config: Configuration for register map
 *
 * The return value will be an ERR_PTR() on error or a valid pointer to
 * a struct regmap.
 */
struct regmap *regmap_init_ac97(struct snd_ac97 *ac97,
				const struct regmap_config *config)
{
	return regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config);
}
/**
 * regmap_init_spmi_ext(): Create regmap for Ext register space
 * @sdev:	Device that will be interacted with
 * @config:	Configuration for register map
 *
 * The return value will be an ERR_PTR() on error or a valid pointer to
 * a struct regmap.
 */
struct regmap *regmap_init_spmi_ext(struct spmi_device *sdev,
				    const struct regmap_config *config)
{
	return regmap_init(&sdev->dev, &regmap_spmi_ext, sdev, config);
}
示例#10
0
/**
 * regmap_init_i2c(): Initialise register map
 *
 * @i2c: Device that will be interacted with
 * @config: Configuration for register map
 *
 * The return value will be an ERR_PTR() on error or a valid pointer to
 * a struct regmap.
 */
struct regmap *regmap_init_i2c(struct i2c_client *i2c,
			       const struct regmap_config *config)
{
	return regmap_init(&i2c->dev, &regmap_i2c, &i2c->dev, config);
}
static int mc13xxx_spi_read(void *context, const void *reg, size_t reg_size,
				void *val, size_t val_size)
{
	unsigned char w[4] = { *((unsigned char *) reg), 0, 0, 0};
	unsigned char r[4];
	unsigned char *p = val;
	struct device *dev = context;
	struct spi_device *spi = to_spi_device(dev);
	struct spi_transfer t = {
		.tx_buf = w,
		.rx_buf = r,
		.len = 4,
	};

	struct spi_message m;
	int ret;

	if (val_size != 3 || reg_size != 1)
		return -ENOTSUPP;

	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	ret = spi_sync(spi, &m);

	memcpy(p, &r[1], 3);

	return ret;
}

static int mc13xxx_spi_write(void *context, const void *data, size_t count)
{
	struct device *dev = context;
	struct spi_device *spi = to_spi_device(dev);

	if (count != 4)
		return -ENOTSUPP;

	return spi_write(spi, data, count);
}

/*
 * We cannot use regmap-spi generic bus implementation here.
 * The MC13783 chip will get corrupted if CS signal is deasserted
 * and on i.Mx31 SoC (the target SoC for MC13783 PMIC) the SPI controller
 * has the following errata (DSPhl22960):
 * "The CSPI negates SS when the FIFO becomes empty with
 * SSCTL= 0. Software cannot guarantee that the FIFO will not
 * drain because of higher priority interrupts and the
 * non-realtime characteristics of the operating system. As a
 * result, the SS will negate before all of the data has been
 * transferred to/from the peripheral."
 * We workaround this by accessing the SPI controller with a
 * single transfert.
 */

static struct regmap_bus regmap_mc13xxx_bus = {
	.write = mc13xxx_spi_write,
	.read = mc13xxx_spi_read,
};

static int mc13xxx_spi_probe(struct spi_device *spi)
{
	const struct of_device_id *of_id;
	struct spi_driver *sdrv = to_spi_driver(spi->dev.driver);
	struct mc13xxx *mc13xxx;
	struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
	int ret;

	of_id = of_match_device(mc13xxx_dt_ids, &spi->dev);
	if (of_id)
		sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data];

	mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
	if (!mc13xxx)
		return -ENOMEM;

	dev_set_drvdata(&spi->dev, mc13xxx);
	spi->mode = SPI_MODE_0 | SPI_CS_HIGH;

	mc13xxx->dev = &spi->dev;
	mutex_init(&mc13xxx->lock);

	mc13xxx->regmap = regmap_init(&spi->dev, &regmap_mc13xxx_bus, &spi->dev,
					&mc13xxx_regmap_spi_config);

	if (IS_ERR(mc13xxx->regmap)) {
		ret = PTR_ERR(mc13xxx->regmap);
		dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
				ret);
		dev_set_drvdata(&spi->dev, NULL);
		kfree(mc13xxx);
		return ret;
	}

	ret = mc13xxx_common_init(mc13xxx, pdata, spi->irq);

	if (ret) {
		dev_set_drvdata(&spi->dev, NULL);
	} else {
		const struct spi_device_id *devid =
			spi_get_device_id(spi);
		if (!devid || devid->driver_data != mc13xxx->ictype)
			dev_warn(mc13xxx->dev,
				"device id doesn't match auto detection!\n");
	}

	return ret;
}

static int __devexit mc13xxx_spi_remove(struct spi_device *spi)
{
	struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev);

	mc13xxx_common_cleanup(mc13xxx);

	return 0;
}

static struct spi_driver mc13xxx_spi_driver = {
	.id_table = mc13xxx_device_id,
	.driver = {
		.name = "mc13xxx",
		.owner = THIS_MODULE,
		.of_match_table = mc13xxx_dt_ids,
	},
	.probe = mc13xxx_spi_probe,
	.remove = __devexit_p(mc13xxx_spi_remove),
};
示例#12
0
static int imx_ocotp_probe(struct device_d *dev)
{
	struct resource *iores;
	struct ocotp_priv *priv;
	int ret = 0;
	const struct imx_ocotp_data *data;
	struct nvmem_device *nvmem;

	ret = dev_get_drvdata(dev, (const void **)&data);
	if (ret)
		return ret;

	iores = dev_request_mem_resource(dev, 0);
	if (IS_ERR(iores))
		return PTR_ERR(iores);

	priv = xzalloc(sizeof(*priv));

	priv->data      = data;
	priv->base	= IOMEM(iores->start);
	priv->clk	= clk_get(dev, NULL);
	if (IS_ERR(priv->clk))
		return PTR_ERR(priv->clk);

	strcpy(priv->dev.name, "ocotp");
	priv->dev.parent = dev;
	register_device(&priv->dev);

	priv->map_config.reg_bits = 32;
	priv->map_config.val_bits = 32;
	priv->map_config.reg_stride = 4;
	priv->map_config.max_register = data->num_regs - 1;

	priv->map = regmap_init(dev, &imx_ocotp_regmap_bus, priv, &priv->map_config);
	if (IS_ERR(priv->map))
		return PTR_ERR(priv->map);

	priv->config.name = "imx-ocotp";
	priv->config.dev = dev;
	priv->config.stride = 4;
	priv->config.word_size = 4;
	priv->config.size = data->num_regs;
	priv->config.bus = &imx_ocotp_nvmem_bus;
	dev->priv = priv;

	nvmem = nvmem_register(&priv->config);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	imx_ocotp = priv;

	if (IS_ENABLED(CONFIG_IMX_OCOTP_WRITE)) {
		dev_add_param_bool(&(priv->dev), "permanent_write_enable",
				NULL, NULL, &priv->permanent_write_enable, NULL);
	}

	if (IS_ENABLED(CONFIG_NET)) {
		int i;
		struct ocotp_priv_ethaddr *ethaddr;

		for (i = 0; i < priv->data->mac_offsets_num; i++) {
			ethaddr = &priv->ethaddr[i];
			ethaddr->map = priv->map;
			ethaddr->offset = priv->data->mac_offsets[i];
			ethaddr->data = data;

			dev_add_param_mac(&priv->dev, xasprintf("mac_addr%d", i),
					  imx_ocotp_set_mac, imx_ocotp_get_mac,
					  ethaddr->value, ethaddr);
		}

		/*
		 * Alias to mac_addr0 for backwards compatibility
		 */
		ethaddr = &priv->ethaddr[0];
		dev_add_param_mac(&priv->dev, "mac_addr",
				  imx_ocotp_set_mac, imx_ocotp_get_mac,
				  ethaddr->value, ethaddr);
	}

	imx_ocotp_init_dt(priv);

	dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv);

	return 0;
}