I.MX6 U-boot PWM hacking

/*******************************************************************************
 *                          I.MX6 U-boot PWM hacking
 * 说明:
 *     本文主要记录I.MX6 U-boot是如何配置PWM,发现文中的pwm0对应的引脚和真正的
 * 电路板的pwm0不是一个,也就意味着其实是引脚连接错了,另外之前一直有一个
 * 疑问:为什么双屏显示的时候,有一个屏在U-boot阶段和Kernel阶段总是不亮。原因
 * 应该是这里只初始化了一个显示控制部分,也就是不会初始两个PWM。
 *
 *                                          2016-3-7 深圳 南山平山村 曾剑锋
 ******************************************************************************/

cat bootable/bootloader/uboot-imx/board/freescale/mx6q_sabresd/mx6q_sabresd.c
    ......
    #ifdef CONFIG_LCD
    void lcd_enable(void)
    {
        ......
        imx_pwm_config(pwm0, 25000, 50000);                     ------------+
        imx_pwm_enable(pwm0);                                   ------------*-+
                                                                            | |
        #if defined CONFIG_MX6Q                                             | |
        /* PWM backlight */                                                 | |
        mxc_iomux_v3_setup_pad(MX6Q_PAD_SD1_DAT3__PWM1_PWMO);               | |
        /* LVDS panel CABC_EN0 */                                           | |
        mxc_iomux_v3_setup_pad(MX6Q_PAD_NANDF_CS2__GPIO_6_15);              | |
        /* LVDS panel CABC_EN1 */                                           | |
        mxc_iomux_v3_setup_pad(MX6Q_PAD_NANDF_CS3__GPIO_6_16);              | |
        #elif defined CONFIG_MX6DL                                          | |
        /* PWM backlight */                                                 | |
        mxc_iomux_v3_setup_pad(MX6DL_PAD_SD1_DAT3__PWM1_PWMO);              | |
        /* LVDS panel CABC_EN0 */                                           | |
        mxc_iomux_v3_setup_pad(MX6DL_PAD_NANDF_CS2__GPIO_6_15);             | |
        /* LVDS panel CABC_EN1 */                                           | |
        mxc_iomux_v3_setup_pad(MX6DL_PAD_NANDF_CS3__GPIO_6_16);             | |
        #endif                                                              | |
        ......                                                              | |
    }                                                                       | |
    ......                                                                  | |
                                                                            | |
static struct pwm_device pwm0 = {                               <-----------+ |
    .pwm_id = 0,                                                            | |
    .pwmo_invert = 0,                                                       | |
};                                                                          | |
                                                                            | |
                                                                            | |
int imx_pwm_config(struct pwm_device pwm, int duty_ns, int period_ns)  <----+ |
{                                                                             |
    unsigned long long c;                                                     |
    unsigned long period_cycles, duty_cycles, prescale;                       |
    u32 cr;                                                                   |
                                                                              |
    if (period_ns == 0 || duty_ns > period_ns)                                |
        return -1;                                                            |
                                                                              |
    pwm.mmio_base = pwm.pwm_id ? (unsigned long)IMX_PWM2_BASE:                |
                (unsigned long)IMX_PWM1_BASE;                                 |
                                                                              |
    if (pwm.pwmo_invert)                                                      |
        duty_ns = period_ns - duty_ns;                                        |
                                                                              |
    c = mxc_get_clock(MXC_IPG_PERCLK);                                        |
    c = c * period_ns;                                                        |
    do_div(c, 1000000000);                                                    |
    period_cycles = c;                                                        |
                                                                              |
    prescale = period_cycles / 0x10000 + 1;                                   |
                                                                              |
    period_cycles /= prescale;                                                |
    c = (unsigned long long)period_cycles * duty_ns;                          |
    do_div(c, period_ns);                                                     |
    duty_cycles = c;                                                          |
                                                                              |
    writel(duty_cycles, pwm.mmio_base + MX_PWMSAR);                           |
    writel(period_cycles, pwm.mmio_base + MX_PWMPR);                          |
                                                                              |
    cr = MX_PWMCR_PRESCALER(prescale) |                                       |
        MX_PWMCR_STOPEN | MX_PWMCR_DOZEEN |                                   |
        MX_PWMCR_WAITEN | MX_PWMCR_DBGEN;                                     |
                                                                              |
    cr |= MX_PWMCR_CLKSRC_IPG_HIGH;                                           |
                                                                              |
    writel(cr, pwm.mmio_base + MX_PWMCR);                                     |
                                                                              |
    return 0;                                                                 |
}                                                                             |
                                                                              |
