/* * ---------------------------------------------------------------- * Copyright Realtek Semiconductor Corporation, 2013 * All rights reserved. * * Description: Realtek platform clock management unit driver * * --------------------------------------------------------------- */ #include <linux/config.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/mman.h> #include <linux/ioctl.h> #include <linux/fd.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/proc_fs.h> #include <linux/serial_core.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/byteorder.h> #include <bspchip.h> static int proc_cmu_status_print_r(char *buf, char **start, off_t offset, int length, int *eof, void *data) { int pos = 0; unsigned int reg_val; unsigned int lx_reg_val, cmu_cpu0_sleep_cnt = 0;; if(offset > 0) return 0; reg_val = REG32(BSP_CMU_CTRL); lx_reg_val = REG32(BSP_CMU_LXBR_REG); cmu_cpu0_sleep_cnt = REG32(0xb8000328); pos += sprintf(&buf[pos], "Bus busy: 0-sleep, 1-busy\n"); pos += sprintf(&buf[pos], "\tOCP0 busy : %d\n", ( (reg_val >> 31) & 0x1)); pos += sprintf(&buf[pos], "\tLX0 busy : %d\n", ( (lx_reg_val >> 31) & 0x1)); pos += sprintf(&buf[pos], "\tLX1 busy : %d\n", ( (lx_reg_val >> 27) & 0x1)); pos += sprintf(&buf[pos], "\tLX2 busy : %d\n", ( (lx_reg_val >> 23) & 0x1)); pos += sprintf(&buf[pos], "\tLXP busy : %d\n", ( (lx_reg_val >> 19) & 0x1)); pos += sprintf(&buf[pos], "\n"); pos += sprintf(&buf[pos], "Frequency divisor : \n"); pos += sprintf(&buf[pos], "\tOCP0 divisor : %d\n", ( 1 << ((reg_val >> 23) & 0x7))); pos += sprintf(&buf[pos], "\n"); pos += sprintf(&buf[pos], "CMU mode: 0-disable mode, 1-fixed mode, 2-dynamic mode\n"); pos += sprintf(&buf[pos], "\tMode : %d \n", ( (reg_val >> 6) & 0x3)); pos += sprintf(&buf[pos], "\n"); pos += sprintf(&buf[pos], "Bus slow bit (versus DRAM) : 0-Higher than DRAM frequency, 1-Slower than DRAM frequency\n"); pos += sprintf(&buf[pos], "\tOCP0 slow : %d\n", ( (reg_val >> 4) & 0x1)); pos += sprintf(&buf[pos], "\tLX0 slow : %d\n", ( (reg_val >> 2) & 0x1)); pos += sprintf(&buf[pos], "\tLX1 slow : %d\n", ( (reg_val >> 1) & 0x1)); pos += sprintf(&buf[pos], "\tLXP slow : %d\n", ( (reg_val >> 0) & 0x1)); pos += sprintf(&buf[pos], "\n"); pos += sprintf(&buf[pos], "CMU sleep counter : \n"); pos += sprintf(&buf[pos], "\tOCP0 sleep counter : %u\n", cmu_cpu0_sleep_cnt); return pos; } static int proc_cmu_registers_print_r(char *buf, char **start, off_t offset, int length, int *eof, void *data) { int pos = 0; int i; for(i=0; i<4; i++) { pos += sprintf(&buf[pos], "REG32(0x%08x)=0x%08x\n", (0xb8000300+(i*4)), REG32((0xb8000300+(i*4)))); //printk("REG32(0x%08x)=0x%08x\n", (0xb8000300+(i*4)), REG32((0xb8000300+(i*4)))); } return pos; } static struct proc_dir_entry *proc_cmu_dir ; static void rtk_cmu_proc_init(void) { struct proc_dir_entry *entry; /* * create root directory */ proc_cmu_dir = proc_mkdir("cmu", NULL); if (proc_cmu_dir == NULL) { printk("create proc root failed!\n"); return; } if((entry = create_proc_entry("status", 0644, proc_cmu_dir)) == NULL) { printk("create proc cmu/status failed!\n"); return; } //entry->write_proc = proc_cmu_status_print_w; entry->read_proc = proc_cmu_status_print_r; if((entry = create_proc_entry("registers", 0644, proc_cmu_dir)) == NULL) { printk("create proc cmu/registers failed!\n"); return; } //entry->write_proc = proc_cmu_registers_print_w; entry->read_proc = proc_cmu_registers_print_r; } int __init rtk_cmu_init(void) { /* TODO: move cmu init from prom.c to here */ printk("=================================\n"); printk("%s\n", __FUNCTION__); printk("=================================\n"); rtk_cmu_proc_init(); return 0; } static void __exit rtk_cmu_exit (void) { } module_init(rtk_cmu_init); module_exit(rtk_cmu_exit);