且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

OK335xS pwm device register hacking

更新时间:2022-08-12 20:33:11

/*************************************************************************
 *               OK335xS pwm device register hacking
 * 声明:
 *     本文是对OK335xS pwm设备注册进行代码跟踪,其中有些部分是由于本人自己
 * 添加的,但都是经过测试。
 *
 *                                2015-8-25 晴 深圳 南山平山村 曾剑锋
 ************************************************************************/
MACHINE_START(AM335XEVM, "am335xevm")
    /* Maintainer: Texas Instruments */
    .atag_offset    = 0x100,
    .map_io         = am335x_evm_map_io,
    .init_early     = am33xx_init_early,
    .init_irq       = ti81xx_init_irq,
    .handle_irq     = omap3_intc_handle_irq,
    .timer          = &omap3_am33xx_timer,
    .init_machine   = am335x_evm_init,    ---------+
MACHINE_END                                        |
                                                   |
MACHINE_START(AM335XIAEVM, "am335xiaevm")          |
    /* Maintainer: Texas Instruments */            |
    .atag_offset    = 0x100,                       |
    .map_io         = am335x_evm_map_io,           |
    .init_irq       = ti81xx_init_irq,             |
    .init_early     = am33xx_init_early,           |
    .timer          = &omap3_am33xx_timer,         |
    .init_machine   = am335x_evm_init,             |
MACHINE_END                                        |
                                                   |
                                                   |
static void __init am335x_evm_init(void)  <--------+
{
    ......
    setup_ok335xs();                      ---------+
    ......                                         |
}                                                  |
                                                   |
static void setup_ok335xs(void)           <--------+
{
    pr_info("The board is a ok335xs.\n");

    /* Starter Kit has Micro-SD slot which doesn't have Write Protect pin */
    am335x_mmc[0].gpio_wp = -EINVAL;

    _configure_device(EVM_SK, ok335xs_dev_cfg, PROFILE_NONE);    --------+
                                                                         |
    am33xx_cpsw_init(AM33XX_CPSW_MODE_RGMII, NULL, NULL);                |
    /* Atheros Tx Clk delay Phy fixup */                                 |
    phy_register_fixup_for_uid(AM335X_EVM_PHY_ID, AM335X_EVM_PHY_MASK,   |
                   am33xx_evm_tx_clk_dly_phy_fixup);                     |
}                                                                        |
                                                                         |
