Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 90566
b: refs/heads/master
c: d625a29
h: refs/heads/master
v: v3
  • Loading branch information
Michael Buesch authored and John W. Linville committed Apr 8, 2008
1 parent e8a54f4 commit 06a918a
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 93af2614513103216038afa708718295e7016dbb
refs/heads/master: d625a29ba649a4df6027520ffc378f23c0e6883e
5 changes: 5 additions & 0 deletions trunk/drivers/ssb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ config SSB
config SSB_SPROM
bool

# Support for Block-I/O. SELECT this from the driver that needs it.
config SSB_BLOCKIO
bool
depends on SSB

config SSB_PCIHOST_POSSIBLE
bool
depends on SSB && (PCI = y || PCI = SSB)
Expand Down
102 changes: 102 additions & 0 deletions trunk/drivers/ssb/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,55 @@ static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
return readl(bus->mmio + offset);
}

#ifdef CONFIG_SSB_BLOCKIO
static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
size_t count, u16 offset, u8 reg_width)
{
struct ssb_bus *bus = dev->bus;
void __iomem *addr;

offset += dev->core_index * SSB_CORE_SIZE;
addr = bus->mmio + offset;

switch (reg_width) {
case sizeof(u8): {
u8 *buf = buffer;

while (count) {
*buf = __raw_readb(addr);
buf++;
count--;
}
break;
}
case sizeof(u16): {
__le16 *buf = buffer;

SSB_WARN_ON(count & 1);
while (count) {
*buf = (__force __le16)__raw_readw(addr);
buf++;
count -= 2;
}
break;
}
case sizeof(u32): {
__le32 *buf = buffer;

SSB_WARN_ON(count & 3);
while (count) {
*buf = (__force __le32)__raw_readl(addr);
buf++;
count -= 4;
}
break;
}
default:
SSB_WARN_ON(1);
}
}
#endif /* CONFIG_SSB_BLOCKIO */

static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
{
struct ssb_bus *bus = dev->bus;
Expand All @@ -579,6 +628,55 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
writel(value, bus->mmio + offset);
}

#ifdef CONFIG_SSB_BLOCKIO
static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width)
{
struct ssb_bus *bus = dev->bus;
void __iomem *addr;

offset += dev->core_index * SSB_CORE_SIZE;
addr = bus->mmio + offset;

switch (reg_width) {
case sizeof(u8): {
const u8 *buf = buffer;

while (count) {
__raw_writeb(*buf, addr);
buf++;
count--;
}
break;
}
case sizeof(u16): {
const __le16 *buf = buffer;

SSB_WARN_ON(count & 1);
while (count) {
__raw_writew((__force u16)(*buf), addr);
buf++;
count -= 2;
}
break;
}
case sizeof(u32): {
const __le32 *buf = buffer;

SSB_WARN_ON(count & 3);
while (count) {
__raw_writel((__force u32)(*buf), addr);
buf++;
count -= 4;
}
break;
}
default:
SSB_WARN_ON(1);
}
}
#endif /* CONFIG_SSB_BLOCKIO */

/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
static const struct ssb_bus_ops ssb_ssb_ops = {
.read8 = ssb_ssb_read8,
Expand All @@ -587,6 +685,10 @@ static const struct ssb_bus_ops ssb_ssb_ops = {
.write8 = ssb_ssb_write8,
.write16 = ssb_ssb_write16,
.write32 = ssb_ssb_write32,
#ifdef CONFIG_SSB_BLOCKIO
.block_read = ssb_ssb_block_read,
.block_write = ssb_ssb_block_write,
#endif
};

static int ssb_fetch_invariants(struct ssb_bus *bus,
Expand Down
70 changes: 70 additions & 0 deletions trunk/drivers/ssb/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,41 @@ static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
return ioread32(bus->mmio + offset);
}

#ifdef CONFIG_SSB_BLOCKIO
static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
size_t count, u16 offset, u8 reg_width)
{
struct ssb_bus *bus = dev->bus;
void __iomem *addr = bus->mmio + offset;

if (unlikely(ssb_pci_assert_buspower(bus)))
goto error;
if (unlikely(bus->mapped_device != dev)) {
if (unlikely(ssb_pci_switch_core(bus, dev)))
goto error;
}
switch (reg_width) {
case sizeof(u8):
ioread8_rep(addr, buffer, count);
break;
case sizeof(u16):
SSB_WARN_ON(count & 1);
ioread16_rep(addr, buffer, count >> 1);
break;
case sizeof(u32):
SSB_WARN_ON(count & 3);
ioread32_rep(addr, buffer, count >> 2);
break;
default:
SSB_WARN_ON(1);
}

return;
error:
memset(buffer, 0xFF, count);
}
#endif /* CONFIG_SSB_BLOCKIO */

static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
{
struct ssb_bus *bus = dev->bus;
Expand Down Expand Up @@ -652,6 +687,37 @@ static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
iowrite32(value, bus->mmio + offset);
}

