16b1baefeSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c1167ceeSYang Shen /*
3f410f157SJesse Brandeburg  * DOC: Cadence GEM PCI wrapper.
483a77e9eSBartosz Folta  *
55d75c043SAlexander A. Klimov  * Copyright (C) 2016 Cadence Design Systems - https://www.cadence.com
683a77e9eSBartosz Folta  *
783a77e9eSBartosz Folta  * Authors: Rafal Ozieblo <rafalo@cadence.com>
883a77e9eSBartosz Folta  *	    Bartosz Folta <bfolta@cadence.com>
983a77e9eSBartosz Folta  */
1083a77e9eSBartosz Folta 
1183a77e9eSBartosz Folta #include <linux/clk.h>
1283a77e9eSBartosz Folta #include <linux/clk-provider.h>
1383a77e9eSBartosz Folta #include <linux/etherdevice.h>
1483a77e9eSBartosz Folta #include <linux/module.h>
1583a77e9eSBartosz Folta #include <linux/pci.h>
1683a77e9eSBartosz Folta #include <linux/platform_device.h>
1783a77e9eSBartosz Folta #include "macb.h"
1883a77e9eSBartosz Folta 
1983a77e9eSBartosz Folta #define PCI_DRIVER_NAME "macb_pci"
2083a77e9eSBartosz Folta #define PLAT_DRIVER_NAME "macb"
2183a77e9eSBartosz Folta 
2283a77e9eSBartosz Folta #define CDNS_VENDOR_ID 0x17cd
2383a77e9eSBartosz Folta #define CDNS_DEVICE_ID 0xe007
2483a77e9eSBartosz Folta 
2583a77e9eSBartosz Folta #define GEM_PCLK_RATE 50000000
2683a77e9eSBartosz Folta #define GEM_HCLK_RATE 50000000
2783a77e9eSBartosz Folta 
macb_probe(struct pci_dev * pdev,const struct pci_device_id * id)2883a77e9eSBartosz Folta static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2983a77e9eSBartosz Folta {
3083a77e9eSBartosz Folta 	int err;
3183a77e9eSBartosz Folta 	struct platform_device *plat_dev;
3283a77e9eSBartosz Folta 	struct platform_device_info plat_info;
3383a77e9eSBartosz Folta 	struct macb_platform_data plat_data;
3483a77e9eSBartosz Folta 	struct resource res[2];
3583a77e9eSBartosz Folta 
3683a77e9eSBartosz Folta 	/* enable pci device */
37515028feSBartosz Folta 	err = pcim_enable_device(pdev);
3883a77e9eSBartosz Folta 	if (err < 0) {
39515028feSBartosz Folta 		dev_err(&pdev->dev, "Enabling PCI device has failed: %d", err);
40515028feSBartosz Folta 		return err;
4183a77e9eSBartosz Folta 	}
4283a77e9eSBartosz Folta 
4383a77e9eSBartosz Folta 	pci_set_master(pdev);
4483a77e9eSBartosz Folta 
4583a77e9eSBartosz Folta 	/* set up resources */
4683a77e9eSBartosz Folta 	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
47515028feSBartosz Folta 	res[0].start = pci_resource_start(pdev, 0);
48515028feSBartosz Folta 	res[0].end = pci_resource_end(pdev, 0);
4983a77e9eSBartosz Folta 	res[0].name = PCI_DRIVER_NAME;
5083a77e9eSBartosz Folta 	res[0].flags = IORESOURCE_MEM;
51515028feSBartosz Folta 	res[1].start = pci_irq_vector(pdev, 0);
5283a77e9eSBartosz Folta 	res[1].name = PCI_DRIVER_NAME;
5383a77e9eSBartosz Folta 	res[1].flags = IORESOURCE_IRQ;
5483a77e9eSBartosz Folta 
55515028feSBartosz Folta 	dev_info(&pdev->dev, "EMAC physical base addr: %pa\n",
56515028feSBartosz Folta 		 &res[0].start);
5783a77e9eSBartosz Folta 
5883a77e9eSBartosz Folta 	/* set up macb platform data */
5983a77e9eSBartosz Folta 	memset(&plat_data, 0, sizeof(plat_data));
6083a77e9eSBartosz Folta 
6183a77e9eSBartosz Folta 	/* initialize clocks */
6283a77e9eSBartosz Folta 	plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0,
6383a77e9eSBartosz Folta 						 GEM_PCLK_RATE);
6483a77e9eSBartosz Folta 	if (IS_ERR(plat_data.pclk)) {
6583a77e9eSBartosz Folta 		err = PTR_ERR(plat_data.pclk);
6683a77e9eSBartosz Folta 		goto err_pclk_register;
6783a77e9eSBartosz Folta 	}
6883a77e9eSBartosz Folta 
6983a77e9eSBartosz Folta 	plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0,
7083a77e9eSBartosz Folta 						 GEM_HCLK_RATE);
7183a77e9eSBartosz Folta 	if (IS_ERR(plat_data.hclk)) {
7283a77e9eSBartosz Folta 		err = PTR_ERR(plat_data.hclk);
7383a77e9eSBartosz Folta 		goto err_hclk_register;
7483a77e9eSBartosz Folta 	}
7583a77e9eSBartosz Folta 
7683a77e9eSBartosz Folta 	/* set up platform device info */
7783a77e9eSBartosz Folta 	memset(&plat_info, 0, sizeof(plat_info));
7883a77e9eSBartosz Folta 	plat_info.parent = &pdev->dev;
7983a77e9eSBartosz Folta 	plat_info.fwnode = pdev->dev.fwnode;
8083a77e9eSBartosz Folta 	plat_info.name = PLAT_DRIVER_NAME;
8183a77e9eSBartosz Folta 	plat_info.id = pdev->devfn;
8283a77e9eSBartosz Folta 	plat_info.res = res;
8383a77e9eSBartosz Folta 	plat_info.num_res = ARRAY_SIZE(res);
8483a77e9eSBartosz Folta 	plat_info.data = &plat_data;
8583a77e9eSBartosz Folta 	plat_info.size_data = sizeof(plat_data);
86515028feSBartosz Folta 	plat_info.dma_mask = pdev->dma_mask;
8783a77e9eSBartosz Folta 
8883a77e9eSBartosz Folta 	/* register platform device */
8983a77e9eSBartosz Folta 	plat_dev = platform_device_register_full(&plat_info);
9083a77e9eSBartosz Folta 	if (IS_ERR(plat_dev)) {
9183a77e9eSBartosz Folta 		err = PTR_ERR(plat_dev);
9283a77e9eSBartosz Folta 		goto err_plat_dev_register;
9383a77e9eSBartosz Folta 	}
9483a77e9eSBartosz Folta 
9583a77e9eSBartosz Folta 	pci_set_drvdata(pdev, plat_dev);
9683a77e9eSBartosz Folta 
9783a77e9eSBartosz Folta 	return 0;
9883a77e9eSBartosz Folta 
9983a77e9eSBartosz Folta err_plat_dev_register:
10083a77e9eSBartosz Folta 	clk_unregister(plat_data.hclk);
10183a77e9eSBartosz Folta 
10283a77e9eSBartosz Folta err_hclk_register:
10383a77e9eSBartosz Folta 	clk_unregister(plat_data.pclk);
10483a77e9eSBartosz Folta 
10583a77e9eSBartosz Folta err_pclk_register:
10683a77e9eSBartosz Folta 	return err;
10783a77e9eSBartosz Folta }
10883a77e9eSBartosz Folta 
macb_remove(struct pci_dev * pdev)10983a77e9eSBartosz Folta static void macb_remove(struct pci_dev *pdev)
11083a77e9eSBartosz Folta {
11183a77e9eSBartosz Folta 	struct platform_device *plat_dev = pci_get_drvdata(pdev);
11283a77e9eSBartosz Folta 	struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);
11383a77e9eSBartosz Folta 
11483a77e9eSBartosz Folta 	clk_unregister(plat_data->pclk);
11583a77e9eSBartosz Folta 	clk_unregister(plat_data->hclk);
116*d82d5303STong Zhang 	platform_device_unregister(plat_dev);
11783a77e9eSBartosz Folta }
11883a77e9eSBartosz Folta 
119c744cf5bSArvind Yadav static const struct pci_device_id dev_id_table[] = {
12083a77e9eSBartosz Folta 	{ PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), },
12183a77e9eSBartosz Folta 	{ 0, }
12283a77e9eSBartosz Folta };
12383a77e9eSBartosz Folta 
12483a77e9eSBartosz Folta static struct pci_driver macb_pci_driver = {
12583a77e9eSBartosz Folta 	.name     = PCI_DRIVER_NAME,
12683a77e9eSBartosz Folta 	.id_table = dev_id_table,
12783a77e9eSBartosz Folta 	.probe    = macb_probe,
12883a77e9eSBartosz Folta 	.remove	  = macb_remove,
12983a77e9eSBartosz Folta };
13083a77e9eSBartosz Folta 
13183a77e9eSBartosz Folta module_pci_driver(macb_pci_driver);
13283a77e9eSBartosz Folta MODULE_DEVICE_TABLE(pci, dev_id_table);
13383a77e9eSBartosz Folta MODULE_LICENSE("GPL");
13483a77e9eSBartosz Folta MODULE_DESCRIPTION("Cadence NIC PCI wrapper");
135