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