int imx_pwm_enable(struct pwm_device pwm)                    <----------------+
{
    unsigned long reg;
    int rc = 0;                                                                                     

    if (pwm.enable_pwm_clk)
        pwm.enable_pwm_clk();                                                                       

    pwm.mmio_base = pwm.pwm_id ? (unsigned long)IMX_PWM2_BASE:
                (unsigned long)IMX_PWM1_BASE;                                                       

    reg = readl(pwm.mmio_base + MX_PWMCR);
    reg |= MX_PWMCR_EN;
    writel(reg, pwm.mmio_base + MX_PWMCR);                                                          

    if (pwm.enable_pwm_pad)
        pwm.enable_pwm_pad();                                                                       

    return rc;
}                                                                                                   

 

时间: 2024-09-29 13:09:37

I.MX6 U-boot PWM hacking的相关文章

I.MX6 U-boot lvds display hacking

/*********************************************************************************** * I.MX6 U-boot lvds display hacking * 声明: * 本文主要是为了跟踪I.MX6中的U-boot中显示部分代码,查看是否支持24bit显示. * * 2015-10-8 晴 深圳 南山平山村 曾剑锋 ***********************************************

I.MX6 android BatteryService jni hacking

/**************************************************************************** * I.MX6 android BatteryService jni hacking * 声明: * 本文主要是为了知道Android的获取的电源管理的数据的jni是从Linux系统的 * 什么位置获取的,获取的机制是什么. * * 2016-2-22 深圳 南山平山村 曾剑锋 ********************************

I.MX6 Ar8031 device register hacking

/***************************************************************************** * I.MX6 Ar8031 device register hacking * 声明: * 主要是为了知道网卡的注册流程,如果需要对网卡中的一些需求进行修改时,能够 * 能够快速的对需求进行分析.修改. * * 2015-8-15 雨 深圳 南山区平山村 曾剑锋 **************************************

I.MX6 change boot partition 1 to User area

/************************************************************************************ * I.MX6 change boot partition 1 to User area * 说明: * 需要在eMMC中切换U-Boot所在的位置,看一下eMMC的驱动,测试一下效果. * * 2017-5-26 台湾 中和区 曾剑锋 *********************************************

I.MX6 PWM buzzer driver hacking with Demo test

/***************************************************************************** * I.MX6 PWM buzzer driver hacking with Demo test * 声明: * 1. I.MX6和OK335xS实现PWM驱动函数是不一样的: * 2. 通过分析PWM驱动,了解有哪些驱动函数可以用: * 3. 使用I.MX6提供的PWM函数,编写测试用例buzzer驱动: * 4. 使用C编写测试程序.

I.MX6 天嵌 E9 U-boot menu hacking

/************************************************************************************ * I.MX6 天嵌 E9 U-boot menu hacking * 说明: * 天嵌在U-boot中添加了自己的选择menu,想看一下怎么实现的. * * 2016-8-5 深圳 南山平山村 曽剑锋 **************************************************************

I.MX6 Linux I2C device&amp; driver hacking

/******************************************************************************************* * I.MX6 Linux I2C device& driver hacking * 声明: * 1. 本文主要是对Linux I2C驱动进行代码跟踪,主要是为了能够对I2C驱动框架有个全面的了解: * 2. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2: * 3. 如果你有兴趣,

I.MX6 mfgtool2-android-mx6q-sabresd-emmc.vbs hacking

/******************************************************************** * I.MX6 mfgtool2-android-mx6q-sabresd-emmc.vbs hacking * 说明: * 以前用的mfgtool2是直接执行MfgTool2.exe就行了,现在的NXP将其封 * 装在vbs文件内,这是左栋告诉我的,这里记录一下命令行参数的本质. * * 2016-9-18 深圳 南山平山村 曾剑锋 ***********

OK335xS pwm buzzer Linux driver hacking

/**************************************************************************** * OK335xS pwm buzzer Linux driver hacking * 声明: * 本文仅仅是为了知道如何使用pwm来控制buzzer,已达到控制不同声音的频率. * * 2015-10-7 雨 深圳 南山平山村 曾剑锋 *****************************************************