brintos

brintos / linux-shallow public Read only

0
0
Text · 17.2 KiB · 2819bbd Raw
698 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * This is the driver for the MGB4 video grabber card by Digiteq Automotive.4 *5 * Copyright (C) 2021-2023 Digiteq Automotive6 *     author: Martin Tuma <martin.tuma@digiteqautomotive.com>7 *8 * This is the main driver module. The DMA, I2C and SPI sub-drivers are9 * initialized here and the input/output v4l2 devices are created.10 *11 * The mgb4 card uses different expansion modules for different video sources12 * (GMSL and FPDL3 for now) so in probe() we detect the module type based on13 * what we see on the I2C bus and check if it matches the FPGA bitstream (there14 * are different bitstreams for different expansion modules). When no expansion15 * module is present, we still let the driver initialize to allow flashing of16 * the FPGA firmware using the SPI FLASH device. No v4l2 video devices are17 * created in this case.18 */19 20#include <linux/types.h>21#include <linux/module.h>22#include <linux/pci.h>23#include <linux/platform_device.h>24#include <linux/clk.h>25#include <linux/clk-provider.h>26#include <linux/clkdev.h>27#include <linux/i2c.h>28#include <linux/delay.h>29#include <linux/dma/amd_xdma.h>30#include <linux/platform_data/amd_xdma.h>31#include <linux/spi/xilinx_spi.h>32#include <linux/mtd/mtd.h>33#include <linux/hwmon.h>34#include <linux/debugfs.h>35#include "mgb4_dma.h"36#include "mgb4_i2c.h"37#include "mgb4_sysfs.h"38#include "mgb4_vout.h"39#include "mgb4_vin.h"40#include "mgb4_trigger.h"41#include "mgb4_core.h"42 43#define MGB4_USER_IRQS 1644 45#define DIGITEQ_VID 0x1ed846#define T100_DID    0x010147#define T200_DID    0x020148 49ATTRIBUTE_GROUPS(mgb4_pci);50 51static int flashid;52 53static struct xdma_chan_info h2c_chan_info = {54	.dir = DMA_MEM_TO_DEV,55};56 57static struct xdma_chan_info c2h_chan_info = {58	.dir = DMA_DEV_TO_MEM,59};60 61static struct xspi_platform_data spi_platform_data = {62	.num_chipselect = 1,63	.bits_per_word = 864};65 66static const struct i2c_board_info extender_info = {67	I2C_BOARD_INFO("extender", 0x21)68};69 70#if IS_REACHABLE(CONFIG_HWMON)71static umode_t temp_is_visible(const void *data, enum hwmon_sensor_types type,72			       u32 attr, int channel)73{74	if (type == hwmon_temp &&75	    (attr == hwmon_temp_input || attr == hwmon_temp_label))76		return 0444;77	else78		return 0;79}80 81static int temp_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,82		     int channel, long *val)83{84	struct mgb4_dev *mgbdev = dev_get_drvdata(dev);85	u32 val10, raw;86 87	if (type != hwmon_temp || attr != hwmon_temp_input)88		return -EOPNOTSUPP;89 90	raw = mgb4_read_reg(&mgbdev->video, 0xD0);91	/* register value -> Celsius degrees formula given by Xilinx */92	val10 = ((((raw >> 20) & 0xFFF) * 503975) - 1118822400) / 409600;93	*val = val10 * 100;94 95	return 0;96}97 98static int temp_read_string(struct device *dev, enum hwmon_sensor_types type,99			    u32 attr, int channel, const char **str)100{101	if (type != hwmon_temp || attr != hwmon_temp_label)102		return -EOPNOTSUPP;103 104	*str = "FPGA Temperature";105 106	return 0;107}108 109static const struct hwmon_ops temp_ops = {110	.is_visible = temp_is_visible,111	.read = temp_read,112	.read_string = temp_read_string113};114 115static const struct hwmon_channel_info *temp_channel_info[] = {116	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL),117	NULL118};119 120static const struct hwmon_chip_info temp_chip_info = {121	.ops = &temp_ops,122	.info = temp_channel_info,123};124#endif125 126static int match_i2c_adap(struct device *dev, void *data)127{128	return i2c_verify_adapter(dev) ? 1 : 0;129}130 131static struct i2c_adapter *get_i2c_adap(struct platform_device *pdev)132{133	struct device *dev;134 135	mutex_lock(&pdev->dev.mutex);136	dev = device_find_child(&pdev->dev, NULL, match_i2c_adap);137	mutex_unlock(&pdev->dev.mutex);138 139	return dev ? to_i2c_adapter(dev) : NULL;140}141 142static int match_spi_adap(struct device *dev, void *data)143{144	return to_spi_device(dev) ? 1 : 0;145}146 147static struct spi_controller *get_spi_adap(struct platform_device *pdev)148{149	struct device *dev;150 151	mutex_lock(&pdev->dev.mutex);152	dev = device_find_child(&pdev->dev, NULL, match_spi_adap);153	mutex_unlock(&pdev->dev.mutex);154 155	return dev ? container_of(dev, struct spi_controller, dev) : NULL;156}157 158static int init_spi(struct mgb4_dev *mgbdev, u32 devid)159{160	struct resource spi_resources[] = {161		{162			.start	= 0x400,163			.end	= 0x47f,164			.flags	= IORESOURCE_MEM,165			.name	= "io-memory",166		},167		{168			.start	= 14,169			.end	= 14,170			.flags	= IORESOURCE_IRQ,171			.name	= "irq",172		},173	};174	struct spi_board_info spi_info = {175		.max_speed_hz = 10000000,176		.modalias = "m25p80",177		.chip_select = 0,178		.mode = SPI_MODE_3,179	};180	struct pci_dev *pdev = mgbdev->pdev;181	struct device *dev = &pdev->dev;182	struct spi_controller *ctlr;183	struct spi_device *spi_dev;184	u32 irq;185	int rv, id;186	resource_size_t mapbase = pci_resource_start(pdev, MGB4_MGB4_BAR_ID);187 188	request_module("platform:xilinx_spi");189 190	irq = xdma_get_user_irq(mgbdev->xdev, 14);191	xdma_enable_user_irq(mgbdev->xdev, irq);192 193	spi_resources[0].parent = &pdev->resource[MGB4_MGB4_BAR_ID];194	spi_resources[0].start += mapbase;195	spi_resources[0].end += mapbase;196	spi_resources[1].start = irq;197	spi_resources[1].end = irq;198 199	id = pci_dev_id(pdev);200	mgbdev->spi_pdev = platform_device_register_resndata(dev, "xilinx_spi",201							     id, spi_resources,202							     ARRAY_SIZE(spi_resources),203							     &spi_platform_data,204							     sizeof(spi_platform_data));205	if (IS_ERR(mgbdev->spi_pdev)) {206		dev_err(dev, "failed to register SPI device\n");207		return PTR_ERR(mgbdev->spi_pdev);208	}209 210	ctlr = get_spi_adap(mgbdev->spi_pdev);211	if (!ctlr) {212		dev_err(dev, "failed to get SPI adapter\n");213		rv = -EINVAL;214		goto err_pdev;215	}216 217	snprintf(mgbdev->fw_part_name, sizeof(mgbdev->fw_part_name),218		 "mgb4-fw.%d", flashid);219	mgbdev->partitions[0].name = mgbdev->fw_part_name;220	if (devid == T200_DID) {221		mgbdev->partitions[0].size = 0x950000;222		mgbdev->partitions[0].offset = 0x1000000;223	} else {224		mgbdev->partitions[0].size = 0x400000;225		mgbdev->partitions[0].offset = 0x400000;226	}227	mgbdev->partitions[0].mask_flags = 0;228 229	snprintf(mgbdev->data_part_name, sizeof(mgbdev->data_part_name),230		 "mgb4-data.%d", flashid);231	mgbdev->partitions[1].name = mgbdev->data_part_name;232	mgbdev->partitions[1].size = 0x10000;233	mgbdev->partitions[1].offset = 0xFF0000;234	mgbdev->partitions[1].mask_flags = MTD_CAP_NORFLASH;235 236	snprintf(mgbdev->flash_name, sizeof(mgbdev->flash_name),237		 "mgb4-flash.%d", flashid);238	mgbdev->flash_data.name = mgbdev->flash_name;239	mgbdev->flash_data.parts = mgbdev->partitions;240	mgbdev->flash_data.nr_parts = ARRAY_SIZE(mgbdev->partitions);241	mgbdev->flash_data.type = "spi-nor";242 243	spi_info.platform_data = &mgbdev->flash_data;244 245	spi_dev = spi_new_device(ctlr, &spi_info);246	put_device(&ctlr->dev);247	if (!spi_dev) {248		dev_err(dev, "failed to create MTD device\n");249		rv = -EINVAL;250		goto err_pdev;251	}252 253	return 0;254 255err_pdev:256	platform_device_unregister(mgbdev->spi_pdev);257 258	return rv;259}260 261static void free_spi(struct mgb4_dev *mgbdev)262{263	platform_device_unregister(mgbdev->spi_pdev);264}265 266static int init_i2c(struct mgb4_dev *mgbdev)267{268	struct resource i2c_resources[] = {269		{270			.start	= 0x200,271			.end	= 0x3ff,272			.flags	= IORESOURCE_MEM,273			.name	= "io-memory",274		},275		{276			.start	= 15,277			.end	= 15,278			.flags	= IORESOURCE_IRQ,279			.name	= "irq",280		},281	};282	struct pci_dev *pdev = mgbdev->pdev;283	struct device *dev = &pdev->dev;284	char clk_name[16];285	u32 irq;286	int rv, id;287	resource_size_t mapbase = pci_resource_start(pdev, MGB4_MGB4_BAR_ID);288 289	request_module("platform:xiic-i2c");290 291	irq = xdma_get_user_irq(mgbdev->xdev, 15);292	xdma_enable_user_irq(mgbdev->xdev, irq);293 294	i2c_resources[0].parent = &pdev->resource[MGB4_MGB4_BAR_ID];295	i2c_resources[0].start += mapbase;296	i2c_resources[0].end += mapbase;297	i2c_resources[1].start = irq;298	i2c_resources[1].end = irq;299 300	id = pci_dev_id(pdev);301 302	/* create dummy clock required by the xiic-i2c adapter */303	snprintf(clk_name, sizeof(clk_name), "xiic-i2c.%d", id);304	mgbdev->i2c_clk = clk_hw_register_fixed_rate(NULL, clk_name, NULL,305						     0, MGB4_HW_FREQ);306	if (IS_ERR(mgbdev->i2c_clk)) {307		dev_err(dev, "failed to register I2C clock\n");308		return PTR_ERR(mgbdev->i2c_clk);309	}310	mgbdev->i2c_cl = clkdev_hw_create(mgbdev->i2c_clk, NULL, "xiic-i2c.%d",311					  id);312	if (!mgbdev->i2c_cl) {313		dev_err(dev, "failed to register I2C clockdev\n");314		rv = -ENOMEM;315		goto err_clk;316	}317 318	mgbdev->i2c_pdev = platform_device_register_resndata(dev, "xiic-i2c",319							     id, i2c_resources,320							     ARRAY_SIZE(i2c_resources),321							     NULL, 0);322	if (IS_ERR(mgbdev->i2c_pdev)) {323		dev_err(dev, "failed to register I2C device\n");324		rv = PTR_ERR(mgbdev->i2c_pdev);325		goto err_clkdev;326	}327 328	mgbdev->i2c_adap = get_i2c_adap(mgbdev->i2c_pdev);329	if (!mgbdev->i2c_adap) {330		dev_err(dev, "failed to get I2C adapter\n");331		rv = -EINVAL;332		goto err_pdev;333	}334 335	mutex_init(&mgbdev->i2c_lock);336 337	return 0;338 339err_pdev:340	platform_device_unregister(mgbdev->i2c_pdev);341err_clkdev:342	clkdev_drop(mgbdev->i2c_cl);343err_clk:344	clk_hw_unregister(mgbdev->i2c_clk);345 346	return rv;347}348 349static void free_i2c(struct mgb4_dev *mgbdev)350{351	put_device(&mgbdev->i2c_adap->dev);352	platform_device_unregister(mgbdev->i2c_pdev);353	clkdev_drop(mgbdev->i2c_cl);354	clk_hw_unregister(mgbdev->i2c_clk);355}356 357static int get_serial_number(struct mgb4_dev *mgbdev)358{359	struct device *dev = &mgbdev->pdev->dev;360	struct mtd_info *mtd;361	size_t rs;362	int rv;363 364	mgbdev->serial_number = 0;365 366	mtd = get_mtd_device_nm(mgbdev->data_part_name);367	if (IS_ERR(mtd)) {368		dev_warn(dev, "failed to get data MTD device\n");369		return -ENOENT;370	}371	rv = mtd_read(mtd, 0, sizeof(mgbdev->serial_number), &rs,372		      (u_char *)&mgbdev->serial_number);373	put_mtd_device(mtd);374	if (rv < 0 || rs != sizeof(mgbdev->serial_number)) {375		dev_warn(dev, "error reading MTD device\n");376		return -EIO;377	}378 379	return 0;380}381 382static int get_module_version(struct mgb4_dev *mgbdev)383{384	struct device *dev = &mgbdev->pdev->dev;385	struct mgb4_i2c_client extender;386	s32 version;387	u32 fw_version;388	int rv;389 390	rv = mgb4_i2c_init(&extender, mgbdev->i2c_adap, &extender_info, 8);391	if (rv < 0) {392		dev_err(dev, "failed to create extender I2C device\n");393		return rv;394	}395	version = mgb4_i2c_read_byte(&extender, 0x00);396	mgb4_i2c_free(&extender);397	if (version < 0) {398		dev_err(dev, "error reading module version\n");399		return -EIO;400	}401 402	mgbdev->module_version = ~((u32)version) & 0xff;403	if (!(MGB4_IS_FPDL3(mgbdev) || MGB4_IS_GMSL(mgbdev))) {404		dev_err(dev, "unknown module type\n");405		return -EINVAL;406	}407	fw_version = mgb4_read_reg(&mgbdev->video, 0xC4);408	if (fw_version >> 24 != mgbdev->module_version >> 4) {409		dev_err(dev, "module/firmware type mismatch\n");410		return -EINVAL;411	}412 413	dev_info(dev, "%s module detected\n",414		 MGB4_IS_FPDL3(mgbdev) ? "FPDL3" : "GMSL");415 416	return 0;417}418 419static int map_regs(struct pci_dev *pdev, struct resource *res,420		    struct mgb4_regs *regs)421{422	int rv;423	resource_size_t mapbase = pci_resource_start(pdev, MGB4_MGB4_BAR_ID);424 425	res->start += mapbase;426	res->end += mapbase;427 428	rv = mgb4_regs_map(res, regs);429	if (rv < 0) {430		dev_err(&pdev->dev, "failed to map %s registers\n", res->name);431		return rv;432	}433 434	return 0;435}436 437static int init_xdma(struct mgb4_dev *mgbdev)438{439	struct xdma_platdata data;440	struct resource res[2] = { 0 };441	struct dma_slave_map *map;442	struct pci_dev *pdev = mgbdev->pdev;443	struct device *dev = &pdev->dev;444	int i;445 446	res[0].start = pci_resource_start(pdev, MGB4_XDMA_BAR_ID);447	res[0].end = pci_resource_end(pdev, MGB4_XDMA_BAR_ID);448	res[0].flags = IORESOURCE_MEM;449	res[0].parent = &pdev->resource[MGB4_XDMA_BAR_ID];450	res[1].start = pci_irq_vector(pdev, 0);451	res[1].end = res[1].start + MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES452		     + MGB4_USER_IRQS - 1;453	res[1].flags = IORESOURCE_IRQ;454 455	data.max_dma_channels = MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES;456	data.device_map = mgbdev->slave_map;457	data.device_map_cnt = MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES;458 459	for (i = 0; i < MGB4_VIN_DEVICES; i++) {460		sprintf(mgbdev->channel_names[i], "c2h%d", i);461		map = &data.device_map[i];462		map->slave = mgbdev->channel_names[i];463		map->devname = dev_name(dev);464		map->param = XDMA_FILTER_PARAM(&c2h_chan_info);465	}466	for (i = 0; i < MGB4_VOUT_DEVICES; i++) {467		sprintf(mgbdev->channel_names[i + MGB4_VIN_DEVICES], "h2c%d", i);468		map = &data.device_map[i + MGB4_VIN_DEVICES];469		map->slave = mgbdev->channel_names[i + MGB4_VIN_DEVICES];470		map->devname = dev_name(dev);471		map->param = XDMA_FILTER_PARAM(&h2c_chan_info);472	}473 474	mgbdev->xdev = platform_device_register_resndata(dev, "xdma",475							 PLATFORM_DEVID_AUTO, res,476							 2, &data, sizeof(data));477	if (IS_ERR(mgbdev->xdev)) {478		dev_err(dev, "failed to register XDMA device\n");479		return PTR_ERR(mgbdev->xdev);480	}481 482	return 0;483}484 485static void free_xdma(struct mgb4_dev *mgbdev)486{487	platform_device_unregister(mgbdev->xdev);488}489 490static int mgb4_probe(struct pci_dev *pdev, const struct pci_device_id *id)491{492	int i, rv;493	struct mgb4_dev *mgbdev;494	struct resource video = {495		.start	= 0x0,496		.end	= 0xff,497		.flags	= IORESOURCE_MEM,498		.name	= "mgb4-video",499	};500	struct resource cmt = {501		.start	= 0x1000,502		.end	= 0x17ff,503		.flags	= IORESOURCE_MEM,504		.name	= "mgb4-cmt",505	};506	int irqs = pci_msix_vec_count(pdev);507 508	mgbdev = kzalloc(sizeof(*mgbdev), GFP_KERNEL);509	if (!mgbdev)510		return -ENOMEM;511 512	mgbdev->pdev = pdev;513	pci_set_drvdata(pdev, mgbdev);514 515	/* PCIe related stuff */516	rv = pci_enable_device(pdev);517	if (rv) {518		dev_err(&pdev->dev, "error enabling PCI device\n");519		goto err_mgbdev;520	}521 522	rv = pcie_capability_set_word(pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);523	if (rv)524		dev_warn(&pdev->dev, "error enabling PCIe relaxed ordering\n");525	rv = pcie_capability_set_word(pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_EXT_TAG);526	if (rv)527		dev_warn(&pdev->dev, "error enabling PCIe extended tag field\n");528	rv = pcie_set_readrq(pdev, 512);529	if (rv)530		dev_warn(&pdev->dev, "error setting PCIe max. memory read size\n");531	pci_set_master(pdev);532 533	rv = pci_alloc_irq_vectors(pdev, irqs, irqs, PCI_IRQ_MSIX);534	if (rv < 0) {535		dev_err(&pdev->dev, "error allocating MSI-X IRQs\n");536		goto err_enable_pci;537	}538 539	rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));540	if (rv) {541		dev_err(&pdev->dev, "error setting DMA mask\n");542		goto err_enable_pci;543	}544 545	/* DMA + IRQ engine */546	rv = init_xdma(mgbdev);547	if (rv)548		goto err_alloc_irq;549	rv = mgb4_dma_channel_init(mgbdev);550	if (rv)551		goto err_dma_chan;552 553	/* mgb4 video registers */554	rv = map_regs(pdev, &video, &mgbdev->video);555	if (rv < 0)556		goto err_dma_chan;557	/* mgb4 cmt registers */558	rv = map_regs(pdev, &cmt, &mgbdev->cmt);559	if (rv < 0)560		goto err_video_regs;561 562	/* SPI FLASH */563	rv = init_spi(mgbdev, id->device);564	if (rv < 0)565		goto err_cmt_regs;566 567	/* I2C controller */568	rv = init_i2c(mgbdev);569	if (rv < 0)570		goto err_spi;571 572	/* PCI card related sysfs attributes */573	rv = device_add_groups(&pdev->dev, mgb4_pci_groups);574	if (rv < 0)575		goto err_i2c;576 577#if IS_REACHABLE(CONFIG_HWMON)578	/* HWmon (card temperature) */579	mgbdev->hwmon_dev = hwmon_device_register_with_info(&pdev->dev, "mgb4",580							    mgbdev,581							    &temp_chip_info,582							    NULL);583#endif584 585#ifdef CONFIG_DEBUG_FS586	mgbdev->debugfs = debugfs_create_dir(dev_name(&pdev->dev), NULL);587#endif588 589	/* Get card serial number. On systems without MTD flash support we may590	 * get an error thus ignore the return value. An invalid serial number591	 * should not break anything...592	 */593	if (get_serial_number(mgbdev) < 0)594		dev_warn(&pdev->dev, "error reading card serial number\n");595 596	/* Get module type. If no valid module is found, skip the video device597	 * creation part but do not exit with error to allow flashing the card.598	 */599	rv = get_module_version(mgbdev);600	if (rv < 0)601		goto exit;602 603	/* Video input v4l2 devices */604	for (i = 0; i < MGB4_VIN_DEVICES; i++)605		mgbdev->vin[i] = mgb4_vin_create(mgbdev, i);606 607	/* Video output v4l2 devices */608	for (i = 0; i < MGB4_VOUT_DEVICES; i++)609		mgbdev->vout[i] = mgb4_vout_create(mgbdev, i);610 611	/* Triggers */612	mgbdev->indio_dev = mgb4_trigger_create(mgbdev);613 614exit:615	flashid++;616 617	return 0;618 619err_i2c:620	free_i2c(mgbdev);621err_spi:622	free_spi(mgbdev);623err_cmt_regs:624	mgb4_regs_free(&mgbdev->cmt);625err_video_regs:626	mgb4_regs_free(&mgbdev->video);627err_dma_chan:628	mgb4_dma_channel_free(mgbdev);629	free_xdma(mgbdev);630err_alloc_irq:631	pci_disable_msix(pdev);632err_enable_pci:633	pci_disable_device(pdev);634err_mgbdev:635	kfree(mgbdev);636 637	return rv;638}639 640static void mgb4_remove(struct pci_dev *pdev)641{642	struct mgb4_dev *mgbdev = pci_get_drvdata(pdev);643	int i;644 645#if IS_REACHABLE(CONFIG_HWMON)646	hwmon_device_unregister(mgbdev->hwmon_dev);647#endif648 649	if (mgbdev->indio_dev)650		mgb4_trigger_free(mgbdev->indio_dev);651 652	for (i = 0; i < MGB4_VOUT_DEVICES; i++)653		if (mgbdev->vout[i])654			mgb4_vout_free(mgbdev->vout[i]);655	for (i = 0; i < MGB4_VIN_DEVICES; i++)656		if (mgbdev->vin[i])657			mgb4_vin_free(mgbdev->vin[i]);658 659#ifdef CONFIG_DEBUG_FS660	debugfs_remove_recursive(mgbdev->debugfs);661#endif662 663	device_remove_groups(&mgbdev->pdev->dev, mgb4_pci_groups);664	free_spi(mgbdev);665	free_i2c(mgbdev);666	mgb4_regs_free(&mgbdev->video);667	mgb4_regs_free(&mgbdev->cmt);668 669	mgb4_dma_channel_free(mgbdev);670	free_xdma(mgbdev);671 672	pci_disable_msix(mgbdev->pdev);673	pci_disable_device(mgbdev->pdev);674 675	kfree(mgbdev);676}677 678static const struct pci_device_id mgb4_pci_ids[] = {679	{ PCI_DEVICE(DIGITEQ_VID, T100_DID), },680	{ PCI_DEVICE(DIGITEQ_VID, T200_DID), },681	{ 0, }682};683MODULE_DEVICE_TABLE(pci, mgb4_pci_ids);684 685static struct pci_driver mgb4_pci_driver = {686	.name = KBUILD_MODNAME,687	.id_table = mgb4_pci_ids,688	.probe = mgb4_probe,689	.remove = mgb4_remove,690};691 692module_pci_driver(mgb4_pci_driver);693 694MODULE_AUTHOR("Digiteq Automotive s.r.o.");695MODULE_DESCRIPTION("Digiteq Automotive MGB4 Driver");696MODULE_LICENSE("GPL");697MODULE_SOFTDEP("pre: platform:xiic-i2c platform:xilinx_spi spi-nor");698