Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/pci/controller/mobiveil/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  pcie-mobiveil.c   Sprache: C

 
// 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);
  break;
 default:
  return PCIBIOS_BAD_REGISTER_NUMBER;
 }

 return PCIBIOS_SUCCESSFUL;
}

u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size)
{
 void __iomem *addr;
 u32 val;
 int ret;

 addr = mobiveil_pcie_comp_addr(pcie, off);

 ret = mobiveil_pcie_read(addr, size, &val);
 if (ret)
  dev_err(&pcie->pdev->dev, "read CSR address failed\n");

 return val;
}

void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
          size_t size)
{
 void __iomem *addr;
 int ret;

 addr = mobiveil_pcie_comp_addr(pcie, off);

 ret = mobiveil_pcie_write(addr, size, val);
 if (ret)
  dev_err(&pcie->pdev->dev, "write CSR address failed\n");
}

bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
{
 if (pcie->ops->link_up)
  return pcie->ops->link_up(pcie);

 return (mobiveil_csr_readl(pcie, LTSSM_STATUS) &
  LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0;
}

void program_ib_windows(struct mobiveil_pcie *pcie, int win_num,
   u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
{
 u32 value;
 u64 size64 = ~(size - 1);

 if (win_num >= pcie->ppio_wins) {
  dev_err(&pcie->pdev->dev,
   "ERROR: max inbound windows reached !\n");
  return;
 }

 value = mobiveil_csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num));
 value &= ~(AMAP_CTRL_TYPE_MASK << AMAP_CTRL_TYPE_SHIFT | WIN_SIZE_MASK);
 value |= type << AMAP_CTRL_TYPE_SHIFT | 1 << AMAP_CTRL_EN_SHIFT |
   (lower_32_bits(size64) & WIN_SIZE_MASK);
 mobiveil_csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num));

 mobiveil_csr_writel(pcie, upper_32_bits(size64),
       PAB_EXT_PEX_AMAP_SIZEN(win_num));

 mobiveil_csr_writel(pcie, lower_32_bits(cpu_addr),
       PAB_PEX_AMAP_AXI_WIN(win_num));
 mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
       PAB_EXT_PEX_AMAP_AXI_WIN(win_num));

 mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
       PAB_PEX_AMAP_PEX_WIN_L(win_num));
 mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
       PAB_PEX_AMAP_PEX_WIN_H(win_num));

 pcie->ib_wins_configured++;
}

/*
 * routine to program the outbound windows
 */

void program_ob_windows(struct mobiveil_pcie *pcie, int win_num,
   u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
{
 u32 value;
 u64 size64 = ~(size - 1);

 if (win_num >= pcie->apio_wins) {
  dev_err(&pcie->pdev->dev,
   "ERROR: max outbound windows reached !\n");
  return;
 }

 /*
 * program Enable Bit to 1, Type Bit to (00) base 2, AXI Window Size Bit
 * to 4 KB in PAB_AXI_AMAP_CTRL register
 */

 value = mobiveil_csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num));
 value &= ~(WIN_TYPE_MASK << WIN_TYPE_SHIFT | WIN_SIZE_MASK);
 value |= 1 << WIN_ENABLE_SHIFT | type << WIN_TYPE_SHIFT |
   (lower_32_bits(size64) & WIN_SIZE_MASK);
 mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num));

 mobiveil_csr_writel(pcie, upper_32_bits(size64),
       PAB_EXT_AXI_AMAP_SIZE(win_num));

 /*
 * program AXI window base with appropriate value in
 * PAB_AXI_AMAP_AXI_WIN0 register
 */

 mobiveil_csr_writel(pcie,
       lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK),
       PAB_AXI_AMAP_AXI_WIN(win_num));
 mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
       PAB_EXT_AXI_AMAP_AXI_WIN(win_num));

 mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
       PAB_AXI_AMAP_PEX_WIN_L(win_num));
 mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
       PAB_AXI_AMAP_PEX_WIN_H(win_num));

 pcie->ob_wins_configured++;
}

int mobiveil_bringup_link(struct mobiveil_pcie *pcie)
{
 int retries;

 /* check if the link is up or not */
 for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
  if (mobiveil_pcie_link_up(pcie))
   return 0;

  usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX);
 }

 dev_err(&pcie->pdev->dev, "link never came up\n");

 return -ETIMEDOUT;
}

Messung V0.5
C=96 H=91 G=93

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.