aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ssb/main.c18
-rw-r--r--drivers/ssb/pci.c28
-rw-r--r--drivers/ssb/pcmcia.c32
-rw-r--r--include/linux/ssb/ssb.h10
4 files changed, 88 insertions, 0 deletions
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index bedb2b4ee9d2..8db40c4b86e9 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -505,6 +505,14 @@ error:
505 return err; 505 return err;
506} 506}
507 507
508static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
509{
510 struct ssb_bus *bus = dev->bus;
511
512 offset += dev->core_index * SSB_CORE_SIZE;
513 return readb(bus->mmio + offset);
514}
515
508static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) 516static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
509{ 517{
510 struct ssb_bus *bus = dev->bus; 518 struct ssb_bus *bus = dev->bus;
@@ -521,6 +529,14 @@ static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
521 return readl(bus->mmio + offset); 529 return readl(bus->mmio + offset);
522} 530}
523 531
532static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
533{
534 struct ssb_bus *bus = dev->bus;
535
536 offset += dev->core_index * SSB_CORE_SIZE;
537 writeb(value, bus->mmio + offset);
538}
539
524static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) 540static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
525{ 541{
526 struct ssb_bus *bus = dev->bus; 542 struct ssb_bus *bus = dev->bus;
@@ -539,8 +555,10 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
539 555
540/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ 556/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
541static const struct ssb_bus_ops ssb_ssb_ops = { 557static const struct ssb_bus_ops ssb_ssb_ops = {
558 .read8 = ssb_ssb_read8,
542 .read16 = ssb_ssb_read16, 559 .read16 = ssb_ssb_read16,
543 .read32 = ssb_ssb_read32, 560 .read32 = ssb_ssb_read32,
561 .write8 = ssb_ssb_write8,
544 .write16 = ssb_ssb_write16, 562 .write16 = ssb_ssb_write16,
545 .write32 = ssb_ssb_write32, 563 .write32 = ssb_ssb_write32,
546}; 564};
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index b434df75047f..1facc7620fc8 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -572,6 +572,19 @@ static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
572} 572}
573#endif /* DEBUG */ 573#endif /* DEBUG */
574 574
575static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
576{
577 struct ssb_bus *bus = dev->bus;
578
579 if (unlikely(ssb_pci_assert_buspower(bus)))
580 return 0xFF;
581 if (unlikely(bus->mapped_device != dev)) {
582 if (unlikely(ssb_pci_switch_core(bus, dev)))
583 return 0xFF;
584 }
585 return ioread8(bus->mmio + offset);
586}
587
575static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset) 588static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
576{ 589{
577 struct ssb_bus *bus = dev->bus; 590 struct ssb_bus *bus = dev->bus;
@@ -598,6 +611,19 @@ static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
598 return ioread32(bus->mmio + offset); 611 return ioread32(bus->mmio + offset);
599} 612}
600 613
614static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
615{
616 struct ssb_bus *bus = dev->bus;
617
618 if (unlikely(ssb_pci_assert_buspower(bus)))
619 return;
620 if (unlikely(bus->mapped_device != dev)) {
621 if (unlikely(ssb_pci_switch_core(bus, dev)))
622 return;
623 }
624 iowrite8(value, bus->mmio + offset);
625}
626
601static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value) 627static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
602{ 628{
603 struct ssb_bus *bus = dev->bus; 629 struct ssb_bus *bus = dev->bus;
@@ -626,8 +652,10 @@ static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
626 652
627/* Not "static", as it's used in main.c */ 653/* Not "static", as it's used in main.c */
628const struct ssb_bus_ops ssb_pci_ops = { 654const struct ssb_bus_ops ssb_pci_ops = {
655 .read8 = ssb_pci_read8,
629 .read16 = ssb_pci_read16, 656 .read16 = ssb_pci_read16,
630 .read32 = ssb_pci_read32, 657 .read32 = ssb_pci_read32,
658 .write8 = ssb_pci_write8,
631 .write16 = ssb_pci_write16, 659 .write16 = ssb_pci_write16,
632 .write32 = ssb_pci_write32, 660 .write32 = ssb_pci_write32,
633}; 661};
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index 46816cda8b98..84b3a845a8a8 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -172,6 +172,22 @@ static int select_core_and_segment(struct ssb_device *dev,
172 return 0; 172 return 0;
173} 173}
174 174
175static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
176{
177 struct ssb_bus *bus = dev->bus;
178 unsigned long flags;
179 int err;
180 u8 value = 0xFF;
181
182 spin_lock_irqsave(&bus->bar_lock, flags);
183 err = select_core_and_segment(dev, &offset);
184 if (likely(!err))
185 value = readb(bus->mmio + offset);
186 spin_unlock_irqrestore(&bus->bar_lock, flags);
187
188 return value;
189}
190
175static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) 191static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
176{ 192{
177 struct ssb_bus *bus = dev->bus; 193 struct ssb_bus *bus = dev->bus;
@@ -206,6 +222,20 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
206 return (lo | (hi << 16)); 222 return (lo | (hi << 16));
207} 223}
208 224
225static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
226{
227 struct ssb_bus *bus = dev->bus;
228 unsigned long flags;
229 int err;
230
231 spin_lock_irqsave(&bus->bar_lock, flags);
232 err = select_core_and_segment(dev, &offset);
233 if (likely(!err))
234 writeb(value, bus->mmio + offset);
235 mmiowb();
236 spin_unlock_irqrestore(&bus->bar_lock, flags);
237}
238
209static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) 239static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
210{ 240{
211 struct ssb_bus *bus = dev->bus; 241 struct ssb_bus *bus = dev->bus;
@@ -238,8 +268,10 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
238 268
239/* Not "static", as it's used in main.c */ 269/* Not "static", as it's used in main.c */
240const struct ssb_bus_ops ssb_pcmcia_ops = { 270const struct ssb_bus_ops ssb_pcmcia_ops = {
271 .read8 = ssb_pcmcia_read8,
241 .read16 = ssb_pcmcia_read16, 272 .read16 = ssb_pcmcia_read16,
242 .read32 = ssb_pcmcia_read32, 273 .read32 = ssb_pcmcia_read32,
274 .write8 = ssb_pcmcia_write8,
243 .write16 = ssb_pcmcia_write16, 275 .write16 = ssb_pcmcia_write16,
244 .write32 = ssb_pcmcia_write32, 276 .write32 = ssb_pcmcia_write32,
245}; 277};
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 20add65215af..860d28c6d149 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -72,8 +72,10 @@ struct ssb_device;
72/* Lowlevel read/write operations on the device MMIO. 72/* Lowlevel read/write operations on the device MMIO.
73 * Internal, don't use that outside of ssb. */ 73 * Internal, don't use that outside of ssb. */
74struct ssb_bus_ops { 74struct ssb_bus_ops {
75 u8 (*read8)(struct ssb_device *dev, u16 offset);
75 u16 (*read16)(struct ssb_device *dev, u16 offset); 76 u16 (*read16)(struct ssb_device *dev, u16 offset);
76 u32 (*read32)(struct ssb_device *dev, u16 offset); 77 u32 (*read32)(struct ssb_device *dev, u16 offset);
78 void (*write8)(struct ssb_device *dev, u16 offset, u8 value);
77 void (*write16)(struct ssb_device *dev, u16 offset, u16 value); 79 void (*write16)(struct ssb_device *dev, u16 offset, u16 value);
78 void (*write32)(struct ssb_device *dev, u16 offset, u32 value); 80 void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
79}; 81};
@@ -344,6 +346,10 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
344 346
345 347
346/* Device MMIO register read/write functions. */ 348/* Device MMIO register read/write functions. */
349static inline u8 ssb_read8(struct ssb_device *dev, u16 offset)
350{
351 return dev->ops->read8(dev, offset);
352}
347static inline u16 ssb_read16(struct ssb_device *dev, u16 offset) 353static inline u16 ssb_read16(struct ssb_device *dev, u16 offset)
348{ 354{
349 return dev->ops->read16(dev, offset); 355 return dev->ops->read16(dev, offset);
@@ -352,6 +358,10 @@ static inline u32 ssb_read32(struct ssb_device *dev, u16 offset)
352{ 358{
353 return dev->ops->read32(dev, offset); 359 return dev->ops->read32(dev, offset);
354} 360}
361static inline void ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
362{
363 dev->ops->write8(dev, offset, value);
364}
355static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value) 365static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
356{ 366{
357 dev->ops->write16(dev, offset, value); 367 dev->ops->write16(dev, offset, value);