brintos

brintos / linux-shallow public Read only

0
0
Text · 19.1 KiB · 4550209 Raw
832 lines · c
1/*2 * Sonics Silicon Backplane3 * PCMCIA-Hostbus related functions4 *5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>6 * Copyright 2007-2008 Michael Buesch <m@bues.ch>7 *8 * Licensed under the GNU/GPL. See COPYING for details.9 */10 11#include "ssb_private.h"12 13#include <linux/ssb/ssb.h>14#include <linux/delay.h>15#include <linux/io.h>16#include <linux/etherdevice.h>17 18#include <pcmcia/cistpl.h>19#include <pcmcia/ciscode.h>20#include <pcmcia/ds.h>21#include <pcmcia/cisreg.h>22 23 24/* Define the following to 1 to enable a printk on each coreswitch. */25#define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG		026 27 28/* PCMCIA configuration registers */29#define SSB_PCMCIA_ADDRESS0		0x2E30#define SSB_PCMCIA_ADDRESS1		0x3031#define SSB_PCMCIA_ADDRESS2		0x3232#define SSB_PCMCIA_MEMSEG		0x3433#define SSB_PCMCIA_SPROMCTL		0x3634#define  SSB_PCMCIA_SPROMCTL_IDLE	035#define  SSB_PCMCIA_SPROMCTL_WRITE	136#define  SSB_PCMCIA_SPROMCTL_READ	237#define  SSB_PCMCIA_SPROMCTL_WRITEEN	438#define  SSB_PCMCIA_SPROMCTL_WRITEDIS	739#define  SSB_PCMCIA_SPROMCTL_DONE	840#define SSB_PCMCIA_SPROM_DATALO		0x3841#define SSB_PCMCIA_SPROM_DATAHI		0x3A42#define SSB_PCMCIA_SPROM_ADDRLO		0x3C43#define SSB_PCMCIA_SPROM_ADDRHI		0x3E44 45/* Hardware invariants CIS tuples */46#define SSB_PCMCIA_CIS			0x8047#define  SSB_PCMCIA_CIS_ID		0x0148#define  SSB_PCMCIA_CIS_BOARDREV	0x0249#define  SSB_PCMCIA_CIS_PA		0x0350#define   SSB_PCMCIA_CIS_PA_PA0B0_LO	051#define   SSB_PCMCIA_CIS_PA_PA0B0_HI	152#define   SSB_PCMCIA_CIS_PA_PA0B1_LO	253#define   SSB_PCMCIA_CIS_PA_PA0B1_HI	354#define   SSB_PCMCIA_CIS_PA_PA0B2_LO	455#define   SSB_PCMCIA_CIS_PA_PA0B2_HI	556#define   SSB_PCMCIA_CIS_PA_ITSSI	657#define   SSB_PCMCIA_CIS_PA_MAXPOW	758#define  SSB_PCMCIA_CIS_OEMNAME		0x0459#define  SSB_PCMCIA_CIS_CCODE		0x0560#define  SSB_PCMCIA_CIS_ANTENNA		0x0661#define  SSB_PCMCIA_CIS_ANTGAIN		0x0762#define  SSB_PCMCIA_CIS_BFLAGS		0x0863#define  SSB_PCMCIA_CIS_LEDS		0x0964 65/* PCMCIA SPROM size. */66#define SSB_PCMCIA_SPROM_SIZE		25667#define SSB_PCMCIA_SPROM_SIZE_BYTES	(SSB_PCMCIA_SPROM_SIZE * sizeof(u16))68 69 70/* Write to a PCMCIA configuration register. */71static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)72{73	int res;74 75	res = pcmcia_write_config_byte(bus->host_pcmcia, offset, value);76	if (unlikely(res != 0))77		return -EBUSY;78 79	return 0;80}81 82/* Read from a PCMCIA configuration register. */83static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)84{85	int res;86 87	res = pcmcia_read_config_byte(bus->host_pcmcia, offset, value);88	if (unlikely(res != 0))89		return -EBUSY;90 91	return 0;92}93 94int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,95			      u8 coreidx)96{97	int err;98	int attempts = 0;99	u32 cur_core;100	u32 addr;101	u32 read_addr;102	u8 val;103 104	addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;105	while (1) {106		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,107					   (addr & 0x0000F000) >> 12);108		if (err)109			goto error;110		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,111					   (addr & 0x00FF0000) >> 16);112		if (err)113			goto error;114		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,115					   (addr & 0xFF000000) >> 24);116		if (err)117			goto error;118 119		read_addr = 0;120 121		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);122		if (err)123			goto error;124		read_addr |= ((u32)(val & 0x0F)) << 12;125		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);126		if (err)127			goto error;128		read_addr |= ((u32)val) << 16;129		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);130		if (err)131			goto error;132		read_addr |= ((u32)val) << 24;133 134		cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;135		if (cur_core == coreidx)136			break;137 138		err = -ETIMEDOUT;139		if (attempts++ > SSB_BAR0_MAX_RETRIES)140			goto error;141		udelay(10);142	}143 144	return 0;145error:146	pr_err("Failed to switch to core %u\n", coreidx);147	return err;148}149 150static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev)151{152	int err;153 154#if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG155	pr_info("Switching to %s core, index %d\n",156		ssb_core_name(dev->id.coreid), dev->core_index);157#endif158 159	err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);160	if (!err)161		bus->mapped_device = dev;162 163	return err;164}165 166int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)167{168	int attempts = 0;169	int err;170	u8 val;171 172	WARN_ON((seg != 0) && (seg != 1));173	while (1) {174		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);175		if (err)176			goto error;177		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);178		if (err)179			goto error;180		if (val == seg)181			break;182 183		err = -ETIMEDOUT;184		if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))185			goto error;186		udelay(10);187	}188	bus->mapped_pcmcia_seg = seg;189 190	return 0;191error:192	pr_err("Failed to switch pcmcia segment\n");193	return err;194}195 196static int select_core_and_segment(struct ssb_device *dev,197				   u16 *offset)198{199	struct ssb_bus *bus = dev->bus;200	int err;201	u8 need_segment;202 203	if (*offset >= 0x800) {204		*offset -= 0x800;205		need_segment = 1;206	} else207		need_segment = 0;208 209	if (unlikely(dev != bus->mapped_device)) {210		err = ssb_pcmcia_switch_core(bus, dev);211		if (unlikely(err))212			return err;213	}214	if (unlikely(need_segment != bus->mapped_pcmcia_seg)) {215		err = ssb_pcmcia_switch_segment(bus, need_segment);216		if (unlikely(err))217			return err;218	}219 220	return 0;221}222 223static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)224{225	struct ssb_bus *bus = dev->bus;226	unsigned long flags;227	int err;228	u8 value = 0xFF;229 230	spin_lock_irqsave(&bus->bar_lock, flags);231	err = select_core_and_segment(dev, &offset);232	if (likely(!err))233		value = readb(bus->mmio + offset);234	spin_unlock_irqrestore(&bus->bar_lock, flags);235 236	return value;237}238 239static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)240{241	struct ssb_bus *bus = dev->bus;242	unsigned long flags;243	int err;244	u16 value = 0xFFFF;245 246	spin_lock_irqsave(&bus->bar_lock, flags);247	err = select_core_and_segment(dev, &offset);248	if (likely(!err))249		value = readw(bus->mmio + offset);250	spin_unlock_irqrestore(&bus->bar_lock, flags);251 252	return value;253}254 255static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)256{257	struct ssb_bus *bus = dev->bus;258	unsigned long flags;259	int err;260	u32 lo = 0xFFFFFFFF, hi = 0xFFFFFFFF;261 262	spin_lock_irqsave(&bus->bar_lock, flags);263	err = select_core_and_segment(dev, &offset);264	if (likely(!err)) {265		lo = readw(bus->mmio + offset);266		hi = readw(bus->mmio + offset + 2);267	}268	spin_unlock_irqrestore(&bus->bar_lock, flags);269 270	return (lo | (hi << 16));271}272 273#ifdef CONFIG_SSB_BLOCKIO274static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,275				  size_t count, u16 offset, u8 reg_width)276{277	struct ssb_bus *bus = dev->bus;278	unsigned long flags;279	void __iomem *addr = bus->mmio + offset;280	int err;281 282	spin_lock_irqsave(&bus->bar_lock, flags);283	err = select_core_and_segment(dev, &offset);284	if (unlikely(err)) {285		memset(buffer, 0xFF, count);286		goto unlock;287	}288	switch (reg_width) {289	case sizeof(u8): {290		u8 *buf = buffer;291 292		while (count) {293			*buf = __raw_readb(addr);294			buf++;295			count--;296		}297		break;298	}299	case sizeof(u16): {300		__le16 *buf = buffer;301 302		WARN_ON(count & 1);303		while (count) {304			*buf = (__force __le16)__raw_readw(addr);305			buf++;306			count -= 2;307		}308		break;309	}310	case sizeof(u32): {311		__le16 *buf = buffer;312 313		WARN_ON(count & 3);314		while (count) {315			*buf = (__force __le16)__raw_readw(addr);316			buf++;317			*buf = (__force __le16)__raw_readw(addr + 2);318			buf++;319			count -= 4;320		}321		break;322	}323	default:324		WARN_ON(1);325	}326unlock:327	spin_unlock_irqrestore(&bus->bar_lock, flags);328}329#endif /* CONFIG_SSB_BLOCKIO */330 331static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)332{333	struct ssb_bus *bus = dev->bus;334	unsigned long flags;335	int err;336 337	spin_lock_irqsave(&bus->bar_lock, flags);338	err = select_core_and_segment(dev, &offset);339	if (likely(!err))340		writeb(value, bus->mmio + offset);341	spin_unlock_irqrestore(&bus->bar_lock, flags);342}343 344static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)345{346	struct ssb_bus *bus = dev->bus;347	unsigned long flags;348	int err;349 350	spin_lock_irqsave(&bus->bar_lock, flags);351	err = select_core_and_segment(dev, &offset);352	if (likely(!err))353		writew(value, bus->mmio + offset);354	spin_unlock_irqrestore(&bus->bar_lock, flags);355}356 357static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)358{359	struct ssb_bus *bus = dev->bus;360	unsigned long flags;361	int err;362 363	spin_lock_irqsave(&bus->bar_lock, flags);364	err = select_core_and_segment(dev, &offset);365	if (likely(!err)) {366		writew((value & 0x0000FFFF), bus->mmio + offset);367		writew(((value & 0xFFFF0000) >> 16), bus->mmio + offset + 2);368	}369	spin_unlock_irqrestore(&bus->bar_lock, flags);370}371 372#ifdef CONFIG_SSB_BLOCKIO373static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,374				   size_t count, u16 offset, u8 reg_width)375{376	struct ssb_bus *bus = dev->bus;377	unsigned long flags;378	void __iomem *addr = bus->mmio + offset;379	int err;380 381	spin_lock_irqsave(&bus->bar_lock, flags);382	err = select_core_and_segment(dev, &offset);383	if (unlikely(err))384		goto unlock;385	switch (reg_width) {386	case sizeof(u8): {387		const u8 *buf = buffer;388 389		while (count) {390			__raw_writeb(*buf, addr);391			buf++;392			count--;393		}394		break;395	}396	case sizeof(u16): {397		const __le16 *buf = buffer;398 399		WARN_ON(count & 1);400		while (count) {401			__raw_writew((__force u16)(*buf), addr);402			buf++;403			count -= 2;404		}405		break;406	}407	case sizeof(u32): {408		const __le16 *buf = buffer;409 410		WARN_ON(count & 3);411		while (count) {412			__raw_writew((__force u16)(*buf), addr);413			buf++;414			__raw_writew((__force u16)(*buf), addr + 2);415			buf++;416			count -= 4;417		}418		break;419	}420	default:421		WARN_ON(1);422	}423unlock:424	spin_unlock_irqrestore(&bus->bar_lock, flags);425}426#endif /* CONFIG_SSB_BLOCKIO */427 428/* Not "static", as it's used in main.c */429const struct ssb_bus_ops ssb_pcmcia_ops = {430	.read8		= ssb_pcmcia_read8,431	.read16		= ssb_pcmcia_read16,432	.read32		= ssb_pcmcia_read32,433	.write8		= ssb_pcmcia_write8,434	.write16	= ssb_pcmcia_write16,435	.write32	= ssb_pcmcia_write32,436#ifdef CONFIG_SSB_BLOCKIO437	.block_read	= ssb_pcmcia_block_read,438	.block_write	= ssb_pcmcia_block_write,439#endif440};441 442static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)443{444	unsigned int i;445	int err;446	u8 value;447 448	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);449	if (err)450		return err;451	for (i = 0; i < 1000; i++) {452		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);453		if (err)454			return err;455		if (value & SSB_PCMCIA_SPROMCTL_DONE)456			return 0;457		udelay(10);458	}459 460	return -ETIMEDOUT;461}462 463/* offset is the 16bit word offset */464static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)465{466	int err;467	u8 lo, hi;468 469	offset *= 2; /* Make byte offset */470 471	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,472				   (offset & 0x00FF));473	if (err)474		return err;475	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,476				   (offset & 0xFF00) >> 8);477	if (err)478		return err;479	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);480	if (err)481		return err;482	err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);483	if (err)484		return err;485	err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);486	if (err)487		return err;488	*value = (lo | (((u16)hi) << 8));489 490	return 0;491}492 493/* offset is the 16bit word offset */494static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)495{496	int err;497 498	offset *= 2; /* Make byte offset */499 500	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,501				   (offset & 0x00FF));502	if (err)503		return err;504	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,505				   (offset & 0xFF00) >> 8);506	if (err)507		return err;508	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,509				   (value & 0x00FF));510	if (err)511		return err;512	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,513				   (value & 0xFF00) >> 8);514	if (err)515		return err;516	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);517	if (err)518		return err;519	msleep(20);520 521	return 0;522}523 524/* Read the SPROM image. bufsize is in 16bit words. */525static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)526{527	int err, i;528 529	for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {530		err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);531		if (err)532			return err;533	}534 535	return 0;536}537 538/* Write the SPROM image. size is in 16bit words. */539static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)540{541	int i, err;542	bool failed = 0;543	size_t size = SSB_PCMCIA_SPROM_SIZE;544 545	pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");546	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);547	if (err) {548		pr_notice("Could not enable SPROM write access\n");549		return -EBUSY;550	}551	pr_notice("[ 0%%");552	msleep(500);553	for (i = 0; i < size; i++) {554		if (i == size / 4)555			pr_cont("25%%");556		else if (i == size / 2)557			pr_cont("50%%");558		else if (i == (size * 3) / 4)559			pr_cont("75%%");560		else if (i % 2)561			pr_cont(".");562		err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);563		if (err) {564			pr_notice("Failed to write to SPROM\n");565			failed = 1;566			break;567		}568	}569	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);570	if (err) {571		pr_notice("Could not disable SPROM write access\n");572		failed = 1;573	}574	msleep(500);575	if (!failed) {576		pr_cont("100%% ]\n");577		pr_notice("SPROM written\n");578	}579 580	return failed ? -EBUSY : 0;581}582 583static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)584{585	//TODO586	return 0;587}588 589#define GOTO_ERROR_ON(condition, description) do {	\590	if (unlikely(condition)) {			\591		error_description = description;	\592		goto error;				\593	}						\594  } while (0)595 596static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev,597			tuple_t *tuple,598			void *priv)599{600	struct ssb_sprom *sprom = priv;601 602	if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)603		return -EINVAL;604	if (tuple->TupleDataLen != ETH_ALEN + 2)605		return -EINVAL;606	if (tuple->TupleData[1] != ETH_ALEN)607		return -EINVAL;608	memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN);609	return 0;610};611 612static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,613					tuple_t *tuple,614					void *priv)615{616	struct ssb_init_invariants *iv = priv;617	struct ssb_sprom *sprom = &iv->sprom;618	struct ssb_boardinfo *bi = &iv->boardinfo;619	const char *error_description;620 621	GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1");622	switch (tuple->TupleData[0]) {623	case SSB_PCMCIA_CIS_ID:624		GOTO_ERROR_ON((tuple->TupleDataLen != 5) &&625			      (tuple->TupleDataLen != 7),626			      "id tpl size");627		bi->vendor = tuple->TupleData[1] |628			((u16)tuple->TupleData[2] << 8);629		break;630	case SSB_PCMCIA_CIS_BOARDREV:631		GOTO_ERROR_ON(tuple->TupleDataLen != 2,632			"boardrev tpl size");633		sprom->board_rev = tuple->TupleData[1];634		break;635	case SSB_PCMCIA_CIS_PA:636		GOTO_ERROR_ON((tuple->TupleDataLen != 9) &&637			(tuple->TupleDataLen != 10),638			"pa tpl size");639		sprom->pa0b0 = tuple->TupleData[1] |640			((u16)tuple->TupleData[2] << 8);641		sprom->pa0b1 = tuple->TupleData[3] |642			((u16)tuple->TupleData[4] << 8);643		sprom->pa0b2 = tuple->TupleData[5] |644			((u16)tuple->TupleData[6] << 8);645		sprom->itssi_a = tuple->TupleData[7];646		sprom->itssi_bg = tuple->TupleData[7];647		sprom->maxpwr_a = tuple->TupleData[8];648		sprom->maxpwr_bg = tuple->TupleData[8];649		break;650	case SSB_PCMCIA_CIS_OEMNAME:651		/* We ignore this. */652		break;653	case SSB_PCMCIA_CIS_CCODE:654		GOTO_ERROR_ON(tuple->TupleDataLen != 2,655			"ccode tpl size");656		sprom->country_code = tuple->TupleData[1];657		break;658	case SSB_PCMCIA_CIS_ANTENNA:659		GOTO_ERROR_ON(tuple->TupleDataLen != 2,660			"ant tpl size");661		sprom->ant_available_a = tuple->TupleData[1];662		sprom->ant_available_bg = tuple->TupleData[1];663		break;664	case SSB_PCMCIA_CIS_ANTGAIN:665		GOTO_ERROR_ON(tuple->TupleDataLen != 2,666			"antg tpl size");667		sprom->antenna_gain.a0 = tuple->TupleData[1];668		sprom->antenna_gain.a1 = tuple->TupleData[1];669		sprom->antenna_gain.a2 = tuple->TupleData[1];670		sprom->antenna_gain.a3 = tuple->TupleData[1];671		break;672	case SSB_PCMCIA_CIS_BFLAGS:673		GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&674			(tuple->TupleDataLen != 5),675			"bfl tpl size");676		sprom->boardflags_lo = tuple->TupleData[1] |677			((u16)tuple->TupleData[2] << 8);678		break;679	case SSB_PCMCIA_CIS_LEDS:680		GOTO_ERROR_ON(tuple->TupleDataLen != 5,681			"leds tpl size");682		sprom->gpio0 = tuple->TupleData[1];683		sprom->gpio1 = tuple->TupleData[2];684		sprom->gpio2 = tuple->TupleData[3];685		sprom->gpio3 = tuple->TupleData[4];686		break;687	}688	return -ENOSPC; /* continue with next entry */689 690error:691	pr_err("PCMCIA: Failed to fetch device invariants: %s\n",692	       error_description);693	return -ENODEV;694}695 696 697int ssb_pcmcia_get_invariants(struct ssb_bus *bus,698			      struct ssb_init_invariants *iv)699{700	struct ssb_sprom *sprom = &iv->sprom;701	int res;702 703	memset(sprom, 0xFF, sizeof(*sprom));704	sprom->revision = 1;705	sprom->boardflags_lo = 0;706	sprom->boardflags_hi = 0;707 708	/* First fetch the MAC address. */709	res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,710				ssb_pcmcia_get_mac, sprom);711	if (res != 0) {712		pr_err("PCMCIA: Failed to fetch MAC address\n");713		return -ENODEV;714	}715 716	/* Fetch the vendor specific tuples. */717	res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS,718				ssb_pcmcia_do_get_invariants, iv);719	if ((res == 0) || (res == -ENOSPC))720		return 0;721 722	pr_err("PCMCIA: Failed to fetch device invariants\n");723	return -ENODEV;724}725 726static ssize_t ssb_sprom_show(struct device *pcmciadev,727			      struct device_attribute *attr,728			      char *buf)729{730	struct pcmcia_device *pdev =731		container_of(pcmciadev, struct pcmcia_device, dev);732	struct ssb_bus *bus;733 734	bus = ssb_pcmcia_dev_to_bus(pdev);735	if (!bus)736		return -ENODEV;737 738	return ssb_attr_sprom_show(bus, buf,739				   ssb_pcmcia_sprom_read_all);740}741 742static ssize_t ssb_sprom_store(struct device *pcmciadev,743			       struct device_attribute *attr,744			       const char *buf, size_t count)745{746	struct pcmcia_device *pdev =747		container_of(pcmciadev, struct pcmcia_device, dev);748	struct ssb_bus *bus;749 750	bus = ssb_pcmcia_dev_to_bus(pdev);751	if (!bus)752		return -ENODEV;753 754	return ssb_attr_sprom_store(bus, buf, count,755				    ssb_pcmcia_sprom_check_crc,756				    ssb_pcmcia_sprom_write_all);757}758 759static DEVICE_ATTR_ADMIN_RW(ssb_sprom);760 761static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)762{763	u8 val;764	int err;765 766	err = ssb_pcmcia_cfg_read(bus, cor, &val);767	if (err)768		return err;769	val &= ~COR_SOFT_RESET;770	val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;771	err = ssb_pcmcia_cfg_write(bus, cor, val);772	if (err)773		return err;774	msleep(40);775 776	return 0;777}778 779/* Initialize the PCMCIA hardware. This is called on Init and Resume. */780int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)781{782	int err;783 784	if (bus->bustype != SSB_BUSTYPE_PCMCIA)785		return 0;786 787	/* Switch segment to a known state and sync788	 * bus->mapped_pcmcia_seg with hardware state. */789	ssb_pcmcia_switch_segment(bus, 0);790	/* Init the COR register. */791	err = ssb_pcmcia_cor_setup(bus, CISREG_COR);792	if (err)793		return err;794	/* Some cards also need this register to get poked. */795	err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);796	if (err)797		return err;798 799	return 0;800}801 802void ssb_pcmcia_exit(struct ssb_bus *bus)803{804	if (bus->bustype != SSB_BUSTYPE_PCMCIA)805		return;806 807	device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);808}809 810int ssb_pcmcia_init(struct ssb_bus *bus)811{812	int err;813 814	if (bus->bustype != SSB_BUSTYPE_PCMCIA)815		return 0;816 817	err = ssb_pcmcia_hardware_setup(bus);818	if (err)819		goto error;820 821	bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;822	mutex_init(&bus->sprom_mutex);823	err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);824	if (err)825		goto error;826 827	return 0;828error:829	pr_err("Failed to initialize PCMCIA host device\n");830	return err;831}832