drivers/pci/controller/mobiveil/pcie-mobiveil.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/mobiveil/pcie-mobiveil.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/mobiveil/pcie-mobiveil.c
Extension
.c
Size
5855 bytes
Lines
232
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: implementation source
Status
source implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * PCIe host controller driver for Mobiveil PCIe Host controller
 *
 * Copyright (c) 2018 Mobiveil Inc.
 * Copyright 2019 NXP
 *
 * Author: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
 *	   Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
 */

#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/platform_device.h>

#include "pcie-mobiveil.h"

/*
 * mobiveil_pcie_sel_page - routine to access paged register
 *
 * Registers whose address greater than PAGED_ADDR_BNDRY (0xc00) are paged,
 * for this scheme to work extracted higher 6 bits of the offset will be
 * written to pg_sel field of PAB_CTRL register and rest of the lower 10
 * bits enabled with PAGED_ADDR_BNDRY are used as offset of the register.
 */
static void mobiveil_pcie_sel_page(struct mobiveil_pcie *pcie, u8 pg_idx)
{
	u32 val;

	val = readl(pcie->csr_axi_slave_base + PAB_CTRL);
	val &= ~(PAGE_SEL_MASK << PAGE_SEL_SHIFT);
	val |= (pg_idx & PAGE_SEL_MASK) << PAGE_SEL_SHIFT;

	writel(val, pcie->csr_axi_slave_base + PAB_CTRL);
}

static void __iomem *mobiveil_pcie_comp_addr(struct mobiveil_pcie *pcie,
					     u32 off)
{
	if (off < PAGED_ADDR_BNDRY) {
		/* For directly accessed registers, clear the pg_sel field */
		mobiveil_pcie_sel_page(pcie, 0);
		return pcie->csr_axi_slave_base + off;
	}

	mobiveil_pcie_sel_page(pcie, OFFSET_TO_PAGE_IDX(off));
	return pcie->csr_axi_slave_base + OFFSET_TO_PAGE_ADDR(off);
}

static int mobiveil_pcie_read(void __iomem *addr, int size, u32 *val)
{
	if ((uintptr_t)addr & (size - 1)) {
		*val = 0;
		return PCIBIOS_BAD_REGISTER_NUMBER;
	}

	switch (size) {
	case 4:
		*val = readl(addr);
		break;
	case 2:
		*val = readw(addr);
		break;
	case 1:
		*val = readb(addr);
		break;
	default:
		*val = 0;
		return PCIBIOS_BAD_REGISTER_NUMBER;
	}

	return PCIBIOS_SUCCESSFUL;
}

static int mobiveil_pcie_write(void __iomem *addr, int size, u32 val)
{
	if ((uintptr_t)addr & (size - 1))
		return PCIBIOS_BAD_REGISTER_NUMBER;

	switch (size) {
	case 4:
		writel(val, addr);
		break;
	case 2:
		writew(val, addr);
		break;
	case 1:
		writeb(val, addr);

Annotation

Implementation Notes