134 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * DOC: Cadence GEM PCI wrapper.4 *5 * Copyright (C) 2016 Cadence Design Systems - https://www.cadence.com6 *7 * Authors: Rafal Ozieblo <rafalo@cadence.com>8 * Bartosz Folta <bfolta@cadence.com>9 */10 11#include <linux/clk.h>12#include <linux/clk-provider.h>13#include <linux/etherdevice.h>14#include <linux/module.h>15#include <linux/pci.h>16#include <linux/platform_device.h>17#include "macb.h"18 19#define PCI_DRIVER_NAME "macb_pci"20#define PLAT_DRIVER_NAME "macb"21 22#define PCI_DEVICE_ID_CDNS_MACB 0xe00723 24#define GEM_PCLK_RATE 5000000025#define GEM_HCLK_RATE 5000000026 27static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)28{29 int err;30 struct platform_device *plat_dev;31 struct platform_device_info plat_info;32 struct macb_platform_data plat_data;33 struct resource res[2];34 35 /* enable pci device */36 err = pcim_enable_device(pdev);37 if (err < 0) {38 dev_err(&pdev->dev, "Enabling PCI device has failed: %d", err);39 return err;40 }41 42 pci_set_master(pdev);43 44 /* set up resources */45 memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));46 res[0].start = pci_resource_start(pdev, 0);47 res[0].end = pci_resource_end(pdev, 0);48 res[0].name = PCI_DRIVER_NAME;49 res[0].flags = IORESOURCE_MEM;50 res[1].start = pci_irq_vector(pdev, 0);51 res[1].name = PCI_DRIVER_NAME;52 res[1].flags = IORESOURCE_IRQ;53 54 dev_info(&pdev->dev, "EMAC physical base addr: %pa\n",55 &res[0].start);56 57 /* set up macb platform data */58 memset(&plat_data, 0, sizeof(plat_data));59 60 /* initialize clocks */61 plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0,62 GEM_PCLK_RATE);63 if (IS_ERR(plat_data.pclk)) {64 err = PTR_ERR(plat_data.pclk);65 goto err_pclk_register;66 }67 68 plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0,69 GEM_HCLK_RATE);70 if (IS_ERR(plat_data.hclk)) {71 err = PTR_ERR(plat_data.hclk);72 goto err_hclk_register;73 }74 75 /* set up platform device info */76 memset(&plat_info, 0, sizeof(plat_info));77 plat_info.parent = &pdev->dev;78 plat_info.fwnode = pdev->dev.fwnode;79 plat_info.name = PLAT_DRIVER_NAME;80 plat_info.id = pdev->devfn;81 plat_info.res = res;82 plat_info.num_res = ARRAY_SIZE(res);83 plat_info.data = &plat_data;84 plat_info.size_data = sizeof(plat_data);85 plat_info.dma_mask = pdev->dma_mask;86 87 /* register platform device */88 plat_dev = platform_device_register_full(&plat_info);89 if (IS_ERR(plat_dev)) {90 err = PTR_ERR(plat_dev);91 goto err_plat_dev_register;92 }93 94 pci_set_drvdata(pdev, plat_dev);95 96 return 0;97 98err_plat_dev_register:99 clk_unregister(plat_data.hclk);100 101err_hclk_register:102 clk_unregister(plat_data.pclk);103 104err_pclk_register:105 return err;106}107 108static void macb_remove(struct pci_dev *pdev)109{110 struct platform_device *plat_dev = pci_get_drvdata(pdev);111 struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);112 113 clk_unregister(plat_data->pclk);114 clk_unregister(plat_data->hclk);115 platform_device_unregister(plat_dev);116}117 118static const struct pci_device_id dev_id_table[] = {119 { PCI_VDEVICE(CDNS, PCI_DEVICE_ID_CDNS_MACB) },120 { 0, }121};122 123static struct pci_driver macb_pci_driver = {124 .name = PCI_DRIVER_NAME,125 .id_table = dev_id_table,126 .probe = macb_probe,127 .remove = macb_remove,128};129 130module_pci_driver(macb_pci_driver);131MODULE_DEVICE_TABLE(pci, dev_id_table);132MODULE_LICENSE("GPL");133MODULE_DESCRIPTION("Cadence NIC PCI wrapper");134