static struct evm_dev_cfg ok335xs_dev_cfg[] = {                  <-------+
    {mmc0_init,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
    #if defined(CONFIG_ANDROID)
    {mfd_tscadc_init,         DEV_ON_BASEBOARD, PROFILE_ALL},
    #endif
    {rgmii1_init,    DEV_ON_BASEBOARD, PROFILE_ALL},
    {rgmii2_init,    DEV_ON_BASEBOARD, PROFILE_ALL},
    {lcdc_init,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
    {i2c1_init,     DEV_ON_BASEBOARD, PROFILE_ALL},
    {buzzer_init,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed     --------+
    {enable_ecap2,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed            |
    {usb0_init,     DEV_ON_BASEBOARD, PROFILE_ALL},                      |
    {usb1_init,     DEV_ON_BASEBOARD, PROFILE_ALL},                      |
    {evm_nand_init,DEV_ON_BASEBOARD, PROFILE_ALL},//fixed                |
    {mcasp1_init,   DEV_ON_BASEBOARD, PROFILE_NONE},//fixed              |
    {gpio_keys_init_forlinx_s,  DEV_ON_BASEBOARD, PROFILE_ALL},//fixed   |
    {gpio_led_init_s,  DEV_ON_BASEBOARD, PROFILE_ALL},//fixed            |
    {uart2_init_s,  DEV_ON_BASEBOARD, PROFILE_ALL},//fixed               |
    {spi1_init_s,           DEV_ON_BASEBOARD, PROFILE_ALL},//fixed       |
    {d_can_init, DEV_ON_BASEBOARD, PROFILE_ALL},//fixed                  |
    {sgx_init,       DEV_ON_BASEBOARD, PROFILE_ALL},                     |
    {NULL, 0, 0},                                                        |
};                                                                       |
                                                                         |
static void buzzer_init(int evm_id, int profile)                <--------+
{
        //setup_pin_mux(ecap0_pin_mux);
        setup_pin_mux(ecap1_pin_mux);             -----+  -------------------+
        am33xx_register_ecap(1, &pwm_pdata[1]);    ----*---------------------*+-+
}                                                      |                     || |
                                                       |                     || |
/* Module pin mux for eCAP1 */                         |                     || |
static struct pinmux_config ecap1_pin_mux[] = {   <----+                     || |
    {"spi0_cs1.ecap1_in_pwm1_out",            -----+                         || |
        OMAP_MUX_MODE2 | AM33XX_PIN_OUTPUT},       |  ---------------------+ || |
    {NULL, 0},                                     |                       | || |
};                                                 |                       | || |
                                                   |                       | || |
/* AM33XX pin mux super set */                     |                       | || |
static struct omap_mux am33xx_muxmodes[] = {       |         --------------*+|| |
    ......                                         |                       |||| |
    _AM33XX_MUXENTRY(SPI0_CS1, 0,                  V                       |||| |
                 //"spi0_cs1", "uart3_rxd", NULL, "mmc0_pow",              |||| |
                 "spi0_cs1", "uart3_rxd", "ecap1_in_pwm1_out", "mmc0_pow", |||| |
                 NULL, "mmc0_sdcd", NULL, "gpio0_6"),                      |||| |
    ......                                                                 |||| |
}                                                                          |||| |
                                                                           |||| |
                                                                           |||| |
/* 34xx mux mode options for each pin. See TRM for options */              |||| |
#define OMAP_MUX_MODE0      0                                              |||| |
#define OMAP_MUX_MODE1      1                                              |||| |
#define OMAP_MUX_MODE2      2        <-------------------------------------+||| |
#define OMAP_MUX_MODE3      3                                               ||| |
#define OMAP_MUX_MODE4      4                                               ||| |
#define OMAP_MUX_MODE5      5                                               ||| |
#define OMAP_MUX_MODE6      6                                               ||| |
#define OMAP_MUX_MODE7      7                                               ||| |
                                                                            ||| |
/* module pin mux structure */                                              ||| |
struct pinmux_config {                                  <-------------------+|| |
    const char *string_name; /* signal name format */                        || |
    int val; /* Options for the mux register value */                        || |
};                                                                           || |
                                                                             || |
static void setup_pin_mux(struct pinmux_config *pin_mux)     <---------------+| |
{                                                                             | |
    int i;                                                                    | |
                                                                              | |
    for (i = 0; pin_mux->string_name != NULL; pin_mux++)                      | |
        omap_mux_init_signal(pin_mux->string_name, pin_mux->val); --------+   | |
                                                                          |   | |
}                                                                         |   | |
                                                                          |   | |
int __init omap_mux_init_signal(const char *muxname, int val)     <-------+   | |
{                                                                             | |
    struct omap_mux_partition *partition = NULL;                              | |
    struct omap_mux *mux = NULL;                                              | |
    u16 old_mode;                                                             | |
    int mux_mode;                                                             | |
                                                                              | |
    mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);  --------+    | |
    if (mux_mode < 0)                                                    |    | |
        return mux_mode;                                                 |    | |
                                                                         |    | |
    old_mode = omap_mux_read(partition, mux->reg_offset);                |    | |
    mux_mode |= val;                                                     |    | |
    pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",                 |    | |
             __func__, muxname, old_mode, mux_mode);                     |    | |
    omap_mux_write(partition, mux_mode, mux->reg_offset);                |    | |
                                                                         |    | |
    return 0;                                                            |    | |
}                                                                        |    | |
                                                                         |    | |
int omap_mux_get_by_name(const char *muxname,                    <-------+    | |
            struct omap_mux_partition **found_partition,                      | |
            struct omap_mux **found_mux)                                      | |
{                                                                             | |
    struct omap_mux_partition *partition;                                     | |
                                                                              | |
    list_for_each_entry(partition, &mux_partitions, node) {                   | |
        struct omap_mux *mux = NULL;                                          | |
        int mux_mode = _omap_mux_get_by_name(partition, muxname, &mux);  ---+ | |
        if (mux_mode < 0)                                                   | | |
            continue;                                                       | | |
                                                                            | | |
        *found_partition = partition;                                       | | |
        *found_mux = mux;                                                   | | |
                                                                            | | |
        return mux_mode;       +--------------------------------------------+ | |
    }                          |                                              | |
                               |                                              | |
    return -ENODEV;            |                                              | |
}                              |                                              | |
                               V                                              | |
static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition, | |
                    const char *muxname,                                      | |
                    struct omap_mux **found_mux)                              | |
{                                                                             | |
    struct omap_mux *mux = NULL;                                              | |
    struct omap_mux_entry *e;                                                 | |
    const char *mode_name;                                                    | |
    int found = 0, found_mode = 0, mode0_len = 0;                             | |
    struct list_head *muxmodes = &partition->muxmodes;                        | |
                                                                              | |
    mode_name = strchr(muxname, '.');                                         | |
    if (mode_name) {                                                          | |
        mode0_len = strlen(muxname) - strlen(mode_name);                      | |
        mode_name++;                                                          | |
    } else {                                                                  | |
        mode_name = muxname;                                                  | |
    }                                                                         | |
                                                                              | |
    list_for_each_entry(e, muxmodes, node) {                                  | |
        char *m0_entry;                                                       | |
        int i;                                                                | |
                                                                              | |
        mux = &e->mux;                                                        | |
        m0_entry = mux->muxnames[0];                                          | |
                                                                              | |
        /* First check for full name in mode0.muxmode format */               | |
        if (mode0_len && strncmp(muxname, m0_entry, mode0_len))               | |
            continue;                                                         | |
                                                                              | |
        /* Then check for muxmode only */                                     | |
        for (i = 0; i < OMAP_MUX_NR_MODES; i++) {                             | |
            char *mode_cur = mux->muxnames[i];                                | |
                                                                              | |
            if (!mode_cur)                                                    | |
                continue;                                                     | |
                                                                              | |
            if (!strcmp(mode_name, mode_cur)) {                               | |
                *found_mux = mux;                                             | |
                found++;                                                      | |
                found_mode = i;                                               | |
            }                                                                 | |
        }                                                                     | |
    }                                                                         | |
                                                                              | |
    if (found == 1) {                                                         | |
        return found_mode;                                                    | |
    }                                                                         | |
                                                                              | |
    if (found > 1) {                                                          | |
        pr_err("%s: Multiple signal paths (%i) for %s\n", __func__,           | |
               found, muxname);                                               | |
        return -EINVAL;                                                       | |
    }                                                                         | |
                                                                              | |
    pr_err("%s: Could not find signal %s\n", __func__, muxname);              | |
                                                                              | |
    return -ENODEV;                                                           | |
}                                                                             | |
                                                                              | |
static struct pwmss_platform_data  pwm_pdata[3] = {          <----------------+ |
    {                                                                           |
        .version = PWM_VERSION_1,                                               |
    },                                                                          |
    {                                                                           |
        .version = PWM_VERSION_1,                                               |
    },                                                                          |
    {                                                                           |
        .version = PWM_VERSION_1,                                               |
    },                                                                          |
};                                                                              |
                                                                                |
#ifdef CONFIG_SOC_OMAPAM33XX                                                    |
#define PWM_STR_LEN 10                                                          |
int __init am33xx_register_ecap(int id, struct pwmss_platform_data *pdata)  <---+
{
    struct platform_device *pdev;
    struct omap_hwmod *oh;
    char *oh_name = "ecap";
    char dev_name[PWM_STR_LEN];

    sprintf(dev_name, "ecap.%d", id);    // for driver to match device name

    oh = omap_hwmod_lookup(dev_name);
    if (!oh) {
        pr_err("Could not look up %s hwmod\n", dev_name);
        return -ENODEV;
    }

    pdev = omap_device_build(oh_name, id, oh, pdata,
            sizeof(*pdata), NULL, 0, 0);

    if (IS_ERR(pdev)) {
        WARN(1, "Can't build omap_device for %s:%s.\n",
            dev_name, oh->name);
        return PTR_ERR(pdev);
    }
    return 0;
}