xref: /openbmc/linux/drivers/bcma/main.c (revision 200351c7)
18369ae33SRafał Miłecki /*
28369ae33SRafał Miłecki  * Broadcom specific AMBA
38369ae33SRafał Miłecki  * Bus subsystem
48369ae33SRafał Miłecki  *
58369ae33SRafał Miłecki  * Licensed under the GNU/GPL. See COPYING for details.
68369ae33SRafał Miłecki  */
78369ae33SRafał Miłecki 
88369ae33SRafał Miłecki #include "bcma_private.h"
9200351c7SPaul Gortmaker #include <linux/module.h>
108369ae33SRafał Miłecki #include <linux/bcma/bcma.h>
11eef72699SGeert Uytterhoeven #include <linux/slab.h>
128369ae33SRafał Miłecki 
138369ae33SRafał Miłecki MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
148369ae33SRafał Miłecki MODULE_LICENSE("GPL");
158369ae33SRafał Miłecki 
168369ae33SRafał Miłecki static int bcma_bus_match(struct device *dev, struct device_driver *drv);
178369ae33SRafał Miłecki static int bcma_device_probe(struct device *dev);
188369ae33SRafał Miłecki static int bcma_device_remove(struct device *dev);
19886b66efSDavid Woodhouse static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
208369ae33SRafał Miłecki 
218369ae33SRafał Miłecki static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
228369ae33SRafał Miłecki {
238369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
248369ae33SRafał Miłecki 	return sprintf(buf, "0x%03X\n", core->id.manuf);
258369ae33SRafał Miłecki }
268369ae33SRafał Miłecki static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
278369ae33SRafał Miłecki {
288369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
298369ae33SRafał Miłecki 	return sprintf(buf, "0x%03X\n", core->id.id);
308369ae33SRafał Miłecki }
318369ae33SRafał Miłecki static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
328369ae33SRafał Miłecki {
338369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
348369ae33SRafał Miłecki 	return sprintf(buf, "0x%02X\n", core->id.rev);
358369ae33SRafał Miłecki }
368369ae33SRafał Miłecki static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
378369ae33SRafał Miłecki {
388369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
398369ae33SRafał Miłecki 	return sprintf(buf, "0x%X\n", core->id.class);
408369ae33SRafał Miłecki }
418369ae33SRafał Miłecki static struct device_attribute bcma_device_attrs[] = {
428369ae33SRafał Miłecki 	__ATTR_RO(manuf),
438369ae33SRafał Miłecki 	__ATTR_RO(id),
448369ae33SRafał Miłecki 	__ATTR_RO(rev),
458369ae33SRafał Miłecki 	__ATTR_RO(class),
468369ae33SRafał Miłecki 	__ATTR_NULL,
478369ae33SRafał Miłecki };
488369ae33SRafał Miłecki 
498369ae33SRafał Miłecki static struct bus_type bcma_bus_type = {
508369ae33SRafał Miłecki 	.name		= "bcma",
518369ae33SRafał Miłecki 	.match		= bcma_bus_match,
528369ae33SRafał Miłecki 	.probe		= bcma_device_probe,
538369ae33SRafał Miłecki 	.remove		= bcma_device_remove,
54886b66efSDavid Woodhouse 	.uevent		= bcma_device_uevent,
558369ae33SRafał Miłecki 	.dev_attrs	= bcma_device_attrs,
568369ae33SRafał Miłecki };
578369ae33SRafał Miłecki 
588369ae33SRafał Miłecki static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
598369ae33SRafał Miłecki {
608369ae33SRafał Miłecki 	struct bcma_device *core;
618369ae33SRafał Miłecki 
628369ae33SRafał Miłecki 	list_for_each_entry(core, &bus->cores, list) {
638369ae33SRafał Miłecki 		if (core->id.id == coreid)
648369ae33SRafał Miłecki 			return core;
658369ae33SRafał Miłecki 	}
668369ae33SRafał Miłecki 	return NULL;
678369ae33SRafał Miłecki }
688369ae33SRafał Miłecki 
698369ae33SRafał Miłecki static void bcma_release_core_dev(struct device *dev)
708369ae33SRafał Miłecki {
718369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
72ecd177c2SHauke Mehrtens 	if (core->io_addr)
73ecd177c2SHauke Mehrtens 		iounmap(core->io_addr);
74ecd177c2SHauke Mehrtens 	if (core->io_wrap)
75ecd177c2SHauke Mehrtens 		iounmap(core->io_wrap);
768369ae33SRafał Miłecki 	kfree(core);
778369ae33SRafał Miłecki }
788369ae33SRafał Miłecki 
798369ae33SRafał Miłecki static int bcma_register_cores(struct bcma_bus *bus)
808369ae33SRafał Miłecki {
818369ae33SRafał Miłecki 	struct bcma_device *core;
828369ae33SRafał Miłecki 	int err, dev_id = 0;
838369ae33SRafał Miłecki 
848369ae33SRafał Miłecki 	list_for_each_entry(core, &bus->cores, list) {
858369ae33SRafał Miłecki 		/* We support that cores ourself */
868369ae33SRafał Miłecki 		switch (core->id.id) {
878369ae33SRafał Miłecki 		case BCMA_CORE_CHIPCOMMON:
888369ae33SRafał Miłecki 		case BCMA_CORE_PCI:
898369ae33SRafał Miłecki 		case BCMA_CORE_PCIE:
9021e0534aSHauke Mehrtens 		case BCMA_CORE_MIPS_74K:
918369ae33SRafał Miłecki 			continue;
928369ae33SRafał Miłecki 		}
938369ae33SRafał Miłecki 
948369ae33SRafał Miłecki 		core->dev.release = bcma_release_core_dev;
958369ae33SRafał Miłecki 		core->dev.bus = &bcma_bus_type;
968369ae33SRafał Miłecki 		dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
978369ae33SRafał Miłecki 
988369ae33SRafał Miłecki 		switch (bus->hosttype) {
998369ae33SRafał Miłecki 		case BCMA_HOSTTYPE_PCI:
1008369ae33SRafał Miłecki 			core->dev.parent = &bus->host_pci->dev;
1011bdcd095SRafał Miłecki 			core->dma_dev = &bus->host_pci->dev;
1021bdcd095SRafał Miłecki 			core->irq = bus->host_pci->irq;
1038369ae33SRafał Miłecki 			break;
104ecd177c2SHauke Mehrtens 		case BCMA_HOSTTYPE_SOC:
105ecd177c2SHauke Mehrtens 			core->dev.dma_mask = &core->dev.coherent_dma_mask;
106ecd177c2SHauke Mehrtens 			core->dma_dev = &core->dev;
107ecd177c2SHauke Mehrtens 			break;
1088369ae33SRafał Miłecki 		case BCMA_HOSTTYPE_SDIO:
1098369ae33SRafał Miłecki 			break;
1108369ae33SRafał Miłecki 		}
1118369ae33SRafał Miłecki 
1128369ae33SRafał Miłecki 		err = device_register(&core->dev);
1138369ae33SRafał Miłecki 		if (err) {
1148369ae33SRafał Miłecki 			pr_err("Could not register dev for core 0x%03X\n",
1158369ae33SRafał Miłecki 			       core->id.id);
1168369ae33SRafał Miłecki 			continue;
1178369ae33SRafał Miłecki 		}
1188369ae33SRafał Miłecki 		core->dev_registered = true;
1198369ae33SRafał Miłecki 		dev_id++;
1208369ae33SRafał Miłecki 	}
1218369ae33SRafał Miłecki 
1228369ae33SRafał Miłecki 	return 0;
1238369ae33SRafał Miłecki }
1248369ae33SRafał Miłecki 
1258369ae33SRafał Miłecki static void bcma_unregister_cores(struct bcma_bus *bus)
1268369ae33SRafał Miłecki {
1278369ae33SRafał Miłecki 	struct bcma_device *core;
1288369ae33SRafał Miłecki 
1298369ae33SRafał Miłecki 	list_for_each_entry(core, &bus->cores, list) {
1308369ae33SRafał Miłecki 		if (core->dev_registered)
1318369ae33SRafał Miłecki 			device_unregister(&core->dev);
1328369ae33SRafał Miłecki 	}
1338369ae33SRafał Miłecki }
1348369ae33SRafał Miłecki 
1358369ae33SRafał Miłecki int bcma_bus_register(struct bcma_bus *bus)
1368369ae33SRafał Miłecki {
1378369ae33SRafał Miłecki 	int err;
1388369ae33SRafał Miłecki 	struct bcma_device *core;
1398369ae33SRafał Miłecki 
1408369ae33SRafał Miłecki 	/* Scan for devices (cores) */
1418369ae33SRafał Miłecki 	err = bcma_bus_scan(bus);
1428369ae33SRafał Miłecki 	if (err) {
1438369ae33SRafał Miłecki 		pr_err("Failed to scan: %d\n", err);
1448369ae33SRafał Miłecki 		return -1;
1458369ae33SRafał Miłecki 	}
1468369ae33SRafał Miłecki 
1478369ae33SRafał Miłecki 	/* Init CC core */
1488369ae33SRafał Miłecki 	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
1498369ae33SRafał Miłecki 	if (core) {
1508369ae33SRafał Miłecki 		bus->drv_cc.core = core;
1518369ae33SRafał Miłecki 		bcma_core_chipcommon_init(&bus->drv_cc);
1528369ae33SRafał Miłecki 	}
1538369ae33SRafał Miłecki 
15421e0534aSHauke Mehrtens 	/* Init MIPS core */
15521e0534aSHauke Mehrtens 	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
15621e0534aSHauke Mehrtens 	if (core) {
15721e0534aSHauke Mehrtens 		bus->drv_mips.core = core;
15821e0534aSHauke Mehrtens 		bcma_core_mips_init(&bus->drv_mips);
15921e0534aSHauke Mehrtens 	}
16021e0534aSHauke Mehrtens 
1618369ae33SRafał Miłecki 	/* Init PCIE core */
1628369ae33SRafał Miłecki 	core = bcma_find_core(bus, BCMA_CORE_PCIE);
1638369ae33SRafał Miłecki 	if (core) {
1648369ae33SRafał Miłecki 		bus->drv_pci.core = core;
1658369ae33SRafał Miłecki 		bcma_core_pci_init(&bus->drv_pci);
1668369ae33SRafał Miłecki 	}
1678369ae33SRafał Miłecki 
16827f18dc2SRafał Miłecki 	/* Try to get SPROM */
16927f18dc2SRafał Miłecki 	err = bcma_sprom_get(bus);
170534e7a45SHauke Mehrtens 	if (err == -ENOENT) {
171534e7a45SHauke Mehrtens 		pr_err("No SPROM available\n");
172534e7a45SHauke Mehrtens 	} else if (err) {
17327f18dc2SRafał Miłecki 		pr_err("Failed to get SPROM: %d\n", err);
17427f18dc2SRafał Miłecki 		return -ENOENT;
17527f18dc2SRafał Miłecki 	}
17627f18dc2SRafał Miłecki 
1778369ae33SRafał Miłecki 	/* Register found cores */
1788369ae33SRafał Miłecki 	bcma_register_cores(bus);
1798369ae33SRafał Miłecki 
1808369ae33SRafał Miłecki 	pr_info("Bus registered\n");
1818369ae33SRafał Miłecki 
1828369ae33SRafał Miłecki 	return 0;
1838369ae33SRafał Miłecki }
1848369ae33SRafał Miłecki 
1858369ae33SRafał Miłecki void bcma_bus_unregister(struct bcma_bus *bus)
1868369ae33SRafał Miłecki {
1878369ae33SRafał Miłecki 	bcma_unregister_cores(bus);
1888369ae33SRafał Miłecki }
1898369ae33SRafał Miłecki 
190517f43e5SHauke Mehrtens int __init bcma_bus_early_register(struct bcma_bus *bus,
191517f43e5SHauke Mehrtens 				   struct bcma_device *core_cc,
192517f43e5SHauke Mehrtens 				   struct bcma_device *core_mips)
193517f43e5SHauke Mehrtens {
194517f43e5SHauke Mehrtens 	int err;
195517f43e5SHauke Mehrtens 	struct bcma_device *core;
196517f43e5SHauke Mehrtens 	struct bcma_device_id match;
197517f43e5SHauke Mehrtens 
198517f43e5SHauke Mehrtens 	bcma_init_bus(bus);
199517f43e5SHauke Mehrtens 
200517f43e5SHauke Mehrtens 	match.manuf = BCMA_MANUF_BCM;
201517f43e5SHauke Mehrtens 	match.id = BCMA_CORE_CHIPCOMMON;
202517f43e5SHauke Mehrtens 	match.class = BCMA_CL_SIM;
203517f43e5SHauke Mehrtens 	match.rev = BCMA_ANY_REV;
204517f43e5SHauke Mehrtens 
205517f43e5SHauke Mehrtens 	/* Scan for chip common core */
206517f43e5SHauke Mehrtens 	err = bcma_bus_scan_early(bus, &match, core_cc);
207517f43e5SHauke Mehrtens 	if (err) {
208517f43e5SHauke Mehrtens 		pr_err("Failed to scan for common core: %d\n", err);
209517f43e5SHauke Mehrtens 		return -1;
210517f43e5SHauke Mehrtens 	}
211517f43e5SHauke Mehrtens 
212517f43e5SHauke Mehrtens 	match.manuf = BCMA_MANUF_MIPS;
213517f43e5SHauke Mehrtens 	match.id = BCMA_CORE_MIPS_74K;
214517f43e5SHauke Mehrtens 	match.class = BCMA_CL_SIM;
215517f43e5SHauke Mehrtens 	match.rev = BCMA_ANY_REV;
216517f43e5SHauke Mehrtens 
217517f43e5SHauke Mehrtens 	/* Scan for mips core */
218517f43e5SHauke Mehrtens 	err = bcma_bus_scan_early(bus, &match, core_mips);
219517f43e5SHauke Mehrtens 	if (err) {
220517f43e5SHauke Mehrtens 		pr_err("Failed to scan for mips core: %d\n", err);
221517f43e5SHauke Mehrtens 		return -1;
222517f43e5SHauke Mehrtens 	}
223517f43e5SHauke Mehrtens 
224517f43e5SHauke Mehrtens 	/* Init CC core */
225517f43e5SHauke Mehrtens 	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
226517f43e5SHauke Mehrtens 	if (core) {
227517f43e5SHauke Mehrtens 		bus->drv_cc.core = core;
228517f43e5SHauke Mehrtens 		bcma_core_chipcommon_init(&bus->drv_cc);
229517f43e5SHauke Mehrtens 	}
230517f43e5SHauke Mehrtens 
23121e0534aSHauke Mehrtens 	/* Init MIPS core */
23221e0534aSHauke Mehrtens 	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
23321e0534aSHauke Mehrtens 	if (core) {
23421e0534aSHauke Mehrtens 		bus->drv_mips.core = core;
23521e0534aSHauke Mehrtens 		bcma_core_mips_init(&bus->drv_mips);
23621e0534aSHauke Mehrtens 	}
23721e0534aSHauke Mehrtens 
238517f43e5SHauke Mehrtens 	pr_info("Early bus registered\n");
239517f43e5SHauke Mehrtens 
240517f43e5SHauke Mehrtens 	return 0;
241517f43e5SHauke Mehrtens }
242517f43e5SHauke Mehrtens 
2438369ae33SRafał Miłecki int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
2448369ae33SRafał Miłecki {
2458369ae33SRafał Miłecki 	drv->drv.name = drv->name;
2468369ae33SRafał Miłecki 	drv->drv.bus = &bcma_bus_type;
2478369ae33SRafał Miłecki 	drv->drv.owner = owner;
2488369ae33SRafał Miłecki 
2498369ae33SRafał Miłecki 	return driver_register(&drv->drv);
2508369ae33SRafał Miłecki }
2518369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(__bcma_driver_register);
2528369ae33SRafał Miłecki 
2538369ae33SRafał Miłecki void bcma_driver_unregister(struct bcma_driver *drv)
2548369ae33SRafał Miłecki {
2558369ae33SRafał Miłecki 	driver_unregister(&drv->drv);
2568369ae33SRafał Miłecki }
2578369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(bcma_driver_unregister);
2588369ae33SRafał Miłecki 
2598369ae33SRafał Miłecki static int bcma_bus_match(struct device *dev, struct device_driver *drv)
2608369ae33SRafał Miłecki {
2618369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
2628369ae33SRafał Miłecki 	struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
2638369ae33SRafał Miłecki 	const struct bcma_device_id *cid = &core->id;
2648369ae33SRafał Miłecki 	const struct bcma_device_id *did;
2658369ae33SRafał Miłecki 
2668369ae33SRafał Miłecki 	for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
2678369ae33SRafał Miłecki 	    if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
2688369ae33SRafał Miłecki 		(did->id == cid->id || did->id == BCMA_ANY_ID) &&
2698369ae33SRafał Miłecki 		(did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
2708369ae33SRafał Miłecki 		(did->class == cid->class || did->class == BCMA_ANY_CLASS))
2718369ae33SRafał Miłecki 			return 1;
2728369ae33SRafał Miłecki 	}
2738369ae33SRafał Miłecki 	return 0;
2748369ae33SRafał Miłecki }
2758369ae33SRafał Miłecki 
2768369ae33SRafał Miłecki static int bcma_device_probe(struct device *dev)
2778369ae33SRafał Miłecki {
2788369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
2798369ae33SRafał Miłecki 	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
2808369ae33SRafał Miłecki 					       drv);
2818369ae33SRafał Miłecki 	int err = 0;
2828369ae33SRafał Miłecki 
2838369ae33SRafał Miłecki 	if (adrv->probe)
2848369ae33SRafał Miłecki 		err = adrv->probe(core);
2858369ae33SRafał Miłecki 
2868369ae33SRafał Miłecki 	return err;
2878369ae33SRafał Miłecki }
2888369ae33SRafał Miłecki 
2898369ae33SRafał Miłecki static int bcma_device_remove(struct device *dev)
2908369ae33SRafał Miłecki {
2918369ae33SRafał Miłecki 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
2928369ae33SRafał Miłecki 	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
2938369ae33SRafał Miłecki 					       drv);
2948369ae33SRafał Miłecki 
2958369ae33SRafał Miłecki 	if (adrv->remove)
2968369ae33SRafał Miłecki 		adrv->remove(core);
2978369ae33SRafał Miłecki 
2988369ae33SRafał Miłecki 	return 0;
2998369ae33SRafał Miłecki }
3008369ae33SRafał Miłecki 
301886b66efSDavid Woodhouse static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
302886b66efSDavid Woodhouse {
303886b66efSDavid Woodhouse 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
304886b66efSDavid Woodhouse 
305886b66efSDavid Woodhouse 	return add_uevent_var(env,
306886b66efSDavid Woodhouse 			      "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
307886b66efSDavid Woodhouse 			      core->id.manuf, core->id.id,
308886b66efSDavid Woodhouse 			      core->id.rev, core->id.class);
309886b66efSDavid Woodhouse }
310886b66efSDavid Woodhouse 
3118369ae33SRafał Miłecki static int __init bcma_modinit(void)
3128369ae33SRafał Miłecki {
3138369ae33SRafał Miłecki 	int err;
3148369ae33SRafał Miłecki 
3158369ae33SRafał Miłecki 	err = bus_register(&bcma_bus_type);
3168369ae33SRafał Miłecki 	if (err)
3178369ae33SRafał Miłecki 		return err;
3188369ae33SRafał Miłecki 
3198369ae33SRafał Miłecki #ifdef CONFIG_BCMA_HOST_PCI
3208369ae33SRafał Miłecki 	err = bcma_host_pci_init();
3218369ae33SRafał Miłecki 	if (err) {
3228369ae33SRafał Miłecki 		pr_err("PCI host initialization failed\n");
3238369ae33SRafał Miłecki 		err = 0;
3248369ae33SRafał Miłecki 	}
3258369ae33SRafał Miłecki #endif
3268369ae33SRafał Miłecki 
3278369ae33SRafał Miłecki 	return err;
3288369ae33SRafał Miłecki }
3298369ae33SRafał Miłecki fs_initcall(bcma_modinit);
3308369ae33SRafał Miłecki 
3318369ae33SRafał Miłecki static void __exit bcma_modexit(void)
3328369ae33SRafał Miłecki {
3338369ae33SRafał Miłecki #ifdef CONFIG_BCMA_HOST_PCI
3348369ae33SRafał Miłecki 	bcma_host_pci_exit();
3358369ae33SRafał Miłecki #endif
3368369ae33SRafał Miłecki 	bus_unregister(&bcma_bus_type);
3378369ae33SRafał Miłecki }
3388369ae33SRafał Miłecki module_exit(bcma_modexit)
339