#ifdef CONFIG_SSB_BLOCKIO
static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width)
{
struct ssb_bus *bus = dev->bus;
void __iomem *addr = bus->mmio + offset;

if (unlikely(ssb_pci_assert_buspower(bus)))
return;
if (unlikely(bus->mapped_device != dev)) {
if (unlikely(ssb_pci_switch_core(bus, dev)))
return;
}
switch (reg_width) {
case sizeof(u8):
iowrite8_rep(addr, buffer, count);
break;
case sizeof(u16):
SSB_WARN_ON(count & 1);
iowrite16_rep(addr, buffer, count >> 1);
break;
case sizeof(u32):
SSB_WARN_ON(count & 3);
iowrite32_rep(addr, buffer, count >> 2);
break;
default:
SSB_WARN_ON(1);
}
}
#endif /* CONFIG_SSB_BLOCKIO */

/* Not "static", as it's used in main.c */
const struct ssb_bus_ops ssb_pci_ops = {
.read8 = ssb_pci_read8,
Expand All @@ -660,6 +726,10 @@ const struct ssb_bus_ops ssb_pci_ops = {
.write8 = ssb_pci_write8,
.write16 = ssb_pci_write16,
.write32 = ssb_pci_write32,
#ifdef CONFIG_SSB_BLOCKIO
.block_read = ssb_pci_block_read,
.block_write = ssb_pci_block_write,
#endif
};

static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
Expand Down
119 changes: 119 additions & 0 deletions trunk/drivers/ssb/pcmcia.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,64 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
return (lo | (hi << 16));
}

#ifdef CONFIG_SSB_BLOCKIO
static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
size_t count, u16 offset, u8 reg_width)
{
struct ssb_bus *bus = dev->bus;
unsigned long flags;
void __iomem *addr = bus->mmio + offset;
int err;

spin_lock_irqsave(&bus->bar_lock, flags);
err = select_core_and_segment(dev, &offset);
if (unlikely(err)) {
memset(buffer, 0xFF, count);
goto unlock;
}
switch (reg_width) {
case sizeof(u8): {
u8 *buf = buffer;

while (count) {
*buf = __raw_readb(addr);
buf++;
count--;
}
break;
}
case sizeof(u16): {
__le16 *buf = buffer;

SSB_WARN_ON(count & 1);
while (count) {
*buf = (__force __le16)__raw_readw(addr);
buf++;
count -= 2;
}
break;
}
case sizeof(u32): {
__le16 *buf = buffer;

SSB_WARN_ON(count & 3);
while (count) {
*buf = (__force __le16)__raw_readw(addr);
buf++;
*buf = (__force __le16)__raw_readw(addr + 2);
buf++;
count -= 4;
}
break;
}
default:
SSB_WARN_ON(1);
}
unlock:
spin_unlock_irqrestore(&bus->bar_lock, flags);
}
#endif /* CONFIG_SSB_BLOCKIO */

static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
{
struct ssb_bus *bus = dev->bus;
Expand Down Expand Up @@ -329,6 +387,63 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
spin_unlock_irqrestore(&bus->bar_lock, flags);
}

#ifdef CONFIG_SSB_BLOCKIO
static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
size_t count, u16 offset, u8 reg_width)
{
struct ssb_bus *bus = dev->bus;
unsigned long flags;
void __iomem *addr = bus->mmio + offset;
int err;

spin_lock_irqsave(&bus->bar_lock, flags);
err = select_core_and_segment(dev, &offset);
if (unlikely(err))
goto unlock;
switch (reg_width) {
case sizeof(u8): {
const u8 *buf = buffer;

while (count) {
__raw_writeb(*buf, addr);
buf++;
count--;
}
break;
}
case sizeof(u16): {
const __le16 *buf = buffer;

SSB_WARN_ON(count & 1);
while (count) {
__raw_writew((__force u16)(*buf), addr);
buf++;
count -= 2;
}
break;
}
case sizeof(u32): {
const __le16 *buf = buffer;

SSB_WARN_ON(count & 3);
while (count) {
__raw_writew((__force u16)(*buf), addr);
buf++;
__raw_writew((__force u16)(*buf), addr + 2);
buf++;
count -= 4;
}
break;
}
default:
SSB_WARN_ON(1);
}
unlock:
mmiowb();
spin_unlock_irqrestore(&bus->bar_lock, flags);
}
#endif /* CONFIG_SSB_BLOCKIO */

/* Not "static", as it's used in main.c */
const struct ssb_bus_ops ssb_pcmcia_ops = {
.read8 = ssb_pcmcia_read8,
Expand All @@ -337,6 +452,10 @@ const struct ssb_bus_ops ssb_pcmcia_ops = {
.write8 = ssb_pcmcia_write8,
.write16 = ssb_pcmcia_write16,
.write32 = ssb_pcmcia_write32,
#ifdef CONFIG_SSB_BLOCKIO
.block_read = ssb_pcmcia_block_read,
.block_write = ssb_pcmcia_block_write,
#endif
};

static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
Expand Down
Loading

0 comments on commit 06a918a

Please sign in to comment.