blob: a59b6c4bb5b89444139ae3907deb73c9947147d0 [file] [log] [blame]
Finn Thain7f86c762018-01-13 17:37:14 -05001// SPDX-License-Identifier: GPL-2.0
2//
3// Bus implementation for the NuBus subsystem.
4//
5// Copyright (C) 2017 Finn Thain
6
7#include <linux/device.h>
8#include <linux/list.h>
9#include <linux/nubus.h>
10#include <linux/seq_file.h>
11#include <linux/slab.h>
12
13#define to_nubus_board(d) container_of(d, struct nubus_board, dev)
14#define to_nubus_driver(d) container_of(d, struct nubus_driver, driver)
15
16static int nubus_bus_match(struct device *dev, struct device_driver *driver)
17{
18 return 1;
19}
20
21static int nubus_device_probe(struct device *dev)
22{
23 struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
24 int err = -ENODEV;
25
26 if (ndrv->probe)
27 err = ndrv->probe(to_nubus_board(dev));
28 return err;
29}
30
31static int nubus_device_remove(struct device *dev)
32{
33 struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
34 int err = -ENODEV;
35
36 if (dev->driver && ndrv->remove)
37 err = ndrv->remove(to_nubus_board(dev));
38 return err;
39}
40
41struct bus_type nubus_bus_type = {
42 .name = "nubus",
43 .match = nubus_bus_match,
44 .probe = nubus_device_probe,
45 .remove = nubus_device_remove,
46};
47EXPORT_SYMBOL(nubus_bus_type);
48
49int nubus_driver_register(struct nubus_driver *ndrv)
50{
51 ndrv->driver.bus = &nubus_bus_type;
52 return driver_register(&ndrv->driver);
53}
54EXPORT_SYMBOL(nubus_driver_register);
55
56void nubus_driver_unregister(struct nubus_driver *ndrv)
57{
58 driver_unregister(&ndrv->driver);
59}
60EXPORT_SYMBOL(nubus_driver_unregister);
61
62static struct device nubus_parent = {
63 .init_name = "nubus",
64};
65
Finn Thainbdeeed02018-05-09 11:04:48 +100066static int __init nubus_bus_register(void)
Finn Thain7f86c762018-01-13 17:37:14 -050067{
Finn Thainbdeeed02018-05-09 11:04:48 +100068 return bus_register(&nubus_bus_type);
69}
70postcore_initcall(nubus_bus_register);
Finn Thain7f86c762018-01-13 17:37:14 -050071
Finn Thainbdeeed02018-05-09 11:04:48 +100072int __init nubus_parent_device_register(void)
73{
74 return device_register(&nubus_parent);
Finn Thain7f86c762018-01-13 17:37:14 -050075}
76
77static void nubus_device_release(struct device *dev)
78{
79 struct nubus_board *board = to_nubus_board(dev);
80 struct nubus_rsrc *fres, *tmp;
81
82 list_for_each_entry_safe(fres, tmp, &nubus_func_rsrcs, list)
83 if (fres->board == board) {
84 list_del(&fres->list);
85 kfree(fres);
86 }
87 kfree(board);
88}
89
90int nubus_device_register(struct nubus_board *board)
91{
92 board->dev.parent = &nubus_parent;
93 board->dev.release = nubus_device_release;
94 board->dev.bus = &nubus_bus_type;
95 dev_set_name(&board->dev, "slot.%X", board->slot);
96 return device_register(&board->dev);
97}
98
99static int nubus_print_device_name_fn(struct device *dev, void *data)
100{
101 struct nubus_board *board = to_nubus_board(dev);
102 struct seq_file *m = data;
103
104 seq_printf(m, "Slot %X: %s\n", board->slot, board->name);
105 return 0;
106}
107
108int nubus_proc_show(struct seq_file *m, void *data)
109{
110 return bus_for_each_dev(&nubus_bus_type, NULL, m,
111 nubus_print_device_name_fn);
112}