drivers/mfd/stw481x.c

Source file repositories/reference/linux-study-clean/drivers/mfd/stw481x.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/stw481x.c
Extension
.c
Size
6742 bytes
Lines
251
Domain
Driver Families
Bucket
drivers/mfd
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Core driver for STw4810/STw4811
 *
 * Copyright (C) 2013 ST-Ericsson SA
 * Written on behalf of Linaro for ST-Ericsson
 *
 * Author: Linus Walleij <linus.walleij@linaro.org>
 */

#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/mfd/stw481x.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <linux/slab.h>

/*
 * This driver can only access the non-USB portions of STw4811, the register
 * range 0x00-0x10 dealing with USB is bound to the two special I2C pins used
 * for USB control.
 */

/* Registers inside the power control address space */
#define STW_PC_VCORE_SEL	0x05U
#define STW_PC_VAUX_SEL		0x06U
#define STW_PC_VPLL_SEL		0x07U

/**
 * stw481x_get_pctl_reg() - get a power control register
 * @stw481x: handle to the stw481x chip
 * @reg: power control register to fetch
 *
 * The power control registers is a set of one-time-programmable registers
 * in its own register space, accessed by writing addess bits to these
 * two registers: bits 7,6,5 of PCTL_REG_LO corresponds to the 3 LSBs of
 * the address and bits 8,9 of PCTL_REG_HI corresponds to the 2 MSBs of
 * the address, forming an address space of 5 bits, i.e. 32 registers
 * 0x00 ... 0x1f can be obtained.
 */
static int stw481x_get_pctl_reg(struct stw481x *stw481x, u8 reg)
{
	u8 msb = (reg >> 3) & 0x03;
	u8 lsb = (reg << 5) & 0xe0;
	unsigned int val;
	u8 vrfy;
	int ret;

	ret = regmap_write(stw481x->map, STW_PCTL_REG_HI, msb);
	if (ret)
		return ret;
	ret = regmap_write(stw481x->map, STW_PCTL_REG_LO, lsb);
	if (ret)
		return ret;
	ret = regmap_read(stw481x->map, STW_PCTL_REG_HI, &val);
	if (ret)
		return ret;
	vrfy = (val & 0x03) << 3;
	ret = regmap_read(stw481x->map, STW_PCTL_REG_LO, &val);
	if (ret)
		return ret;
	vrfy |= ((val >> 5) & 0x07);
	if (vrfy != reg)
		return -EIO;
	return (val >> 1) & 0x0f;
}

static int stw481x_startup(struct stw481x *stw481x)
{
	/* Voltages multiplied by 100 */
	static const u8 vcore_val[] = {
		100, 105, 110, 115, 120, 122, 124, 126, 128,
		130, 132, 134, 136, 138, 140, 145
	};
	static const u8 vpll_val[] = { 105, 120, 130, 180 };
	static const u8 vaux_val[] = { 15, 18, 25, 28 };
	u8 vcore;
	u8 vcore_slp;
	u8 vpll;
	u8 vaux;
	bool vaux_en;
	bool it_warn;
	int ret;
	unsigned int val;

	ret = regmap_read(stw481x->map, STW_CONF1, &val);
	if (ret)

Annotation

Implementation Notes