aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-03-07 12:12:56 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:03:15 -0500
commitd60d7f1d5ce83d1be8d79256f711d6a645b7a2fa (patch)
treedd3f02960657d4270efb0990b5cdfe0eeef62ad5 /drivers
parent473d28c730e2de888c24b226cfe4183868eacde2 (diff)
firewire: Implement CSR cycle time and bus time registers.
Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firewire/fw-ohci.c26
-rw-r--r--drivers/firewire/fw-transaction.c61
-rw-r--r--drivers/firewire/fw-transaction.h2
3 files changed, 86 insertions, 3 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index a9e13468f60c..6f9895d201b8 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -139,6 +139,7 @@ struct fw_ohci {
139 int node_id; 139 int node_id;
140 int generation; 140 int generation;
141 int request_generation; 141 int request_generation;
142 u32 bus_seconds;
142 143
143 /* Spinlock for accessing fw_ohci data. Never call out of 144 /* Spinlock for accessing fw_ohci data. Never call out of
144 * this driver with this lock held. */ 145 * this driver with this lock held. */
@@ -959,7 +960,7 @@ static void bus_reset_tasklet(unsigned long data)
959static irqreturn_t irq_handler(int irq, void *data) 960static irqreturn_t irq_handler(int irq, void *data)
960{ 961{
961 struct fw_ohci *ohci = data; 962 struct fw_ohci *ohci = data;
962 u32 event, iso_event; 963 u32 event, iso_event, cycle_time;
963 int i; 964 int i;
964 965
965 event = reg_read(ohci, OHCI1394_IntEventClear); 966 event = reg_read(ohci, OHCI1394_IntEventClear);
@@ -1002,6 +1003,12 @@ static irqreturn_t irq_handler(int irq, void *data)
1002 iso_event &= ~(1 << i); 1003 iso_event &= ~(1 << i);
1003 } 1004 }
1004 1005
1006 if (event & OHCI1394_cycle64Seconds) {
1007 cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
1008 if ((cycle_time & 0x80000000) == 0)
1009 ohci->bus_seconds++;
1010 }
1011
1005 return IRQ_HANDLED; 1012 return IRQ_HANDLED;
1006} 1013}
1007 1014
@@ -1213,6 +1220,19 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
1213 return retval; 1220 return retval;
1214} 1221}
1215 1222
1223static u64
1224ohci_get_bus_time(struct fw_card *card)
1225{
1226 struct fw_ohci *ohci = fw_ohci(card);
1227 u32 cycle_time;
1228 u64 bus_time;
1229
1230 cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
1231 bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time;
1232
1233 return bus_time;
1234}
1235
1216static int handle_ir_bufferfill_packet(struct context *context, 1236static int handle_ir_bufferfill_packet(struct context *context,
1217 struct descriptor *d, 1237 struct descriptor *d,
1218 struct descriptor *last) 1238 struct descriptor *last)
@@ -1686,6 +1706,7 @@ static const struct fw_card_driver ohci_driver = {
1686 .send_response = ohci_send_response, 1706 .send_response = ohci_send_response,
1687 .cancel_packet = ohci_cancel_packet, 1707 .cancel_packet = ohci_cancel_packet,
1688 .enable_phys_dma = ohci_enable_phys_dma, 1708 .enable_phys_dma = ohci_enable_phys_dma,
1709 .get_bus_time = ohci_get_bus_time,
1689 1710
1690 .allocate_iso_context = ohci_allocate_iso_context, 1711 .allocate_iso_context = ohci_allocate_iso_context,
1691 .free_iso_context = ohci_free_iso_context, 1712 .free_iso_context = ohci_free_iso_context,
@@ -1862,7 +1883,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
1862 OHCI1394_RQPkt | OHCI1394_RSPkt | 1883 OHCI1394_RQPkt | OHCI1394_RSPkt |
1863 OHCI1394_reqTxComplete | OHCI1394_respTxComplete | 1884 OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
1864 OHCI1394_isochRx | OHCI1394_isochTx | 1885 OHCI1394_isochRx | OHCI1394_isochTx |
1865 OHCI1394_masterIntEnable); 1886 OHCI1394_masterIntEnable |
1887 OHCI1394_cycle64Seconds);
1866 1888
1867 bus_options = reg_read(ohci, OHCI1394_BusOptions); 1889 bus_options = reg_read(ohci, OHCI1394_BusOptions);
1868 max_receive = (bus_options >> 12) & 0xf; 1890 max_receive = (bus_options >> 12) & 0xf;
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 38b286ed744f..d36dd512a59d 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -752,10 +752,65 @@ handle_topology_map(struct fw_card *card, struct fw_request *request,
752} 752}
753 753
754static struct fw_address_handler topology_map = { 754static struct fw_address_handler topology_map = {
755 .length = 0x400, 755 .length = 0x200,
756 .address_callback = handle_topology_map, 756 .address_callback = handle_topology_map,
757}; 757};
758 758
759const struct fw_address_region registers_region =
760 { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
761
762static void
763handle_registers(struct fw_card *card, struct fw_request *request,
764 int tcode, int destination, int source,
765 int generation, int speed,
766 unsigned long long offset,
767 void *payload, size_t length, void *callback_data)
768{
769 int reg = offset - CSR_REGISTER_BASE;
770 unsigned long long bus_time;
771 __be32 *data = payload;
772
773 switch (reg) {
774 case CSR_CYCLE_TIME:
775 case CSR_BUS_TIME:
776 if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) {
777 fw_send_response(card, request, RCODE_TYPE_ERROR);
778 break;
779 }
780
781 bus_time = card->driver->get_bus_time(card);
782 if (reg == CSR_CYCLE_TIME)
783 *data = cpu_to_be32(bus_time);
784 else
785 *data = cpu_to_be32(bus_time >> 25);
786 fw_send_response(card, request, RCODE_COMPLETE);
787 break;
788
789 case CSR_BUS_MANAGER_ID:
790 case CSR_BANDWIDTH_AVAILABLE:
791 case CSR_CHANNELS_AVAILABLE_HI:
792 case CSR_CHANNELS_AVAILABLE_LO:
793 /* FIXME: these are handled by the OHCI hardware and
794 * the stack never sees these request. If we add
795 * support for a new type of controller that doesn't
796 * handle this in hardware we need to deal with these
797 * transactions. */
798 BUG();
799 break;
800
801 case CSR_BUSY_TIMEOUT:
802 /* FIXME: Implement this. */
803 default:
804 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
805 break;
806 }
807}
808
809static struct fw_address_handler registers = {
810 .length = 0x400,
811 .address_callback = handle_registers,
812};
813
759MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); 814MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
760MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); 815MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
761MODULE_LICENSE("GPL"); 816MODULE_LICENSE("GPL");
@@ -811,6 +866,10 @@ static int __init fw_core_init(void)
811 &topology_map_region); 866 &topology_map_region);
812 BUG_ON(retval < 0); 867 BUG_ON(retval < 0);
813 868
869 retval = fw_core_add_address_handler(&registers,
870 &registers_region);
871 BUG_ON(retval < 0);
872
814 /* Add the vendor textual descriptor. */ 873 /* Add the vendor textual descriptor. */
815 retval = fw_core_add_descriptor(&vendor_id_descriptor); 874 retval = fw_core_add_descriptor(&vendor_id_descriptor);
816 BUG_ON(retval < 0); 875 BUG_ON(retval < 0);
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index a661afb9d68f..855beb27216d 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -433,6 +433,8 @@ struct fw_card_driver {
433 int (*enable_phys_dma) (struct fw_card *card, 433 int (*enable_phys_dma) (struct fw_card *card,
434 int node_id, int generation); 434 int node_id, int generation);
435 435
436 u64 (*get_bus_time) (struct fw_card *card);
437
436 struct fw_iso_context * 438 struct fw_iso_context *
437 (*allocate_iso_context)(struct fw_card *card, int sync, int tags, 439 (*allocate_iso_context)(struct fw_card *card, int sync, int tags,
438 int type, size_t header_size); 440 int type, size_t header_size);