brintos

brintos / linux-shallow public Read only

0
0
Text · 15.8 KiB · 5865683 Raw
674 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * SGI IOC3 multifunction device driver4 *5 * Copyright (C) 2018, 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de>6 *7 * Based on work by:8 *   Stanislaw Skowronek <skylark@unaligned.org>9 *   Joshua Kinard <kumba@gentoo.org>10 *   Brent Casavant <bcasavan@sgi.com> - IOC4 master driver11 *   Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer12 */13 14#include <linux/delay.h>15#include <linux/errno.h>16#include <linux/interrupt.h>17#include <linux/irqdomain.h>18#include <linux/mfd/core.h>19#include <linux/module.h>20#include <linux/pci.h>21#include <linux/platform_device.h>22#include <linux/platform_data/sgi-w1.h>23#include <linux/rtc/ds1685.h>24 25#include <asm/pci/bridge.h>26#include <asm/sn/ioc3.h>27 28#define IOC3_IRQ_SERIAL_A	629#define IOC3_IRQ_SERIAL_B	1530#define IOC3_IRQ_KBD		2231 32/* Bitmask for selecting which IRQs are level triggered */33#define IOC3_LVL_MASK	(BIT(IOC3_IRQ_SERIAL_A) | BIT(IOC3_IRQ_SERIAL_B))34 35#define M48T35_REG_SIZE	32768	/* size of m48t35 registers */36 37/* 1.2 us latency timer (40 cycles at 33 MHz) */38#define IOC3_LATENCY	4039 40struct ioc3_priv_data {41	struct irq_domain *domain;42	struct ioc3 __iomem *regs;43	struct pci_dev *pdev;44	int domain_irq;45};46 47static void ioc3_irq_ack(struct irq_data *d)48{49	struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d);50	unsigned int hwirq = irqd_to_hwirq(d);51 52	writel(BIT(hwirq), &ipd->regs->sio_ir);53}54 55static void ioc3_irq_mask(struct irq_data *d)56{57	struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d);58	unsigned int hwirq = irqd_to_hwirq(d);59 60	writel(BIT(hwirq), &ipd->regs->sio_iec);61}62 63static void ioc3_irq_unmask(struct irq_data *d)64{65	struct ioc3_priv_data *ipd = irq_data_get_irq_chip_data(d);66	unsigned int hwirq = irqd_to_hwirq(d);67 68	writel(BIT(hwirq), &ipd->regs->sio_ies);69}70 71static struct irq_chip ioc3_irq_chip = {72	.name		= "IOC3",73	.irq_ack	= ioc3_irq_ack,74	.irq_mask	= ioc3_irq_mask,75	.irq_unmask	= ioc3_irq_unmask,76};77 78static int ioc3_irq_domain_map(struct irq_domain *d, unsigned int irq,79			      irq_hw_number_t hwirq)80{81	/* Set level IRQs for every interrupt contained in IOC3_LVL_MASK */82	if (BIT(hwirq) & IOC3_LVL_MASK)83		irq_set_chip_and_handler(irq, &ioc3_irq_chip, handle_level_irq);84	else85		irq_set_chip_and_handler(irq, &ioc3_irq_chip, handle_edge_irq);86 87	irq_set_chip_data(irq, d->host_data);88	return 0;89}90 91static void ioc3_irq_domain_unmap(struct irq_domain *d, unsigned int irq)92{93	irq_set_chip_and_handler(irq, NULL, NULL);94	irq_set_chip_data(irq, NULL);95}96 97static const struct irq_domain_ops ioc3_irq_domain_ops = {98	.map = ioc3_irq_domain_map,99	.unmap = ioc3_irq_domain_unmap,100};101 102static void ioc3_irq_handler(struct irq_desc *desc)103{104	struct irq_domain *domain = irq_desc_get_handler_data(desc);105	struct ioc3_priv_data *ipd = domain->host_data;106	struct ioc3 __iomem *regs = ipd->regs;107	u32 pending, mask;108 109	pending = readl(&regs->sio_ir);110	mask = readl(&regs->sio_ies);111	pending &= mask; /* Mask off not enabled interrupts */112 113	if (pending)114		generic_handle_domain_irq(domain, __ffs(pending));115	else116		spurious_interrupt();117}118 119/*120 * System boards/BaseIOs use more interrupt pins of the bridge ASIC121 * to which the IOC3 is connected. Since the IOC3 MFD driver122 * knows wiring of these extra pins, we use the map_irq function123 * to get interrupts activated124 */125static int ioc3_map_irq(struct pci_dev *pdev, int slot, int pin)126{127	struct pci_host_bridge *hbrg = pci_find_host_bridge(pdev->bus);128 129	return hbrg->map_irq(pdev, slot, pin);130}131 132static int ioc3_irq_domain_setup(struct ioc3_priv_data *ipd, int irq)133{134	struct irq_domain *domain;135	struct fwnode_handle *fn;136 137	fn = irq_domain_alloc_named_fwnode("IOC3");138	if (!fn)139		goto err;140 141	domain = irq_domain_create_linear(fn, 24, &ioc3_irq_domain_ops, ipd);142	if (!domain) {143		irq_domain_free_fwnode(fn);144		goto err;145	}146 147	ipd->domain = domain;148 149	irq_set_chained_handler_and_data(irq, ioc3_irq_handler, domain);150	ipd->domain_irq = irq;151	return 0;152 153err:154	dev_err(&ipd->pdev->dev, "irq domain setup failed\n");155	return -ENOMEM;156}157 158static const struct resource ioc3_uarta_resources[] = {159	DEFINE_RES_MEM(offsetof(struct ioc3, sregs.uarta),160		       sizeof_field(struct ioc3, sregs.uarta)),161	DEFINE_RES_IRQ(IOC3_IRQ_SERIAL_A)162};163 164static const struct resource ioc3_uartb_resources[] = {165	DEFINE_RES_MEM(offsetof(struct ioc3, sregs.uartb),166		       sizeof_field(struct ioc3, sregs.uartb)),167	DEFINE_RES_IRQ(IOC3_IRQ_SERIAL_B)168};169 170static struct mfd_cell ioc3_serial_cells[] = {171	{172		.name = "ioc3-serial8250",173		.resources = ioc3_uarta_resources,174		.num_resources = ARRAY_SIZE(ioc3_uarta_resources),175	},176	{177		.name = "ioc3-serial8250",178		.resources = ioc3_uartb_resources,179		.num_resources = ARRAY_SIZE(ioc3_uartb_resources),180	}181};182 183static int ioc3_serial_setup(struct ioc3_priv_data *ipd)184{185	int ret;186 187	/* Set gpio pins for RS232/RS422 mode selection */188	writel(GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL,189		&ipd->regs->gpcr_s);190	/* Select RS232 mode for uart a */191	writel(0, &ipd->regs->gppr[6]);192	/* Select RS232 mode for uart b */193	writel(0, &ipd->regs->gppr[7]);194 195	/* Switch both ports to 16650 mode */196	writel(readl(&ipd->regs->port_a.sscr) & ~SSCR_DMA_EN,197	       &ipd->regs->port_a.sscr);198	writel(readl(&ipd->regs->port_b.sscr) & ~SSCR_DMA_EN,199	       &ipd->regs->port_b.sscr);200	udelay(1000); /* Wait until mode switch is done */201 202	ret = mfd_add_devices(&ipd->pdev->dev, PLATFORM_DEVID_AUTO,203			      ioc3_serial_cells, ARRAY_SIZE(ioc3_serial_cells),204			      &ipd->pdev->resource[0], 0, ipd->domain);205	if (ret) {206		dev_err(&ipd->pdev->dev, "Failed to add 16550 subdevs\n");207		return ret;208	}209 210	return 0;211}212 213static const struct resource ioc3_kbd_resources[] = {214	DEFINE_RES_MEM(offsetof(struct ioc3, serio),215		       sizeof_field(struct ioc3, serio)),216	DEFINE_RES_IRQ(IOC3_IRQ_KBD)217};218 219static struct mfd_cell ioc3_kbd_cells[] = {220	{221		.name = "ioc3-kbd",222		.resources = ioc3_kbd_resources,223		.num_resources = ARRAY_SIZE(ioc3_kbd_resources),224	}225};226 227static int ioc3_kbd_setup(struct ioc3_priv_data *ipd)228{229	int ret;230 231	ret = mfd_add_devices(&ipd->pdev->dev, PLATFORM_DEVID_AUTO,232			      ioc3_kbd_cells, ARRAY_SIZE(ioc3_kbd_cells),233			      &ipd->pdev->resource[0], 0, ipd->domain);234	if (ret) {235		dev_err(&ipd->pdev->dev, "Failed to add 16550 subdevs\n");236		return ret;237	}238 239	return 0;240}241 242static const struct resource ioc3_eth_resources[] = {243	DEFINE_RES_MEM(offsetof(struct ioc3, eth),244		       sizeof_field(struct ioc3, eth)),245	DEFINE_RES_MEM(offsetof(struct ioc3, ssram),246		       sizeof_field(struct ioc3, ssram)),247	DEFINE_RES_IRQ(0)248};249 250static const struct resource ioc3_w1_resources[] = {251	DEFINE_RES_MEM(offsetof(struct ioc3, mcr),252		       sizeof_field(struct ioc3, mcr)),253};254static struct sgi_w1_platform_data ioc3_w1_platform_data;255 256static struct mfd_cell ioc3_eth_cells[] = {257	{258		.name = "ioc3-eth",259		.resources = ioc3_eth_resources,260		.num_resources = ARRAY_SIZE(ioc3_eth_resources),261	},262	{263		.name = "sgi_w1",264		.resources = ioc3_w1_resources,265		.num_resources = ARRAY_SIZE(ioc3_w1_resources),266		.platform_data = &ioc3_w1_platform_data,267		.pdata_size = sizeof(ioc3_w1_platform_data),268	}269};270 271static int ioc3_eth_setup(struct ioc3_priv_data *ipd)272{273	int ret;274 275	/* Enable One-Wire bus */276	writel(GPCR_MLAN_EN, &ipd->regs->gpcr_s);277 278	/* Generate unique identifier */279	snprintf(ioc3_w1_platform_data.dev_id,280		 sizeof(ioc3_w1_platform_data.dev_id), "ioc3-%012llx",281		 ipd->pdev->resource->start);282 283	ret = mfd_add_devices(&ipd->pdev->dev, PLATFORM_DEVID_AUTO,284			      ioc3_eth_cells, ARRAY_SIZE(ioc3_eth_cells),285			      &ipd->pdev->resource[0], ipd->pdev->irq, NULL);286	if (ret) {287		dev_err(&ipd->pdev->dev, "Failed to add ETH/W1 subdev\n");288		return ret;289	}290 291	return 0;292}293 294static const struct resource ioc3_m48t35_resources[] = {295	DEFINE_RES_MEM(IOC3_BYTEBUS_DEV0, M48T35_REG_SIZE)296};297 298static struct mfd_cell ioc3_m48t35_cells[] = {299	{300		.name = "rtc-m48t35",301		.resources = ioc3_m48t35_resources,302		.num_resources = ARRAY_SIZE(ioc3_m48t35_resources),303	}304};305 306static int ioc3_m48t35_setup(struct ioc3_priv_data *ipd)307{308	int ret;309 310	ret = mfd_add_devices(&ipd->pdev->dev, PLATFORM_DEVID_AUTO,311			      ioc3_m48t35_cells, ARRAY_SIZE(ioc3_m48t35_cells),312			      &ipd->pdev->resource[0], 0, ipd->domain);313	if (ret)314		dev_err(&ipd->pdev->dev, "Failed to add M48T35 subdev\n");315 316	return ret;317}318 319static struct ds1685_rtc_platform_data ip30_rtc_platform_data = {320	.bcd_mode = false,321	.no_irq = false,322	.uie_unsupported = true,323	.access_type = ds1685_reg_indirect,324};325 326static const struct resource ioc3_rtc_ds1685_resources[] = {327	DEFINE_RES_MEM(IOC3_BYTEBUS_DEV1, 1),328	DEFINE_RES_MEM(IOC3_BYTEBUS_DEV2, 1),329	DEFINE_RES_IRQ(0)330};331 332static struct mfd_cell ioc3_ds1685_cells[] = {333	{334		.name = "rtc-ds1685",335		.resources = ioc3_rtc_ds1685_resources,336		.num_resources = ARRAY_SIZE(ioc3_rtc_ds1685_resources),337		.platform_data = &ip30_rtc_platform_data,338		.pdata_size = sizeof(ip30_rtc_platform_data),339		.id = PLATFORM_DEVID_NONE,340	}341};342 343static int ioc3_ds1685_setup(struct ioc3_priv_data *ipd)344{345	int ret, irq;346 347	irq = ioc3_map_irq(ipd->pdev, 6, 0);348 349	ret = mfd_add_devices(&ipd->pdev->dev, 0, ioc3_ds1685_cells,350			      ARRAY_SIZE(ioc3_ds1685_cells),351			      &ipd->pdev->resource[0], irq, NULL);352	if (ret)353		dev_err(&ipd->pdev->dev, "Failed to add DS1685 subdev\n");354 355	return ret;356};357 358 359static const struct resource ioc3_leds_resources[] = {360	DEFINE_RES_MEM(offsetof(struct ioc3, gppr[0]),361		       sizeof_field(struct ioc3, gppr[0])),362	DEFINE_RES_MEM(offsetof(struct ioc3, gppr[1]),363		       sizeof_field(struct ioc3, gppr[1])),364};365 366static struct mfd_cell ioc3_led_cells[] = {367	{368		.name = "ip30-leds",369		.resources = ioc3_leds_resources,370		.num_resources = ARRAY_SIZE(ioc3_leds_resources),371		.id = PLATFORM_DEVID_NONE,372	}373};374 375static int ioc3_led_setup(struct ioc3_priv_data *ipd)376{377	int ret;378 379	ret = mfd_add_devices(&ipd->pdev->dev, 0, ioc3_led_cells,380			      ARRAY_SIZE(ioc3_led_cells),381			      &ipd->pdev->resource[0], 0, ipd->domain);382	if (ret)383		dev_err(&ipd->pdev->dev, "Failed to add LED subdev\n");384 385	return ret;386}387 388static int ip27_baseio_setup(struct ioc3_priv_data *ipd)389{390	int ret, io_irq;391 392	io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),393			      PCI_INTERRUPT_INTB);394	ret = ioc3_irq_domain_setup(ipd, io_irq);395	if (ret)396		return ret;397 398	ret = ioc3_eth_setup(ipd);399	if (ret)400		return ret;401 402	ret = ioc3_serial_setup(ipd);403	if (ret)404		return ret;405 406	return ioc3_m48t35_setup(ipd);407}408 409static int ip27_baseio6g_setup(struct ioc3_priv_data *ipd)410{411	int ret, io_irq;412 413	io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),414			      PCI_INTERRUPT_INTB);415	ret = ioc3_irq_domain_setup(ipd, io_irq);416	if (ret)417		return ret;418 419	ret = ioc3_eth_setup(ipd);420	if (ret)421		return ret;422 423	ret = ioc3_serial_setup(ipd);424	if (ret)425		return ret;426 427	ret = ioc3_m48t35_setup(ipd);428	if (ret)429		return ret;430 431	return ioc3_kbd_setup(ipd);432}433 434static int ip27_mio_setup(struct ioc3_priv_data *ipd)435{436	int ret;437 438	ret = ioc3_irq_domain_setup(ipd, ipd->pdev->irq);439	if (ret)440		return ret;441 442	ret = ioc3_serial_setup(ipd);443	if (ret)444		return ret;445 446	return ioc3_kbd_setup(ipd);447}448 449static int ip30_sysboard_setup(struct ioc3_priv_data *ipd)450{451	int ret, io_irq;452 453	io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),454			      PCI_INTERRUPT_INTB);455	ret = ioc3_irq_domain_setup(ipd, io_irq);456	if (ret)457		return ret;458 459	ret = ioc3_eth_setup(ipd);460	if (ret)461		return ret;462 463	ret = ioc3_serial_setup(ipd);464	if (ret)465		return ret;466 467	ret = ioc3_kbd_setup(ipd);468	if (ret)469		return ret;470 471	ret = ioc3_ds1685_setup(ipd);472	if (ret)473		return ret;474 475	return ioc3_led_setup(ipd);476}477 478static int ioc3_menet_setup(struct ioc3_priv_data *ipd)479{480	int ret, io_irq;481 482	io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),483			      PCI_INTERRUPT_INTB);484	ret = ioc3_irq_domain_setup(ipd, io_irq);485	if (ret)486		return ret;487 488	ret = ioc3_eth_setup(ipd);489	if (ret)490		return ret;491 492	return ioc3_serial_setup(ipd);493}494 495static int ioc3_menet4_setup(struct ioc3_priv_data *ipd)496{497	return ioc3_eth_setup(ipd);498}499 500static int ioc3_cad_duo_setup(struct ioc3_priv_data *ipd)501{502	int ret, io_irq;503 504	io_irq = ioc3_map_irq(ipd->pdev, PCI_SLOT(ipd->pdev->devfn),505			      PCI_INTERRUPT_INTB);506	ret = ioc3_irq_domain_setup(ipd, io_irq);507	if (ret)508		return ret;509 510	ret = ioc3_eth_setup(ipd);511	if (ret)512		return ret;513 514	return ioc3_kbd_setup(ipd);515}516 517/* Helper macro for filling ioc3_info array */518#define IOC3_SID(_name, _sid, _setup) \519	{								   \520		.name = _name,						   \521		.sid = PCI_VENDOR_ID_SGI | (IOC3_SUBSYS_ ## _sid << 16),   \522		.setup = _setup,					   \523	}524 525static struct {526	const char *name;527	u32 sid;528	int (*setup)(struct ioc3_priv_data *ipd);529} ioc3_infos[] = {530	IOC3_SID("IP27 BaseIO6G", IP27_BASEIO6G, &ip27_baseio6g_setup),531	IOC3_SID("IP27 MIO", IP27_MIO, &ip27_mio_setup),532	IOC3_SID("IP27 BaseIO", IP27_BASEIO, &ip27_baseio_setup),533	IOC3_SID("IP29 System Board", IP29_SYSBOARD, &ip27_baseio6g_setup),534	IOC3_SID("IP30 System Board", IP30_SYSBOARD, &ip30_sysboard_setup),535	IOC3_SID("MENET", MENET, &ioc3_menet_setup),536	IOC3_SID("MENET4", MENET4, &ioc3_menet4_setup)537};538#undef IOC3_SID539 540static int ioc3_setup(struct ioc3_priv_data *ipd)541{542	u32 sid;543	int i;544 545	/* Clear IRQs */546	writel(~0, &ipd->regs->sio_iec);547	writel(~0, &ipd->regs->sio_ir);548	writel(0, &ipd->regs->eth.eier);549	writel(~0, &ipd->regs->eth.eisr);550 551	/* Read subsystem vendor id and subsystem id */552	pci_read_config_dword(ipd->pdev, PCI_SUBSYSTEM_VENDOR_ID, &sid);553 554	for (i = 0; i < ARRAY_SIZE(ioc3_infos); i++)555		if (sid == ioc3_infos[i].sid) {556			pr_info("ioc3: %s\n", ioc3_infos[i].name);557			return ioc3_infos[i].setup(ipd);558		}559 560	/* Treat everything not identified by PCI subid as CAD DUO */561	pr_info("ioc3: CAD DUO\n");562	return ioc3_cad_duo_setup(ipd);563}564 565static int ioc3_mfd_probe(struct pci_dev *pdev,566			  const struct pci_device_id *pci_id)567{568	struct ioc3_priv_data *ipd;569	struct ioc3 __iomem *regs;570	int ret;571 572	ret = pci_enable_device(pdev);573	if (ret)574		return ret;575 576	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, IOC3_LATENCY);577	pci_set_master(pdev);578 579	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));580	if (ret) {581		pr_err("%s: No usable DMA configuration, aborting.\n",582		       pci_name(pdev));583		goto out_disable_device;584	}585 586	/* Set up per-IOC3 data */587	ipd = devm_kzalloc(&pdev->dev, sizeof(struct ioc3_priv_data),588			   GFP_KERNEL);589	if (!ipd) {590		ret = -ENOMEM;591		goto out_disable_device;592	}593	ipd->pdev = pdev;594 595	/*596	 * Map all IOC3 registers.  These are shared between subdevices597	 * so the main IOC3 module manages them.598	 */599	regs = pci_ioremap_bar(pdev, 0);600	if (!regs) {601		dev_warn(&pdev->dev, "ioc3: Unable to remap PCI BAR for %s.\n",602			 pci_name(pdev));603		ret = -ENOMEM;604		goto out_disable_device;605	}606	ipd->regs = regs;607 608	/* Track PCI-device specific data */609	pci_set_drvdata(pdev, ipd);610 611	ret = ioc3_setup(ipd);612	if (ret) {613		/* Remove all already added MFD devices */614		mfd_remove_devices(&ipd->pdev->dev);615		if (ipd->domain) {616			struct fwnode_handle *fn = ipd->domain->fwnode;617 618			irq_domain_remove(ipd->domain);619			irq_domain_free_fwnode(fn);620			free_irq(ipd->domain_irq, (void *)ipd);621		}622		pci_iounmap(pdev, regs);623		goto out_disable_device;624	}625 626	return 0;627 628out_disable_device:629	pci_disable_device(pdev);630	return ret;631}632 633static void ioc3_mfd_remove(struct pci_dev *pdev)634{635	struct ioc3_priv_data *ipd;636 637	ipd = pci_get_drvdata(pdev);638 639	/* Clear and disable all IRQs */640	writel(~0, &ipd->regs->sio_iec);641	writel(~0, &ipd->regs->sio_ir);642 643	/* Release resources */644	mfd_remove_devices(&ipd->pdev->dev);645	if (ipd->domain) {646		struct fwnode_handle *fn = ipd->domain->fwnode;647 648		irq_domain_remove(ipd->domain);649		irq_domain_free_fwnode(fn);650		free_irq(ipd->domain_irq, (void *)ipd);651	}652	pci_iounmap(pdev, ipd->regs);653	pci_disable_device(pdev);654}655 656static struct pci_device_id ioc3_mfd_id_table[] = {657	{ PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID },658	{ 0, },659};660MODULE_DEVICE_TABLE(pci, ioc3_mfd_id_table);661 662static struct pci_driver ioc3_mfd_driver = {663	.name = "IOC3",664	.id_table = ioc3_mfd_id_table,665	.probe = ioc3_mfd_probe,666	.remove = ioc3_mfd_remove,667};668 669module_pci_driver(ioc3_mfd_driver);670 671MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>");672MODULE_DESCRIPTION("SGI IOC3 MFD driver");673MODULE_LICENSE("GPL v2");674