xref: /openbmc/linux/drivers/nubus/bus.c (revision 7f400a1d)
17f86c765SFinn Thain // SPDX-License-Identifier: GPL-2.0
27f86c765SFinn Thain //
37f86c765SFinn Thain // Bus implementation for the NuBus subsystem.
47f86c765SFinn Thain //
57f86c765SFinn Thain // Copyright (C) 2017 Finn Thain
67f86c765SFinn Thain 
77f86c765SFinn Thain #include <linux/device.h>
8a8c5cb99SFinn Thain #include <linux/dma-mapping.h>
97f86c765SFinn Thain #include <linux/list.h>
107f86c765SFinn Thain #include <linux/nubus.h>
117f86c765SFinn Thain #include <linux/seq_file.h>
127f86c765SFinn Thain #include <linux/slab.h>
137f86c765SFinn Thain 
147f86c765SFinn Thain #define to_nubus_board(d)       container_of(d, struct nubus_board, dev)
157f86c765SFinn Thain #define to_nubus_driver(d)      container_of(d, struct nubus_driver, driver)
167f86c765SFinn Thain 
nubus_device_probe(struct device * dev)177f86c765SFinn Thain static int nubus_device_probe(struct device *dev)
187f86c765SFinn Thain {
197f86c765SFinn Thain 	struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
207f86c765SFinn Thain 	int err = -ENODEV;
217f86c765SFinn Thain 
227f86c765SFinn Thain 	if (ndrv->probe)
237f86c765SFinn Thain 		err = ndrv->probe(to_nubus_board(dev));
247f86c765SFinn Thain 	return err;
257f86c765SFinn Thain }
267f86c765SFinn Thain 
nubus_device_remove(struct device * dev)27fc7a6209SUwe Kleine-König static void nubus_device_remove(struct device *dev)
287f86c765SFinn Thain {
297f86c765SFinn Thain 	struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
307f86c765SFinn Thain 
31*f52c9ccbSUwe Kleine-König 	if (ndrv->remove)
32fc7a6209SUwe Kleine-König 		ndrv->remove(to_nubus_board(dev));
337f86c765SFinn Thain }
347f86c765SFinn Thain 
357f86c765SFinn Thain struct bus_type nubus_bus_type = {
367f86c765SFinn Thain 	.name		= "nubus",
377f86c765SFinn Thain 	.probe		= nubus_device_probe,
387f86c765SFinn Thain 	.remove		= nubus_device_remove,
397f86c765SFinn Thain };
407f86c765SFinn Thain EXPORT_SYMBOL(nubus_bus_type);
417f86c765SFinn Thain 
nubus_driver_register(struct nubus_driver * ndrv)427f86c765SFinn Thain int nubus_driver_register(struct nubus_driver *ndrv)
437f86c765SFinn Thain {
447f86c765SFinn Thain 	ndrv->driver.bus = &nubus_bus_type;
457f86c765SFinn Thain 	return driver_register(&ndrv->driver);
467f86c765SFinn Thain }
477f86c765SFinn Thain EXPORT_SYMBOL(nubus_driver_register);
487f86c765SFinn Thain 
nubus_driver_unregister(struct nubus_driver * ndrv)497f86c765SFinn Thain void nubus_driver_unregister(struct nubus_driver *ndrv)
507f86c765SFinn Thain {
517f86c765SFinn Thain 	driver_unregister(&ndrv->driver);
527f86c765SFinn Thain }
537f86c765SFinn Thain EXPORT_SYMBOL(nubus_driver_unregister);
547f86c765SFinn Thain 
557f86c765SFinn Thain static struct device nubus_parent = {
567f86c765SFinn Thain 	.init_name	= "nubus",
577f86c765SFinn Thain };
587f86c765SFinn Thain 
nubus_bus_register(void)59bdeeed09SFinn Thain static int __init nubus_bus_register(void)
607f86c765SFinn Thain {
61bdeeed09SFinn Thain 	return bus_register(&nubus_bus_type);
62bdeeed09SFinn Thain }
63bdeeed09SFinn Thain postcore_initcall(nubus_bus_register);
647f86c765SFinn Thain 
nubus_parent_device_register(void)65bdeeed09SFinn Thain int __init nubus_parent_device_register(void)
66bdeeed09SFinn Thain {
67bdeeed09SFinn Thain 	return device_register(&nubus_parent);
687f86c765SFinn Thain }
697f86c765SFinn Thain 
nubus_device_release(struct device * dev)707f86c765SFinn Thain static void nubus_device_release(struct device *dev)
717f86c765SFinn Thain {
727f86c765SFinn Thain 	struct nubus_board *board = to_nubus_board(dev);
737f86c765SFinn Thain 	struct nubus_rsrc *fres, *tmp;
747f86c765SFinn Thain 
757f86c765SFinn Thain 	list_for_each_entry_safe(fres, tmp, &nubus_func_rsrcs, list)
767f86c765SFinn Thain 		if (fres->board == board) {
777f86c765SFinn Thain 			list_del(&fres->list);
787f86c765SFinn Thain 			kfree(fres);
797f86c765SFinn Thain 		}
807f86c765SFinn Thain 	kfree(board);
817f86c765SFinn Thain }
827f86c765SFinn Thain 
nubus_device_register(struct nubus_board * board)837f86c765SFinn Thain int nubus_device_register(struct nubus_board *board)
847f86c765SFinn Thain {
857f86c765SFinn Thain 	board->dev.parent = &nubus_parent;
867f86c765SFinn Thain 	board->dev.release = nubus_device_release;
877f86c765SFinn Thain 	board->dev.bus = &nubus_bus_type;
887f86c765SFinn Thain 	dev_set_name(&board->dev, "slot.%X", board->slot);
89a8c5cb99SFinn Thain 	board->dev.dma_mask = &board->dev.coherent_dma_mask;
90a8c5cb99SFinn Thain 	dma_set_mask(&board->dev, DMA_BIT_MASK(32));
917f86c765SFinn Thain 	return device_register(&board->dev);
927f86c765SFinn Thain }
937f86c765SFinn Thain 
nubus_print_device_name_fn(struct device * dev,void * data)947f86c765SFinn Thain static int nubus_print_device_name_fn(struct device *dev, void *data)
957f86c765SFinn Thain {
967f86c765SFinn Thain 	struct nubus_board *board = to_nubus_board(dev);
977f86c765SFinn Thain 	struct seq_file *m = data;
987f86c765SFinn Thain 
997f86c765SFinn Thain 	seq_printf(m, "Slot %X: %s\n", board->slot, board->name);
1007f86c765SFinn Thain 	return 0;
1017f86c765SFinn Thain }
1027f86c765SFinn Thain 
nubus_proc_show(struct seq_file * m,void * data)1037f86c765SFinn Thain int nubus_proc_show(struct seq_file *m, void *data)
1047f86c765SFinn Thain {
1057f86c765SFinn Thain 	return bus_for_each_dev(&nubus_bus_type, NULL, m,
1067f86c765SFinn Thain 				nubus_print_device_name_fn);
1077f86c765SFinn Thain }
108