xref: /linux/drivers/mfd/ls2k-bmc-core.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Loongson-2K Board Management Controller (BMC) Core Driver.
4  *
5  * Copyright (C) 2024-2025 Loongson Technology Corporation Limited.
6  *
7  * Authors:
8  *	Chong Qiao <qiaochong@loongson.cn>
9  *	Binbin Zhou <zhoubinbin@loongson.cn>
10  */
11 
12 #include <linux/aperture.h>
13 #include <linux/bitfield.h>
14 #include <linux/delay.h>
15 #include <linux/errno.h>
16 #include <linux/init.h>
17 #include <linux/iopoll.h>
18 #include <linux/kbd_kern.h>
19 #include <linux/kernel.h>
20 #include <linux/mfd/core.h>
21 #include <linux/module.h>
22 #include <linux/pci.h>
23 #include <linux/pci_ids.h>
24 #include <linux/platform_data/simplefb.h>
25 #include <linux/platform_device.h>
26 #include <linux/stop_machine.h>
27 #include <linux/vt_kern.h>
28 
29 /* LS2K BMC resources */
30 #define LS2K_DISPLAY_RES_START		(SZ_16M + SZ_2M)
31 #define LS2K_IPMI_RES_SIZE		0x1C
32 #define LS2K_IPMI0_RES_START		(SZ_16M + 0xF00000)
33 #define LS2K_IPMI1_RES_START		(LS2K_IPMI0_RES_START + LS2K_IPMI_RES_SIZE)
34 #define LS2K_IPMI2_RES_START		(LS2K_IPMI1_RES_START + LS2K_IPMI_RES_SIZE)
35 #define LS2K_IPMI3_RES_START		(LS2K_IPMI2_RES_START + LS2K_IPMI_RES_SIZE)
36 #define LS2K_IPMI4_RES_START		(LS2K_IPMI3_RES_START + LS2K_IPMI_RES_SIZE)
37 
38 #define LS7A_PCI_CFG_SIZE		0x100
39 
40 /* LS7A bridge registers */
41 #define LS7A_PCIE_PORT_CTL0		0x0
42 #define LS7A_PCIE_PORT_STS1		0xC
43 #define LS7A_GEN2_CTL			0x80C
44 #define LS7A_SYMBOL_TIMER		0x71C
45 
46 /* Bits of LS7A_PCIE_PORT_CTL0 */
47 #define LS2K_BMC_PCIE_LTSSM_ENABLE	BIT(3)
48 
49 /* Bits of LS7A_PCIE_PORT_STS1 */
50 #define LS2K_BMC_PCIE_LTSSM_STS		GENMASK(5, 0)
51 #define LS2K_BMC_PCIE_CONNECTED		0x11
52 
53 #define LS2K_BMC_PCIE_DELAY_US		1000
54 #define LS2K_BMC_PCIE_TIMEOUT_US	1000000
55 
56 /* Bits of LS7A_GEN2_CTL */
57 #define LS7A_GEN2_SPEED_CHANG		BIT(17)
58 #define LS7A_CONF_PHY_TX		BIT(18)
59 
60 /* Bits of LS7A_SYMBOL_TIMER */
61 #define LS7A_MASK_LEN_MATCH		BIT(26)
62 
63 /* Interval between interruptions */
64 #define LS2K_BMC_INT_INTERVAL		(60 * HZ)
65 
66 /* Maximum time to wait for U-Boot and DDR to be ready with ms. */
67 #define LS2K_BMC_RESET_WAIT_TIME	10000
68 
69 /* It's an experience value */
70 #define LS7A_BAR0_CHECK_MAX_TIMES	2000
71 
72 #define PCI_REG_STRIDE			0x4
73 
74 #define LS2K_BMC_RESET_GPIO		14
75 #define LOONGSON_GPIO_REG_BASE		0x1FE00500
76 #define LOONGSON_GPIO_REG_SIZE		0x18
77 #define LOONGSON_GPIO_OEN		0x0
78 #define LOONGSON_GPIO_FUNC		0x4
79 #define LOONGSON_GPIO_INTPOL		0x10
80 #define LOONGSON_GPIO_INTEN		0x14
81 
82 #define LOONGSON_IO_INT_BASE		16
83 #define LS2K_BMC_RESET_GPIO_INT_VEC	(LS2K_BMC_RESET_GPIO % 8)
84 #define LS2K_BMC_RESET_GPIO_GSI		(LOONGSON_IO_INT_BASE + LS2K_BMC_RESET_GPIO_INT_VEC)
85 
86 enum {
87 	LS2K_BMC_DISPLAY,
88 	LS2K_BMC_IPMI0,
89 	LS2K_BMC_IPMI1,
90 	LS2K_BMC_IPMI2,
91 	LS2K_BMC_IPMI3,
92 	LS2K_BMC_IPMI4,
93 };
94 
95 static struct resource ls2k_display_resources[] = {
96 	DEFINE_RES_MEM_NAMED(LS2K_DISPLAY_RES_START, SZ_4M, "simpledrm-res"),
97 };
98 
99 static struct resource ls2k_ipmi0_resources[] = {
100 	DEFINE_RES_MEM_NAMED(LS2K_IPMI0_RES_START, LS2K_IPMI_RES_SIZE, "ipmi0-res"),
101 };
102 
103 static struct resource ls2k_ipmi1_resources[] = {
104 	DEFINE_RES_MEM_NAMED(LS2K_IPMI1_RES_START, LS2K_IPMI_RES_SIZE, "ipmi1-res"),
105 };
106 
107 static struct resource ls2k_ipmi2_resources[] = {
108 	DEFINE_RES_MEM_NAMED(LS2K_IPMI2_RES_START, LS2K_IPMI_RES_SIZE, "ipmi2-res"),
109 };
110 
111 static struct resource ls2k_ipmi3_resources[] = {
112 	DEFINE_RES_MEM_NAMED(LS2K_IPMI3_RES_START, LS2K_IPMI_RES_SIZE, "ipmi3-res"),
113 };
114 
115 static struct resource ls2k_ipmi4_resources[] = {
116 	DEFINE_RES_MEM_NAMED(LS2K_IPMI4_RES_START, LS2K_IPMI_RES_SIZE, "ipmi4-res"),
117 };
118 
119 static struct mfd_cell ls2k_bmc_cells[] = {
120 	[LS2K_BMC_DISPLAY] = {
121 		.name = "simple-framebuffer",
122 		.num_resources = ARRAY_SIZE(ls2k_display_resources),
123 		.resources = ls2k_display_resources
124 	},
125 	[LS2K_BMC_IPMI0] = {
126 		.name = "ls2k-ipmi-si",
127 		.num_resources = ARRAY_SIZE(ls2k_ipmi0_resources),
128 		.resources = ls2k_ipmi0_resources
129 	},
130 	[LS2K_BMC_IPMI1] = {
131 		.name = "ls2k-ipmi-si",
132 		.num_resources = ARRAY_SIZE(ls2k_ipmi1_resources),
133 		.resources = ls2k_ipmi1_resources
134 	},
135 	[LS2K_BMC_IPMI2] = {
136 		.name = "ls2k-ipmi-si",
137 		.num_resources = ARRAY_SIZE(ls2k_ipmi2_resources),
138 		.resources = ls2k_ipmi2_resources
139 	},
140 	[LS2K_BMC_IPMI3] = {
141 		.name = "ls2k-ipmi-si",
142 		.num_resources = ARRAY_SIZE(ls2k_ipmi3_resources),
143 		.resources = ls2k_ipmi3_resources
144 	},
145 	[LS2K_BMC_IPMI4] = {
146 		.name = "ls2k-ipmi-si",
147 		.num_resources = ARRAY_SIZE(ls2k_ipmi4_resources),
148 		.resources = ls2k_ipmi4_resources
149 	},
150 };
151 
152 /* Index of the BMC PCI configuration space to be restored at BMC reset. */
153 struct ls2k_bmc_pci_data {
154 	u32 pci_command;
155 	u32 base_address0;
156 	u32 interrupt_line;
157 };
158 
159 /* Index of the parent PCI configuration space to be restored at BMC reset. */
160 struct ls2k_bmc_bridge_pci_data {
161 	u32 pci_command;
162 	u32 base_address[6];
163 	u32 rom_addreess;
164 	u32 interrupt_line;
165 	u32 msi_hi;
166 	u32 msi_lo;
167 	u32 devctl;
168 	u32 linkcap;
169 	u32 linkctl_sts;
170 	u32 symbol_timer;
171 	u32 gen2_ctrl;
172 };
173 
174 struct ls2k_bmc_ddata {
175 	struct device *dev;
176 	struct work_struct bmc_reset_work;
177 	struct ls2k_bmc_pci_data bmc_pci_data;
178 	struct ls2k_bmc_bridge_pci_data bridge_pci_data;
179 };
180 
181 static bool ls2k_bmc_bar0_addr_is_set(struct pci_dev *pdev)
182 {
183 	u32 addr;
184 
185 	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &addr);
186 
187 	return addr & PCI_BASE_ADDRESS_MEM_MASK ? true : false;
188 }
189 
190 static bool ls2k_bmc_pcie_is_connected(struct pci_dev *parent, struct ls2k_bmc_ddata *ddata)
191 {
192 	void __iomem *base;
193 	int val, ret;
194 
195 	base = pci_iomap(parent, 0, LS7A_PCI_CFG_SIZE);
196 	if (!base)
197 		return false;
198 
199 	val = readl(base + LS7A_PCIE_PORT_CTL0);
200 	writel(val | LS2K_BMC_PCIE_LTSSM_ENABLE, base + LS7A_PCIE_PORT_CTL0);
201 
202 	ret = readl_poll_timeout_atomic(base + LS7A_PCIE_PORT_STS1, val,
203 					(val & LS2K_BMC_PCIE_LTSSM_STS) == LS2K_BMC_PCIE_CONNECTED,
204 					LS2K_BMC_PCIE_DELAY_US, LS2K_BMC_PCIE_TIMEOUT_US);
205 	if (ret) {
206 		pci_iounmap(parent, base);
207 		dev_err(ddata->dev, "PCI-E training failed status=0x%x\n", val);
208 		return false;
209 	}
210 
211 	pci_iounmap(parent, base);
212 	return true;
213 }
214 
215 static void ls2k_bmc_restore_bridge_pci_data(struct pci_dev *parent, struct ls2k_bmc_ddata *ddata)
216 {
217 	int base, i = 0;
218 
219 	pci_write_config_dword(parent, PCI_COMMAND, ddata->bridge_pci_data.pci_command);
220 
221 	for (base = PCI_BASE_ADDRESS_0; base <= PCI_BASE_ADDRESS_5; base += PCI_REG_STRIDE, i++)
222 		pci_write_config_dword(parent, base, ddata->bridge_pci_data.base_address[i]);
223 
224 	pci_write_config_dword(parent, PCI_ROM_ADDRESS, ddata->bridge_pci_data.rom_addreess);
225 	pci_write_config_dword(parent, PCI_INTERRUPT_LINE, ddata->bridge_pci_data.interrupt_line);
226 
227 	pci_write_config_dword(parent, parent->msi_cap + PCI_MSI_ADDRESS_LO,
228 			       ddata->bridge_pci_data.msi_lo);
229 	pci_write_config_dword(parent, parent->msi_cap + PCI_MSI_ADDRESS_HI,
230 			       ddata->bridge_pci_data.msi_hi);
231 	pci_write_config_dword(parent, parent->pcie_cap + PCI_EXP_DEVCTL,
232 			       ddata->bridge_pci_data.devctl);
233 	pci_write_config_dword(parent, parent->pcie_cap + PCI_EXP_LNKCAP,
234 			       ddata->bridge_pci_data.linkcap);
235 	pci_write_config_dword(parent, parent->pcie_cap + PCI_EXP_LNKCTL,
236 			       ddata->bridge_pci_data.linkctl_sts);
237 
238 	pci_write_config_dword(parent, LS7A_GEN2_CTL, ddata->bridge_pci_data.gen2_ctrl);
239 	pci_write_config_dword(parent, LS7A_SYMBOL_TIMER, ddata->bridge_pci_data.symbol_timer);
240 }
241 
242 static int ls2k_bmc_recover_pci_data(void *data)
243 {
244 	struct ls2k_bmc_ddata *ddata = data;
245 	struct pci_dev *pdev = to_pci_dev(ddata->dev);
246 	struct pci_dev *parent = pdev->bus->self;
247 	u32 i;
248 
249 	/*
250 	 * Clear the bus, io and mem resources of the PCI-E bridge to zero, so that
251 	 * the processor can not access the LS2K PCI-E port, to avoid crashing due to
252 	 * the lack of return signal from accessing the LS2K PCI-E port.
253 	 */
254 	pci_write_config_dword(parent, PCI_BASE_ADDRESS_2, 0);
255 	pci_write_config_dword(parent, PCI_BASE_ADDRESS_3, 0);
256 	pci_write_config_dword(parent, PCI_BASE_ADDRESS_4, 0);
257 
258 	/*
259 	 * When the LS2K BMC is reset, the LS7A PCI-E port is also reset, and its PCI
260 	 * BAR0 register is cleared. Due to the time gap between the GPIO interrupt
261 	 * generation and the LS2K BMC reset, the LS7A PCI BAR0 register is read to
262 	 * determine whether the reset has begun.
263 	 */
264 	for (i = LS7A_BAR0_CHECK_MAX_TIMES; i > 0 ; i--) {
265 		if (!ls2k_bmc_bar0_addr_is_set(parent))
266 			break;
267 		mdelay(1);
268 	};
269 
270 	if (i == 0)
271 		return false;
272 
273 	ls2k_bmc_restore_bridge_pci_data(parent, ddata);
274 
275 	/* Check if PCI-E is connected */
276 	if (!ls2k_bmc_pcie_is_connected(parent, ddata))
277 		return false;
278 
279 	/* Waiting for U-Boot and DDR ready */
280 	mdelay(LS2K_BMC_RESET_WAIT_TIME);
281 	if (!ls2k_bmc_bar0_addr_is_set(parent))
282 		return false;
283 
284 	/* Restore LS2K BMC PCI-E config data */
285 	pci_write_config_dword(pdev, PCI_COMMAND, ddata->bmc_pci_data.pci_command);
286 	pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, ddata->bmc_pci_data.base_address0);
287 	pci_write_config_dword(pdev, PCI_INTERRUPT_LINE, ddata->bmc_pci_data.interrupt_line);
288 
289 	return 0;
290 }
291 
292 static void ls2k_bmc_events_fn(struct work_struct *work)
293 {
294 	struct ls2k_bmc_ddata *ddata = container_of(work, struct ls2k_bmc_ddata, bmc_reset_work);
295 
296 	/*
297 	 * The PCI-E is lost when the BMC resets, at which point access to the PCI-E
298 	 * from other CPUs is suspended to prevent a crash.
299 	 */
300 	stop_machine(ls2k_bmc_recover_pci_data, ddata, NULL);
301 
302 	if (IS_ENABLED(CONFIG_VT)) {
303 		/* Re-push the display due to previous PCI-E loss. */
304 		set_console(vt_move_to_console(MAX_NR_CONSOLES - 1, 1));
305 	}
306 }
307 
308 static irqreturn_t ls2k_bmc_interrupt(int irq, void *arg)
309 {
310 	struct ls2k_bmc_ddata *ddata = arg;
311 	static unsigned long last_jiffies;
312 
313 	if (system_state != SYSTEM_RUNNING)
314 		return IRQ_HANDLED;
315 
316 	/* Skip interrupt in LS2K_BMC_INT_INTERVAL */
317 	if (time_after(jiffies, last_jiffies + LS2K_BMC_INT_INTERVAL)) {
318 		schedule_work(&ddata->bmc_reset_work);
319 		last_jiffies = jiffies;
320 	}
321 
322 	return IRQ_HANDLED;
323 }
324 
325 /*
326  * Saves the BMC parent device (LS7A) and its own PCI configuration space registers
327  * that need to be restored after BMC reset.
328  */
329 static void ls2k_bmc_save_pci_data(struct pci_dev *pdev, struct ls2k_bmc_ddata *ddata)
330 {
331 	struct pci_dev *parent = pdev->bus->self;
332 	int base, i = 0;
333 
334 	pci_read_config_dword(parent, PCI_COMMAND, &ddata->bridge_pci_data.pci_command);
335 
336 	for (base = PCI_BASE_ADDRESS_0; base <= PCI_BASE_ADDRESS_5; base += PCI_REG_STRIDE, i++)
337 		pci_read_config_dword(parent, base, &ddata->bridge_pci_data.base_address[i]);
338 
339 	pci_read_config_dword(parent, PCI_ROM_ADDRESS, &ddata->bridge_pci_data.rom_addreess);
340 	pci_read_config_dword(parent, PCI_INTERRUPT_LINE, &ddata->bridge_pci_data.interrupt_line);
341 
342 	pci_read_config_dword(parent, parent->msi_cap + PCI_MSI_ADDRESS_LO,
343 			      &ddata->bridge_pci_data.msi_lo);
344 	pci_read_config_dword(parent, parent->msi_cap + PCI_MSI_ADDRESS_HI,
345 			      &ddata->bridge_pci_data.msi_hi);
346 
347 	pci_read_config_dword(parent, parent->pcie_cap + PCI_EXP_DEVCTL,
348 			      &ddata->bridge_pci_data.devctl);
349 	pci_read_config_dword(parent, parent->pcie_cap + PCI_EXP_LNKCAP,
350 			      &ddata->bridge_pci_data.linkcap);
351 	pci_read_config_dword(parent, parent->pcie_cap + PCI_EXP_LNKCTL,
352 			      &ddata->bridge_pci_data.linkctl_sts);
353 
354 	pci_read_config_dword(parent, LS7A_GEN2_CTL, &ddata->bridge_pci_data.gen2_ctrl);
355 	ddata->bridge_pci_data.gen2_ctrl |= FIELD_PREP(LS7A_GEN2_SPEED_CHANG, 0x1) |
356 					    FIELD_PREP(LS7A_CONF_PHY_TX, 0x0);
357 
358 	pci_read_config_dword(parent, LS7A_SYMBOL_TIMER, &ddata->bridge_pci_data.symbol_timer);
359 	ddata->bridge_pci_data.symbol_timer |= LS7A_MASK_LEN_MATCH;
360 
361 	pci_read_config_dword(pdev, PCI_COMMAND, &ddata->bmc_pci_data.pci_command);
362 	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &ddata->bmc_pci_data.base_address0);
363 	pci_read_config_dword(pdev, PCI_INTERRUPT_LINE, &ddata->bmc_pci_data.interrupt_line);
364 }
365 
366 static int ls2k_bmc_init(struct ls2k_bmc_ddata *ddata)
367 {
368 	struct pci_dev *pdev = to_pci_dev(ddata->dev);
369 	void __iomem *gpio_base;
370 	int gpio_irq, ret, val;
371 
372 	ls2k_bmc_save_pci_data(pdev, ddata);
373 
374 	INIT_WORK(&ddata->bmc_reset_work, ls2k_bmc_events_fn);
375 
376 	ret = devm_request_irq(&pdev->dev, pdev->irq, ls2k_bmc_interrupt,
377 			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc pcie", ddata);
378 	if (ret) {
379 		dev_err(ddata->dev, "Failed to request LS2KBMC PCI-E IRQ %d.\n", pdev->irq);
380 		return ret;
381 	}
382 
383 	gpio_base = ioremap(LOONGSON_GPIO_REG_BASE, LOONGSON_GPIO_REG_SIZE);
384 	if (!gpio_base)
385 		return -ENOMEM;
386 
387 	/* Disable GPIO output */
388 	val = readl(gpio_base + LOONGSON_GPIO_OEN);
389 	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_OEN);
390 
391 	/* Enable GPIO functionality */
392 	val = readl(gpio_base + LOONGSON_GPIO_FUNC);
393 	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_FUNC);
394 
395 	/* Set GPIO interrupts to low-level active */
396 	val = readl(gpio_base + LOONGSON_GPIO_INTPOL);
397 	writel(val & ~BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTPOL);
398 
399 	/* Enable GPIO interrupts */
400 	val = readl(gpio_base + LOONGSON_GPIO_INTEN);
401 	writel(val | BIT(LS2K_BMC_RESET_GPIO), gpio_base + LOONGSON_GPIO_INTEN);
402 
403 	iounmap(gpio_base);
404 
405 	/*
406 	 * Since gpio_chip->to_irq is not implemented in the Loongson-3 GPIO driver,
407 	 * acpi_register_gsi() is used to obtain the GPIO IRQ. The GPIO interrupt is a
408 	 * watchdog interrupt that is triggered when the BMC resets.
409 	 */
410 	gpio_irq = acpi_register_gsi(NULL, LS2K_BMC_RESET_GPIO_GSI, ACPI_EDGE_SENSITIVE,
411 				     ACPI_ACTIVE_LOW);
412 	if (gpio_irq < 0)
413 		return gpio_irq;
414 
415 	ret = devm_request_irq(ddata->dev, gpio_irq, ls2k_bmc_interrupt,
416 			       IRQF_SHARED | IRQF_TRIGGER_FALLING, "ls2kbmc gpio", ddata);
417 	if (ret)
418 		dev_err(ddata->dev, "Failed to request LS2KBMC GPIO IRQ %d.\n", gpio_irq);
419 
420 	acpi_unregister_gsi(LS2K_BMC_RESET_GPIO_GSI);
421 	return ret;
422 }
423 
424 /*
425  * Currently the Loongson-2K BMC hardware does not have an I2C interface to adapt to the
426  * resolution. We set the resolution by presetting "video=1280x1024-16@2M" to the BMC memory.
427  */
428 static int ls2k_bmc_parse_mode(struct pci_dev *pdev, struct simplefb_platform_data *pd)
429 {
430 	char *mode;
431 	int depth, ret;
432 
433 	/* The last 16M of PCI BAR0 is used to store the resolution string. */
434 	mode = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0) + SZ_16M, SZ_16M);
435 	if (!mode)
436 		return -ENOMEM;
437 
438 	/* The resolution field starts with the flag "video=". */
439 	if (!strncmp(mode, "video=", 6))
440 		mode = mode + 6;
441 
442 	ret = kstrtoint(strsep(&mode, "x"), 10, &pd->width);
443 	if (ret)
444 		return ret;
445 
446 	ret = kstrtoint(strsep(&mode, "-"), 10, &pd->height);
447 	if (ret)
448 		return ret;
449 
450 	ret = kstrtoint(strsep(&mode, "@"), 10, &depth);
451 	if (ret)
452 		return ret;
453 
454 	pd->stride = pd->width * depth / 8;
455 	pd->format = depth == 32 ? "a8r8g8b8" : "r5g6b5";
456 
457 	return 0;
458 }
459 
460 static int ls2k_bmc_probe(struct pci_dev *dev, const struct pci_device_id *id)
461 {
462 	struct simplefb_platform_data pd;
463 	struct ls2k_bmc_ddata *ddata;
464 	resource_size_t base;
465 	int ret;
466 
467 	ret = pci_enable_device(dev);
468 	if (ret)
469 		return ret;
470 
471 	ddata = devm_kzalloc(&dev->dev, sizeof(*ddata), GFP_KERNEL);
472 	if (IS_ERR(ddata)) {
473 		ret = -ENOMEM;
474 		goto disable_pci;
475 	}
476 
477 	ddata->dev = &dev->dev;
478 
479 	ret = ls2k_bmc_init(ddata);
480 	if (ret)
481 		goto disable_pci;
482 
483 	ret = ls2k_bmc_parse_mode(dev, &pd);
484 	if (ret)
485 		goto disable_pci;
486 
487 	ls2k_bmc_cells[LS2K_BMC_DISPLAY].platform_data = &pd;
488 	ls2k_bmc_cells[LS2K_BMC_DISPLAY].pdata_size = sizeof(pd);
489 	base = dev->resource[0].start + LS2K_DISPLAY_RES_START;
490 
491 	/* Remove conflicting efifb device */
492 	ret = aperture_remove_conflicting_devices(base, SZ_4M, "simple-framebuffer");
493 	if (ret) {
494 		dev_err(&dev->dev, "Failed to removed firmware framebuffers: %d\n", ret);
495 		goto disable_pci;
496 	}
497 
498 	return devm_mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
499 				    ls2k_bmc_cells, ARRAY_SIZE(ls2k_bmc_cells),
500 				    &dev->resource[0], 0, NULL);
501 
502 disable_pci:
503 	pci_disable_device(dev);
504 	return ret;
505 }
506 
507 static void ls2k_bmc_remove(struct pci_dev *dev)
508 {
509 	pci_disable_device(dev);
510 }
511 
512 static struct pci_device_id ls2k_bmc_devices[] = {
513 	{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x1a05) },
514 	{ }
515 };
516 MODULE_DEVICE_TABLE(pci, ls2k_bmc_devices);
517 
518 static struct pci_driver ls2k_bmc_driver = {
519 	.name = "ls2k-bmc",
520 	.id_table = ls2k_bmc_devices,
521 	.probe = ls2k_bmc_probe,
522 	.remove = ls2k_bmc_remove,
523 };
524 module_pci_driver(ls2k_bmc_driver);
525 
526 MODULE_DESCRIPTION("Loongson-2K Board Management Controller (BMC) Core driver");
527 MODULE_AUTHOR("Loongson Technology Corporation Limited");
528 MODULE_LICENSE("GPL");
529