diff options
Diffstat (limited to 'drivers/ssb/main.c')
-rw-r--r-- | drivers/ssb/main.c | 260 |
1 files changed, 207 insertions, 53 deletions
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 72017bf2e577..6ce92e82b64e 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/ssb/ssb.h> | 15 | #include <linux/ssb/ssb.h> |
16 | #include <linux/ssb/ssb_regs.h> | 16 | #include <linux/ssb/ssb_regs.h> |
17 | #include <linux/ssb/ssb_driver_gige.h> | ||
17 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
18 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
19 | 20 | ||
@@ -68,6 +69,44 @@ found: | |||
68 | } | 69 | } |
69 | #endif /* CONFIG_SSB_PCIHOST */ | 70 | #endif /* CONFIG_SSB_PCIHOST */ |
70 | 71 | ||
72 | #ifdef CONFIG_SSB_PCMCIAHOST | ||
73 | struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev) | ||
74 | { | ||
75 | struct ssb_bus *bus; | ||
76 | |||
77 | ssb_buses_lock(); | ||
78 | list_for_each_entry(bus, &buses, list) { | ||
79 | if (bus->bustype == SSB_BUSTYPE_PCMCIA && | ||
80 | bus->host_pcmcia == pdev) | ||
81 | goto found; | ||
82 | } | ||
83 | bus = NULL; | ||
84 | found: | ||
85 | ssb_buses_unlock(); | ||
86 | |||
87 | return bus; | ||
88 | } | ||
89 | #endif /* CONFIG_SSB_PCMCIAHOST */ | ||
90 | |||
91 | int ssb_for_each_bus_call(unsigned long data, | ||
92 | int (*func)(struct ssb_bus *bus, unsigned long data)) | ||
93 | { | ||
94 | struct ssb_bus *bus; | ||
95 | int res; | ||
96 | |||
97 | ssb_buses_lock(); | ||
98 | list_for_each_entry(bus, &buses, list) { | ||
99 | res = func(bus, data); | ||
100 | if (res >= 0) { | ||
101 | ssb_buses_unlock(); | ||
102 | return res; | ||
103 | } | ||
104 | } | ||
105 | ssb_buses_unlock(); | ||
106 | |||
107 | return -ENODEV; | ||
108 | } | ||
109 | |||
71 | static struct ssb_device *ssb_device_get(struct ssb_device *dev) | 110 | static struct ssb_device *ssb_device_get(struct ssb_device *dev) |
72 | { | 111 | { |
73 | if (dev) | 112 | if (dev) |
@@ -81,35 +120,12 @@ static void ssb_device_put(struct ssb_device *dev) | |||
81 | put_device(dev->dev); | 120 | put_device(dev->dev); |
82 | } | 121 | } |
83 | 122 | ||
84 | static int ssb_bus_resume(struct ssb_bus *bus) | ||
85 | { | ||
86 | int err; | ||
87 | |||
88 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); | ||
89 | err = ssb_pcmcia_init(bus); | ||
90 | if (err) { | ||
91 | /* No need to disable XTAL, as we don't have one on PCMCIA. */ | ||
92 | return err; | ||
93 | } | ||
94 | ssb_chipco_resume(&bus->chipco); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static int ssb_device_resume(struct device *dev) | 123 | static int ssb_device_resume(struct device *dev) |
100 | { | 124 | { |
101 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 125 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
102 | struct ssb_driver *ssb_drv; | 126 | struct ssb_driver *ssb_drv; |
103 | struct ssb_bus *bus; | ||
104 | int err = 0; | 127 | int err = 0; |
105 | 128 | ||
106 | bus = ssb_dev->bus; | ||
107 | if (bus->suspend_cnt == bus->nr_devices) { | ||
108 | err = ssb_bus_resume(bus); | ||
109 | if (err) | ||
110 | return err; | ||
111 | } | ||
112 | bus->suspend_cnt--; | ||
113 | if (dev->driver) { | 129 | if (dev->driver) { |
114 | ssb_drv = drv_to_ssb_drv(dev->driver); | 130 | ssb_drv = drv_to_ssb_drv(dev->driver); |
115 | if (ssb_drv && ssb_drv->resume) | 131 | if (ssb_drv && ssb_drv->resume) |
@@ -121,27 +137,10 @@ out: | |||
121 | return err; | 137 | return err; |
122 | } | 138 | } |
123 | 139 | ||
124 | static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state) | ||
125 | { | ||
126 | ssb_chipco_suspend(&bus->chipco, state); | ||
127 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); | ||
128 | |||
129 | /* Reset HW state information in memory, so that HW is | ||
130 | * completely reinitialized on resume. */ | ||
131 | bus->mapped_device = NULL; | ||
132 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
133 | bus->pcicore.setup_done = 0; | ||
134 | #endif | ||
135 | #ifdef CONFIG_SSB_DEBUG | ||
136 | bus->powered_up = 0; | ||
137 | #endif | ||
138 | } | ||
139 | |||
140 | static int ssb_device_suspend(struct device *dev, pm_message_t state) | 140 | static int ssb_device_suspend(struct device *dev, pm_message_t state) |
141 | { | 141 | { |
142 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 142 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
143 | struct ssb_driver *ssb_drv; | 143 | struct ssb_driver *ssb_drv; |
144 | struct ssb_bus *bus; | ||
145 | int err = 0; | 144 | int err = 0; |
146 | 145 | ||
147 | if (dev->driver) { | 146 | if (dev->driver) { |
@@ -151,19 +150,46 @@ static int ssb_device_suspend(struct device *dev, pm_message_t state) | |||
151 | if (err) | 150 | if (err) |
152 | goto out; | 151 | goto out; |
153 | } | 152 | } |
153 | out: | ||
154 | return err; | ||
155 | } | ||
156 | |||
157 | int ssb_bus_resume(struct ssb_bus *bus) | ||
158 | { | ||
159 | int err; | ||
160 | |||
161 | /* Reset HW state information in memory, so that HW is | ||
162 | * completely reinitialized. */ | ||
163 | bus->mapped_device = NULL; | ||
164 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
165 | bus->pcicore.setup_done = 0; | ||
166 | #endif | ||
154 | 167 | ||
155 | bus = ssb_dev->bus; | 168 | err = ssb_bus_powerup(bus, 0); |
156 | bus->suspend_cnt++; | 169 | if (err) |
157 | if (bus->suspend_cnt == bus->nr_devices) { | 170 | return err; |
158 | /* All devices suspended. Shutdown the bus. */ | 171 | err = ssb_pcmcia_hardware_setup(bus); |
159 | ssb_bus_suspend(bus, state); | 172 | if (err) { |
173 | ssb_bus_may_powerdown(bus); | ||
174 | return err; | ||
160 | } | 175 | } |
176 | ssb_chipco_resume(&bus->chipco); | ||
177 | ssb_bus_may_powerdown(bus); | ||
161 | 178 | ||
162 | out: | 179 | return 0; |
163 | return err; | ||
164 | } | 180 | } |
181 | EXPORT_SYMBOL(ssb_bus_resume); | ||
165 | 182 | ||
166 | #ifdef CONFIG_SSB_PCIHOST | 183 | int ssb_bus_suspend(struct ssb_bus *bus) |
184 | { | ||
185 | ssb_chipco_suspend(&bus->chipco); | ||
186 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | EXPORT_SYMBOL(ssb_bus_suspend); | ||
191 | |||
192 | #ifdef CONFIG_SSB_SPROM | ||
167 | int ssb_devices_freeze(struct ssb_bus *bus) | 193 | int ssb_devices_freeze(struct ssb_bus *bus) |
168 | { | 194 | { |
169 | struct ssb_device *dev; | 195 | struct ssb_device *dev; |
@@ -249,7 +275,7 @@ int ssb_devices_thaw(struct ssb_bus *bus) | |||
249 | 275 | ||
250 | return 0; | 276 | return 0; |
251 | } | 277 | } |
252 | #endif /* CONFIG_SSB_PCIHOST */ | 278 | #endif /* CONFIG_SSB_SPROM */ |
253 | 279 | ||
254 | static void ssb_device_shutdown(struct device *dev) | 280 | static void ssb_device_shutdown(struct device *dev) |
255 | { | 281 | { |
@@ -378,7 +404,7 @@ void ssb_bus_unregister(struct ssb_bus *bus) | |||
378 | list_del(&bus->list); | 404 | list_del(&bus->list); |
379 | ssb_buses_unlock(); | 405 | ssb_buses_unlock(); |
380 | 406 | ||
381 | /* ssb_pcmcia_exit(bus); */ | 407 | ssb_pcmcia_exit(bus); |
382 | ssb_pci_exit(bus); | 408 | ssb_pci_exit(bus); |
383 | ssb_iounmap(bus); | 409 | ssb_iounmap(bus); |
384 | } | 410 | } |
@@ -505,6 +531,14 @@ error: | |||
505 | return err; | 531 | return err; |
506 | } | 532 | } |
507 | 533 | ||
534 | static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset) | ||
535 | { | ||
536 | struct ssb_bus *bus = dev->bus; | ||
537 | |||
538 | offset += dev->core_index * SSB_CORE_SIZE; | ||
539 | return readb(bus->mmio + offset); | ||
540 | } | ||
541 | |||
508 | static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) | 542 | static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) |
509 | { | 543 | { |
510 | struct ssb_bus *bus = dev->bus; | 544 | struct ssb_bus *bus = dev->bus; |
@@ -521,6 +555,63 @@ static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset) | |||
521 | return readl(bus->mmio + offset); | 555 | return readl(bus->mmio + offset); |
522 | } | 556 | } |
523 | 557 | ||
558 | #ifdef CONFIG_SSB_BLOCKIO | ||
559 | static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer, | ||
560 | size_t count, u16 offset, u8 reg_width) | ||
561 | { | ||
562 | struct ssb_bus *bus = dev->bus; | ||
563 | void __iomem *addr; | ||
564 | |||
565 | offset += dev->core_index * SSB_CORE_SIZE; | ||
566 | addr = bus->mmio + offset; | ||
567 | |||
568 | switch (reg_width) { | ||
569 | case sizeof(u8): { | ||
570 | u8 *buf = buffer; | ||
571 | |||
572 | while (count) { | ||
573 | *buf = __raw_readb(addr); | ||
574 | buf++; | ||
575 | count--; | ||
576 | } | ||
577 | break; | ||
578 | } | ||
579 | case sizeof(u16): { | ||
580 | __le16 *buf = buffer; | ||
581 | |||
582 | SSB_WARN_ON(count & 1); | ||
583 | while (count) { | ||
584 | *buf = (__force __le16)__raw_readw(addr); | ||
585 | buf++; | ||
586 | count -= 2; | ||
587 | } | ||
588 | break; | ||
589 | } | ||
590 | case sizeof(u32): { | ||
591 | __le32 *buf = buffer; | ||
592 | |||
593 | SSB_WARN_ON(count & 3); | ||
594 | while (count) { | ||
595 | *buf = (__force __le32)__raw_readl(addr); | ||
596 | buf++; | ||
597 | count -= 4; | ||
598 | } | ||
599 | break; | ||
600 | } | ||
601 | default: | ||
602 | SSB_WARN_ON(1); | ||
603 | } | ||
604 | } | ||
605 | #endif /* CONFIG_SSB_BLOCKIO */ | ||
606 | |||
607 | static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value) | ||
608 | { | ||
609 | struct ssb_bus *bus = dev->bus; | ||
610 | |||
611 | offset += dev->core_index * SSB_CORE_SIZE; | ||
612 | writeb(value, bus->mmio + offset); | ||
613 | } | ||
614 | |||
524 | static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) | 615 | static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) |
525 | { | 616 | { |
526 | struct ssb_bus *bus = dev->bus; | 617 | struct ssb_bus *bus = dev->bus; |
@@ -537,12 +628,67 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value) | |||
537 | writel(value, bus->mmio + offset); | 628 | writel(value, bus->mmio + offset); |
538 | } | 629 | } |
539 | 630 | ||
631 | #ifdef CONFIG_SSB_BLOCKIO | ||
632 | static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer, | ||
633 | size_t count, u16 offset, u8 reg_width) | ||
634 | { | ||
635 | struct ssb_bus *bus = dev->bus; | ||
636 | void __iomem *addr; | ||
637 | |||
638 | offset += dev->core_index * SSB_CORE_SIZE; | ||
639 | addr = bus->mmio + offset; | ||
640 | |||
641 | switch (reg_width) { | ||
642 | case sizeof(u8): { | ||
643 | const u8 *buf = buffer; | ||
644 | |||
645 | while (count) { | ||
646 | __raw_writeb(*buf, addr); | ||
647 | buf++; | ||
648 | count--; | ||
649 | } | ||
650 | break; | ||
651 | } | ||
652 | case sizeof(u16): { | ||
653 | const __le16 *buf = buffer; | ||
654 | |||
655 | SSB_WARN_ON(count & 1); | ||
656 | while (count) { | ||
657 | __raw_writew((__force u16)(*buf), addr); | ||
658 | buf++; | ||
659 | count -= 2; | ||
660 | } | ||
661 | break; | ||
662 | } | ||
663 | case sizeof(u32): { | ||
664 | const __le32 *buf = buffer; | ||
665 | |||
666 | SSB_WARN_ON(count & 3); | ||
667 | while (count) { | ||
668 | __raw_writel((__force u32)(*buf), addr); | ||
669 | buf++; | ||
670 | count -= 4; | ||
671 | } | ||
672 | break; | ||
673 | } | ||
674 | default: | ||
675 | SSB_WARN_ON(1); | ||
676 | } | ||
677 | } | ||
678 | #endif /* CONFIG_SSB_BLOCKIO */ | ||
679 | |||
540 | /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ | 680 | /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ |
541 | static const struct ssb_bus_ops ssb_ssb_ops = { | 681 | static const struct ssb_bus_ops ssb_ssb_ops = { |
682 | .read8 = ssb_ssb_read8, | ||
542 | .read16 = ssb_ssb_read16, | 683 | .read16 = ssb_ssb_read16, |
543 | .read32 = ssb_ssb_read32, | 684 | .read32 = ssb_ssb_read32, |
685 | .write8 = ssb_ssb_write8, | ||
544 | .write16 = ssb_ssb_write16, | 686 | .write16 = ssb_ssb_write16, |
545 | .write32 = ssb_ssb_write32, | 687 | .write32 = ssb_ssb_write32, |
688 | #ifdef CONFIG_SSB_BLOCKIO | ||
689 | .block_read = ssb_ssb_block_read, | ||
690 | .block_write = ssb_ssb_block_write, | ||
691 | #endif | ||
546 | }; | 692 | }; |
547 | 693 | ||
548 | static int ssb_fetch_invariants(struct ssb_bus *bus, | 694 | static int ssb_fetch_invariants(struct ssb_bus *bus, |
@@ -625,7 +771,7 @@ out: | |||
625 | err_dequeue: | 771 | err_dequeue: |
626 | list_del(&bus->list); | 772 | list_del(&bus->list); |
627 | err_pcmcia_exit: | 773 | err_pcmcia_exit: |
628 | /* ssb_pcmcia_exit(bus); */ | 774 | ssb_pcmcia_exit(bus); |
629 | err_pci_exit: | 775 | err_pci_exit: |
630 | ssb_pci_exit(bus); | 776 | ssb_pci_exit(bus); |
631 | err_unmap: | 777 | err_unmap: |
@@ -1007,9 +1153,9 @@ u32 ssb_dma_translation(struct ssb_device *dev) | |||
1007 | { | 1153 | { |
1008 | switch (dev->bus->bustype) { | 1154 | switch (dev->bus->bustype) { |
1009 | case SSB_BUSTYPE_SSB: | 1155 | case SSB_BUSTYPE_SSB: |
1156 | case SSB_BUSTYPE_PCMCIA: | ||
1010 | return 0; | 1157 | return 0; |
1011 | case SSB_BUSTYPE_PCI: | 1158 | case SSB_BUSTYPE_PCI: |
1012 | case SSB_BUSTYPE_PCMCIA: | ||
1013 | return SSB_PCI_DMA; | 1159 | return SSB_PCI_DMA; |
1014 | } | 1160 | } |
1015 | return 0; | 1161 | return 0; |
@@ -1159,7 +1305,14 @@ static int __init ssb_modinit(void) | |||
1159 | err = b43_pci_ssb_bridge_init(); | 1305 | err = b43_pci_ssb_bridge_init(); |
1160 | if (err) { | 1306 | if (err) { |
1161 | ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " | 1307 | ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " |
1162 | "initialization failed"); | 1308 | "initialization failed\n"); |
1309 | /* don't fail SSB init because of this */ | ||
1310 | err = 0; | ||
1311 | } | ||
1312 | err = ssb_gige_init(); | ||
1313 | if (err) { | ||
1314 | ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet " | ||
1315 | "driver initialization failed\n"); | ||
1163 | /* don't fail SSB init because of this */ | 1316 | /* don't fail SSB init because of this */ |
1164 | err = 0; | 1317 | err = 0; |
1165 | } | 1318 | } |
@@ -1173,6 +1326,7 @@ fs_initcall(ssb_modinit); | |||
1173 | 1326 | ||
1174 | static void __exit ssb_modexit(void) | 1327 | static void __exit ssb_modexit(void) |
1175 | { | 1328 | { |
1329 | ssb_gige_exit(); | ||
1176 | b43_pci_ssb_bridge_exit(); | 1330 | b43_pci_ssb_bridge_exit(); |
1177 | bus_unregister(&ssb_bustype); | 1331 | bus_unregister(&ssb_bustype); |
1178 | } | 1332 | } |