📄 prcm_34xx.c
字号:
{PRCM_GPT8, &PRCM_GPT8_SYSCONFIG}, {PRCM_GPT9, &PRCM_GPT9_SYSCONFIG}, {PRCM_UART3, &PRCM_UART3_SYSCONFIG}, {PRCM_WDT3, &PRCM_WDT3_SYSCONFIG}, {PRCM_GPIO2, &PRCM_GPIO2_SYSCONFIG}, {PRCM_GPIO3, &PRCM_GPIO3_SYSCONFIG}, {PRCM_GPIO4, &PRCM_GPIO4_SYSCONFIG}, {PRCM_GPIO5, &PRCM_GPIO5_SYSCONFIG}, {PRCM_GPIO6, &PRCM_GPIO6_SYSCONFIG}, {0x0, 0x0},};/* Array containing possible divider values for all clocks * which have dividers */u32 div_arr[] = { /* L3 divs */ 1, 2, 0, 0, 0, 0, /* L4 divs */ 1, 2, 0, 0, 0, 0, /* RM divs */ 1, 2, 0, 0, 0, 0, /* USB L4 divs */ 0, 0, 0, 0, 0, 0, /* sys clkout2 divs */ 1, 2, 4, 8, 16, 0, /* sgx divs */ 3, 4, 6, 0, 0, 0, /* SSI divs */ 1, 2, 3, 4, 5, 6, /* dpll1 fclk divs */ 1, 2, 4, 0, 0, 0, /* dpll2 fclk divs */ 1, 2, 4, 0, 0, 0, /* cm usim divs */ 2, 4, 8, 10, 16, 20,};/* * Possible values for DPLL dividers */const u32 div_dpll[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};/* * Possible values for DPLL3 dividers */const u32 div_dpll3[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};u32 dpll_mx_shift[NO_OF_DPLL][NO_DPLL_DIV] = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, {0x1B, 0x1B, 0x10, 0x0, 0x0, 0x0}, {0x0, 0x0, 0x8, 0x0, 0x0, 0x18}, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0},};/* * Offset in registers for clocks which have dividers */u32 clk_div_offset[PRCM_NO_OF_CLKS] = { 0x0, /* L3_ICLK */ 0x2, /* L4_ICLK */ 0x1, /* RM_ICLK */ 0x0, /* USB_L4_ICLK */ 0x3, /* SYS_CLKOUT2 */ 0x0, /* SGX_L3_FCLK */ 0x8, /* SSI_CLK */ 0x13, /* DPLL1_FCLK */ 0x13, /* DPLL2_FCLK */ 0x3, /* SYS_USIM_CLK */};/* * The DPLL parameter tables are organized as: * Rows: Correspond to clock speed * Columns: Correspond to OPPs *//* * DPLL Parameters: MPU */struct dpll_param mpu_dpll_param[5][PRCM_NO_VDD1_OPPS] = { /* 12M values */ { /* OPP1 (125MHz) */ {0x0FA, 0x05, 0x07, 0x04}, /* OPP2 (250MHz) */ {0x0FA, 0x05, 0x07, 0x02}, /* OPP3 (500MHz) */ {0x0FA, 0x05, 0x07, 0x01}, /* OPP4 (550MHz) */ {0x113, 0x05, 0x07, 0x01}, /* OPP5 (600MHz) */ {0x12C, 0x05, 0x07, 0x01} }, /* 13M values */ { /* OPP1 (250MHz) */ {0x1F4, 0x0C, 0x03, 0x04}, /* OPP2 (125MHz) */ {0x1F4, 0x0C, 0x03, 0x02}, /* OPP3 (500MHz) */ {0x1F4, 0x0C, 0x03, 0x01}, /* OPP4 (500MHz) */ {0x226, 0x0C, 0x03, 0x01}, /* OPP5 (600MHz) */ {0x258, 0x0C, 0x03, 0x01} }, /* 19.2M values */ { /* OPP1 (125MHz) */ {0x271, 0x17, 0x03, 0x04}, /* OPP2 (250MHz) */ {0x271, 0x17, 0x03, 0x02}, /* OPP3 (500MHz) */ {0x271, 0x17, 0x03, 0x01}, /* OPP4 (500MHz) */ {0x191, 0x0D, 0x05, 0x01}, /* OPP5 (600MHz) */ {0x177, 0x0B, 0x06, 0x01} }, /* 26M values */ { /* OPP1 (125MHz) */ {0x0FA, 0x0C, 0x07, 0x04}, /* OPP2 (250MHz) */ {0x0FA, 0x0C, 0x07, 0x02}, /* OPP3 (500MHz) */ {0x0FA, 0x0C, 0x07, 0x01}, /* OPP4 (500MHz) */ {0x113, 0x0C, 0x07, 0x01}, /* OPP5 (600MHz) */ {0x12C, 0x0C, 0x07, 0x01} }, /* 38.4M values */ { /* OPP1 (125MHz) */ {0x271, 0x2F, 0x03, 0x04}, /* OPP2 (250MHz) */ {0x271, 0x2F, 0x03, 0x02}, /* OPP3 (500MHz) */ {0x271, 0x2F, 0x03, 0x01}, /* OPP4 (500MHz) */ {0x1BC, 0x1E, 0x04, 0x01}, /* OPP5 (600MHz) */ {0x177, 0x17, 0x06, 0x01} },};/* * DPLL Parameters: IVA */struct dpll_param iva_dpll_param[5][PRCM_NO_VDD1_OPPS] = { /* 12M values */ { /* OPP1 ( 90MHz) */ {0x0B4, 0x05, 0x07, 0x04}, /* OPP2 (180MHz) */ {0x0B4, 0x05, 0x07, 0x02}, /* OPP3 (360MHz) */ {0x0B4, 0x05, 0x07, 0x01}, /* OPP4 (396MHz) */ {0x0C6, 0x05, 0x07, 0x01}, /* OPP5 (430MHz) */ {0x0D7, 0x05, 0x07, 0x01} }, /* 13M values */ { /* OPP1 ( 90MHz) */ {0x168, 0x0C, 0x03, 0x04}, /* OPP2 (180MHz) */ {0x168, 0x0C, 0x03, 0x02}, /* OPP3 (360MHz) */ {0x168, 0x0C, 0x03, 0x01}, /* OPP4 (396MHz) */ {0x18C, 0x0C, 0x03, 0x01}, /* OPP5 (430MHz) */ {0x1AE, 0x0C, 0x03, 0x01} }, /* 19.2M values */ { /* OPP1 ( 90MHz) */ {0x0E1, 0x0B, 0x06, 0x04}, /* OPP2 (180MHz) */ {0x0E1, 0x0B, 0x06, 0x02}, /* OPP3 (360MHz) */ {0x0E1, 0x0B, 0x06, 0x01}, /* OPP4 (396MHz) */ {0x14A, 0x0F, 0x04, 0x01}, /* OPP5 (430MHz) */ {0x203, 0x16, 0x03, 0x01} }, /* 26M values */ { /* OPP1 ( 90MHz) */ {0x0B4, 0x0C, 0x07, 0x04}, /* OPP2 (180MHz) */ {0x0B4, 0x0C, 0x07, 0x02}, /* OPP3 (360MHz) */ {0x0B4, 0x0C, 0x07, 0x01}, /* OPP4 (396MHz) */ {0x0C6, 0x0C, 0x07, 0x01}, /* OPP5 (430MHz) */ {0x0D7, 0x0C, 0x07, 0x01} }, /* 38.4M values */ { /* OPP1 ( 90MHz) */ {0x0E1, 0x17, 0x06, 0x04}, /* OPP2 (180MHz) */ {0x0E1, 0x17, 0x06, 0x02}, /* OPP3 (360MHz) */ {0x0E1, 0x17, 0x06, 0x01}, /* OPP4 (396MHz) */ {0x14A, 0x1F, 0x04, 0x01}, /* OPP5 (430MHz) */ {0x23B, 0x32, 0x01, 0x01} },};/* * DPLL Parameters: CORE */struct dpll_param core_dpll_param[5][PRCM_NO_VDD2_OPPS] = { /* 12M values */ { {0x000, 0x00, 0x00, 0x00}, /* OPP1 ( 83MHz) */ {0x0A6, 0x05, 0x07, 0x02}, /* OPP2 (166MHz) */ {0x0A6, 0x05, 0x07, 0x01} }, /* 13M values */ { {0x000, 0x00, 0x00, 0x00}, /* OPP1 ( 83MHz) */ {0x14C, 0x0C, 0x03, 0x02}, /* OPP2 (166MHz) */ {0x14C, 0x0C, 0x03, 0x01} }, /* 19.2M values */ { {0x000, 0x00, 0x00, 0x00}, /* OPP1 ( 83MHz) */ {0x19F, 0x17, 0x03, 0x02}, /* OPP2 (166MHz) */ {0x19F, 0x17, 0x03, 0x01} }, /* 26M values */ { {0x000, 0x00, 0x00, 0x00}, /* OPP1 ( 83MHz) */ {0x0A6, 0x0C, 0x07, 0x02}, /* OPP2 (166MHz) */ {0x0A6, 0x0C, 0x07, 0x01} }, /* 38.4M values */ { {0x000, 0x00, 0x00, 0x00}, /* OPP1 ( 83MHz) */ {0x19F, 0x2F, 0x03, 0x02}, /* OPP2 (166MHz) */ {0x19F, 0x2F, 0x03, 0x01} },};/* * DPLL Parameters: USB */struct dpll_param usb_dpll_param[5] = { /* 12M values */ {0x3C, 0x05, 0x07, 0x01}, /* 13M values */ {0x78, 0x0C, 0x03, 0x01}, /* 19.2M values */ {0x4B, 0x0B, 0x06, 0x01}, /* 26M values */ {0x3C, 0x0C, 0x07, 0x01}, /* 38.4M values */ {0x4B, 0x17, 0x06, 0x01},};/* * VSEL corresponding to various OPPs: VDD1 */u8 mpu_iva2_vdd1_volts [PRCM_NO_VDD1_OPPS] = { /* OPP1 (0.90V) */ 0x18, /* OPP2 (1.00V) */ 0x20, /* OPP3 (1.20V) */ 0x30, /* OPP4 (1.27V) */ 0x36, /* OPP5 (1.35V) */ 0x3C};/* * VSEL corresponding to various OPPs: VDD2 */u8 core_l3_vdd2_volts [PRCM_NO_VDD2_OPPS] = { /* OPP1 (0.90V) */ 0x18, /* OPP2 (1.00V) */ 0x20, /* OPP3 (1.15V) */ 0x2C};/* * These tables should come from a board specific file. * Memory timings and population is board specific. *//* * VDD2 Configuration (TBD) */struct dvfs_config omap3_vdd2_config[2] = { { /* SDRC CS0/CS1 values 83MHZ*/ { {0x00025801, 0x629db4c6, 0x00012214}, {0x00025801, 0x31512283, 0x1110A} }, /* GPMC CS0/1/2/3 values 83 MHZ*/ /* CS0 values are for NOR */ /* CS1 values are for NAND */ /* CS2 values are for ONE-NAND */ /* CS3 values are for FPGA */ { {0x00101000, 0x00040401, 0x0E050E05, 0x010A1010, 0x100802C1}, {0x000A0A00, 0x000A0A00, 0x08010801, 0x01060A0A, 0x10080580}, {0x00080801, 0x00020201, 0x08020802, 0x01080808, 0x10030000}, {0x00101001, 0x00040402, 0x0E050E05, 0x020F1010, 0x0F0502C2} } }, { /* SDRC CS0/CS1 values 166MHZ*/ { {0x0004e201, 0x629db4c6, 0x00012214}, {0x0004e201, 0x629db4c6, 0x00012214} }, /* GPMC CS0/1/2/3 values 166 MHZ*/ { {0x001f1f00, 0x00080802, 0x1C091C09, 0x01131F1F, 0x1F0F03C2}, {0x00141400, 0x00141400, 0x0F010F01, 0x010C1414, 0x1F0F0A80}, {0x000F0F01, 0x00030301, 0x0F040F04, 0x010F1010, 0x1F060000}, {0x001F1F01, 0x00080803, 0x1D091D09, 0x041D1F1F, 0x1D0904C4} } },};/*============================================================================*/extern void omap3_clk_prepare_for_reboot(void);u32 omap_prcm_get_reset_sources(void){ omap3_clk_prepare_for_reboot(); return PRM_RSTST & 0x7fb;}EXPORT_SYMBOL(omap_prcm_get_reset_sources);/** * omap_udelay: Generates delay in usecs * @udelay: delay in usecs * * Generates delay in usecs using omap 32K sync timer. The granularity of the * delay is ~30us. */void omap_udelay(u32 udelay){ u32 counter_val, timeout_val; counter_val = OMAP_TIMER32K_SYNC_CR_READ; /* Since the 32 sync timer runs on a 32K clock, the granularity of the delay achieved is around 30 us, hence divide the delay provided by user by 30 */ timeout_val = counter_val + (udelay / 30); if (timeout_val < counter_val) /* There seems to be a overflow */ /* take care of the overflow by waiting first for the CR to reach the MAX value */ while (OMAP_MAX_32K_CR > OMAP_TIMER32K_SYNC_CR_READ) ; /* wait for the specified delay */ while (timeout_val > OMAP_TIMER32K_SYNC_CR_READ) ; return;}inline int loop_wait(u32 *lcnt, u32 *rcnt, u32 delay){ (*lcnt)++; if (*lcnt > MAXLOOPCNT) { *lcnt = 0; if (*rcnt < MAXRETRIES) omap_udelay(delay); else { DPRINTK("Max retries exceeded in loop_wait\n"); return PRCM_FAIL; } (*rcnt)++; } return PRCM_PASS;}/** * omap_prcm_arch_reset: Resets clock rates and reboots the system * @mode: * * Resets clock rates and reboots the system. Called only from system.h. */void omap_prcm_arch_reset(char mode){ omap3_clk_prepare_for_reboot(); /* Assert global software reset */ PRM_RSTCTRL |= 2;}/** * check_device_status: Check if the device is in desired state * @deviceid: id of the device * @control: desired status * * Checks is the specified device is in desired state. * Valid 'control' params are PRCM_ENABLE and PRCM_DISABLE. * When control is PRCM_ENABLE, the function returns PRCM_TRUE if device * is accessible, else PRCM_FAIL. * When control is PRCM_DISABLE, the function returns PRCM_TRUE if device * is not accessible, else PRCM_FAIL. */static int check_device_status(u32 deviceid, u8 control){ u8 curr_state; u32 loop_cnt = 0, retries_cnt = 0; int ret; if ((control != PRCM_ENABLE) && (control != PRCM_DISABLE)) return PRCM_FAIL; curr_state = !control; while (curr_state != control) { ret = prcm_is_device_accessible(deviceid, &curr_state); if (ret != PRCM_PASS) return ret; ret = loop_wait(&loop_cnt, &retries_cnt, 100); if (ret != PRCM_PASS) { printk(KERN_INFO "check_device_status : " "Timeout accessing deviceid (0x%x).\n", deviceid); return ret; } } if (control == PRCM_ENABLE) DPRINTK("Device is accessible\n"); else DPRINTK("Device is not accessible\n"); return PRCM_PASS;}/** * get_dpll_mx: Get the MX divider value for specified DPLL. * @dpll_id: DPLL id * @dpll_div: * @dpll_mxsft: * * Get the MX divider value (e.g M2,M3,M4,M5,M6) for specified DPLL. */static int get_dpll_mx(u32 dpll_id, u32 dpll_div, u32 dpll_mxsft){ u32 valid; volatile u32 *addr; addr = get_addr_pll(dpll_id, dpll_div + MX_ARRAY_OFFSET); if (!addr) DPRINTK(KERN_INFO "Address not valid\n"); valid = get_val_bits_pll(dpll_id, dpll_div + MX_ARRAY_OFFSET); return ((*addr & ~valid) >> dpll_mxsft);}/** * get_dpll_m_n: Get the mult and div values for specified DPLL. * @dpll_id: DPLL id * @mult: (out) Multiplier value * @div: (out) Divisor value * * Get the multiplier and divisor value for the specified DPLL. */int get_dpll_m_n(u32 dpll_id, u32 *mult, u32 *div){ u32 valid; volatile u32 *addr; addr = get_addr_pll(dpll_id, REG_CLKSEL1_PLL); if (!addr) return PRCM_FAIL; valid = get_val_bits_pll(dpll_id, REG_CLKSEL1_PLL); if (dpll_id == DPLL3_CORE) { *mult = (*addr & ~valid) >> 16; *div = (*addr & ~DPLL3_N_MASK) >> 8; } else { *mult = (*addr & ~valid) >> 8; *div = (*addr & ~DPLL_N_MASK); } return PRCM_PASS;}/** * is_dpll_locked: Is DPLL locked? * @dpll_id: DPLL id * @result: (out) result
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -