| #include <console/console.h> |
| #include <device/device.h> |
| #include <device/smbus.h> |
| #include <device/pci.h> |
| #include <device/pci_ids.h> |
| #include <device/pci_ops.h> |
| #include <cpu/x86/msr.h> |
| #include <part/hard_reset.h> |
| #include <delay.h> |
| #include "chip.h" |
| |
| static void print_pci_regs(struct device *dev) |
| { |
| uint8_t byte; |
| int i; |
| |
| for(i=0;i<256;i++) { |
| byte = pci_read_config8(dev, i); |
| |
| if((i & 0xf)==0) printk_debug("\n%02x:",i); |
| printk_debug(" %02x",byte); |
| } |
| printk_debug("\n"); |
| } |
| |
| static void print_mem(void) |
| { |
| unsigned int i; |
| unsigned int start = 0xfffff000; |
| for(i=start;i<0xffffffff;i++) { |
| if((i & 0xf)==0) printk_debug("\n %08x:",i); |
| printk_debug(" %02x",(unsigned char)*((unsigned char *)i)); |
| } |
| printk_debug(" %02x\n",(unsigned char)*((unsigned char *)i)); |
| |
| } |
| static void print_pci_regs_all(void) |
| { |
| struct device *dev; |
| unsigned bus, device, function; |
| |
| for(bus=0; bus<256; bus++) { |
| for(device=0; device<=0x1f; device++) { |
| for (function=0; function<=7; function++){ |
| unsigned devfn; |
| devfn = PCI_DEVFN(device, function); |
| dev = dev_find_slot(bus, devfn); |
| if(!dev) { |
| continue; |
| } |
| if(!dev->enabled) { |
| continue; |
| } |
| printk_debug("\n%02x:%02x:%02x aka %s", |
| bus, device, function, dev_path(dev)); |
| print_pci_regs(dev); |
| } |
| } |
| } |
| } |
| |
| static void print_cpuid() |
| { |
| msr_t msr; |
| unsigned index; |
| unsigned eax, ebx, ecx, edx; |
| index = 0x80000007; |
| printk_debug("calling cpuid 0x%08x\n", index); |
| asm volatile( |
| "cpuid" |
| : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| : "a" (index) |
| ); |
| printk_debug("cpuid[%08x]: %08x %08x %08x %08x\n", |
| index, eax, ebx, ecx, edx); |
| if (edx & (3 << 1)) { |
| index = 0xC0010042; |
| printk_debug("Reading msr: 0x%08x\n", index); |
| msr = rdmsr(index); |
| printk_debug("msr[0x%08x]: 0x%08x%08x\n", |
| index, msr.hi, msr.lo); |
| } |
| |
| } |
| static void print_smbus_regs(struct device *dev) |
| { |
| int j; |
| printk_debug("smbus: %s[%d]->", dev_path(dev->bus->dev), dev->bus->link); |
| printk_debug("%s", dev_path(dev)); |
| for(j = 0; j < 256; j++) { |
| int status; |
| unsigned char byte; |
| status = smbus_read_byte(dev, j); |
| if (status < 0) { |
| // printk_debug("bad device status= %08x\r\n", status); |
| break; |
| } |
| if ((j & 0xf) == 0) { |
| printk_debug("\r\n%02x: ", j); |
| } |
| byte = status & 0xff; |
| printk_debug("%02x ", byte); |
| } |
| printk_debug("\r\n"); |
| } |
| |
| static void print_smbus_regs_all(struct device *dev) |
| { |
| struct device *child; |
| int i; |
| if (dev->enabled && dev->path.type == DEVICE_PATH_I2C) |
| { |
| // Here don't need to call smbus_set_link, because we scan it from top to down |
| if( dev->bus->dev->path.type == DEVICE_PATH_I2C) { // it's under i2c MUX so set mux at first |
| if(ops_smbus_bus(get_pbus_smbus(dev->bus->dev))) { |
| if(dev->bus->dev->ops && dev->bus->dev->ops->set_link) |
| dev->bus->dev->ops->set_link(dev->bus->dev, dev->bus->link); |
| } |
| } |
| |
| if(ops_smbus_bus(get_pbus_smbus(dev))) print_smbus_regs(dev); |
| } |
| |
| for(i=0; i< dev->links; i++) { |
| for (child = dev->link[i].children; child; child = child->sibling) { |
| print_smbus_regs_all(child); |
| } |
| } |
| } |
| static void print_msr_dualcore(void) |
| { |
| msr_t msr; |
| unsigned index; |
| unsigned eax, ebx, ecx, edx; |
| index = 0x80000008; |
| printk_debug("calling cpuid 0x%08x\n", index); |
| asm volatile( |
| "cpuid" |
| : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| : "a" (index) |
| ); |
| printk_debug("cpuid[%08x]: %08x %08x %08x %08x\n", |
| index, eax, ebx, ecx, edx); |
| |
| printk_debug("core number %d\n", ecx & 0xff); |
| |
| index = 0xc001001f; |
| printk_debug("Reading msr: 0x%08x\n", index); |
| msr = rdmsr(index); |
| printk_debug("msr[0x%08x]: 0x%08x%08x bit 54 is %d\n", |
| index, msr.hi, msr.lo, (msr.hi>> (54-32)) & 1); |
| #if 0 |
| msr.hi |= (1<<(54-32)); |
| wrmsr(index, msr); |
| |
| msr = rdmsr(index); |
| printk_debug("msr[0x%08x]: 0x%08x%08x\n", |
| index, msr.hi, msr.lo); |
| #endif |
| |
| } |
| |
| static void print_cache_size(void) |
| { |
| unsigned index; |
| unsigned int n, eax, ebx, ecx, edx; |
| |
| index = 0x80000000; |
| printk_debug("calling cpuid 0x%08x\n", index); |
| asm volatile( |
| "cpuid" |
| : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| : "a" (index) |
| ); |
| n = eax; |
| |
| if (n >= 0x80000005) { |
| index = 0x80000005; |
| printk_debug("calling cpuid 0x%08x\n", index); |
| asm volatile( |
| "cpuid" |
| : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| : "a" (index) |
| ); |
| printk_debug("CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", |
| edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); |
| } |
| |
| if (n >= 0x80000006) { |
| index = 0x80000006; |
| printk_debug("calling cpuid 0x%08x\n", index); |
| asm volatile( |
| "cpuid" |
| : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) |
| : "a" (index) |
| ); |
| printk_debug("CPU: L2 Cache: %dK (%d bytes/line)\n", |
| ecx >> 16, ecx & 0xFF); |
| } |
| |
| } |
| |
| struct tsc_struct { |
| unsigned lo; |
| unsigned hi; |
| }; |
| typedef struct tsc_struct tsc_t; |
| |
| static tsc_t rdtsc(void) |
| { |
| tsc_t res; |
| asm volatile( |
| "rdtsc" |
| : "=a" (res.lo), "=d"(res.hi) /* outputs */ |
| ); |
| return res; |
| } |
| |
| static void print_tsc(void) { |
| |
| tsc_t tsc; |
| tsc = rdtsc(); |
| printk_debug("tsc: 0x%08x%08x\n", |
| tsc.hi, tsc.lo); |
| udelay(1); |
| tsc = rdtsc(); |
| printk_debug("tsc: 0x%08x%08x after udelay(1) \n", |
| tsc.hi, tsc.lo); |
| |
| } |
| |
| static void debug_init(device_t dev) |
| { |
| device_t parent; |
| |
| if (!dev->enabled) |
| return; |
| switch(dev->path.pnp.device) { |
| case 0: |
| parent = dev->bus->dev; |
| printk_debug("DEBUG: %s", dev_path(parent)); |
| if(parent->chip_ops && parent->chip_ops->name) { |
| printk_debug(": %s\n", parent->chip_ops->name); |
| } else { |
| printk_debug("\n"); |
| } |
| break; |
| |
| case 1: |
| print_pci_regs_all(); |
| break; |
| case 2: |
| print_mem(); |
| break; |
| case 3: |
| print_cpuid(); |
| break; |
| case 4: |
| print_smbus_regs_all(&dev_root); |
| break; |
| case 5: |
| print_msr_dualcore(); |
| break; |
| case 6: |
| print_cache_size(); |
| break; |
| case 7: |
| print_tsc(); |
| break; |
| case 8: |
| hard_reset(); |
| break; |
| } |
| } |
| |
| static void debug_noop(device_t dummy) |
| { |
| } |
| |
| static struct device_operations debug_operations = { |
| .read_resources = debug_noop, |
| .set_resources = debug_noop, |
| .enable_resources = debug_noop, |
| .init = debug_init, |
| }; |
| |
| static void enable_dev(struct device *dev) |
| { |
| dev->ops = &debug_operations; |
| } |
| |
| struct chip_operations drivers_generic_debug_ops = { |
| CHIP_NAME("Debug device") |
| .enable_dev = enable_dev, |
| }; |