diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-02-20 13:08:10 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-02-29 15:37:26 -0500 |
commit | ffc7689ddae5cbe12bde437ae0f2b386d568b5cd (patch) | |
tree | 638e7dcf083c88cf45763953aa244504d357a220 | |
parent | 004c872e78d433f84f0a5cd4db7a6c780c0946e1 (diff) |
ssb: Add support for 8bit register access
This adds support for 8bit wide register reads/writes.
This is needed in order to support the gigabit ethernet core.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/ssb/main.c | 18 | ||||
-rw-r--r-- | drivers/ssb/pci.c | 28 | ||||
-rw-r--r-- | drivers/ssb/pcmcia.c | 32 | ||||
-rw-r--r-- | include/linux/ssb/ssb.h | 10 |
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 | ||
508 | static 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 | |||
508 | static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) | 516 | static 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 | ||
532 | static 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 | |||
524 | static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) | 540 | static 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). */ |
541 | static const struct ssb_bus_ops ssb_ssb_ops = { | 557 | static 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 | ||
575 | static 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 | |||
575 | static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset) | 588 | static 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 | ||
614 | static 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 | |||
601 | static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value) | 627 | static 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 */ |
628 | const struct ssb_bus_ops ssb_pci_ops = { | 654 | const 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 | ||
175 | static 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 | |||
175 | static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) | 191 | static 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 | ||
225 | static 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 | |||
209 | static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) | 239 | static 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 */ |
240 | const struct ssb_bus_ops ssb_pcmcia_ops = { | 270 | const 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. */ |
74 | struct ssb_bus_ops { | 74 | struct 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. */ |
349 | static inline u8 ssb_read8(struct ssb_device *dev, u16 offset) | ||
350 | { | ||
351 | return dev->ops->read8(dev, offset); | ||
352 | } | ||
347 | static inline u16 ssb_read16(struct ssb_device *dev, u16 offset) | 353 | static 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 | } |
361 | static inline void ssb_write8(struct ssb_device *dev, u16 offset, u8 value) | ||
362 | { | ||
363 | dev->ops->write8(dev, offset, value); | ||
364 | } | ||
355 | static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value) | 365 | static 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); |