drivers/soc/samsung/exynos-usi.c

Source file repositories/reference/linux-study-clean/drivers/soc/samsung/exynos-usi.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/samsung/exynos-usi.c
Extension
.c
Size
9514 bytes
Lines
356
Domain
Driver Families
Bucket
drivers/soc
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

struct exynos_usi_variant {
	enum exynos_usi_ver ver;	/* USI IP-core version */
	unsigned int sw_conf_mask;	/* SW_CONF mask for all protocols */
	size_t min_mode;		/* first index in exynos_usi_modes[] */
	size_t max_mode;		/* last index in exynos_usi_modes[] */
	size_t num_clks;		/* number of clocks to assert */
	const char * const *clk_names;	/* clock names to assert */
};

struct exynos_usi {
	struct device *dev;
	void __iomem *regs;		/* USI register map */
	struct clk_bulk_data *clks;	/* USI clocks */

	size_t mode;			/* current USI SW_CONF mode index */
	bool clkreq_on;			/* always provide clock to IP */

	/* System Register */
	struct regmap *sysreg;		/* System Register map */
	unsigned int sw_conf;		/* SW_CONF register offset in sysreg */

	const struct exynos_usi_variant *data;
};

struct exynos_usi_mode {
	const char *name;		/* mode name */
	unsigned int val;		/* mode register value */
};

#define USI_MODES_MAX (USI_MODE_UART_I2C1 + 1)
static const struct exynos_usi_mode exynos_usi_modes[][USI_MODES_MAX] = {
	[USI_VER1] = {
		[USI_MODE_NONE] =	{ .name = "none", .val = USI_V1_SW_CONF_NONE },
		[USI_MODE_UART] =	{ .name = "uart", .val = USI_V1_SW_CONF_UART },
		[USI_MODE_SPI] =	{ .name = "spi",  .val = USI_V1_SW_CONF_SPI },
		[USI_MODE_I2C] =	{ .name = "i2c",  .val = USI_V1_SW_CONF_I2C0 },
		[USI_MODE_I2C1] =	{ .name = "i2c1", .val = USI_V1_SW_CONF_I2C1 },
		[USI_MODE_I2C0_1] =	{ .name = "i2c0_1", .val = USI_V1_SW_CONF_I2C0_1 },
		[USI_MODE_UART_I2C1] =	{ .name = "uart_i2c1", .val = USI_V1_SW_CONF_UART_I2C1 },
	}, [USI_VER2] = {
		[USI_MODE_NONE] =	{ .name = "none", .val = USI_V2_SW_CONF_NONE },
		[USI_MODE_UART] =	{ .name = "uart", .val = USI_V2_SW_CONF_UART },
		[USI_MODE_SPI] =	{ .name = "spi",  .val = USI_V2_SW_CONF_SPI },
		[USI_MODE_I2C] =	{ .name = "i2c",  .val = USI_V2_SW_CONF_I2C },
	},
};

static const char * const exynos850_usi_clk_names[] = { "pclk", "ipclk" };
static const struct exynos_usi_variant exynos850_usi_data = {
	.ver		= USI_VER2,
	.sw_conf_mask	= USI_V2_SW_CONF_MASK,
	.min_mode	= USI_MODE_NONE,
	.max_mode	= USI_MODE_I2C,
	.num_clks	= ARRAY_SIZE(exynos850_usi_clk_names),
	.clk_names	= exynos850_usi_clk_names,
};

static const struct exynos_usi_variant exynos8895_usi_data = {
	.ver		= USI_VER1,
	.sw_conf_mask	= USI_V1_SW_CONF_MASK,
	.min_mode	= USI_MODE_NONE,
	.max_mode	= USI_MODE_UART_I2C1,
	.num_clks	= ARRAY_SIZE(exynos850_usi_clk_names),
	.clk_names	= exynos850_usi_clk_names,
};

static const struct of_device_id exynos_usi_dt_match[] = {
	{
		.compatible = "samsung,exynos850-usi",
		.data = &exynos850_usi_data,
	}, {
		.compatible = "samsung,exynos8895-usi",
		.data = &exynos8895_usi_data,
	},
	{ } /* sentinel */
};
MODULE_DEVICE_TABLE(of, exynos_usi_dt_match);

/**
 * exynos_usi_set_sw_conf - Set USI block configuration mode
 * @usi: USI driver object
 * @mode: Mode index
 *
 * Select underlying serial protocol (UART/SPI/I2C) in USI IP-core.
 *
 * Return: 0 on success, or negative error code on failure.
 */
static int exynos_usi_set_sw_conf(struct exynos_usi *usi, size_t mode)
{
	unsigned int val;

Annotation

Implementation Notes