cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcmcia.c (19535B)


      1/*
      2 * Sonics Silicon Backplane
      3 * PCMCIA-Hostbus related functions
      4 *
      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		0
     26
     27
     28/* PCMCIA configuration registers */
     29#define SSB_PCMCIA_ADDRESS0		0x2E
     30#define SSB_PCMCIA_ADDRESS1		0x30
     31#define SSB_PCMCIA_ADDRESS2		0x32
     32#define SSB_PCMCIA_MEMSEG		0x34
     33#define SSB_PCMCIA_SPROMCTL		0x36
     34#define  SSB_PCMCIA_SPROMCTL_IDLE	0
     35#define  SSB_PCMCIA_SPROMCTL_WRITE	1
     36#define  SSB_PCMCIA_SPROMCTL_READ	2
     37#define  SSB_PCMCIA_SPROMCTL_WRITEEN	4
     38#define  SSB_PCMCIA_SPROMCTL_WRITEDIS	7
     39#define  SSB_PCMCIA_SPROMCTL_DONE	8
     40#define SSB_PCMCIA_SPROM_DATALO		0x38
     41#define SSB_PCMCIA_SPROM_DATAHI		0x3A
     42#define SSB_PCMCIA_SPROM_ADDRLO		0x3C
     43#define SSB_PCMCIA_SPROM_ADDRHI		0x3E
     44
     45/* Hardware invariants CIS tuples */
     46#define SSB_PCMCIA_CIS			0x80
     47#define  SSB_PCMCIA_CIS_ID		0x01
     48#define  SSB_PCMCIA_CIS_BOARDREV	0x02
     49#define  SSB_PCMCIA_CIS_PA		0x03
     50#define   SSB_PCMCIA_CIS_PA_PA0B0_LO	0
     51#define   SSB_PCMCIA_CIS_PA_PA0B0_HI	1
     52#define   SSB_PCMCIA_CIS_PA_PA0B1_LO	2
     53#define   SSB_PCMCIA_CIS_PA_PA0B1_HI	3
     54#define   SSB_PCMCIA_CIS_PA_PA0B2_LO	4
     55#define   SSB_PCMCIA_CIS_PA_PA0B2_HI	5
     56#define   SSB_PCMCIA_CIS_PA_ITSSI	6
     57#define   SSB_PCMCIA_CIS_PA_MAXPOW	7
     58#define  SSB_PCMCIA_CIS_OEMNAME		0x04
     59#define  SSB_PCMCIA_CIS_CCODE		0x05
     60#define  SSB_PCMCIA_CIS_ANTENNA		0x06
     61#define  SSB_PCMCIA_CIS_ANTGAIN		0x07
     62#define  SSB_PCMCIA_CIS_BFLAGS		0x08
     63#define  SSB_PCMCIA_CIS_LEDS		0x09
     64
     65/* PCMCIA SPROM size. */
     66#define SSB_PCMCIA_SPROM_SIZE		256
     67#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_DEBUG
    155	pr_info("Switching to %s core, index %d\n",
    156		ssb_core_name(dev->id.coreid), dev->core_index);
    157#endif
    158
    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	} else
    207		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_BLOCKIO
    274static 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_BLOCKIO
    373static 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_BLOCKIO
    437	.block_read	= ssb_pcmcia_block_read,
    438	.block_write	= ssb_pcmcia_block_write,
    439#endif
    440};
    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	//TODO
    586	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 sync
    788	 * 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}