xref: /openbmc/linux/drivers/ssb/main.c (revision 26d0dfbb16fcb17d128a79dc70f3020ea6992af0)
161e115a5SMichael Buesch /*
261e115a5SMichael Buesch  * Sonics Silicon Backplane
361e115a5SMichael Buesch  * Subsystem core
461e115a5SMichael Buesch  *
561e115a5SMichael Buesch  * Copyright 2005, Broadcom Corporation
6eb032b98SMichael Büsch  * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
761e115a5SMichael Buesch  *
861e115a5SMichael Buesch  * Licensed under the GNU/GPL. See COPYING for details.
961e115a5SMichael Buesch  */
1061e115a5SMichael Buesch 
1161e115a5SMichael Buesch #include "ssb_private.h"
1261e115a5SMichael Buesch 
1361e115a5SMichael Buesch #include <linux/delay.h>
146faf035cSGeert Uytterhoeven #include <linux/io.h>
1520a112d0SPaul Gortmaker #include <linux/module.h>
16bde327efSHauke Mehrtens #include <linux/platform_device.h>
1761e115a5SMichael Buesch #include <linux/ssb/ssb.h>
1861e115a5SMichael Buesch #include <linux/ssb/ssb_regs.h>
19aab547ceSMichael Buesch #include <linux/ssb/ssb_driver_gige.h>
2061e115a5SMichael Buesch #include <linux/dma-mapping.h>
2161e115a5SMichael Buesch #include <linux/pci.h>
2224ea602eSAlbert Herranz #include <linux/mmc/sdio_func.h>
235a0e3ad6STejun Heo #include <linux/slab.h>
2461e115a5SMichael Buesch 
2561e115a5SMichael Buesch #include <pcmcia/cistpl.h>
2661e115a5SMichael Buesch #include <pcmcia/ds.h>
2761e115a5SMichael Buesch 
2861e115a5SMichael Buesch 
2961e115a5SMichael Buesch MODULE_DESCRIPTION("Sonics Silicon Backplane driver");
3061e115a5SMichael Buesch MODULE_LICENSE("GPL");
3161e115a5SMichael Buesch 
3261e115a5SMichael Buesch 
3361e115a5SMichael Buesch /* Temporary list of yet-to-be-attached buses */
3461e115a5SMichael Buesch static LIST_HEAD(attach_queue);
3561e115a5SMichael Buesch /* List if running buses */
3661e115a5SMichael Buesch static LIST_HEAD(buses);
3761e115a5SMichael Buesch /* Software ID counter */
3861e115a5SMichael Buesch static unsigned int next_busnumber;
3961e115a5SMichael Buesch /* buses_mutes locks the two buslists and the next_busnumber.
40f3028212SShubhankar Kuranagatti  * Don't lock this directly, but use ssb_buses_[un]lock() below.
41f3028212SShubhankar Kuranagatti  */
4261e115a5SMichael Buesch static DEFINE_MUTEX(buses_mutex);
4361e115a5SMichael Buesch 
4461e115a5SMichael Buesch /* There are differences in the codeflow, if the bus is
4561e115a5SMichael Buesch  * initialized from early boot, as various needed services
4661e115a5SMichael Buesch  * are not available early. This is a mechanism to delay
4761e115a5SMichael Buesch  * these initializations to after early boot has finished.
4861e115a5SMichael Buesch  * It's also used to avoid mutex locking, as that's not
49f3028212SShubhankar Kuranagatti  * available and needed early.
50f3028212SShubhankar Kuranagatti  */
5161e115a5SMichael Buesch static bool ssb_is_early_boot = 1;
5261e115a5SMichael Buesch 
5361e115a5SMichael Buesch static void ssb_buses_lock(void);
5461e115a5SMichael Buesch static void ssb_buses_unlock(void);
5561e115a5SMichael Buesch 
5661e115a5SMichael Buesch 
5761e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST
ssb_pci_dev_to_bus(struct pci_dev * pdev)5861e115a5SMichael Buesch struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev)
5961e115a5SMichael Buesch {
6061e115a5SMichael Buesch 	struct ssb_bus *bus;
6161e115a5SMichael Buesch 
6261e115a5SMichael Buesch 	ssb_buses_lock();
6361e115a5SMichael Buesch 	list_for_each_entry(bus, &buses, list) {
6461e115a5SMichael Buesch 		if (bus->bustype == SSB_BUSTYPE_PCI &&
6561e115a5SMichael Buesch 		    bus->host_pci == pdev)
6661e115a5SMichael Buesch 			goto found;
6761e115a5SMichael Buesch 	}
6861e115a5SMichael Buesch 	bus = NULL;
6961e115a5SMichael Buesch found:
7061e115a5SMichael Buesch 	ssb_buses_unlock();
7161e115a5SMichael Buesch 
7261e115a5SMichael Buesch 	return bus;
7361e115a5SMichael Buesch }
7461e115a5SMichael Buesch #endif /* CONFIG_SSB_PCIHOST */
7561e115a5SMichael Buesch 
76e7ec2e32SMichael Buesch #ifdef CONFIG_SSB_PCMCIAHOST
ssb_pcmcia_dev_to_bus(struct pcmcia_device * pdev)77e7ec2e32SMichael Buesch struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev)
78e7ec2e32SMichael Buesch {
79e7ec2e32SMichael Buesch 	struct ssb_bus *bus;
80e7ec2e32SMichael Buesch 
81e7ec2e32SMichael Buesch 	ssb_buses_lock();
82e7ec2e32SMichael Buesch 	list_for_each_entry(bus, &buses, list) {
83e7ec2e32SMichael Buesch 		if (bus->bustype == SSB_BUSTYPE_PCMCIA &&
84e7ec2e32SMichael Buesch 		    bus->host_pcmcia == pdev)
85e7ec2e32SMichael Buesch 			goto found;
86e7ec2e32SMichael Buesch 	}
87e7ec2e32SMichael Buesch 	bus = NULL;
88e7ec2e32SMichael Buesch found:
89e7ec2e32SMichael Buesch 	ssb_buses_unlock();
90e7ec2e32SMichael Buesch 
91e7ec2e32SMichael Buesch 	return bus;
92e7ec2e32SMichael Buesch }
93e7ec2e32SMichael Buesch #endif /* CONFIG_SSB_PCMCIAHOST */
94e7ec2e32SMichael Buesch 
ssb_for_each_bus_call(unsigned long data,int (* func)(struct ssb_bus * bus,unsigned long data))95aab547ceSMichael Buesch int ssb_for_each_bus_call(unsigned long data,
96aab547ceSMichael Buesch 			  int (*func)(struct ssb_bus *bus, unsigned long data))
97aab547ceSMichael Buesch {
98aab547ceSMichael Buesch 	struct ssb_bus *bus;
99aab547ceSMichael Buesch 	int res;
100aab547ceSMichael Buesch 
101aab547ceSMichael Buesch 	ssb_buses_lock();
102aab547ceSMichael Buesch 	list_for_each_entry(bus, &buses, list) {
103aab547ceSMichael Buesch 		res = func(bus, data);
104aab547ceSMichael Buesch 		if (res >= 0) {
105aab547ceSMichael Buesch 			ssb_buses_unlock();
106aab547ceSMichael Buesch 			return res;
107aab547ceSMichael Buesch 		}
108aab547ceSMichael Buesch 	}
109aab547ceSMichael Buesch 	ssb_buses_unlock();
110aab547ceSMichael Buesch 
111aab547ceSMichael Buesch 	return -ENODEV;
112aab547ceSMichael Buesch }
113aab547ceSMichael Buesch 
ssb_device_get(struct ssb_device * dev)11461e115a5SMichael Buesch static struct ssb_device *ssb_device_get(struct ssb_device *dev)
11561e115a5SMichael Buesch {
11661e115a5SMichael Buesch 	if (dev)
11761e115a5SMichael Buesch 		get_device(dev->dev);
11861e115a5SMichael Buesch 	return dev;
11961e115a5SMichael Buesch }
12061e115a5SMichael Buesch 
ssb_device_put(struct ssb_device * dev)12161e115a5SMichael Buesch static void ssb_device_put(struct ssb_device *dev)
12261e115a5SMichael Buesch {
12361e115a5SMichael Buesch 	if (dev)
12461e115a5SMichael Buesch 		put_device(dev->dev);
12561e115a5SMichael Buesch }
12661e115a5SMichael Buesch 
ssb_device_resume(struct device * dev)12761e115a5SMichael Buesch static int ssb_device_resume(struct device *dev)
12861e115a5SMichael Buesch {
12961e115a5SMichael Buesch 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
13061e115a5SMichael Buesch 	struct ssb_driver *ssb_drv;
13161e115a5SMichael Buesch 	int err = 0;
13261e115a5SMichael Buesch 
13361e115a5SMichael Buesch 	if (dev->driver) {
13461e115a5SMichael Buesch 		ssb_drv = drv_to_ssb_drv(dev->driver);
13561e115a5SMichael Buesch 		if (ssb_drv && ssb_drv->resume)
13661e115a5SMichael Buesch 			err = ssb_drv->resume(ssb_dev);
13761e115a5SMichael Buesch 		if (err)
13861e115a5SMichael Buesch 			goto out;
13961e115a5SMichael Buesch 	}
14061e115a5SMichael Buesch out:
14161e115a5SMichael Buesch 	return err;
14261e115a5SMichael Buesch }
14361e115a5SMichael Buesch 
ssb_device_suspend(struct device * dev,pm_message_t state)14461e115a5SMichael Buesch static int ssb_device_suspend(struct device *dev, pm_message_t state)
14561e115a5SMichael Buesch {
14661e115a5SMichael Buesch 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
14761e115a5SMichael Buesch 	struct ssb_driver *ssb_drv;
14861e115a5SMichael Buesch 	int err = 0;
14961e115a5SMichael Buesch 
15061e115a5SMichael Buesch 	if (dev->driver) {
15161e115a5SMichael Buesch 		ssb_drv = drv_to_ssb_drv(dev->driver);
15261e115a5SMichael Buesch 		if (ssb_drv && ssb_drv->suspend)
15361e115a5SMichael Buesch 			err = ssb_drv->suspend(ssb_dev, state);
15461e115a5SMichael Buesch 		if (err)
15561e115a5SMichael Buesch 			goto out;
15661e115a5SMichael Buesch 	}
15761e115a5SMichael Buesch out:
15861e115a5SMichael Buesch 	return err;
15961e115a5SMichael Buesch }
16061e115a5SMichael Buesch 
ssb_bus_resume(struct ssb_bus * bus)1618fe2b65aSMichael Buesch int ssb_bus_resume(struct ssb_bus *bus)
1628fe2b65aSMichael Buesch {
1638fe2b65aSMichael Buesch 	int err;
1648fe2b65aSMichael Buesch 
1658fe2b65aSMichael Buesch 	/* Reset HW state information in memory, so that HW is
166f3028212SShubhankar Kuranagatti 	 * completely reinitialized.
167f3028212SShubhankar Kuranagatti 	 */
1688fe2b65aSMichael Buesch 	bus->mapped_device = NULL;
1698fe2b65aSMichael Buesch #ifdef CONFIG_SSB_DRIVER_PCICORE
1708fe2b65aSMichael Buesch 	bus->pcicore.setup_done = 0;
1718fe2b65aSMichael Buesch #endif
1728fe2b65aSMichael Buesch 
1738fe2b65aSMichael Buesch 	err = ssb_bus_powerup(bus, 0);
1748fe2b65aSMichael Buesch 	if (err)
1758fe2b65aSMichael Buesch 		return err;
1768fe2b65aSMichael Buesch 	err = ssb_pcmcia_hardware_setup(bus);
1778fe2b65aSMichael Buesch 	if (err) {
1788fe2b65aSMichael Buesch 		ssb_bus_may_powerdown(bus);
1798fe2b65aSMichael Buesch 		return err;
1808fe2b65aSMichael Buesch 	}
1818fe2b65aSMichael Buesch 	ssb_chipco_resume(&bus->chipco);
1828fe2b65aSMichael Buesch 	ssb_bus_may_powerdown(bus);
1838fe2b65aSMichael Buesch 
1848fe2b65aSMichael Buesch 	return 0;
1858fe2b65aSMichael Buesch }
1868fe2b65aSMichael Buesch EXPORT_SYMBOL(ssb_bus_resume);
1878fe2b65aSMichael Buesch 
ssb_bus_suspend(struct ssb_bus * bus)1888fe2b65aSMichael Buesch int ssb_bus_suspend(struct ssb_bus *bus)
1898fe2b65aSMichael Buesch {
1908fe2b65aSMichael Buesch 	ssb_chipco_suspend(&bus->chipco);
1918fe2b65aSMichael Buesch 	ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
1928fe2b65aSMichael Buesch 
1938fe2b65aSMichael Buesch 	return 0;
1948fe2b65aSMichael Buesch }
1958fe2b65aSMichael Buesch EXPORT_SYMBOL(ssb_bus_suspend);
1968fe2b65aSMichael Buesch 
197d72bb40fSMichael Buesch #ifdef CONFIG_SSB_SPROM
1983ba6018aSMichael Buesch /** ssb_devices_freeze - Freeze all devices on the bus.
1993ba6018aSMichael Buesch  *
2003ba6018aSMichael Buesch  * After freezing no device driver will be handling a device
2013ba6018aSMichael Buesch  * on this bus anymore. ssb_devices_thaw() must be called after
2023ba6018aSMichael Buesch  * a successful freeze to reactivate the devices.
2033ba6018aSMichael Buesch  *
2043ba6018aSMichael Buesch  * @bus: The bus.
2053ba6018aSMichael Buesch  * @ctx: Context structure. Pass this to ssb_devices_thaw().
2063ba6018aSMichael Buesch  */
ssb_devices_freeze(struct ssb_bus * bus,struct ssb_freeze_context * ctx)2073ba6018aSMichael Buesch int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx)
20861e115a5SMichael Buesch {
2093ba6018aSMichael Buesch 	struct ssb_device *sdev;
2103ba6018aSMichael Buesch 	struct ssb_driver *sdrv;
2113ba6018aSMichael Buesch 	unsigned int i;
21261e115a5SMichael Buesch 
2133ba6018aSMichael Buesch 	memset(ctx, 0, sizeof(*ctx));
2143ba6018aSMichael Buesch 	ctx->bus = bus;
215209b4375SMichael Büsch 	WARN_ON(bus->nr_devices > ARRAY_SIZE(ctx->device_frozen));
2163ba6018aSMichael Buesch 
21761e115a5SMichael Buesch 	for (i = 0; i < bus->nr_devices; i++) {
2183ba6018aSMichael Buesch 		sdev = ssb_device_get(&bus->devices[i]);
2193ba6018aSMichael Buesch 
2203ba6018aSMichael Buesch 		if (!sdev->dev || !sdev->dev->driver ||
2213ba6018aSMichael Buesch 		    !device_is_registered(sdev->dev)) {
2223ba6018aSMichael Buesch 			ssb_device_put(sdev);
22361e115a5SMichael Buesch 			continue;
22461e115a5SMichael Buesch 		}
225f3ff9247SAlan Stern 		sdrv = drv_to_ssb_drv(sdev->dev->driver);
226209b4375SMichael Büsch 		if (WARN_ON(!sdrv->remove))
22761e115a5SMichael Buesch 			continue;
2283ba6018aSMichael Buesch 		sdrv->remove(sdev);
2293ba6018aSMichael Buesch 		ctx->device_frozen[i] = 1;
23061e115a5SMichael Buesch 	}
23161e115a5SMichael Buesch 
23261e115a5SMichael Buesch 	return 0;
23361e115a5SMichael Buesch }
23461e115a5SMichael Buesch 
2353ba6018aSMichael Buesch /** ssb_devices_thaw - Unfreeze all devices on the bus.
2363ba6018aSMichael Buesch  *
2373ba6018aSMichael Buesch  * This will re-attach the device drivers and re-init the devices.
2383ba6018aSMichael Buesch  *
2393ba6018aSMichael Buesch  * @ctx: The context structure from ssb_devices_freeze()
2403ba6018aSMichael Buesch  */
ssb_devices_thaw(struct ssb_freeze_context * ctx)2413ba6018aSMichael Buesch int ssb_devices_thaw(struct ssb_freeze_context *ctx)
24261e115a5SMichael Buesch {
2433ba6018aSMichael Buesch 	struct ssb_bus *bus = ctx->bus;
2443ba6018aSMichael Buesch 	struct ssb_device *sdev;
2453ba6018aSMichael Buesch 	struct ssb_driver *sdrv;
2463ba6018aSMichael Buesch 	unsigned int i;
2473ba6018aSMichael Buesch 	int err, result = 0;
24861e115a5SMichael Buesch 
24961e115a5SMichael Buesch 	for (i = 0; i < bus->nr_devices; i++) {
2503ba6018aSMichael Buesch 		if (!ctx->device_frozen[i])
25161e115a5SMichael Buesch 			continue;
2523ba6018aSMichael Buesch 		sdev = &bus->devices[i];
2533ba6018aSMichael Buesch 
254209b4375SMichael Büsch 		if (WARN_ON(!sdev->dev || !sdev->dev->driver))
25561e115a5SMichael Buesch 			continue;
2563ba6018aSMichael Buesch 		sdrv = drv_to_ssb_drv(sdev->dev->driver);
257209b4375SMichael Büsch 		if (WARN_ON(!sdrv || !sdrv->probe))
25861e115a5SMichael Buesch 			continue;
2593ba6018aSMichael Buesch 
2603ba6018aSMichael Buesch 		err = sdrv->probe(sdev, &sdev->id);
26161e115a5SMichael Buesch 		if (err) {
262b8b6069cSMichael Büsch 			dev_err(sdev->dev,
263b8b6069cSMichael Büsch 				"Failed to thaw device %s\n",
2643ba6018aSMichael Buesch 				dev_name(sdev->dev));
2653ba6018aSMichael Buesch 			result = err;
26661e115a5SMichael Buesch 		}
2673ba6018aSMichael Buesch 		ssb_device_put(sdev);
26861e115a5SMichael Buesch 	}
26961e115a5SMichael Buesch 
2703ba6018aSMichael Buesch 	return result;
27161e115a5SMichael Buesch }
272d72bb40fSMichael Buesch #endif /* CONFIG_SSB_SPROM */
27361e115a5SMichael Buesch 
ssb_device_shutdown(struct device * dev)27461e115a5SMichael Buesch static void ssb_device_shutdown(struct device *dev)
27561e115a5SMichael Buesch {
27661e115a5SMichael Buesch 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
27761e115a5SMichael Buesch 	struct ssb_driver *ssb_drv;
27861e115a5SMichael Buesch 
27961e115a5SMichael Buesch 	if (!dev->driver)
28061e115a5SMichael Buesch 		return;
28161e115a5SMichael Buesch 	ssb_drv = drv_to_ssb_drv(dev->driver);
28261e115a5SMichael Buesch 	if (ssb_drv && ssb_drv->shutdown)
28361e115a5SMichael Buesch 		ssb_drv->shutdown(ssb_dev);
28461e115a5SMichael Buesch }
28561e115a5SMichael Buesch 
ssb_device_remove(struct device * dev)286fc7a6209SUwe Kleine-König static void ssb_device_remove(struct device *dev)
28761e115a5SMichael Buesch {
28861e115a5SMichael Buesch 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
28961e115a5SMichael Buesch 	struct ssb_driver *ssb_drv = drv_to_ssb_drv(dev->driver);
29061e115a5SMichael Buesch 
29161e115a5SMichael Buesch 	if (ssb_drv && ssb_drv->remove)
29261e115a5SMichael Buesch 		ssb_drv->remove(ssb_dev);
29361e115a5SMichael Buesch 	ssb_device_put(ssb_dev);
29461e115a5SMichael Buesch }
29561e115a5SMichael Buesch 
ssb_device_probe(struct device * dev)29661e115a5SMichael Buesch static int ssb_device_probe(struct device *dev)
29761e115a5SMichael Buesch {
29861e115a5SMichael Buesch 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
29961e115a5SMichael Buesch 	struct ssb_driver *ssb_drv = drv_to_ssb_drv(dev->driver);
30061e115a5SMichael Buesch 	int err = 0;
30161e115a5SMichael Buesch 
30261e115a5SMichael Buesch 	ssb_device_get(ssb_dev);
30361e115a5SMichael Buesch 	if (ssb_drv && ssb_drv->probe)
30461e115a5SMichael Buesch 		err = ssb_drv->probe(ssb_dev, &ssb_dev->id);
30561e115a5SMichael Buesch 	if (err)
30661e115a5SMichael Buesch 		ssb_device_put(ssb_dev);
30761e115a5SMichael Buesch 
30861e115a5SMichael Buesch 	return err;
30961e115a5SMichael Buesch }
31061e115a5SMichael Buesch 
ssb_match_devid(const struct ssb_device_id * tabid,const struct ssb_device_id * devid)31161e115a5SMichael Buesch static int ssb_match_devid(const struct ssb_device_id *tabid,
31261e115a5SMichael Buesch 			   const struct ssb_device_id *devid)
31361e115a5SMichael Buesch {
31461e115a5SMichael Buesch 	if ((tabid->vendor != devid->vendor) &&
31561e115a5SMichael Buesch 	    tabid->vendor != SSB_ANY_VENDOR)
31661e115a5SMichael Buesch 		return 0;
31761e115a5SMichael Buesch 	if ((tabid->coreid != devid->coreid) &&
31861e115a5SMichael Buesch 	    tabid->coreid != SSB_ANY_ID)
31961e115a5SMichael Buesch 		return 0;
32061e115a5SMichael Buesch 	if ((tabid->revision != devid->revision) &&
32161e115a5SMichael Buesch 	    tabid->revision != SSB_ANY_REV)
32261e115a5SMichael Buesch 		return 0;
32361e115a5SMichael Buesch 	return 1;
32461e115a5SMichael Buesch }
32561e115a5SMichael Buesch 
ssb_bus_match(struct device * dev,struct device_driver * drv)32661e115a5SMichael Buesch static int ssb_bus_match(struct device *dev, struct device_driver *drv)
32761e115a5SMichael Buesch {
32861e115a5SMichael Buesch 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
32961e115a5SMichael Buesch 	struct ssb_driver *ssb_drv = drv_to_ssb_drv(drv);
33061e115a5SMichael Buesch 	const struct ssb_device_id *id;
33161e115a5SMichael Buesch 
33261e115a5SMichael Buesch 	for (id = ssb_drv->id_table;
33361e115a5SMichael Buesch 	     id->vendor || id->coreid || id->revision;
33461e115a5SMichael Buesch 	     id++) {
33561e115a5SMichael Buesch 		if (ssb_match_devid(id, &ssb_dev->id))
33661e115a5SMichael Buesch 			return 1; /* found */
33761e115a5SMichael Buesch 	}
33861e115a5SMichael Buesch 
33961e115a5SMichael Buesch 	return 0;
34061e115a5SMichael Buesch }
34161e115a5SMichael Buesch 
ssb_device_uevent(const struct device * dev,struct kobj_uevent_env * env)3422a81ada3SGreg Kroah-Hartman static int ssb_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
34361e115a5SMichael Buesch {
344c5dc2d8eSRand Deeb 	const struct ssb_device *ssb_dev;
34561e115a5SMichael Buesch 
34661e115a5SMichael Buesch 	if (!dev)
34761e115a5SMichael Buesch 		return -ENODEV;
34861e115a5SMichael Buesch 
349c5dc2d8eSRand Deeb 	ssb_dev = dev_to_ssb_dev(dev);
350c5dc2d8eSRand Deeb 
3517ac0326cSAl Viro 	return add_uevent_var(env,
35261e115a5SMichael Buesch 			     "MODALIAS=ssb:v%04Xid%04Xrev%02X",
35361e115a5SMichael Buesch 			     ssb_dev->id.vendor, ssb_dev->id.coreid,
35461e115a5SMichael Buesch 			     ssb_dev->id.revision);
35561e115a5SMichael Buesch }
35661e115a5SMichael Buesch 
357aa3bf280SHauke Mehrtens #define ssb_config_attr(attrib, field, format_string) \
358aa3bf280SHauke Mehrtens static ssize_t \
359aa3bf280SHauke Mehrtens attrib##_show(struct device *dev, struct device_attribute *attr, char *buf) \
360aa3bf280SHauke Mehrtens { \
361aa3bf280SHauke Mehrtens 	return sprintf(buf, format_string, dev_to_ssb_dev(dev)->field); \
3624e9072d6SGreg Kroah-Hartman } \
3634e9072d6SGreg Kroah-Hartman static DEVICE_ATTR_RO(attrib);
364aa3bf280SHauke Mehrtens 
365aa3bf280SHauke Mehrtens ssb_config_attr(core_num, core_index, "%u\n")
366aa3bf280SHauke Mehrtens ssb_config_attr(coreid, id.coreid, "0x%04x\n")
367aa3bf280SHauke Mehrtens ssb_config_attr(vendor, id.vendor, "0x%04x\n")
368aa3bf280SHauke Mehrtens ssb_config_attr(revision, id.revision, "%u\n")
369aa3bf280SHauke Mehrtens ssb_config_attr(irq, irq, "%u\n")
370aa3bf280SHauke Mehrtens static ssize_t
name_show(struct device * dev,struct device_attribute * attr,char * buf)371aa3bf280SHauke Mehrtens name_show(struct device *dev, struct device_attribute *attr, char *buf)
372aa3bf280SHauke Mehrtens {
373aa3bf280SHauke Mehrtens 	return sprintf(buf, "%s\n",
374aa3bf280SHauke Mehrtens 		       ssb_core_name(dev_to_ssb_dev(dev)->id.coreid));
375aa3bf280SHauke Mehrtens }
3764e9072d6SGreg Kroah-Hartman static DEVICE_ATTR_RO(name);
377aa3bf280SHauke Mehrtens 
3784e9072d6SGreg Kroah-Hartman static struct attribute *ssb_device_attrs[] = {
3794e9072d6SGreg Kroah-Hartman 	&dev_attr_name.attr,
3804e9072d6SGreg Kroah-Hartman 	&dev_attr_core_num.attr,
3814e9072d6SGreg Kroah-Hartman 	&dev_attr_coreid.attr,
3824e9072d6SGreg Kroah-Hartman 	&dev_attr_vendor.attr,
3834e9072d6SGreg Kroah-Hartman 	&dev_attr_revision.attr,
3844e9072d6SGreg Kroah-Hartman 	&dev_attr_irq.attr,
3854e9072d6SGreg Kroah-Hartman 	NULL,
386aa3bf280SHauke Mehrtens };
3874e9072d6SGreg Kroah-Hartman ATTRIBUTE_GROUPS(ssb_device);
388aa3bf280SHauke Mehrtens 
38961e115a5SMichael Buesch static struct bus_type ssb_bustype = {
39061e115a5SMichael Buesch 	.name		= "ssb",
39161e115a5SMichael Buesch 	.match		= ssb_bus_match,
39261e115a5SMichael Buesch 	.probe		= ssb_device_probe,
39361e115a5SMichael Buesch 	.remove		= ssb_device_remove,
39461e115a5SMichael Buesch 	.shutdown	= ssb_device_shutdown,
39561e115a5SMichael Buesch 	.suspend	= ssb_device_suspend,
39661e115a5SMichael Buesch 	.resume		= ssb_device_resume,
39761e115a5SMichael Buesch 	.uevent		= ssb_device_uevent,
3984e9072d6SGreg Kroah-Hartman 	.dev_groups	= ssb_device_groups,
39961e115a5SMichael Buesch };
40061e115a5SMichael Buesch 
ssb_buses_lock(void)40161e115a5SMichael Buesch static void ssb_buses_lock(void)
40261e115a5SMichael Buesch {
40361e115a5SMichael Buesch 	/* See the comment at the ssb_is_early_boot definition */
40461e115a5SMichael Buesch 	if (!ssb_is_early_boot)
40561e115a5SMichael Buesch 		mutex_lock(&buses_mutex);
40661e115a5SMichael Buesch }
40761e115a5SMichael Buesch 
ssb_buses_unlock(void)40861e115a5SMichael Buesch static void ssb_buses_unlock(void)
40961e115a5SMichael Buesch {
41061e115a5SMichael Buesch 	/* See the comment at the ssb_is_early_boot definition */
41161e115a5SMichael Buesch 	if (!ssb_is_early_boot)
41261e115a5SMichael Buesch 		mutex_unlock(&buses_mutex);
41361e115a5SMichael Buesch }
41461e115a5SMichael Buesch 
ssb_devices_unregister(struct ssb_bus * bus)41561e115a5SMichael Buesch static void ssb_devices_unregister(struct ssb_bus *bus)
41661e115a5SMichael Buesch {
41761e115a5SMichael Buesch 	struct ssb_device *sdev;
41861e115a5SMichael Buesch 	int i;
41961e115a5SMichael Buesch 
42061e115a5SMichael Buesch 	for (i = bus->nr_devices - 1; i >= 0; i--) {
42161e115a5SMichael Buesch 		sdev = &(bus->devices[i]);
42261e115a5SMichael Buesch 		if (sdev->dev)
42361e115a5SMichael Buesch 			device_unregister(sdev->dev);
42461e115a5SMichael Buesch 	}
425bde327efSHauke Mehrtens 
426bde327efSHauke Mehrtens #ifdef CONFIG_SSB_EMBEDDED
427bde327efSHauke Mehrtens 	if (bus->bustype == SSB_BUSTYPE_SSB)
428bde327efSHauke Mehrtens 		platform_device_unregister(bus->watchdog);
429bde327efSHauke Mehrtens #endif
43061e115a5SMichael Buesch }
43161e115a5SMichael Buesch 
ssb_bus_unregister(struct ssb_bus * bus)43261e115a5SMichael Buesch void ssb_bus_unregister(struct ssb_bus *bus)
43361e115a5SMichael Buesch {
434600485edSHauke Mehrtens 	int err;
435600485edSHauke Mehrtens 
436600485edSHauke Mehrtens 	err = ssb_gpio_unregister(bus);
437233bc283STian Tao 	if (err)
438b8b6069cSMichael Büsch 		pr_debug("Can not unregister GPIO driver: %i\n", err);
439600485edSHauke Mehrtens 
44061e115a5SMichael Buesch 	ssb_buses_lock();
44161e115a5SMichael Buesch 	ssb_devices_unregister(bus);
44261e115a5SMichael Buesch 	list_del(&bus->list);
44361e115a5SMichael Buesch 	ssb_buses_unlock();
44461e115a5SMichael Buesch 
445e7ec2e32SMichael Buesch 	ssb_pcmcia_exit(bus);
44661e115a5SMichael Buesch 	ssb_pci_exit(bus);
44761e115a5SMichael Buesch 	ssb_iounmap(bus);
44861e115a5SMichael Buesch }
44961e115a5SMichael Buesch EXPORT_SYMBOL(ssb_bus_unregister);
45061e115a5SMichael Buesch 
ssb_release_dev(struct device * dev)45161e115a5SMichael Buesch static void ssb_release_dev(struct device *dev)
45261e115a5SMichael Buesch {
45361e115a5SMichael Buesch 	struct __ssb_dev_wrapper *devwrap;
45461e115a5SMichael Buesch 
45561e115a5SMichael Buesch 	devwrap = container_of(dev, struct __ssb_dev_wrapper, dev);
45661e115a5SMichael Buesch 	kfree(devwrap);
45761e115a5SMichael Buesch }
45861e115a5SMichael Buesch 
ssb_devices_register(struct ssb_bus * bus)45961e115a5SMichael Buesch static int ssb_devices_register(struct ssb_bus *bus)
46061e115a5SMichael Buesch {
46161e115a5SMichael Buesch 	struct ssb_device *sdev;
46261e115a5SMichael Buesch 	struct device *dev;
46361e115a5SMichael Buesch 	struct __ssb_dev_wrapper *devwrap;
46461e115a5SMichael Buesch 	int i, err = 0;
46561e115a5SMichael Buesch 	int dev_idx = 0;
46661e115a5SMichael Buesch 
46761e115a5SMichael Buesch 	for (i = 0; i < bus->nr_devices; i++) {
46861e115a5SMichael Buesch 		sdev = &(bus->devices[i]);
46961e115a5SMichael Buesch 
47061e115a5SMichael Buesch 		/* We don't register SSB-system devices to the kernel,
471f3028212SShubhankar Kuranagatti 		 * as the drivers for them are built into SSB.
472f3028212SShubhankar Kuranagatti 		 */
47361e115a5SMichael Buesch 		switch (sdev->id.coreid) {
47461e115a5SMichael Buesch 		case SSB_DEV_CHIPCOMMON:
47561e115a5SMichael Buesch 		case SSB_DEV_PCI:
47661e115a5SMichael Buesch 		case SSB_DEV_PCIE:
47761e115a5SMichael Buesch 		case SSB_DEV_PCMCIA:
47861e115a5SMichael Buesch 		case SSB_DEV_MIPS:
47961e115a5SMichael Buesch 		case SSB_DEV_MIPS_3302:
48061e115a5SMichael Buesch 		case SSB_DEV_EXTIF:
48161e115a5SMichael Buesch 			continue;
48261e115a5SMichael Buesch 		}
48361e115a5SMichael Buesch 
48461e115a5SMichael Buesch 		devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL);
48561e115a5SMichael Buesch 		if (!devwrap) {
48661e115a5SMichael Buesch 			err = -ENOMEM;
48761e115a5SMichael Buesch 			goto error;
48861e115a5SMichael Buesch 		}
48961e115a5SMichael Buesch 		dev = &devwrap->dev;
49061e115a5SMichael Buesch 		devwrap->sdev = sdev;
49161e115a5SMichael Buesch 
49261e115a5SMichael Buesch 		dev->release = ssb_release_dev;
49361e115a5SMichael Buesch 		dev->bus = &ssb_bustype;
494b7b05fe7SKay Sievers 		dev_set_name(dev, "ssb%u:%d", bus->busnumber, dev_idx);
49561e115a5SMichael Buesch 
49661e115a5SMichael Buesch 		switch (bus->bustype) {
49761e115a5SMichael Buesch 		case SSB_BUSTYPE_PCI:
49861e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST
49961e115a5SMichael Buesch 			sdev->irq = bus->host_pci->irq;
50061e115a5SMichael Buesch 			dev->parent = &bus->host_pci->dev;
50114f92952SFUJITA Tomonori 			sdev->dma_dev = dev->parent;
50261e115a5SMichael Buesch #endif
50361e115a5SMichael Buesch 			break;
50461e115a5SMichael Buesch 		case SSB_BUSTYPE_PCMCIA:
50561e115a5SMichael Buesch #ifdef CONFIG_SSB_PCMCIAHOST
506eb14120fSDominik Brodowski 			sdev->irq = bus->host_pcmcia->irq;
50761e115a5SMichael Buesch 			dev->parent = &bus->host_pcmcia->dev;
50861e115a5SMichael Buesch #endif
50961e115a5SMichael Buesch 			break;
51024ea602eSAlbert Herranz 		case SSB_BUSTYPE_SDIO:
511391ae22aSMichael Buesch #ifdef CONFIG_SSB_SDIOHOST
51224ea602eSAlbert Herranz 			dev->parent = &bus->host_sdio->dev;
51324ea602eSAlbert Herranz #endif
51424ea602eSAlbert Herranz 			break;
51561e115a5SMichael Buesch 		case SSB_BUSTYPE_SSB:
516ac82da33SAurelien Jarno 			dev->dma_mask = &dev->coherent_dma_mask;
51714f92952SFUJITA Tomonori 			sdev->dma_dev = dev;
51861e115a5SMichael Buesch 			break;
51961e115a5SMichael Buesch 		}
52061e115a5SMichael Buesch 
52161e115a5SMichael Buesch 		sdev->dev = dev;
52261e115a5SMichael Buesch 		err = device_register(dev);
52361e115a5SMichael Buesch 		if (err) {
524b8b6069cSMichael Büsch 			pr_err("Could not register %s\n", dev_name(dev));
52561e115a5SMichael Buesch 			/* Set dev to NULL to not unregister
526f3028212SShubhankar Kuranagatti 			 * dev on error unwinding.
527f3028212SShubhankar Kuranagatti 			 */
52861e115a5SMichael Buesch 			sdev->dev = NULL;
529a24853aaSArvind Yadav 			put_device(dev);
53061e115a5SMichael Buesch 			goto error;
53161e115a5SMichael Buesch 		}
53261e115a5SMichael Buesch 		dev_idx++;
53361e115a5SMichael Buesch 	}
53461e115a5SMichael Buesch 
535c7a4a9e3SRafał Miłecki #ifdef CONFIG_SSB_DRIVER_MIPS
536c7a4a9e3SRafał Miłecki 	if (bus->mipscore.pflash.present) {
537c7a4a9e3SRafał Miłecki 		err = platform_device_register(&ssb_pflash_dev);
538c7a4a9e3SRafał Miłecki 		if (err)
539c7a4a9e3SRafał Miłecki 			pr_err("Error registering parallel flash\n");
540c7a4a9e3SRafał Miłecki 	}
541c7a4a9e3SRafał Miłecki #endif
542c7a4a9e3SRafał Miłecki 
5437b5d6043SRafał Miłecki #ifdef CONFIG_SSB_SFLASH
5447b5d6043SRafał Miłecki 	if (bus->mipscore.sflash.present) {
5457b5d6043SRafał Miłecki 		err = platform_device_register(&ssb_sflash_dev);
5467b5d6043SRafał Miłecki 		if (err)
5477b5d6043SRafał Miłecki 			pr_err("Error registering serial flash\n");
5487b5d6043SRafał Miłecki 	}
5497b5d6043SRafał Miłecki #endif
5507b5d6043SRafał Miłecki 
55161e115a5SMichael Buesch 	return 0;
55261e115a5SMichael Buesch error:
55361e115a5SMichael Buesch 	/* Unwind the already registered devices. */
55461e115a5SMichael Buesch 	ssb_devices_unregister(bus);
55561e115a5SMichael Buesch 	return err;
55661e115a5SMichael Buesch }
55761e115a5SMichael Buesch 
55861e115a5SMichael Buesch /* Needs ssb_buses_lock() */
ssb_attach_queued_buses(void)559163247c1SGreg Kroah-Hartman static int ssb_attach_queued_buses(void)
56061e115a5SMichael Buesch {
56161e115a5SMichael Buesch 	struct ssb_bus *bus, *n;
56261e115a5SMichael Buesch 	int err = 0;
56361e115a5SMichael Buesch 	int drop_them_all = 0;
56461e115a5SMichael Buesch 
56561e115a5SMichael Buesch 	list_for_each_entry_safe(bus, n, &attach_queue, list) {
56661e115a5SMichael Buesch 		if (drop_them_all) {
56761e115a5SMichael Buesch 			list_del(&bus->list);
56861e115a5SMichael Buesch 			continue;
56961e115a5SMichael Buesch 		}
57061e115a5SMichael Buesch 		/* Can't init the PCIcore in ssb_bus_register(), as that
57161e115a5SMichael Buesch 		 * is too early in boot for embedded systems
57261e115a5SMichael Buesch 		 * (no udelay() available). So do it here in attach stage.
57361e115a5SMichael Buesch 		 */
57461e115a5SMichael Buesch 		err = ssb_bus_powerup(bus, 0);
57561e115a5SMichael Buesch 		if (err)
57661e115a5SMichael Buesch 			goto error;
57761e115a5SMichael Buesch 		ssb_pcicore_init(&bus->pcicore);
578bde327efSHauke Mehrtens 		if (bus->bustype == SSB_BUSTYPE_SSB)
579bde327efSHauke Mehrtens 			ssb_watchdog_register(bus);
5807c1bc0daSRafał Miłecki 
5817c1bc0daSRafał Miłecki 		err = ssb_gpio_init(bus);
5827c1bc0daSRafał Miłecki 		if (err == -ENOTSUPP)
583b8b6069cSMichael Büsch 			pr_debug("GPIO driver not activated\n");
5847c1bc0daSRafał Miłecki 		else if (err)
585b8b6069cSMichael Büsch 			pr_debug("Error registering GPIO driver: %i\n", err);
5867c1bc0daSRafał Miłecki 
58761e115a5SMichael Buesch 		ssb_bus_may_powerdown(bus);
58861e115a5SMichael Buesch 
58961e115a5SMichael Buesch 		err = ssb_devices_register(bus);
59061e115a5SMichael Buesch error:
59161e115a5SMichael Buesch 		if (err) {
59261e115a5SMichael Buesch 			drop_them_all = 1;
59361e115a5SMichael Buesch 			list_del(&bus->list);
59461e115a5SMichael Buesch 			continue;
59561e115a5SMichael Buesch 		}
59661e115a5SMichael Buesch 		list_move_tail(&bus->list, &buses);
59761e115a5SMichael Buesch 	}
59861e115a5SMichael Buesch 
59961e115a5SMichael Buesch 	return err;
60061e115a5SMichael Buesch }
60161e115a5SMichael Buesch 
ssb_fetch_invariants(struct ssb_bus * bus,ssb_invariants_func_t get_invariants)60261e115a5SMichael Buesch static int ssb_fetch_invariants(struct ssb_bus *bus,
60361e115a5SMichael Buesch 				ssb_invariants_func_t get_invariants)
60461e115a5SMichael Buesch {
60561e115a5SMichael Buesch 	struct ssb_init_invariants iv;
60661e115a5SMichael Buesch 	int err;
60761e115a5SMichael Buesch 
60861e115a5SMichael Buesch 	memset(&iv, 0, sizeof(iv));
60961e115a5SMichael Buesch 	err = get_invariants(bus, &iv);
61061e115a5SMichael Buesch 	if (err)
61161e115a5SMichael Buesch 		goto out;
61261e115a5SMichael Buesch 	memcpy(&bus->boardinfo, &iv.boardinfo, sizeof(iv.boardinfo));
61361e115a5SMichael Buesch 	memcpy(&bus->sprom, &iv.sprom, sizeof(iv.sprom));
6147cb44615SMichael Buesch 	bus->has_cardbus_slot = iv.has_cardbus_slot;
61561e115a5SMichael Buesch out:
61661e115a5SMichael Buesch 	return err;
61761e115a5SMichael Buesch }
61861e115a5SMichael Buesch 
619b7e2d195SArnd Bergmann static int __maybe_unused
ssb_bus_register(struct ssb_bus * bus,ssb_invariants_func_t get_invariants,unsigned long baseaddr)620b7e2d195SArnd Bergmann ssb_bus_register(struct ssb_bus *bus,
62161e115a5SMichael Buesch 		 ssb_invariants_func_t get_invariants,
62261e115a5SMichael Buesch 		 unsigned long baseaddr)
62361e115a5SMichael Buesch {
62461e115a5SMichael Buesch 	int err;
62561e115a5SMichael Buesch 
62661e115a5SMichael Buesch 	spin_lock_init(&bus->bar_lock);
62761e115a5SMichael Buesch 	INIT_LIST_HEAD(&bus->list);
62853521d8cSMichael Buesch #ifdef CONFIG_SSB_EMBEDDED
62953521d8cSMichael Buesch 	spin_lock_init(&bus->gpio_lock);
63053521d8cSMichael Buesch #endif
63161e115a5SMichael Buesch 
63261e115a5SMichael Buesch 	/* Powerup the bus */
63361e115a5SMichael Buesch 	err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
63461e115a5SMichael Buesch 	if (err)
63561e115a5SMichael Buesch 		goto out;
63624ea602eSAlbert Herranz 
63724ea602eSAlbert Herranz 	/* Init SDIO-host device (if any), before the scan */
63824ea602eSAlbert Herranz 	err = ssb_sdio_init(bus);
63924ea602eSAlbert Herranz 	if (err)
64024ea602eSAlbert Herranz 		goto err_disable_xtal;
64124ea602eSAlbert Herranz 
64261e115a5SMichael Buesch 	ssb_buses_lock();
64361e115a5SMichael Buesch 	bus->busnumber = next_busnumber;
64461e115a5SMichael Buesch 	/* Scan for devices (cores) */
64561e115a5SMichael Buesch 	err = ssb_bus_scan(bus, baseaddr);
64661e115a5SMichael Buesch 	if (err)
64724ea602eSAlbert Herranz 		goto err_sdio_exit;
64861e115a5SMichael Buesch 
64961e115a5SMichael Buesch 	/* Init PCI-host device (if any) */
65061e115a5SMichael Buesch 	err = ssb_pci_init(bus);
65161e115a5SMichael Buesch 	if (err)
65261e115a5SMichael Buesch 		goto err_unmap;
65361e115a5SMichael Buesch 	/* Init PCMCIA-host device (if any) */
65461e115a5SMichael Buesch 	err = ssb_pcmcia_init(bus);
65561e115a5SMichael Buesch 	if (err)
65661e115a5SMichael Buesch 		goto err_pci_exit;
65761e115a5SMichael Buesch 
65861e115a5SMichael Buesch 	/* Initialize basic system devices (if available) */
65961e115a5SMichael Buesch 	err = ssb_bus_powerup(bus, 0);
66061e115a5SMichael Buesch 	if (err)
66161e115a5SMichael Buesch 		goto err_pcmcia_exit;
66261e115a5SMichael Buesch 	ssb_chipcommon_init(&bus->chipco);
663394bc7e3SHauke Mehrtens 	ssb_extif_init(&bus->extif);
66461e115a5SMichael Buesch 	ssb_mipscore_init(&bus->mipscore);
66561e115a5SMichael Buesch 	err = ssb_fetch_invariants(bus, get_invariants);
66661e115a5SMichael Buesch 	if (err) {
66761e115a5SMichael Buesch 		ssb_bus_may_powerdown(bus);
66861e115a5SMichael Buesch 		goto err_pcmcia_exit;
66961e115a5SMichael Buesch 	}
67061e115a5SMichael Buesch 	ssb_bus_may_powerdown(bus);
67161e115a5SMichael Buesch 
67261e115a5SMichael Buesch 	/* Queue it for attach.
673f3028212SShubhankar Kuranagatti 	 * See the comment at the ssb_is_early_boot definition.
674f3028212SShubhankar Kuranagatti 	 */
67561e115a5SMichael Buesch 	list_add_tail(&bus->list, &attach_queue);
67661e115a5SMichael Buesch 	if (!ssb_is_early_boot) {
67761e115a5SMichael Buesch 		/* This is not early boot, so we must attach the bus now */
67861e115a5SMichael Buesch 		err = ssb_attach_queued_buses();
67961e115a5SMichael Buesch 		if (err)
68061e115a5SMichael Buesch 			goto err_dequeue;
68161e115a5SMichael Buesch 	}
68261e115a5SMichael Buesch 	next_busnumber++;
68361e115a5SMichael Buesch 	ssb_buses_unlock();
68461e115a5SMichael Buesch 
68561e115a5SMichael Buesch out:
68661e115a5SMichael Buesch 	return err;
68761e115a5SMichael Buesch 
68861e115a5SMichael Buesch err_dequeue:
68961e115a5SMichael Buesch 	list_del(&bus->list);
69061e115a5SMichael Buesch err_pcmcia_exit:
691e7ec2e32SMichael Buesch 	ssb_pcmcia_exit(bus);
69261e115a5SMichael Buesch err_pci_exit:
69361e115a5SMichael Buesch 	ssb_pci_exit(bus);
69461e115a5SMichael Buesch err_unmap:
69561e115a5SMichael Buesch 	ssb_iounmap(bus);
69624ea602eSAlbert Herranz err_sdio_exit:
69724ea602eSAlbert Herranz 	ssb_sdio_exit(bus);
69861e115a5SMichael Buesch err_disable_xtal:
69961e115a5SMichael Buesch 	ssb_buses_unlock();
70061e115a5SMichael Buesch 	ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
70161e115a5SMichael Buesch 	return err;
70261e115a5SMichael Buesch }
70361e115a5SMichael Buesch 
70461e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST
ssb_bus_pcibus_register(struct ssb_bus * bus,struct pci_dev * host_pci)705163247c1SGreg Kroah-Hartman int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci)
70661e115a5SMichael Buesch {
70761e115a5SMichael Buesch 	int err;
70861e115a5SMichael Buesch 
70961e115a5SMichael Buesch 	bus->bustype = SSB_BUSTYPE_PCI;
71061e115a5SMichael Buesch 	bus->host_pci = host_pci;
71161e115a5SMichael Buesch 	bus->ops = &ssb_pci_ops;
71261e115a5SMichael Buesch 
71361e115a5SMichael Buesch 	err = ssb_bus_register(bus, ssb_pci_get_invariants, 0);
71461e115a5SMichael Buesch 	if (!err) {
715b8b6069cSMichael Büsch 		dev_info(&host_pci->dev,
716b8b6069cSMichael Büsch 			 "Sonics Silicon Backplane found on PCI device %s\n",
71733a606acSJoe Perches 			 dev_name(&host_pci->dev));
718ce9626eaSLarry Finger 	} else {
719b8b6069cSMichael Büsch 		dev_err(&host_pci->dev,
720b8b6069cSMichael Büsch 			"Failed to register PCI version of SSB with error %d\n",
72133a606acSJoe Perches 			err);
72261e115a5SMichael Buesch 	}
72361e115a5SMichael Buesch 
72461e115a5SMichael Buesch 	return err;
72561e115a5SMichael Buesch }
72661e115a5SMichael Buesch #endif /* CONFIG_SSB_PCIHOST */
72761e115a5SMichael Buesch 
72861e115a5SMichael Buesch #ifdef CONFIG_SSB_PCMCIAHOST
ssb_bus_pcmciabus_register(struct ssb_bus * bus,struct pcmcia_device * pcmcia_dev,unsigned long baseaddr)729163247c1SGreg Kroah-Hartman int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
73061e115a5SMichael Buesch 			       struct pcmcia_device *pcmcia_dev,
73161e115a5SMichael Buesch 			       unsigned long baseaddr)
73261e115a5SMichael Buesch {
73361e115a5SMichael Buesch 	int err;
73461e115a5SMichael Buesch 
73561e115a5SMichael Buesch 	bus->bustype = SSB_BUSTYPE_PCMCIA;
73661e115a5SMichael Buesch 	bus->host_pcmcia = pcmcia_dev;
73761e115a5SMichael Buesch 	bus->ops = &ssb_pcmcia_ops;
73861e115a5SMichael Buesch 
73961e115a5SMichael Buesch 	err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr);
74061e115a5SMichael Buesch 	if (!err) {
741b8b6069cSMichael Büsch 		dev_info(&pcmcia_dev->dev,
742b8b6069cSMichael Büsch 			 "Sonics Silicon Backplane found on PCMCIA device %s\n",
74333a606acSJoe Perches 			 pcmcia_dev->devname);
74461e115a5SMichael Buesch 	}
74561e115a5SMichael Buesch 
74661e115a5SMichael Buesch 	return err;
74761e115a5SMichael Buesch }
74861e115a5SMichael Buesch #endif /* CONFIG_SSB_PCMCIAHOST */
74961e115a5SMichael Buesch 
75024ea602eSAlbert Herranz #ifdef CONFIG_SSB_SDIOHOST
ssb_bus_sdiobus_register(struct ssb_bus * bus,struct sdio_func * func,unsigned int quirks)751163247c1SGreg Kroah-Hartman int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
75224ea602eSAlbert Herranz 			     unsigned int quirks)
75324ea602eSAlbert Herranz {
75424ea602eSAlbert Herranz 	int err;
75524ea602eSAlbert Herranz 
75624ea602eSAlbert Herranz 	bus->bustype = SSB_BUSTYPE_SDIO;
75724ea602eSAlbert Herranz 	bus->host_sdio = func;
75824ea602eSAlbert Herranz 	bus->ops = &ssb_sdio_ops;
75924ea602eSAlbert Herranz 	bus->quirks = quirks;
76024ea602eSAlbert Herranz 
76124ea602eSAlbert Herranz 	err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0);
76224ea602eSAlbert Herranz 	if (!err) {
763b8b6069cSMichael Büsch 		dev_info(&func->dev,
764b8b6069cSMichael Büsch 			 "Sonics Silicon Backplane found on SDIO device %s\n",
76533a606acSJoe Perches 			 sdio_func_id(func));
76624ea602eSAlbert Herranz 	}
76724ea602eSAlbert Herranz 
76824ea602eSAlbert Herranz 	return err;
76924ea602eSAlbert Herranz }
77024ea602eSAlbert Herranz EXPORT_SYMBOL(ssb_bus_sdiobus_register);
77124ea602eSAlbert Herranz #endif /* CONFIG_SSB_PCMCIAHOST */
77224ea602eSAlbert Herranz 
773845da6e5SRafał Miłecki #ifdef CONFIG_SSB_HOST_SOC
ssb_bus_host_soc_register(struct ssb_bus * bus,unsigned long baseaddr)774541c9a84SRafał Miłecki int ssb_bus_host_soc_register(struct ssb_bus *bus, unsigned long baseaddr)
77561e115a5SMichael Buesch {
77661e115a5SMichael Buesch 	int err;
77761e115a5SMichael Buesch 
77861e115a5SMichael Buesch 	bus->bustype = SSB_BUSTYPE_SSB;
779830c7df4SRafał Miłecki 	bus->ops = &ssb_host_soc_ops;
78061e115a5SMichael Buesch 
781541c9a84SRafał Miłecki 	err = ssb_bus_register(bus, ssb_host_soc_get_invariants, baseaddr);
78261e115a5SMichael Buesch 	if (!err) {
783b8b6069cSMichael Büsch 		pr_info("Sonics Silicon Backplane found at address 0x%08lX\n",
78433a606acSJoe Perches 			baseaddr);
78561e115a5SMichael Buesch 	}
78661e115a5SMichael Buesch 
78761e115a5SMichael Buesch 	return err;
78861e115a5SMichael Buesch }
789845da6e5SRafał Miłecki #endif
79061e115a5SMichael Buesch 
__ssb_driver_register(struct ssb_driver * drv,struct module * owner)79161e115a5SMichael Buesch int __ssb_driver_register(struct ssb_driver *drv, struct module *owner)
79261e115a5SMichael Buesch {
79361e115a5SMichael Buesch 	drv->drv.name = drv->name;
79461e115a5SMichael Buesch 	drv->drv.bus = &ssb_bustype;
79561e115a5SMichael Buesch 	drv->drv.owner = owner;
79661e115a5SMichael Buesch 
79761e115a5SMichael Buesch 	return driver_register(&drv->drv);
79861e115a5SMichael Buesch }
79961e115a5SMichael Buesch EXPORT_SYMBOL(__ssb_driver_register);
80061e115a5SMichael Buesch 
ssb_driver_unregister(struct ssb_driver * drv)80161e115a5SMichael Buesch void ssb_driver_unregister(struct ssb_driver *drv)
80261e115a5SMichael Buesch {
80361e115a5SMichael Buesch 	driver_unregister(&drv->drv);
80461e115a5SMichael Buesch }
80561e115a5SMichael Buesch EXPORT_SYMBOL(ssb_driver_unregister);
80661e115a5SMichael Buesch 
ssb_set_devtypedata(struct ssb_device * dev,void * data)80761e115a5SMichael Buesch void ssb_set_devtypedata(struct ssb_device *dev, void *data)
80861e115a5SMichael Buesch {
80961e115a5SMichael Buesch 	struct ssb_bus *bus = dev->bus;
81061e115a5SMichael Buesch 	struct ssb_device *ent;
81161e115a5SMichael Buesch 	int i;
81261e115a5SMichael Buesch 
81361e115a5SMichael Buesch 	for (i = 0; i < bus->nr_devices; i++) {
81461e115a5SMichael Buesch 		ent = &(bus->devices[i]);
81561e115a5SMichael Buesch 		if (ent->id.vendor != dev->id.vendor)
81661e115a5SMichael Buesch 			continue;
81761e115a5SMichael Buesch 		if (ent->id.coreid != dev->id.coreid)
81861e115a5SMichael Buesch 			continue;
81961e115a5SMichael Buesch 
82061e115a5SMichael Buesch 		ent->devtypedata = data;
82161e115a5SMichael Buesch 	}
82261e115a5SMichael Buesch }
82361e115a5SMichael Buesch EXPORT_SYMBOL(ssb_set_devtypedata);
82461e115a5SMichael Buesch 
clkfactor_f6_resolve(u32 v)82561e115a5SMichael Buesch static u32 clkfactor_f6_resolve(u32 v)
82661e115a5SMichael Buesch {
82761e115a5SMichael Buesch 	/* map the magic values */
82861e115a5SMichael Buesch 	switch (v) {
82961e115a5SMichael Buesch 	case SSB_CHIPCO_CLK_F6_2:
83061e115a5SMichael Buesch 		return 2;
83161e115a5SMichael Buesch 	case SSB_CHIPCO_CLK_F6_3:
83261e115a5SMichael Buesch 		return 3;
83361e115a5SMichael Buesch 	case SSB_CHIPCO_CLK_F6_4:
83461e115a5SMichael Buesch 		return 4;
83561e115a5SMichael Buesch 	case SSB_CHIPCO_CLK_F6_5:
83661e115a5SMichael Buesch 		return 5;
83761e115a5SMichael Buesch 	case SSB_CHIPCO_CLK_F6_6:
83861e115a5SMichael Buesch 		return 6;
83961e115a5SMichael Buesch 	case SSB_CHIPCO_CLK_F6_7:
84061e115a5SMichael Buesch 		return 7;
84161e115a5SMichael Buesch 	}
842*8574cdabSRand Deeb 	return 1;
84361e115a5SMichael Buesch }
84461e115a5SMichael Buesch 
84561e115a5SMichael Buesch /* Calculate the speed the backplane would run at a given set of clockcontrol values */
ssb_calc_clock_rate(u32 plltype,u32 n,u32 m)84661e115a5SMichael Buesch u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
84761e115a5SMichael Buesch {
84861e115a5SMichael Buesch 	u32 n1, n2, clock, m1, m2, m3, mc;
84961e115a5SMichael Buesch 
85061e115a5SMichael Buesch 	n1 = (n & SSB_CHIPCO_CLK_N1);
85161e115a5SMichael Buesch 	n2 = ((n & SSB_CHIPCO_CLK_N2) >> SSB_CHIPCO_CLK_N2_SHIFT);
85261e115a5SMichael Buesch 
85361e115a5SMichael Buesch 	switch (plltype) {
85461e115a5SMichael Buesch 	case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */
85561e115a5SMichael Buesch 		if (m & SSB_CHIPCO_CLK_T6_MMASK)
85661e115a5SMichael Buesch 			return SSB_CHIPCO_CLK_T6_M1;
857e913d468SHauke Mehrtens 		return SSB_CHIPCO_CLK_T6_M0;
85861e115a5SMichael Buesch 	case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */
85961e115a5SMichael Buesch 	case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
86061e115a5SMichael Buesch 	case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */
86161e115a5SMichael Buesch 	case SSB_PLLTYPE_7: /* 25Mhz, 4 dividers */
86261e115a5SMichael Buesch 		n1 = clkfactor_f6_resolve(n1);
86361e115a5SMichael Buesch 		n2 += SSB_CHIPCO_CLK_F5_BIAS;
86461e115a5SMichael Buesch 		break;
86561e115a5SMichael Buesch 	case SSB_PLLTYPE_2: /* 48Mhz, 4 dividers */
86661e115a5SMichael Buesch 		n1 += SSB_CHIPCO_CLK_T2_BIAS;
86761e115a5SMichael Buesch 		n2 += SSB_CHIPCO_CLK_T2_BIAS;
868209b4375SMichael Büsch 		WARN_ON(!((n1 >= 2) && (n1 <= 7)));
869209b4375SMichael Büsch 		WARN_ON(!((n2 >= 5) && (n2 <= 23)));
87061e115a5SMichael Buesch 		break;
87161e115a5SMichael Buesch 	case SSB_PLLTYPE_5: /* 25Mhz, 4 dividers */
87261e115a5SMichael Buesch 		return 100000000;
87361e115a5SMichael Buesch 	default:
874209b4375SMichael Büsch 		WARN_ON(1);
87561e115a5SMichael Buesch 	}
87661e115a5SMichael Buesch 
87761e115a5SMichael Buesch 	switch (plltype) {
87861e115a5SMichael Buesch 	case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
87961e115a5SMichael Buesch 	case SSB_PLLTYPE_7: /* 25Mhz, 4 dividers */
88061e115a5SMichael Buesch 		clock = SSB_CHIPCO_CLK_BASE2 * n1 * n2;
88161e115a5SMichael Buesch 		break;
88261e115a5SMichael Buesch 	default:
88361e115a5SMichael Buesch 		clock = SSB_CHIPCO_CLK_BASE1 * n1 * n2;
88461e115a5SMichael Buesch 	}
88561e115a5SMichael Buesch 	if (!clock)
88661e115a5SMichael Buesch 		return 0;
88761e115a5SMichael Buesch 
88861e115a5SMichael Buesch 	m1 = (m & SSB_CHIPCO_CLK_M1);
88961e115a5SMichael Buesch 	m2 = ((m & SSB_CHIPCO_CLK_M2) >> SSB_CHIPCO_CLK_M2_SHIFT);
89061e115a5SMichael Buesch 	m3 = ((m & SSB_CHIPCO_CLK_M3) >> SSB_CHIPCO_CLK_M3_SHIFT);
89161e115a5SMichael Buesch 	mc = ((m & SSB_CHIPCO_CLK_MC) >> SSB_CHIPCO_CLK_MC_SHIFT);
89261e115a5SMichael Buesch 
89361e115a5SMichael Buesch 	switch (plltype) {
89461e115a5SMichael Buesch 	case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */
89561e115a5SMichael Buesch 	case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
89661e115a5SMichael Buesch 	case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */
89761e115a5SMichael Buesch 	case SSB_PLLTYPE_7: /* 25Mhz, 4 dividers */
89861e115a5SMichael Buesch 		m1 = clkfactor_f6_resolve(m1);
89961e115a5SMichael Buesch 		if ((plltype == SSB_PLLTYPE_1) ||
90061e115a5SMichael Buesch 		    (plltype == SSB_PLLTYPE_3))
90161e115a5SMichael Buesch 			m2 += SSB_CHIPCO_CLK_F5_BIAS;
90261e115a5SMichael Buesch 		else
90361e115a5SMichael Buesch 			m2 = clkfactor_f6_resolve(m2);
90461e115a5SMichael Buesch 		m3 = clkfactor_f6_resolve(m3);
90561e115a5SMichael Buesch 
90661e115a5SMichael Buesch 		switch (mc) {
90761e115a5SMichael Buesch 		case SSB_CHIPCO_CLK_MC_BYPASS:
90861e115a5SMichael Buesch 			return clock;
90961e115a5SMichael Buesch 		case SSB_CHIPCO_CLK_MC_M1:
91061e115a5SMichael Buesch 			return (clock / m1);
91161e115a5SMichael Buesch 		case SSB_CHIPCO_CLK_MC_M1M2:
91261e115a5SMichael Buesch 			return (clock / (m1 * m2));
91361e115a5SMichael Buesch 		case SSB_CHIPCO_CLK_MC_M1M2M3:
91461e115a5SMichael Buesch 			return (clock / (m1 * m2 * m3));
91561e115a5SMichael Buesch 		case SSB_CHIPCO_CLK_MC_M1M3:
91661e115a5SMichael Buesch 			return (clock / (m1 * m3));
91761e115a5SMichael Buesch 		}
91861e115a5SMichael Buesch 		return 0;
91961e115a5SMichael Buesch 	case SSB_PLLTYPE_2:
92061e115a5SMichael Buesch 		m1 += SSB_CHIPCO_CLK_T2_BIAS;
92161e115a5SMichael Buesch 		m2 += SSB_CHIPCO_CLK_T2M2_BIAS;
92261e115a5SMichael Buesch 		m3 += SSB_CHIPCO_CLK_T2_BIAS;
923209b4375SMichael Büsch 		WARN_ON(!((m1 >= 2) && (m1 <= 7)));
924209b4375SMichael Büsch 		WARN_ON(!((m2 >= 3) && (m2 <= 10)));
925209b4375SMichael Büsch 		WARN_ON(!((m3 >= 2) && (m3 <= 7)));
92661e115a5SMichael Buesch 
92761e115a5SMichael Buesch 		if (!(mc & SSB_CHIPCO_CLK_T2MC_M1BYP))
92861e115a5SMichael Buesch 			clock /= m1;
92961e115a5SMichael Buesch 		if (!(mc & SSB_CHIPCO_CLK_T2MC_M2BYP))
93061e115a5SMichael Buesch 			clock /= m2;
93161e115a5SMichael Buesch 		if (!(mc & SSB_CHIPCO_CLK_T2MC_M3BYP))
93261e115a5SMichael Buesch 			clock /= m3;
93361e115a5SMichael Buesch 		return clock;
93461e115a5SMichael Buesch 	default:
935209b4375SMichael Büsch 		WARN_ON(1);
93661e115a5SMichael Buesch 	}
93761e115a5SMichael Buesch 	return 0;
93861e115a5SMichael Buesch }
93961e115a5SMichael Buesch 
94061e115a5SMichael Buesch /* Get the current speed the backplane is running at */
ssb_clockspeed(struct ssb_bus * bus)94161e115a5SMichael Buesch u32 ssb_clockspeed(struct ssb_bus *bus)
94261e115a5SMichael Buesch {
94361e115a5SMichael Buesch 	u32 rate;
94461e115a5SMichael Buesch 	u32 plltype;
94561e115a5SMichael Buesch 	u32 clkctl_n, clkctl_m;
94661e115a5SMichael Buesch 
947d486a5b4SHauke Mehrtens 	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
948d486a5b4SHauke Mehrtens 		return ssb_pmu_get_controlclock(&bus->chipco);
949d486a5b4SHauke Mehrtens 
95061e115a5SMichael Buesch 	if (ssb_extif_available(&bus->extif))
95161e115a5SMichael Buesch 		ssb_extif_get_clockcontrol(&bus->extif, &plltype,
95261e115a5SMichael Buesch 					   &clkctl_n, &clkctl_m);
95361e115a5SMichael Buesch 	else if (bus->chipco.dev)
95461e115a5SMichael Buesch 		ssb_chipco_get_clockcontrol(&bus->chipco, &plltype,
95561e115a5SMichael Buesch 					    &clkctl_n, &clkctl_m);
95661e115a5SMichael Buesch 	else
95761e115a5SMichael Buesch 		return 0;
95861e115a5SMichael Buesch 
95961e115a5SMichael Buesch 	if (bus->chip_id == 0x5365) {
96061e115a5SMichael Buesch 		rate = 100000000;
96161e115a5SMichael Buesch 	} else {
96261e115a5SMichael Buesch 		rate = ssb_calc_clock_rate(plltype, clkctl_n, clkctl_m);
96361e115a5SMichael Buesch 		if (plltype == SSB_PLLTYPE_3) /* 25Mhz, 2 dividers */
96461e115a5SMichael Buesch 			rate /= 2;
96561e115a5SMichael Buesch 	}
96661e115a5SMichael Buesch 
96761e115a5SMichael Buesch 	return rate;
96861e115a5SMichael Buesch }
96961e115a5SMichael Buesch EXPORT_SYMBOL(ssb_clockspeed);
97061e115a5SMichael Buesch 
ssb_tmslow_reject_bitmask(struct ssb_device * dev)97161e115a5SMichael Buesch static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
97261e115a5SMichael Buesch {
973c272ef44SLarry Finger 	u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV;
974c272ef44SLarry Finger 
97504ad1fb2SRafał Miłecki 	/* The REJECT bit seems to be different for Backplane rev 2.3 */
976c272ef44SLarry Finger 	switch (rev) {
97761e115a5SMichael Buesch 	case SSB_IDLOW_SSBREV_22:
97804ad1fb2SRafał Miłecki 	case SSB_IDLOW_SSBREV_24:
97904ad1fb2SRafał Miłecki 	case SSB_IDLOW_SSBREV_26:
98004ad1fb2SRafał Miłecki 		return SSB_TMSLOW_REJECT;
98161e115a5SMichael Buesch 	case SSB_IDLOW_SSBREV_23:
98261e115a5SMichael Buesch 		return SSB_TMSLOW_REJECT_23;
98304ad1fb2SRafał Miłecki 	case SSB_IDLOW_SSBREV_25:     /* TODO - find the proper REJECT bit */
984c272ef44SLarry Finger 	case SSB_IDLOW_SSBREV_27:     /* same here */
98504ad1fb2SRafał Miłecki 		return SSB_TMSLOW_REJECT;	/* this is a guess */
98616f7031aSLarry Finger 	case SSB_IDLOW_SSBREV:
98716f7031aSLarry Finger 		break;
98861e115a5SMichael Buesch 	default:
9896cdd6400SCong Ding 		WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
99061e115a5SMichael Buesch 	}
99104ad1fb2SRafał Miłecki 	return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23);
99261e115a5SMichael Buesch }
99361e115a5SMichael Buesch 
ssb_device_is_enabled(struct ssb_device * dev)99461e115a5SMichael Buesch int ssb_device_is_enabled(struct ssb_device *dev)
99561e115a5SMichael Buesch {
99661e115a5SMichael Buesch 	u32 val;
99761e115a5SMichael Buesch 	u32 reject;
99861e115a5SMichael Buesch 
99961e115a5SMichael Buesch 	reject = ssb_tmslow_reject_bitmask(dev);
100061e115a5SMichael Buesch 	val = ssb_read32(dev, SSB_TMSLOW);
100161e115a5SMichael Buesch 	val &= SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET | reject;
100261e115a5SMichael Buesch 
100361e115a5SMichael Buesch 	return (val == SSB_TMSLOW_CLOCK);
100461e115a5SMichael Buesch }
100561e115a5SMichael Buesch EXPORT_SYMBOL(ssb_device_is_enabled);
100661e115a5SMichael Buesch 
ssb_flush_tmslow(struct ssb_device * dev)100761e115a5SMichael Buesch static void ssb_flush_tmslow(struct ssb_device *dev)
100861e115a5SMichael Buesch {
100961e115a5SMichael Buesch 	/* Make _really_ sure the device has finished the TMSLOW
101061e115a5SMichael Buesch 	 * register write transaction, as we risk running into
101161e115a5SMichael Buesch 	 * a machine check exception otherwise.
101261e115a5SMichael Buesch 	 * Do this by reading the register back to commit the
101361e115a5SMichael Buesch 	 * PCI write and delay an additional usec for the device
1014f3028212SShubhankar Kuranagatti 	 * to react to the change.
1015f3028212SShubhankar Kuranagatti 	 */
101661e115a5SMichael Buesch 	ssb_read32(dev, SSB_TMSLOW);
101761e115a5SMichael Buesch 	udelay(1);
101861e115a5SMichael Buesch }
101961e115a5SMichael Buesch 
ssb_device_enable(struct ssb_device * dev,u32 core_specific_flags)102061e115a5SMichael Buesch void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
102161e115a5SMichael Buesch {
102261e115a5SMichael Buesch 	u32 val;
102361e115a5SMichael Buesch 
102461e115a5SMichael Buesch 	ssb_device_disable(dev, core_specific_flags);
102561e115a5SMichael Buesch 	ssb_write32(dev, SSB_TMSLOW,
102661e115a5SMichael Buesch 		    SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |
102761e115a5SMichael Buesch 		    SSB_TMSLOW_FGC | core_specific_flags);
102861e115a5SMichael Buesch 	ssb_flush_tmslow(dev);
102961e115a5SMichael Buesch 
103061e115a5SMichael Buesch 	/* Clear SERR if set. This is a hw bug workaround. */
103161e115a5SMichael Buesch 	if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_SERR)
103261e115a5SMichael Buesch 		ssb_write32(dev, SSB_TMSHIGH, 0);
103361e115a5SMichael Buesch 
103461e115a5SMichael Buesch 	val = ssb_read32(dev, SSB_IMSTATE);
103561e115a5SMichael Buesch 	if (val & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
103661e115a5SMichael Buesch 		val &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
103761e115a5SMichael Buesch 		ssb_write32(dev, SSB_IMSTATE, val);
103861e115a5SMichael Buesch 	}
103961e115a5SMichael Buesch 
104061e115a5SMichael Buesch 	ssb_write32(dev, SSB_TMSLOW,
104161e115a5SMichael Buesch 		    SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC |
104261e115a5SMichael Buesch 		    core_specific_flags);
104361e115a5SMichael Buesch 	ssb_flush_tmslow(dev);
104461e115a5SMichael Buesch 
104561e115a5SMichael Buesch 	ssb_write32(dev, SSB_TMSLOW, SSB_TMSLOW_CLOCK |
104661e115a5SMichael Buesch 		    core_specific_flags);
104761e115a5SMichael Buesch 	ssb_flush_tmslow(dev);
104861e115a5SMichael Buesch }
104961e115a5SMichael Buesch EXPORT_SYMBOL(ssb_device_enable);
105061e115a5SMichael Buesch 
10518c68bd40SMichael Büsch /* Wait for bitmask in a register to get set or cleared.
1052f3028212SShubhankar Kuranagatti  * timeout is in units of ten-microseconds
1053f3028212SShubhankar Kuranagatti  */
ssb_wait_bits(struct ssb_device * dev,u16 reg,u32 bitmask,int timeout,int set)10548c68bd40SMichael Büsch static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask,
105561e115a5SMichael Buesch 			 int timeout, int set)
105661e115a5SMichael Buesch {
105761e115a5SMichael Buesch 	int i;
105861e115a5SMichael Buesch 	u32 val;
105961e115a5SMichael Buesch 
106061e115a5SMichael Buesch 	for (i = 0; i < timeout; i++) {
106161e115a5SMichael Buesch 		val = ssb_read32(dev, reg);
106261e115a5SMichael Buesch 		if (set) {
10638c68bd40SMichael Büsch 			if ((val & bitmask) == bitmask)
106461e115a5SMichael Buesch 				return 0;
106561e115a5SMichael Buesch 		} else {
106661e115a5SMichael Buesch 			if (!(val & bitmask))
106761e115a5SMichael Buesch 				return 0;
106861e115a5SMichael Buesch 		}
106961e115a5SMichael Buesch 		udelay(10);
107061e115a5SMichael Buesch 	}
1071b8b6069cSMichael Büsch 	dev_err(dev->dev,
1072b8b6069cSMichael Büsch 		"Timeout waiting for bitmask %08X on register %04X to %s\n",
1073b8b6069cSMichael Büsch 		bitmask, reg, set ? "set" : "clear");
107461e115a5SMichael Buesch 
107561e115a5SMichael Buesch 	return -ETIMEDOUT;
107661e115a5SMichael Buesch }
107761e115a5SMichael Buesch 
ssb_device_disable(struct ssb_device * dev,u32 core_specific_flags)107861e115a5SMichael Buesch void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
107961e115a5SMichael Buesch {
1080b1a1bcf7SRafał Miłecki 	u32 reject, val;
108161e115a5SMichael Buesch 
108261e115a5SMichael Buesch 	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)
108361e115a5SMichael Buesch 		return;
108461e115a5SMichael Buesch 
108561e115a5SMichael Buesch 	reject = ssb_tmslow_reject_bitmask(dev);
1086011d1835SRafał Miłecki 
1087011d1835SRafał Miłecki 	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_CLOCK) {
108861e115a5SMichael Buesch 		ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
10898c68bd40SMichael Büsch 		ssb_wait_bits(dev, SSB_TMSLOW, reject, 1000, 1);
10908c68bd40SMichael Büsch 		ssb_wait_bits(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
1091b1a1bcf7SRafał Miłecki 
1092b1a1bcf7SRafał Miłecki 		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) {
1093b1a1bcf7SRafał Miłecki 			val = ssb_read32(dev, SSB_IMSTATE);
1094b1a1bcf7SRafał Miłecki 			val |= SSB_IMSTATE_REJECT;
1095b1a1bcf7SRafał Miłecki 			ssb_write32(dev, SSB_IMSTATE, val);
1096011d1835SRafał Miłecki 			ssb_wait_bits(dev, SSB_IMSTATE, SSB_IMSTATE_BUSY, 1000,
1097011d1835SRafał Miłecki 				      0);
1098b1a1bcf7SRafał Miłecki 		}
1099b1a1bcf7SRafał Miłecki 
110061e115a5SMichael Buesch 		ssb_write32(dev, SSB_TMSLOW,
110161e115a5SMichael Buesch 			SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
110261e115a5SMichael Buesch 			reject | SSB_TMSLOW_RESET |
110361e115a5SMichael Buesch 			core_specific_flags);
110461e115a5SMichael Buesch 		ssb_flush_tmslow(dev);
110561e115a5SMichael Buesch 
1106b1a1bcf7SRafał Miłecki 		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) {
1107b1a1bcf7SRafał Miłecki 			val = ssb_read32(dev, SSB_IMSTATE);
1108b1a1bcf7SRafał Miłecki 			val &= ~SSB_IMSTATE_REJECT;
1109b1a1bcf7SRafał Miłecki 			ssb_write32(dev, SSB_IMSTATE, val);
1110b1a1bcf7SRafał Miłecki 		}
1111011d1835SRafał Miłecki 	}
1112b1a1bcf7SRafał Miłecki 
111361e115a5SMichael Buesch 	ssb_write32(dev, SSB_TMSLOW,
111461e115a5SMichael Buesch 		    reject | SSB_TMSLOW_RESET |
111561e115a5SMichael Buesch 		    core_specific_flags);
111661e115a5SMichael Buesch 	ssb_flush_tmslow(dev);
111761e115a5SMichael Buesch }
111861e115a5SMichael Buesch EXPORT_SYMBOL(ssb_device_disable);
111961e115a5SMichael Buesch 
112004023afcSRafał Miłecki /* Some chipsets need routing known for PCIe and 64-bit DMA */
ssb_dma_translation_special_bit(struct ssb_device * dev)112104023afcSRafał Miłecki static bool ssb_dma_translation_special_bit(struct ssb_device *dev)
112204023afcSRafał Miłecki {
112304023afcSRafał Miłecki 	u16 chip_id = dev->bus->chip_id;
112404023afcSRafał Miłecki 
112504023afcSRafał Miłecki 	if (dev->id.coreid == SSB_DEV_80211) {
112604023afcSRafał Miłecki 		return (chip_id == 0x4322 || chip_id == 43221 ||
112704023afcSRafał Miłecki 			chip_id == 43231 || chip_id == 43222);
112804023afcSRafał Miłecki 	}
112904023afcSRafał Miłecki 
1130bd42cd02SGustavo A. R. Silva 	return false;
113104023afcSRafał Miłecki }
113204023afcSRafał Miłecki 
ssb_dma_translation(struct ssb_device * dev)113361e115a5SMichael Buesch u32 ssb_dma_translation(struct ssb_device *dev)
113461e115a5SMichael Buesch {
113561e115a5SMichael Buesch 	switch (dev->bus->bustype) {
113661e115a5SMichael Buesch 	case SSB_BUSTYPE_SSB:
113761e115a5SMichael Buesch 		return 0;
113861e115a5SMichael Buesch 	case SSB_BUSTYPE_PCI:
113904023afcSRafał Miłecki 		if (pci_is_pcie(dev->bus->host_pci) &&
114004023afcSRafał Miłecki 		    ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) {
114104023afcSRafał Miłecki 			return SSB_PCIE_DMA_H32;
114204023afcSRafał Miłecki 		} else {
114304023afcSRafał Miłecki 			if (ssb_dma_translation_special_bit(dev))
1144a9770a81SRafał Miłecki 				return SSB_PCIE_DMA_H32;
1145a9770a81SRafał Miłecki 			else
114661e115a5SMichael Buesch 				return SSB_PCI_DMA;
114704023afcSRafał Miłecki 		}
1148f225763aSMichael Buesch 	default:
1149f225763aSMichael Buesch 		__ssb_dma_not_implemented(dev);
115061e115a5SMichael Buesch 	}
115161e115a5SMichael Buesch 	return 0;
115261e115a5SMichael Buesch }
115361e115a5SMichael Buesch EXPORT_SYMBOL(ssb_dma_translation);
115461e115a5SMichael Buesch 
ssb_bus_may_powerdown(struct ssb_bus * bus)115561e115a5SMichael Buesch int ssb_bus_may_powerdown(struct ssb_bus *bus)
115661e115a5SMichael Buesch {
115761e115a5SMichael Buesch 	struct ssb_chipcommon *cc;
115861e115a5SMichael Buesch 	int err = 0;
115961e115a5SMichael Buesch 
116061e115a5SMichael Buesch 	/* On buses where more than one core may be working
116161e115a5SMichael Buesch 	 * at a time, we must not powerdown stuff if there are
1162f3028212SShubhankar Kuranagatti 	 * still cores that may want to run.
1163f3028212SShubhankar Kuranagatti 	 */
116461e115a5SMichael Buesch 	if (bus->bustype == SSB_BUSTYPE_SSB)
116561e115a5SMichael Buesch 		goto out;
116661e115a5SMichael Buesch 
116761e115a5SMichael Buesch 	cc = &bus->chipco;
1168881400a2SStefano Brivio 
1169881400a2SStefano Brivio 	if (!cc->dev)
1170881400a2SStefano Brivio 		goto out;
1171881400a2SStefano Brivio 	if (cc->dev->id.revision < 5)
1172881400a2SStefano Brivio 		goto out;
1173881400a2SStefano Brivio 
117461e115a5SMichael Buesch 	ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW);
117561e115a5SMichael Buesch 	err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
117661e115a5SMichael Buesch 	if (err)
117761e115a5SMichael Buesch 		goto error;
117861e115a5SMichael Buesch out:
117961e115a5SMichael Buesch 	bus->powered_up = 0;
118061e115a5SMichael Buesch 	return err;
118161e115a5SMichael Buesch error:
1182b8b6069cSMichael Büsch 	pr_err("Bus powerdown failed\n");
118361e115a5SMichael Buesch 	goto out;
118461e115a5SMichael Buesch }
118561e115a5SMichael Buesch EXPORT_SYMBOL(ssb_bus_may_powerdown);
118661e115a5SMichael Buesch 
ssb_bus_powerup(struct ssb_bus * bus,bool dynamic_pctl)118761e115a5SMichael Buesch int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl)
118861e115a5SMichael Buesch {
118961e115a5SMichael Buesch 	int err;
119061e115a5SMichael Buesch 	enum ssb_clkmode mode;
119161e115a5SMichael Buesch 
119261e115a5SMichael Buesch 	err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
119361e115a5SMichael Buesch 	if (err)
119461e115a5SMichael Buesch 		goto error;
119561e115a5SMichael Buesch 
119661e115a5SMichael Buesch 	bus->powered_up = 1;
1197a6ef8143SRafał Miłecki 
1198a6ef8143SRafał Miłecki 	mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST;
1199a6ef8143SRafał Miłecki 	ssb_chipco_set_clockmode(&bus->chipco, mode);
1200a6ef8143SRafał Miłecki 
120161e115a5SMichael Buesch 	return 0;
120261e115a5SMichael Buesch error:
1203b8b6069cSMichael Büsch 	pr_err("Bus powerup failed\n");
120461e115a5SMichael Buesch 	return err;
120561e115a5SMichael Buesch }
120661e115a5SMichael Buesch EXPORT_SYMBOL(ssb_bus_powerup);
120761e115a5SMichael Buesch 
ssb_broadcast_value(struct ssb_device * dev,u32 address,u32 data)12088576f815SRafał Miłecki static void ssb_broadcast_value(struct ssb_device *dev,
12098576f815SRafał Miłecki 				u32 address, u32 data)
12108576f815SRafał Miłecki {
12111159024dSJohn W. Linville #ifdef CONFIG_SSB_DRIVER_PCICORE
12128576f815SRafał Miłecki 	/* This is used for both, PCI and ChipCommon core, so be careful. */
12138576f815SRafał Miłecki 	BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR);
12148576f815SRafał Miłecki 	BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA);
12151159024dSJohn W. Linville #endif
12168576f815SRafał Miłecki 
12171159024dSJohn W. Linville 	ssb_write32(dev, SSB_CHIPCO_BCAST_ADDR, address);
12181159024dSJohn W. Linville 	ssb_read32(dev, SSB_CHIPCO_BCAST_ADDR); /* flush */
12191159024dSJohn W. Linville 	ssb_write32(dev, SSB_CHIPCO_BCAST_DATA, data);
12201159024dSJohn W. Linville 	ssb_read32(dev, SSB_CHIPCO_BCAST_DATA); /* flush */
12218576f815SRafał Miłecki }
12228576f815SRafał Miłecki 
ssb_commit_settings(struct ssb_bus * bus)12238576f815SRafał Miłecki void ssb_commit_settings(struct ssb_bus *bus)
12248576f815SRafał Miłecki {
12258576f815SRafał Miłecki 	struct ssb_device *dev;
12268576f815SRafał Miłecki 
12271159024dSJohn W. Linville #ifdef CONFIG_SSB_DRIVER_PCICORE
12288576f815SRafał Miłecki 	dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev;
12291159024dSJohn W. Linville #else
12301159024dSJohn W. Linville 	dev = bus->chipco.dev;
12311159024dSJohn W. Linville #endif
12328576f815SRafał Miłecki 	if (WARN_ON(!dev))
12338576f815SRafał Miłecki 		return;
12348576f815SRafał Miłecki 	/* This forces an update of the cached registers. */
12358576f815SRafał Miłecki 	ssb_broadcast_value(dev, 0xFD8, 0);
12368576f815SRafał Miłecki }
12378576f815SRafał Miłecki EXPORT_SYMBOL(ssb_commit_settings);
12388576f815SRafał Miłecki 
ssb_admatch_base(u32 adm)123961e115a5SMichael Buesch u32 ssb_admatch_base(u32 adm)
124061e115a5SMichael Buesch {
124161e115a5SMichael Buesch 	u32 base = 0;
124261e115a5SMichael Buesch 
124361e115a5SMichael Buesch 	switch (adm & SSB_ADM_TYPE) {
124461e115a5SMichael Buesch 	case SSB_ADM_TYPE0:
124561e115a5SMichael Buesch 		base = (adm & SSB_ADM_BASE0);
124661e115a5SMichael Buesch 		break;
124761e115a5SMichael Buesch 	case SSB_ADM_TYPE1:
1248209b4375SMichael Büsch 		WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
124961e115a5SMichael Buesch 		base = (adm & SSB_ADM_BASE1);
125061e115a5SMichael Buesch 		break;
125161e115a5SMichael Buesch 	case SSB_ADM_TYPE2:
1252209b4375SMichael Büsch 		WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
125361e115a5SMichael Buesch 		base = (adm & SSB_ADM_BASE2);
125461e115a5SMichael Buesch 		break;
125561e115a5SMichael Buesch 	default:
1256209b4375SMichael Büsch 		WARN_ON(1);
125761e115a5SMichael Buesch 	}
125861e115a5SMichael Buesch 
125961e115a5SMichael Buesch 	return base;
126061e115a5SMichael Buesch }
126161e115a5SMichael Buesch EXPORT_SYMBOL(ssb_admatch_base);
126261e115a5SMichael Buesch 
ssb_admatch_size(u32 adm)126361e115a5SMichael Buesch u32 ssb_admatch_size(u32 adm)
126461e115a5SMichael Buesch {
126561e115a5SMichael Buesch 	u32 size = 0;
126661e115a5SMichael Buesch 
126761e115a5SMichael Buesch 	switch (adm & SSB_ADM_TYPE) {
126861e115a5SMichael Buesch 	case SSB_ADM_TYPE0:
126961e115a5SMichael Buesch 		size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT);
127061e115a5SMichael Buesch 		break;
127161e115a5SMichael Buesch 	case SSB_ADM_TYPE1:
1272209b4375SMichael Büsch 		WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
127361e115a5SMichael Buesch 		size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT);
127461e115a5SMichael Buesch 		break;
127561e115a5SMichael Buesch 	case SSB_ADM_TYPE2:
1276209b4375SMichael Büsch 		WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
127761e115a5SMichael Buesch 		size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT);
127861e115a5SMichael Buesch 		break;
127961e115a5SMichael Buesch 	default:
1280209b4375SMichael Büsch 		WARN_ON(1);
128161e115a5SMichael Buesch 	}
128261e115a5SMichael Buesch 	size = (1 << (size + 1));
128361e115a5SMichael Buesch 
128461e115a5SMichael Buesch 	return size;
128561e115a5SMichael Buesch }
128661e115a5SMichael Buesch EXPORT_SYMBOL(ssb_admatch_size);
128761e115a5SMichael Buesch 
ssb_modinit(void)128861e115a5SMichael Buesch static int __init ssb_modinit(void)
128961e115a5SMichael Buesch {
129061e115a5SMichael Buesch 	int err;
129161e115a5SMichael Buesch 
129261e115a5SMichael Buesch 	/* See the comment at the ssb_is_early_boot definition */
129361e115a5SMichael Buesch 	ssb_is_early_boot = 0;
129461e115a5SMichael Buesch 	err = bus_register(&ssb_bustype);
129561e115a5SMichael Buesch 	if (err)
129661e115a5SMichael Buesch 		return err;
129761e115a5SMichael Buesch 
129861e115a5SMichael Buesch 	/* Maybe we already registered some buses at early boot.
129961e115a5SMichael Buesch 	 * Check for this and attach them
130061e115a5SMichael Buesch 	 */
130161e115a5SMichael Buesch 	ssb_buses_lock();
130261e115a5SMichael Buesch 	err = ssb_attach_queued_buses();
130361e115a5SMichael Buesch 	ssb_buses_unlock();
1304e6c463e3SMichael Buesch 	if (err) {
130561e115a5SMichael Buesch 		bus_unregister(&ssb_bustype);
1306e6c463e3SMichael Buesch 		goto out;
1307e6c463e3SMichael Buesch 	}
130861e115a5SMichael Buesch 
130961e115a5SMichael Buesch 	err = b43_pci_ssb_bridge_init();
131061e115a5SMichael Buesch 	if (err) {
1311b8b6069cSMichael Büsch 		pr_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n");
1312aab547ceSMichael Buesch 		/* don't fail SSB init because of this */
1313aab547ceSMichael Buesch 	}
1314399500daSRafał Miłecki 	err = ssb_host_pcmcia_init();
1315399500daSRafał Miłecki 	if (err) {
1316b8b6069cSMichael Büsch 		pr_err("PCMCIA host initialization failed\n");
1317399500daSRafał Miłecki 		/* don't fail SSB init because of this */
1318399500daSRafał Miłecki 	}
1319aab547ceSMichael Buesch 	err = ssb_gige_init();
1320aab547ceSMichael Buesch 	if (err) {
1321b8b6069cSMichael Büsch 		pr_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
132261e115a5SMichael Buesch 		/* don't fail SSB init because of this */
132361e115a5SMichael Buesch 		err = 0;
132461e115a5SMichael Buesch 	}
1325e6c463e3SMichael Buesch out:
132661e115a5SMichael Buesch 	return err;
132761e115a5SMichael Buesch }
13288d8c90e3SMichael Buesch /* ssb must be initialized after PCI but before the ssb drivers.
13298d8c90e3SMichael Buesch  * That means we must use some initcall between subsys_initcall
1330f3028212SShubhankar Kuranagatti  * and device_initcall.
1331f3028212SShubhankar Kuranagatti  */
13328d8c90e3SMichael Buesch fs_initcall(ssb_modinit);
133361e115a5SMichael Buesch 
ssb_modexit(void)133461e115a5SMichael Buesch static void __exit ssb_modexit(void)
133561e115a5SMichael Buesch {
1336aab547ceSMichael Buesch 	ssb_gige_exit();
1337399500daSRafał Miłecki 	ssb_host_pcmcia_exit();
133861e115a5SMichael Buesch 	b43_pci_ssb_bridge_exit();
133961e115a5SMichael Buesch 	bus_unregister(&ssb_bustype);
134061e115a5SMichael Buesch }
134161e115a5SMichael Buesch module_exit(ssb_modexit)
1342