drivers/soc/qcom/ocmem.c

Source file repositories/reference/linux-study-clean/drivers/soc/qcom/ocmem.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/qcom/ocmem.c
Extension
.c
Size
12235 bytes
Lines
452
Domain
Driver Families
Bucket
drivers/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 ocmem_region {
	bool interleaved;
	enum region_mode mode;
	unsigned int num_macros;
	enum ocmem_macro_state macro_state[4];
	unsigned long macro_size;
	unsigned long region_size;
};

struct ocmem_config {
	uint8_t num_regions;
	unsigned long macro_size;
};

struct ocmem {
	struct device *dev;
	const struct ocmem_config *config;
	struct resource *memory;
	void __iomem *mmio;
	struct clk *core_clk;
	struct clk *iface_clk;
	unsigned int num_ports;
	unsigned int num_macros;
	bool interleaved;
	struct ocmem_region *regions;
	unsigned long active_allocations;
};

#define OCMEM_MIN_ALIGN				SZ_64K
#define OCMEM_MIN_ALLOC				SZ_64K

#define OCMEM_REG_HW_VERSION			0x00000000
#define OCMEM_REG_HW_PROFILE			0x00000004

#define OCMEM_REG_REGION_MODE_CTL		0x00001000
#define OCMEM_REGION_MODE_CTL_REG0_THIN		0x00000001
#define OCMEM_REGION_MODE_CTL_REG1_THIN		0x00000002
#define OCMEM_REGION_MODE_CTL_REG2_THIN		0x00000004
#define OCMEM_REGION_MODE_CTL_REG3_THIN		0x00000008

#define OCMEM_REG_GFX_MPU_START			0x00001004
#define OCMEM_REG_GFX_MPU_END			0x00001008

#define OCMEM_HW_VERSION_MAJOR(val)		FIELD_GET(GENMASK(31, 28), val)
#define OCMEM_HW_VERSION_MINOR(val)		FIELD_GET(GENMASK(27, 16), val)
#define OCMEM_HW_VERSION_STEP(val)		FIELD_GET(GENMASK(15, 0), val)

#define OCMEM_HW_PROFILE_NUM_PORTS(val)		FIELD_GET(0x0000000f, (val))
#define OCMEM_HW_PROFILE_NUM_MACROS(val)	FIELD_GET(0x00003f00, (val))

#define OCMEM_HW_PROFILE_LAST_REGN_HALFSIZE	0x00010000
#define OCMEM_HW_PROFILE_INTERLEAVING		0x00020000
#define OCMEM_REG_GEN_STATUS			0x0000000c

#define OCMEM_REG_PSGSC_STATUS			0x00000038
#define OCMEM_REG_PSGSC_CTL(i0)			(0x0000003c + 0x1*(i0))

#define OCMEM_PSGSC_CTL_MACRO0_MODE(val)	FIELD_PREP(0x00000007, (val))
#define OCMEM_PSGSC_CTL_MACRO1_MODE(val)	FIELD_PREP(0x00000070, (val))
#define OCMEM_PSGSC_CTL_MACRO2_MODE(val)	FIELD_PREP(0x00000700, (val))
#define OCMEM_PSGSC_CTL_MACRO3_MODE(val)	FIELD_PREP(0x00007000, (val))

static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 data)
{
	writel(data, ocmem->mmio + reg);
}

static inline u32 ocmem_read(struct ocmem *ocmem, u32 reg)
{
	return readl(ocmem->mmio + reg);
}

static void update_ocmem(struct ocmem *ocmem)
{
	uint32_t region_mode_ctrl = 0x0;
	int i;

	if (!qcom_scm_ocmem_lock_available()) {
		for (i = 0; i < ocmem->config->num_regions; i++) {
			struct ocmem_region *region = &ocmem->regions[i];

			if (region->mode == THIN_MODE)
				region_mode_ctrl |= BIT(i);
		}

		dev_dbg(ocmem->dev, "ocmem_region_mode_control %x\n",
			region_mode_ctrl);
		ocmem_write(ocmem, OCMEM_REG_REGION_MODE_CTL, region_mode_ctrl);
	}

Annotation

Implementation Notes