#include #include #include #include #include #include #include #include #include #include #include #include #include /*--- #include ---*/ #include #include #ifdef CONFIG_PROC_FS #define PROC_MAGIC_WORD "CONFIG_ARB:" #define PERF_COUNT_VAL 1000000 /*--- Wert für Performance Count Register ---*/ #define PROC_MODE_READ 4 #define PROC_MODE_WRITE 2 #define PROC_MODE_RW 6 #define ARBITER_MAX_MASTER_DEVS 15 #define ARBITER_AMBA_BUS_CNT 5 /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ enum _arb_bus_names { ARB_3, ARB_A, ARB_B, ARB_C, ARB_AMBA, ARB_PCI, ARB_MAX, ARB_NONE }; struct _arb_bus { char *name; char *proc_name; struct proc_dir_entry *proc_dir; char *bus_device_table[ARBITER_MAX_MASTER_DEVS]; }; struct _bus_param_entry { char *name; volatile unsigned int *reg; unsigned int mask; unsigned int shift; unsigned int def_val; unsigned int mode; struct _arb_bus *bus; struct proc_dir_entry *proc_file; unsigned int (*eval_fkt)(char *buff, int size, struct _bus_param_entry *bus_param); }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int arbiter_eval_time_val(char *buff, int size, struct _bus_param_entry *bus_param); unsigned int arbiter_eval_master_num(char *buff, int size, struct _bus_param_entry *bus_param); unsigned int arbiter_eval_bus_prio_flags(char *buff, int size, struct _bus_param_entry *bus_param); unsigned int arbiter_eval_device_list(char *buff, int size, struct _bus_param_entry *bus_param); unsigned int arbiter_eval_bus_name(char *buff, int size, struct _bus_param_entry *bus_param); int manage_arbiter_pci_irq(void); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define BASE_3 VX180_ARBITER_ARB_3_BASE #define BASE_A VX180_ARBITER_ARB_A_BASE #define BASE_B VX180_ARBITER_ARB_B_BASE #define BASE_C VX180_ARBITER_ARB_C_BASE #define PMOD_R S_IRUGO #define PMOD_W S_IWUGO #define PMOD_RW (S_IRUGO | S_IWUGO) #define ARB_REG(BUS, REG) ((volatile unsigned int *)VX180_ARBITER_##REG##_BASE(BUS)) #define ARB_3_REG(REG) ((volatile unsigned int *)VX180_ARBITER_ARB_3_##REG##_BASE) #define ARB_AMBA_REG(REG) ((volatile unsigned int *)VX180_DDR_##REG##_BASE) #define ARB_PCI_REG(REG) ((volatile unsigned int *)VX180_PCI_##REG##_BASE) struct _vx180_pci_error_register *PCI_ERROR_REG = (struct _vx180_pci_error_register *)VX180_PCI_ERROR_BASE; struct _vx180_pci_error_addr_register *PCI_ERROR_ADDR_REG = (struct _vx180_pci_error_addr_register *)VX180_PCI_ERROR_ADDR_BASE; struct _vx180_pci_ahb_error_register *PCI_AHB_ERROR_REG = (struct _vx180_pci_ahb_error_register *)VX180_PCI_AHB_ERROR_BASE; struct _vx180_pci_ahb_error_addr_register *PCI_AHB_ERROR_ADDR_REG = (struct _vx180_pci_ahb_error_addr_register *)VX180_PCI_AHB_ERROR_ADDR_BASE; union __vx180_pci_control2_register *PCI_CONTROL2_REG = (union __vx180_pci_control2_register *)VX180_PCI_CONTROL2_BASE; union __vx180_pci_status_register *PCI_STATUS_REG = (union __vx180_pci_status_register *)VX180_PCI_STATUS_BASE; struct _arb_bus bus_data[] = { [ARB_3] = { .name = "Ikanos Control Bus (CBUS)", .proc_name = "bus/cbus", .bus_device_table = { [2] = "SPA APU", [3] = "HIC", [4] = "VDSL APU", [5] = "CPE (MIPS)", [6] = "SPI", [7] = "PCI", [8] = "Ethernet-1 (GIGE)", [9] = "WLAN APU", [10] = "USB 2.0 HS/FS/LS (EHCI MODE)", [11] = "Ethernet-2 (GIGE2)", [12] = "DMA", [13] = "BMU", [14] = "USB 2.0 FS/LS (OHCI MODE)", }, }, [ARB_A] = { .name = "Ikanos Data Bus A (DBUSA)", .proc_name = "bus/dbus_a", .bus_device_table = { [8] = "GIGE", [12] = "WLAN APU", [13] = "SPA", }, }, [ARB_B] = { .name = "Ikanos Data Bus B (DBUSB)", .proc_name = "bus/dbus_b", .bus_device_table = { [9] = "VDSL_APU", [11] = "GIGE2", [12] = "BMU", }, }, [ARB_C] = { .name = "Ikanos Data Bus C (DBUSC)", .proc_name = "bus/dbus_c", .bus_device_table = { [4] = "DMA", [5] = "PCI", [6] = "SPI", [7] = "USB 2.0 HS/FS/LS (EHCI MODE)", [8] = "USB 2.0 FS/LS (OHCI MODE)" }, }, [ARB_AMBA] = { .name = "Ikanos AMBA Bus", .proc_name = "bus/amba_bus", .bus_device_table = { [0] = "MIPS Bus", [1] = "VPHY CPU", [2] = "DBUS A", [3] = "DBUS B", [4] = "DBUS C", }, }, [ARB_PCI] = { .name = "Ikanos PCI Bus", .proc_name = "bus/pci_bus", .bus_device_table = { [0] = "MIPS Bus", [1] = "VPHY CPU", [2] = "DBUS A", [3] = "DBUS B", [4] = "DBUS C", }, } }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _bus_param_entry bus_param_table[] = { /*--- Arbiter für Datenbusse (CBUS & DBUS) ---*/ { .name = "sbus_error_addr", .reg = ARB_REG(BASE_A, SBUS_ERROR_ADDR), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_A], }, { .name = "sbus_error_addr", .reg = ARB_REG(BASE_B, SBUS_ERROR_ADDR), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_B], }, { .name = "sbus_error_addr", .reg = ARB_REG(BASE_C, SBUS_ERROR_ADDR), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_C], }, { .name = "sbus_error_addr", .reg = ARB_REG(BASE_3, SBUS_ERROR_ADDR), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_3], }, #if 0 { .name = "intr_enable", .reg = ARB_REG(BASE_A, INTR_ENBL), .mask=0x00000001,.shift=0, .def_val=0x1, .mode = PMOD_RW, .bus = &bus_data[ARB_A], }, { .name = "intr_enable", .reg = ARB_REG(BASE_B, INTR_ENBL), .mask=0x00000001,.shift=0, .def_val=0x1, .mode = PMOD_RW, .bus = &bus_data[ARB_B], }, { .name = "intr_enable", .reg = ARB_REG(BASE_C, INTR_ENBL), .mask=0x00000001,.shift=0, .def_val=0x1, .mode = PMOD_RW, .bus = &bus_data[ARB_C], }, { .name = "intr_enable", .reg = ARB_REG(BASE_3, INTR_ENBL), .mask=0x00000001,.shift=0, .def_val=0x1, .mode = PMOD_RW, .bus = &bus_data[ARB_3], }, #endif { .name = "error_master__pci_retry_timeout", .reg = ARB_REG(BASE_A, ERROR_MASTER), .mask=0x00000040,.shift=6, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_A], }, { .name = "error_master__pci_retry_timeout", .reg = ARB_REG(BASE_B, ERROR_MASTER), .mask=0x00000040,.shift=6, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_B], }, { .name = "error_master__pci_retry_timeout", .reg = ARB_REG(BASE_C, ERROR_MASTER), .mask=0x00000040,.shift=6, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_C], }, { .name = "error_master__pci_retry_timeout", .reg = ARB_REG(BASE_3, ERROR_MASTER), .mask=0x00000040,.shift=6, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "error_master__arb_timeout", .reg = ARB_REG(BASE_A, ERROR_MASTER), .mask=0x00000020,.shift=5, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_A], }, { .name = "error_master__arb_timeout", .reg = ARB_REG(BASE_B, ERROR_MASTER), .mask=0x00000020,.shift=5, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_B], }, { .name = "error_master__arb_timeout", .reg = ARB_REG(BASE_C, ERROR_MASTER), .mask=0x00000020,.shift=5, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_C], }, { .name = "error_master__arb_timeout", .reg = ARB_REG(BASE_3, ERROR_MASTER), .mask=0x00000020,.shift=5, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "error_master__sbus_err_mstr", .reg = ARB_REG(BASE_A, ERROR_MASTER), .mask=0x0000001F,.shift=1, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_A], .eval_fkt = arbiter_eval_master_num }, { .name = "error_master__sbus_err_mstr", .reg = ARB_REG(BASE_B, ERROR_MASTER), .mask=0x0000001F,.shift=1, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_B], .eval_fkt = arbiter_eval_master_num }, { .name = "error_master__sbus_err_mstr", .reg = ARB_REG(BASE_C, ERROR_MASTER), .mask=0x0000001F,.shift=1, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_C], .eval_fkt = arbiter_eval_master_num }, { .name = "error_master__sbus_err_mstr", .reg = ARB_REG(BASE_3, ERROR_MASTER), .mask=0x0000001F,.shift=1, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], .eval_fkt = arbiter_eval_master_num }, { .name = "timeout_counter", .reg = ARB_REG(BASE_A, TIMEOUT_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_A], }, { .name = "timeout_counter", .reg = ARB_REG(BASE_B, TIMEOUT_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_B], }, { .name = "timeout_counter", .reg = ARB_REG(BASE_C, TIMEOUT_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_C], }, { .name = "timeout_counter", .reg = ARB_REG(BASE_3, TIMEOUT_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_3], }, { .name = "control__no_of_gr2_grants", .reg = ARB_REG(BASE_A, CONTROL), .mask=0xFFFF0000,.shift=16, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_A], }, { .name = "control__no_of_gr2_grants", .reg = ARB_REG(BASE_B, CONTROL), .mask=0xFFFF0000,.shift=16, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_B], }, { .name = "control__no_of_gr2_grants", .reg = ARB_REG(BASE_C, CONTROL), .mask=0xFFFF0000,.shift=16, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_C], }, { .name = "control__no_of_gr2_grants", .reg = ARB_REG(BASE_3, CONTROL), .mask=0xFFFF0000,.shift=16, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_3], }, { .name = "control__arb_sample_time", .reg = ARB_REG(BASE_A, CONTROL), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_A], .eval_fkt = arbiter_eval_time_val }, { .name = "control__arb_sample_time", .reg = ARB_REG(BASE_B, CONTROL), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_B], .eval_fkt = arbiter_eval_time_val }, { .name = "control__arb_sample_time", .reg = ARB_REG(BASE_C, CONTROL), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_C], .eval_fkt = arbiter_eval_time_val }, { .name = "control__arb_sample_time", .reg = ARB_REG(BASE_3, CONTROL), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_W, .bus = &bus_data[ARB_3], .eval_fkt = arbiter_eval_time_val }, { .name = "performance_counter", .reg = ARB_REG(BASE_A, PERFORMANCE_COUNTER), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_A], .eval_fkt = arbiter_eval_time_val }, { .name = "performance_counter", .reg = ARB_REG(BASE_B, PERFORMANCE_COUNTER), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_B], .eval_fkt = arbiter_eval_time_val }, { .name = "performance_counter", .reg = ARB_REG(BASE_C, PERFORMANCE_COUNTER), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_C], .eval_fkt = arbiter_eval_time_val }, { .name = "performance_counter", .reg = ARB_REG(BASE_3, PERFORMANCE_COUNTER), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_3], .eval_fkt = arbiter_eval_time_val }, { .name = "performance_idle_slots", .reg = ARB_REG(BASE_A, PERFORMANCE_IDLE_SLOTS), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_A], }, { .name = "performance_idle_slots", .reg = ARB_REG(BASE_B, PERFORMANCE_IDLE_SLOTS), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_B], }, { .name = "performance_idle_slots", .reg = ARB_REG(BASE_C, PERFORMANCE_IDLE_SLOTS), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_C], }, { .name = "performance_idle_slots", .reg = ARB_REG(BASE_3, PERFORMANCE_IDLE_SLOTS), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma1_error__data_mem_status", .reg = ARB_3_REG(IDMA1_ERROR_STATUS), .mask=0x00010000,.shift=16, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma2_error__data_mem_status", .reg = ARB_3_REG(IDMA2_ERROR_STATUS), .mask=0x00010000,.shift=16, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma3_error__data_mem_status", .reg = ARB_3_REG(IDMA3_ERROR_STATUS), .mask=0x00010000,.shift=16, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma1_error__prog_mem_status", .reg = ARB_3_REG(IDMA1_ERROR_STATUS), .mask=0x00000100,.shift=8, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma2_error__prog_mem_status", .reg = ARB_3_REG(IDMA2_ERROR_STATUS), .mask=0x00000100,.shift=8, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma3_error__prog_mem_status", .reg = ARB_3_REG(IDMA3_ERROR_STATUS), .mask=0x00000100,.shift=8, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma1_error__ack_status", .reg = ARB_3_REG(IDMA1_ERROR_STATUS), .mask=0x00000001,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma2_error__ack_status", .reg = ARB_3_REG(IDMA2_ERROR_STATUS), .mask=0x00000001,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma3_error__ack_status", .reg = ARB_3_REG(IDMA3_ERROR_STATUS), .mask=0x00000001,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma1_error_address", .reg = ARB_3_REG(IDMA1_ERROR_ADDRESS), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma2_error_address", .reg = ARB_3_REG(IDMA2_ERROR_ADDRESS), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "idma3_error_address", .reg = ARB_3_REG(IDMA3_ERROR_ADDRESS), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_R, .bus = &bus_data[ARB_3], }, { .name = "fixed_priority__master4", .reg = ARB_3_REG(FIXED_PRIORITY), .mask=0xFF000000,.shift=24, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_3], }, { .name = "fixed_priority__master3", .reg = ARB_3_REG(FIXED_PRIORITY), .mask=0x00FF0000,.shift=16, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_3], }, { .name = "fixed_priority__master2", .reg = ARB_3_REG(FIXED_PRIORITY), .mask=0x0000FF00,.shift=8, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_3], }, { .name = "fixed_priority__master1", .reg = ARB_3_REG(FIXED_PRIORITY), .mask=0x000000FF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_3], }, /*--- Arbiter für DDR-RAM ---*/ { .name = "ahb_arb_ctl__en_msec", .reg = ARB_AMBA_REG(AHB_ARBITER_CTL), .mask=0x80000000,.shift=31, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], }, { .name = "ahb_arb_ctl__disable_ddr_prec", .reg = ARB_AMBA_REG(AHB_ARBITER_CTL), .mask=0x01F00000,.shift=20, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_bus_prio_flags }, { .name = "ahb_arb_ctl__static_pri3", .reg = ARB_AMBA_REG(AHB_ARBITER_CTL), .mask=0x0001F000,.shift=12, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_bus_prio_flags }, { .name = "ahb_arb_ctl__static_pri2", .reg = ARB_AMBA_REG(AHB_ARBITER_CTL), .mask=0x000001F0,.shift=4, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_bus_prio_flags }, { .name = "ahb_arb_ctl__dynamic_pri1", .reg = ARB_AMBA_REG(AHB_ARBITER_CTL), .mask=0x0000000C,.shift=2, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_bus_prio_flags }, { .name = "ahb_arb_ctl__dynamic_pri0", .reg = ARB_AMBA_REG(AHB_ARBITER_CTL), .mask=0x00000003,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_bus_prio_flags }, { .name = "ahb0_high_prio_counter", .reg = ARB_AMBA_REG(AHB0_HIGH_PRIO_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_time_val }, { .name = "ahb1_high_prio_counter", .reg = ARB_AMBA_REG(AHB1_HIGH_PRIO_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_time_val }, { .name = "ahb0_low_prio_counter", .reg = ARB_AMBA_REG(AHB0_LOW_PRIO_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_time_val }, { .name = "ahb1_low_prio_counter", .reg = ARB_AMBA_REG(AHB1_LOW_PRIO_COUNTER), .mask=0x0000FFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_time_val }, /*--- Arbiter für PCI-Bus ---*/ { .name = "pci_error_msg", .reg = ARB_PCI_REG(ERROR), .mask=0x00000003,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_PCI], }, { .name = "pci_error_addr", .reg = ARB_PCI_REG(ERROR_ADDR), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_PCI], }, { .name = "ahb_error_msg", .reg = ARB_PCI_REG(AHB_ERROR), .mask=0x00000001,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_PCI], }, { .name = "ahb_error_addr", .reg = ARB_PCI_REG(AHB_ERROR_ADDR), .mask=0xFFFFFFFF,.shift=0, .def_val=0x0, .mode = PMOD_RW, .bus = &bus_data[ARB_PCI], }, /*--- allgemeine Infos ---*/ { .name = "name", .mode = PMOD_R, .bus = &bus_data[ARB_A], .eval_fkt = arbiter_eval_bus_name }, { .name = "name", .mode = PMOD_R, .bus = &bus_data[ARB_B], .eval_fkt = arbiter_eval_bus_name }, { .name = "name", .mode = PMOD_R, .bus = &bus_data[ARB_C], .eval_fkt = arbiter_eval_bus_name }, { .name = "name", .mode = PMOD_R, .bus = &bus_data[ARB_3], .eval_fkt = arbiter_eval_bus_name }, { .name = "name", .mode = PMOD_R, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_bus_name }, { .name = "name", .mode = PMOD_R, .bus = &bus_data[ARB_PCI], .eval_fkt = arbiter_eval_bus_name }, { .name = "devices", .mode = PMOD_R, .bus = &bus_data[ARB_A], .eval_fkt = arbiter_eval_device_list }, { .name = "devices", .mode = PMOD_R, .bus = &bus_data[ARB_B], .eval_fkt = arbiter_eval_device_list }, { .name = "devices", .mode = PMOD_R, .bus = &bus_data[ARB_C], .eval_fkt = arbiter_eval_device_list }, { .name = "devices", .mode = PMOD_R, .bus = &bus_data[ARB_3], .eval_fkt = arbiter_eval_device_list }, { .name = "devices", .mode = PMOD_R, .bus = &bus_data[ARB_AMBA], .eval_fkt = arbiter_eval_device_list }, { .name = NULL } }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int arbiter_eval_time_val(char *buff, int size, struct _bus_param_entry *bus_param) { return snprintf(buff, size, "%u ns", (*(bus_param->reg) & bus_param->mask) >> bus_param->shift); } unsigned int arbiter_eval_master_num(char *buff, int size, struct _bus_param_entry *bus_param) { unsigned int master_num = (*(bus_param->reg) & bus_param->mask) >> bus_param->shift; return snprintf(buff, size, "%u: %s", master_num, bus_param->bus->bus_device_table[master_num]); } unsigned int arbiter_eval_bus_prio_flags(char *buff, int size, struct _bus_param_entry *bus_param) { unsigned int i, bytes_written, bus_mask; bus_mask = (*(bus_param->reg) & bus_param->mask) >> bus_param->shift; bytes_written = 0; for(i = 0; i < ARBITER_AMBA_BUS_CNT; i++) { if(bus_mask & (1 << i)) bytes_written += snprintf(buff + bytes_written, size - bytes_written, "bit %u set: %s\n", i, bus_param->bus->bus_device_table[i]); } return bytes_written; } unsigned int arbiter_eval_device_list(char *buff, int size, struct _bus_param_entry *bus_param) { unsigned int i, bytes_written; bytes_written = 0; for(i = 0; i < ARBITER_MAX_MASTER_DEVS; i++) { if(bus_param->bus->bus_device_table[i]) { bytes_written += snprintf(buff + bytes_written, size - bytes_written, "%u: %s\n", i, bus_param->bus->bus_device_table[i]); printk(KERN_DEBUG "[arbiter_eval_device_list] bytes_written=%u\n", bytes_written); } } return bytes_written; } unsigned int arbiter_eval_bus_name(char *buff, int size, struct _bus_param_entry *bus_param) { return snprintf(buff, size, "%s", bus_param->bus->name); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int arbiter_read_proc(char *buff, char **start, off_t offset, int size, int *p_eof, void *data) { unsigned int bytes_written; struct _bus_param_entry *bus_param; bus_param = (struct _bus_param_entry *)data; if(bus_param->eval_fkt) { bytes_written = bus_param->eval_fkt(buff, size, bus_param); } else { bytes_written = snprintf(buff, size, "%u", (*(bus_param->reg) & bus_param->mask) >> bus_param->shift); } *p_eof = 1; return bytes_written; } int arbiter_write_proc(struct file *file, const char __user *userbuff, unsigned long count, void *data) { #define COPYBUFF_SIZE (16 + sizeof(PROC_MAGIC_WORD)) char copybuff[COPYBUFF_SIZE]; int not_copied; unsigned int reg_val; char *val_end; struct _bus_param_entry *bus_param; bus_param = (struct _bus_param_entry *)data; if(count > COPYBUFF_SIZE) { return -ENOMEM; } not_copied = copy_from_user(copybuff, userbuff, count); copybuff[count - not_copied] = '\0'; /*--- in case '\0' was not copied ---*/ if(strncmp(copybuff, PROC_MAGIC_WORD, sizeof(PROC_MAGIC_WORD) - 1) == 0) { char *val = copybuff + sizeof(PROC_MAGIC_WORD) - 1; reg_val = simple_strtol(val, &val_end, 10); /*--- if((val_end > val) && !*val_end) { ---*/ if(val_end > val) { /*--- unsigned int mask = (((1 << bus_param->bits) - 1) << bus_param->shift); ---*/ *bus_param->reg = (*bus_param->reg & ~bus_param->mask) | ((reg_val << bus_param->shift) & bus_param->mask); printk(KERN_DEBUG "[arbiter:arbiter_write_proc] writing '%d' as 0x%X (0x%X) to register of /proc/bus/[bus]/%s: %s\n", reg_val, *bus_param->reg, (reg_val << bus_param->shift) & bus_param->mask, bus_param->name, copybuff); } else { printk(KERN_WARNING "[arbiter:arbiter_write_proc] invalid write on /proc/bus/[bus]/%s: %s\n", bus_param->name, copybuff); } } else { printk(KERN_WARNING "[arbiter:arbiter_write_proc] invalid write on /proc/bus/[bus]/%s: %s\n", bus_param->name, copybuff); } return count - not_copied; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int create_proc_files(void) { struct _bus_param_entry *bus_param; enum _arb_bus_names bus_id; for(bus_id = 0; bus_id < ARB_MAX; bus_id++) { bus_data[bus_id].proc_dir = proc_mkdir(bus_data[bus_id].proc_name, NULL); if(!bus_data[bus_id].proc_dir) { printk(KERN_WARNING "[arbiter:create_proc_files] error while creating /proc/bus/[bus] directories\n"); } } if(!bus_data[ARB_3].proc_dir || !bus_data[ARB_A].proc_dir || !bus_data[ARB_B].proc_dir || !bus_data[ARB_C].proc_dir) { printk(KERN_WARNING "[arbiter:create_proc_files] error while creating /proc/bus/[bus] directories\n"); return -1; } for(bus_param = bus_param_table; bus_param->name; bus_param++) { bus_param->proc_file = create_proc_entry(bus_param->name, bus_param->mode, bus_param->bus->proc_dir); if(!bus_param->proc_file) { printk(KERN_WARNING "[arbiter:create_proc_files] error while creating /proc/bus/[bus]/%s\n", bus_param->name); continue; } if(bus_param->mode & PMOD_R) bus_param->proc_file->read_proc = arbiter_read_proc; if(bus_param->mode & PMOD_W) bus_param->proc_file->write_proc = arbiter_write_proc; bus_param->proc_file->data = (void *)bus_param; } return 0; } #endif /*--- #ifdef CONFIG_PROC_FS ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ irqreturn_t manage_arbiter_irq(int irq, void *dev_id) { /*--- extern void show_registers(struct pt_regs *); ---*/ /*--- struct pt_regs *regs; ---*/ unsigned int bus; enum _arb_bus_names bus_id; unsigned int error; unsigned int *p_error = &error; static unsigned int INT_CBUS_ARB_count; static unsigned int INT_DBUSA_ARB_count; static unsigned int INT_DBUSB_ARB_count; static unsigned int INT_DBUSC_ARB_count; struct _vx180_arbiter_sbus_error_addr_register *ERROR_ADDR_REG; struct _vx180_arbiter_intr_enbl_register *INTR_ENBL_REG; struct _vx180_arbiter_error_master_register *ERROR_MASTER_REG; struct _vx180_arbiter_timeout_counter_register *TIMEOUT_COUNTER_REG; struct _vx180_arbiter_control_register *CONTROL_REG; struct _vx180_arbiter_performance_counter_register *PERF_COUNTER_REG; struct _vx180_arbiter_performance_idle_slots_register *PERD_IDLE_SLOT_REG; char *name; switch(irq) { case INT_CBUS_ARB: p_error = &INT_CBUS_ARB_count; bus = VX180_ARBITER_ARB_3_BASE; bus_id = ARB_3; break; case INT_DBUSA_ARB: p_error = &INT_DBUSA_ARB_count; bus = VX180_ARBITER_ARB_A_BASE; bus_id = ARB_A; break; case INT_DBUSB_ARB: p_error = &INT_DBUSB_ARB_count; bus = VX180_ARBITER_ARB_B_BASE; bus_id = ARB_B; break; case INT_DBUSC_ARB: p_error = &INT_DBUSC_ARB_count; bus = VX180_ARBITER_ARB_C_BASE; bus_id = ARB_C; break; default: bus = VX180_ARBITER_ARB_3_BASE; bus_id = ARB_NONE; } (*p_error)++; ERROR_ADDR_REG = (struct _vx180_arbiter_sbus_error_addr_register *)VX180_ARBITER_SBUS_ERROR_ADDR_BASE(bus); INTR_ENBL_REG = (struct _vx180_arbiter_intr_enbl_register *)VX180_ARBITER_INTR_ENBL_BASE(bus); ERROR_MASTER_REG = (struct _vx180_arbiter_error_master_register *)VX180_ARBITER_ERROR_MASTER_BASE(bus); TIMEOUT_COUNTER_REG = (struct _vx180_arbiter_timeout_counter_register *)VX180_ARBITER_TIMEOUT_COUNTER_BASE(bus); CONTROL_REG = (struct _vx180_arbiter_control_register *)VX180_ARBITER_CONTROL_BASE(bus); TIMEOUT_COUNTER_REG = (struct _vx180_arbiter_timeout_counter_register *)VX180_ARBITER_TIMEOUT_COUNTER_BASE(bus); PERF_COUNTER_REG = (struct _vx180_arbiter_performance_counter_register *)VX180_ARBITER_PERFORMANCE_COUNTER_BASE(bus); PERD_IDLE_SLOT_REG = (struct _vx180_arbiter_performance_idle_slots_register *)VX180_ARBITER_PERFORMANCE_IDLE_SLOTS_BASE(bus); name = (bus_id == ARB_NONE) ? "non" : bus_data[bus_id].name; printk(KERN_ERR "[%s] ERROR (cnt=%d, idle=%d%%) at 0x%08x", name, *p_error, (PERD_IDLE_SLOT_REG->PERF_IDLE_SLOTS * 100) / PERF_COUNTER_REG->PERF_COUNT_TIME, ERROR_ADDR_REG->SBUS_ERR_ADDR); name = (bus_id == ARB_NONE) ? "non" : bus_data[bus_id].bus_device_table[ERROR_MASTER_REG->SBUS_ERR_MSTR]; printk(" generated by %s: %s%s\n", name, ERROR_MASTER_REG->ARB_TIMEOUT ? "Arbiter timeout " : "", ERROR_MASTER_REG->PCI_RETRY_TIMEOUT ? "PCI retry timeout " : ""); printk(KERN_ERR "Bus priorisation params: SampleTime 0x%x Number of Grants 0x%x Timeout 0x%x\n", CONTROL_REG->ARB_SAMPLE_TIME, CONTROL_REG->NO_OF_GR2_GRANTS, TIMEOUT_COUNTER_REG->TO_CNT); /*--- if(mips) { ---*/ /*--- regs = current->thread_info->regs; ---*/ /*--- show_registers(regs); ---*/ /*--- } ---*/ /*--- clear interrupt ---*/ ERROR_ADDR_REG->SBUS_ERR_ADDR = 0; if(*p_error > 100) { /*--- disable interrupt ---*/ INTR_ENBL_REG->ERR_INTR_ENBL = 0; } /*--------------------------------------------------------------------------------------*\ * Hier muss geprüft werden ob die Adresse auf die zugegriffen wurde zwingend zum * Systemneustart führten muss \*--------------------------------------------------------------------------------------*/ return IRQ_HANDLED; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int manage_arbiter_pci_irq(void) { /*--- extern void show_registers(struct pt_regs *); ---*/ /*--- struct pt_regs *regs; ---*/ static unsigned int error; if(!PCI_ERROR_REG->PCI_ERROR_MESSAGE && !PCI_AHB_ERROR_REG->AHB_ERROR_MESSAGE) { return 0; } error++; printk(KERN_ERR "[%s] ERROR (cnt=%d, PCI_CONTROL2_REG=0x%x, PCI_STATUS_REG=0x%x) at ", bus_data[ARB_PCI].name, error, PCI_CONTROL2_REG->Reg, PCI_STATUS_REG->Reg); if(PCI_ERROR_REG->PCI_ERROR_MESSAGE) { printk("0x%08x : PCI transaction has %s error! \n", PCI_ERROR_ADDR_REG->PCI_ERROR_ADDR, (PCI_ERROR_REG->PCI_ERROR_MESSAGE == 1) ? "fatal" : (PCI_ERROR_REG->PCI_ERROR_MESSAGE == 2) ? "parity" : "unknown"); PCI_ERROR_REG->PCI_ERROR_MESSAGE = 3; /*--- Clear error bits ---*/ } if(PCI_AHB_ERROR_REG->AHB_ERROR_MESSAGE) { printk("0x%08x : AHB-Master received an error response!\n", PCI_AHB_ERROR_ADDR_REG->AHB_ERROR_ADDR); PCI_AHB_ERROR_REG->AHB_ERROR_MESSAGE = 1; /*--- Clear error bit ---*/ } /*--- if(mips) { ---*/ /*--- regs = current->thread_info->regs; ---*/ /*--- show_registers(regs); ---*/ /*--- } ---*/ /*--- clear interrupt ---*/ /*--- ERROR_ADDR_REG->SBUS_ERR_ADDR = 0; ---*/ return 1; } /*------------------------------------------------------------------------------------------*\ * Gibt einen Pointer auf eine Callback-Funktion vom Typ int (*func)(void) zurück. \*------------------------------------------------------------------------------------------*/ int (*arbiter_pci_irq_enable(void))(void) { /*--- ((struct _vx180_mode_control_register *)VX180_MODE_CONTROL_BASE)->PCI_INT_ARB_ENB = 1; ---*/ /*--- PCI-internen Arbiter aktivieren ---*/ PCI_CONTROL2_REG->Bits.SERR_EN = 1; return manage_arbiter_pci_irq; } EXPORT_SYMBOL(arbiter_pci_irq_enable); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void arbiter_pci_irq_disable(void) { PCI_CONTROL2_REG->Bits.SERR_EN = 0; } EXPORT_SYMBOL(arbiter_pci_irq_disable); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int __init manage_arbiter_init( void ) { struct _vx180_arbiter_intr_enbl_register *INTR_ENBL_REG; struct _vx180_arbiter_performance_counter_register *PERF_COUNTER_REG; create_proc_files(); if(request_irq(INT_DBUSC_ARB, manage_arbiter_irq, IRQF_SHARED, "arbiter D-Bus C", NULL)) { return 1; } INTR_ENBL_REG = (struct _vx180_arbiter_intr_enbl_register *)VX180_ARBITER_INTR_ENBL_BASE(VX180_ARBITER_ARB_C_BASE); INTR_ENBL_REG->ERR_INTR_ENBL = 1; /*--- nur error response interrupt ---*/ if(request_irq(INT_DBUSB_ARB, manage_arbiter_irq, IRQF_SHARED, "arbiter D-Bus B", NULL)) { return 1; } INTR_ENBL_REG = (struct _vx180_arbiter_intr_enbl_register *)VX180_ARBITER_INTR_ENBL_BASE(VX180_ARBITER_ARB_B_BASE); INTR_ENBL_REG->ERR_INTR_ENBL = 1; /*--- nur error response interrupt ---*/ if(request_irq(INT_DBUSA_ARB, manage_arbiter_irq, IRQF_SHARED, "arbiter D-Bus A", NULL)) { return 1; } INTR_ENBL_REG = (struct _vx180_arbiter_intr_enbl_register *)VX180_ARBITER_INTR_ENBL_BASE(VX180_ARBITER_ARB_A_BASE); INTR_ENBL_REG->ERR_INTR_ENBL = 1; if(request_irq(INT_CBUS_ARB, manage_arbiter_irq, IRQF_SHARED, "arbiter C-Bus", NULL)) { return 1; } INTR_ENBL_REG = (struct _vx180_arbiter_intr_enbl_register *)VX180_ARBITER_INTR_ENBL_BASE(VX180_ARBITER_ARB_3_BASE); INTR_ENBL_REG->ERR_INTR_ENBL = 1; PERF_COUNTER_REG = (struct _vx180_arbiter_performance_counter_register *)VX180_ARBITER_PERFORMANCE_COUNTER_BASE(VX180_ARBITER_ARB_A_BASE); PERF_COUNTER_REG->PERF_COUNT_TIME = PERF_COUNT_VAL; PERF_COUNTER_REG = (struct _vx180_arbiter_performance_counter_register *)VX180_ARBITER_PERFORMANCE_COUNTER_BASE(VX180_ARBITER_ARB_B_BASE); PERF_COUNTER_REG->PERF_COUNT_TIME = PERF_COUNT_VAL; PERF_COUNTER_REG = (struct _vx180_arbiter_performance_counter_register *)VX180_ARBITER_PERFORMANCE_COUNTER_BASE(VX180_ARBITER_ARB_C_BASE); PERF_COUNTER_REG->PERF_COUNT_TIME = PERF_COUNT_VAL; PERF_COUNTER_REG = (struct _vx180_arbiter_performance_counter_register *)VX180_ARBITER_PERFORMANCE_COUNTER_BASE(VX180_ARBITER_ARB_3_BASE); PERF_COUNTER_REG->PERF_COUNT_TIME = PERF_COUNT_VAL; return 0; } subsys_initcall(manage_arbiter_init);