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