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

Quelle  pcie-spear13xx.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs
 *
 * SPEAr13xx PCIe Glue Layer Source Code
 *
 * Copyright (C) 2010-2014 ST Microelectronics
 * Pratyush Anand <pratyush.anand@gmail.com>
 * Mohit Kumar <mohit.kumar.dhaka@gmail.com>
 */


#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/resource.h>

#include "pcie-designware.h"

struct spear13xx_pcie {
 struct dw_pcie  *pci;
 void __iomem  *app_base;
 struct phy  *phy;
 struct clk  *clk;
};

struct pcie_app_reg {
 u32 app_ctrl_0;  /* cr0 */
 u32 app_ctrl_1;  /* cr1 */
 u32 app_status_0;  /* cr2 */
 u32 app_status_1;  /* cr3 */
 u32 msg_status;  /* cr4 */
 u32 msg_payload;  /* cr5 */
 u32 int_sts;  /* cr6 */
 u32 int_clr;  /* cr7 */
 u32 int_mask;  /* cr8 */
 u32 mst_bmisc;  /* cr9 */
 u32 phy_ctrl;  /* cr10 */
 u32 phy_status;  /* cr11 */
 u32 cxpl_debug_info_0; /* cr12 */
 u32 cxpl_debug_info_1; /* cr13 */
 u32 ven_msg_ctrl_0;  /* cr14 */
 u32 ven_msg_ctrl_1;  /* cr15 */
 u32 ven_msg_data_0;  /* cr16 */
 u32 ven_msg_data_1;  /* cr17 */
 u32 ven_msi_0;  /* cr18 */
 u32 ven_msi_1;  /* cr19 */
 u32 mst_rmisc;  /* cr20 */
};

/* CR0 ID */
#define APP_LTSSM_ENABLE_ID   3
#define DEVICE_TYPE_RC    (4 << 25)
#define MISCTRL_EN_ID    30
#define REG_TRANSLATION_ENABLE   31

/* CR3 ID */
#define XMLH_LINK_UP    (1 << 6)

/* CR6 */
#define MSI_CTRL_INT    (1 << 26)

#define to_spear13xx_pcie(x) dev_get_drvdata((x)->dev)

static int spear13xx_pcie_start_link(struct dw_pcie *pci)
{
 struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;

 /* enable ltssm */
 writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
   | (1 << APP_LTSSM_ENABLE_ID)
   | ((u32)1 << REG_TRANSLATION_ENABLE),
   &app_reg->app_ctrl_0);

 return 0;
}

static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
{
 struct spear13xx_pcie *spear13xx_pcie = arg;
 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;
 struct dw_pcie *pci = spear13xx_pcie->pci;
 struct dw_pcie_rp *pp = &pci->pp;
 unsigned int status;

 status = readl(&app_reg->int_sts);

 if (status & MSI_CTRL_INT) {
  BUG_ON(!IS_ENABLED(CONFIG_PCI_MSI));
  dw_handle_msi_irq(pp);
 }

 writel(status, &app_reg->int_clr);

 return IRQ_HANDLED;
}

static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie)
{
 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;

 /* Enable MSI interrupt */
 if (IS_ENABLED(CONFIG_PCI_MSI))
  writel(readl(&app_reg->int_mask) |
    MSI_CTRL_INT, &app_reg->int_mask);
}

static bool spear13xx_pcie_link_up(struct dw_pcie *pci)
{
 struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;

 return readl(&app_reg->app_status_1) & XMLH_LINK_UP;
}

static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp)
{
 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
 u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
 u32 val;

 spear13xx_pcie->app_base = pci->dbi_base + 0x2000;

 /*
 * this controller support only 128 bytes read size, however its
 * default value in capability register is 512 bytes. So force
 * it to 128 here.
 */

 val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL);
 val &= ~PCI_EXP_DEVCTL_READRQ;
 dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val);

 dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A);
 dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80);

 spear13xx_pcie_enable_interrupts(spear13xx_pcie);

 return 0;
}

static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = {
 .init = spear13xx_pcie_host_init,
};

static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
       struct platform_device *pdev)
{
 struct dw_pcie *pci = spear13xx_pcie->pci;
 struct dw_pcie_rp *pp = &pci->pp;
 struct device *dev = &pdev->dev;
 int ret;

 pp->irq = platform_get_irq(pdev, 0);
 if (pp->irq < 0)
  return pp->irq;

 ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
          IRQF_SHARED | IRQF_NO_THREAD,
          "spear1340-pcie", spear13xx_pcie);
 if (ret) {
  dev_err(dev, "failed to request irq %d\n", pp->irq);
  return ret;
 }

 pp->ops = &spear13xx_pcie_host_ops;
 pp->msi_irq[0] = -ENODEV;

 ret = dw_pcie_host_init(pp);
 if (ret) {
  dev_err(dev, "failed to initialize host\n");
  return ret;
 }

 return 0;
}

static const struct dw_pcie_ops dw_pcie_ops = {
 .link_up = spear13xx_pcie_link_up,
 .start_link = spear13xx_pcie_start_link,
};

static int spear13xx_pcie_probe(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct dw_pcie *pci;
 struct spear13xx_pcie *spear13xx_pcie;
 struct device_node *np = dev->of_node;
 int ret;

 spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL);
 if (!spear13xx_pcie)
  return -ENOMEM;

 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
 if (!pci)
  return -ENOMEM;

 pci->dev = dev;
 pci->ops = &dw_pcie_ops;

 spear13xx_pcie->pci = pci;

 spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy");
 if (IS_ERR(spear13xx_pcie->phy)) {
  ret = PTR_ERR(spear13xx_pcie->phy);
  if (ret == -EPROBE_DEFER)
   dev_info(dev, "probe deferred\n");
  else
   dev_err(dev, "couldn't get pcie-phy\n");
  return ret;
 }

 phy_init(spear13xx_pcie->phy);

 spear13xx_pcie->clk = devm_clk_get(dev, NULL);
 if (IS_ERR(spear13xx_pcie->clk)) {
  dev_err(dev, "couldn't get clk for pcie\n");
  return PTR_ERR(spear13xx_pcie->clk);
 }
 ret = clk_prepare_enable(spear13xx_pcie->clk);
 if (ret) {
  dev_err(dev, "couldn't enable clk for pcie\n");
  return ret;
 }

 if (of_property_read_bool(np, "st,pcie-is-gen1"))
  pci->max_link_speed = 1;

 platform_set_drvdata(pdev, spear13xx_pcie);

 ret = spear13xx_add_pcie_port(spear13xx_pcie, pdev);
 if (ret < 0)
  goto fail_clk;

 return 0;

fail_clk:
 clk_disable_unprepare(spear13xx_pcie->clk);

 return ret;
}

static const struct of_device_id spear13xx_pcie_of_match[] = {
 { .compatible = "st,spear1340-pcie", },
 {},
};

static struct platform_driver spear13xx_pcie_driver = {
 .probe  = spear13xx_pcie_probe,
 .driver = {
  .name = "spear-pcie",
  .of_match_table = spear13xx_pcie_of_match,
  .suppress_bind_attrs = true,
 },
};

builtin_platform_driver(spear13xx_pcie_driver);

Messung V0.5
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.1 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.