am335x gpio

/************************************************************************
 *                       am335x_gpio
 *   本文主要记录am335x gpio初始化过程。
 *   主要文件:
 *      设备初始化:    *          arch/arm/mach-omap2/board_am335xevm.c
 *          arch/arm/mach-omap2/io.c
 *          arch/arm/mach-omap2/omap_hwmod_33xx_data.c
 *      驱动初始化: *          drivers/gpio/gpio-omap.c
 *
 *                                         Tony Liu, 2016-4-30, Shenzhen
 ***********************************************************************/
arch/arm/mach-omap2/board_am335xevm.c
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                                          |
                                                     |
kernel/arch/arm/mach-omap2/io.c             <--------+
void __init am33xx_init_early(void)
{
    omap2_set_globals_am33xx();
    omap3xxx_check_revision();
    am33xx_check_features();
    omap_common_init_early();
    am33xx_voltagedomains_init();
    omap44xx_prminst_init();
    am33xx_powerdomains_init();
    omap44xx_cminst_init();
    am33xx_clockdomains_init();
    am33xx_hwmod_init();                    ---------+
    omap_hwmod_init_postsetup();                     |
    omap3xxx_clk_init();                             |
}                                                    |
                                                     |
kernel/arch/arm/mach-omap2/omap_hwmod_33xx_data.c    |
int __init am33xx_hwmod_init(void)           <-------+
{
    return omap_hwmod_register(am33xx_hwmods);   ---------------------------+
}                                                                           |
//将寄存器的信息添加到链表中                                                |
int __init omap_hwmod_register(struct omap_hwmod **ohs)                     |
{                                                                           |
    int r, i;                                                               |
                                                                            |
    if (!ohs)                                                               |
        return 0;                                                           |
                                                                            |
    i = 0;                                                                  |
    do {                                                                    |
        r = _register(ohs[i]);                           -----------------+ |
        WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,  | |
             r);                                                          | |
    } while (ohs[++i]);                                                   | |
                                                                          | |
    return 0;                                                             | |
}                                                                         | |
                                                                          | |
static int __init _register(struct omap_hwmod *oh)       <----------------+ |
{                                                                           |
    int ms_id;                                                              |
                                                                            |
    if (!oh || !oh->name || !oh->class || !oh->class->name ||               |
        (oh->_state != _HWMOD_STATE_UNKNOWN))                               |
        return -EINVAL;                                                     |
                                                                            |
    pr_debug("omap_hwmod: %s: registering\n", oh->name);                    |
    //查找这个结构是否已经添加到双链中                                      |
    if (_lookup(oh->name))                                                  |
        return -EEXIST;                                                     |
                                                                            |
    ms_id = _find_mpu_port_index(oh);                    --------------+    |
    if (!IS_ERR_VALUE(ms_id))                                          |    |
        oh->_mpu_port_index = ms_id;                                   |    |
    else                                                               |    |
        oh->_int_flags |= _HWMOD_NO_MPU_PORT;                          |    |
                                                                       |    |
    list_add_tail(&oh->node, &omap_hwmod_list);                        |    |
                                                                       |    |
    spin_lock_init(&oh->_lock);                                        |    |
                                                                       |    |
    oh->_state = _HWMOD_STATE_REGISTERED;                              |    |
                                                                       |    |
    /*                                                                 |    |
     * XXX Rather than doing a strcmp(), this should test a flag       |    |
     * set in the hwmod data, inserted by the autogenerator code.      |    |
     */                                                                |    |
    if (!strcmp(oh->name, MPU_INITIATOR_NAME))                         |    |
        mpu_oh = oh;                                                   |    |
                                                                       |    |
    return 0;                                                          |    |
}                                                                      |    |
                                                                       |    |
static int __init _find_mpu_port_index(struct omap_hwmod *oh)     <----+    |
{                                                                           |
    int i;                                                                  |
    int found = 0;                                                          |
                                                                            |
    if (!oh || oh->slaves_cnt == 0)                                         |
        return -EINVAL;                                                     |
                                                                            |
    for (i = 0; i < oh->slaves_cnt; i++) {                                  |
        struct omap_hwmod_ocp_if *os = oh->slaves[i];                       |
                                                                            |
        if (os->user & OCP_USER_MPU) {                                      |
            found = 1;                                                      |
            break;                                                          |
        }                                                                   |
    }                                                                       |
                                                                            |
    if (found)                                                              |
        pr_debug("omap_hwmod: %s: MPU OCP slave port ID  %d\n",             |
             oh->name, i);                                                  |
    else                                                                    |
        pr_debug("omap_hwmod: %s: no MPU OCP slave port found\n",           |
             oh->name);                                                     |
                                                                            |
    return (found) ? i : -EINVAL;                                           |
}                                                                           |
                                                                            |
                                                                            |
//gpio                                                                      |
static __initdata struct omap_hwmod *am33xx_hwmods[] = {         <----------+
    /* l3 class */
    &am33xx_l3_instr_hwmod,
    &am33xx_l3_main_hwmod,
    /* l3s class */
    &am33xx_l3slow_hwmod,
    /* l4hs class */
    &am33xx_l4_hs_hwmod,
    /* l4fw class */
    &am33xx_l4fw_hwmod,
    /* l4ls class */
    &am33xx_l4ls_hwmod,
    /* l4per class */
    &am33xx_l4per_hwmod,
    /* l4wkup class */
    &am33xx_l4wkup_hwmod,
    /* clkdiv32k class */
    &am33xx_clkdiv32k_hwmod,
    /* mpu class */
    &am33xx_mpu_hwmod,
    /* adc_tsc class */
    &am33xx_adc_tsc_hwmod,
    /* aes class */
    &am33xx_aes0_hwmod,
    /* cefuse class */
    &am33xx_cefuse_hwmod,
    /* control class */
    &am33xx_control_hwmod,
    /* dcan class */
    &am33xx_dcan0_hwmod,
    &am33xx_dcan1_hwmod,
    /* debugss class */
    &am33xx_debugss_hwmod,
    /* elm class */
    &am33xx_elm_hwmod,
    /* emif_fw class */
    &am33xx_emif_fw_hwmod,
    /* epwmss class */
    &am33xx_ehrpwm0_hwmod,
    &am33xx_ehrpwm1_hwmod,
    &am33xx_ehrpwm2_hwmod,
    &am33xx_ecap0_hwmod,
    &am33xx_ecap1_hwmod,
    &am33xx_ecap2_hwmod,
    /* gpio class */
    &am33xx_gpio0_hwmod,
    &am33xx_gpio1_hwmod,      -----+
    &am33xx_gpio2_hwmod,           |
    &am33xx_gpio3_hwmod,           |
    /* gpmc class */               |
    &am33xx_gpmc_hwmod,            |
    /* i2c class */                |
    &am33xx_i2c1_hwmod,            |
    &am33xx_i2c2_hwmod,            |
    &am33xx_i2c3_hwmod,            |
    /* ieee5000 class */           |
    &am33xx_ieee5000_hwmod,        |
    /* mailbox class */            |
    &am33xx_mailbox_hwmod,         |
    /* mcasp class */              |
    &am33xx_mcasp0_hwmod,          |
    &am33xx_mcasp1_hwmod,          |
    /* mmc class */                |
    &am33xx_mmc0_hwmod,            |
    &am33xx_mmc1_hwmod,            |
    &am33xx_mmc2_hwmod,            |
    /* ocmcram class */            |
    &am33xx_ocmcram_hwmod,         |
    /* ocpwp class */              |
    &am33xx_ocpwp_hwmod,           |
    /* rtc class */                |
    &am33xx_rtc_hwmod,             |
    /* sha0 class */               |
    &am33xx_sha0_hwmod,            |
    /* smartreflex class */        |
    &am33xx_smartreflex0_hwmod,    |
    &am33xx_smartreflex1_hwmod,    |
    /* spi class */                |
    &am33xx_spi0_hwmod,            |
    &am33xx_spi1_hwmod,            |
    /* spinlock class */           |
    &am33xx_spinlock_hwmod,        |
    /* uart class */               |
    &am33xx_uart1_hwmod,           |
    &am33xx_uart2_hwmod,           |
    &am33xx_uart3_hwmod,           |
    &am33xx_uart4_hwmod,           |
    &am33xx_uart5_hwmod,           |
    &am33xx_uart6_hwmod,           |
    /* timer class */              |
    &am33xx_timer0_hwmod,          |
    &am33xx_timer1_hwmod,          |
    &am33xx_timer2_hwmod,          |
    &am33xx_timer3_hwmod,          |
    &am33xx_timer4_hwmod,          |
    &am33xx_timer5_hwmod,          |
    &am33xx_timer6_hwmod,          |
    &am33xx_timer7_hwmod,          |
    /* wkup_m3 class */            |
    &am33xx_wkup_m3_hwmod,         |
    /* wd_timer class */           |
    &am33xx_wd_timer1_hwmod,       |
    /* usbss hwmod */              |
    &am33xx_usbss_hwmod,           |
    /* cpgmac0 class */            |
    &am33xx_cpgmac0_hwmod,         |
    /* mdio class */               |
    &am33xx_mdio_hwmod,            |
    /* tptc class */               |
    &am33xx_tptc0_hwmod,           |
    &am33xx_tptc1_hwmod,           |
    &am33xx_tptc2_hwmod,           |
    /* tpcc class */               |
    &am33xx_tpcc_hwmod,            |
    /* LCDC class */               |
    &am33xx_lcdc_hwmod,            |
    /* gfx/sgx */                  |
    &am33xx_gfx_hwmod,             |
    /* pruss */                    |
    &am33xx_pruss_hwmod,           |
    NULL,                          |
};                                 |
                                   V
static struct omap_hwmod am33xx_gpio1_hwmod = {
    .name        = "gpio2",
    .class        = &am33xx_gpio_hwmod_class,      ------------------+
    .clkdm_name    = "l4ls_clkdm",                                   |
    .mpu_irqs    = am33xx_gpio1_irqs,              ----------------+ |
    .main_clk    = "gpio1_ick",                                    | |
    .flags        = HWMOD_CONTROL_OPT_CLKS_IN_RESET,               | |
    .prcm        = {                                               | |
        .omap4    = {                                              | |
            .clkctrl_offs    = AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET, | |
            .modulemode    = MODULEMODE_SWCTRL,                    | |
        },                                                         | |
    },                                                             | |
    .opt_clks    = gpio1_opt_clks,              ----------+        | |
    .opt_clks_cnt    = ARRAY_SIZE(gpio1_opt_clks),        |        | |
    .dev_attr    = &gpio_dev_attr,              ------+   |        | |
    .slaves        = am33xx_gpio1_slaves,       ------|---|--------| |-+
    .slaves_cnt    = ARRAY_SIZE(am33xx_gpio1_slaves), |   |        | | |
};                                                    |   |        | | |
                                                      |   |        | | |
                                                      |   |        | | |
static struct omap_gpio_dev_attr gpio_dev_attr = { <--+   |        | | |
    .bank_width    = 32,                                  |        | | |
    .dbck_flag    = true,                                 |        | | |
};                                                        |        | | |
                                                          |        | | |
static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {  <--+        | | |
    { .role = "dbclk", .clk = "gpio1_dbclk" },                     | | |
};                                                                 | | |
                                                                   | | |
//指定irq中断号,和芯片手册中一样                                   | | |
                                                                   | | |
static struct omap_hwmod_irq_info am33xx_gpio1_irqs[] = {    <-----+ | |
    { .irq = 98 },                                                   | |
    { .irq = -1 }                                                    | |
};                                                                   | |
                                                                     | |
//所有的GPIO都有相同的am33xx_gpio_hwmod_class                        | |
static struct omap_hwmod_class am33xx_gpio_hwmod_class = {     <-----+ |
    .name        = "gpio",                                             |
    .sysc        = &am33xx_gpio_sysc,                      ----------+ |
    .rev        = 2,                                                 | |
};                                                                   | |
                                                                     | |
static struct omap_hwmod_class_sysconfig am33xx_gpio_sysc = {    <---+ |
    .rev_offs    = 0x0000,    //GPIO_REVISION 寄存器                   |
    .sysc_offs    = 0x0010,    //GPIO_SYSCONFIG                        |
    .syss_offs    = 0x0114,    //GPIO_SYSSTATUS                        |
    .sysc_flags    = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |         |
               SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |               |
               SYSS_HAS_RESET_STATUS),                                 |
    .idlemodes    = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |            |
            SIDLE_SMART_WKUP),                                         |
    .sysc_fields    = &omap_hwmod_sysc_type1,  ---+                    |
};                                                |                    |
                                                  V                    |
struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1 = {                |
    .midle_shift    = SYSC_TYPE1_MIDLEMODE_SHIFT,                      |
    .clkact_shift    = SYSC_TYPE1_CLOCKACTIVITY_SHIFT,                 |
    .sidle_shift    = SYSC_TYPE1_SIDLEMODE_SHIFT,                      |
    .enwkup_shift    = SYSC_TYPE1_ENAWAKEUP_SHIFT,                     |
    .srst_shift    = SYSC_TYPE1_SOFTRESET_SHIFT,                       |
    .autoidle_shift    = SYSC_TYPE1_AUTOIDLE_SHIFT,                    |
};                                                                     |
                                                                       |
static struct omap_hwmod_ocp_if *am33xx_gpio1_slaves[] = {      <------+
    &am33xx_l4_per__gpio1,       ----+
};                                   |
                                     V
static struct omap_hwmod_ocp_if am33xx_l4_per__gpio1 = {
    .master        = &am33xx_l4per_hwmod,   ---------+
    .slave        = &am33xx_gpio1_hwmod,             |
    .clk        = "l4ls_gclk",                       |
    .addr        = am33xx_gpio1_addrs,               |
    .user        = OCP_USER_MPU | OCP_USER_SDMA,     |
};                                                   |
                                                     |
static struct omap_hwmod am33xx_l4per_hwmod = {   <--+
    .name        = "l4_per",
    .class        = &l4_hwmod_class,
    .clkdm_name    = "l4ls_clkdm",
    .flags        = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
    .masters    = am33xx_l4_per_masters,      -----------------+
    .masters_cnt    = ARRAY_SIZE(am33xx_l4_per_masters),       |
    .slaves        = am33xx_l4_per_slaves,         ------------|--+
    .slaves_cnt    = ARRAY_SIZE(am33xx_l4_per_slaves),         |  |
};                                                             |  |
                                                               |  |
static struct omap_hwmod_ocp_if *am33xx_l4_per_masters[] = { <-+  |
    &am33xx_l4_per__dcan0,                                        |
    &am33xx_l4_per__dcan1,                                        |
    &am33xx_l4_per__gpio1,                                        |
    &am33xx_l4_per__gpio2,            ------+                     |
    &am33xx_l4_per__gpio3,                  |                     |
};                                          |                     |
                                            V                     |
static struct omap_hwmod_ocp_if am33xx_l4_per__gpio2 = {          |
    .master        = &am33xx_l4per_hwmod,                         |
    .slave        = &am33xx_gpio2_hwmod,                          |
    .clk        = "l4ls_gclk",                                    |
    .addr        = am33xx_gpio2_addrs,  ----------+               |
    .user        = OCP_USER_MPU | OCP_USER_SDMA,  |               |
};                                                |               |
                                                  |               |
/* L4 PER -> GPIO3 */                             V               |
static struct omap_hwmod_addr_space am33xx_gpio2_addrs[] = {      |
    {                                                             |
        .pa_start    = 0x481AC000,                                |
        .pa_end        = 0x481AC000 + SZ_4K - 1,                  |
        .flags        = ADDR_TYPE_RT,                             |
    },                                                            |
    { }                                                           |
};                                                                |
                                                                  |
/* Slave interfaces on the L4_PER interconnect */                 |
static struct omap_hwmod_ocp_if *am33xx_l4_per_slaves[] = {    <--+
    &am33xx_l3_slow__l4_per,    -----+
};                                   |
                                     V
static struct omap_hwmod_ocp_if am33xx_l3_slow__l4_per = {
    .master     = &am33xx_l3slow_hwmod,
    .slave        = &am33xx_l4per_hwmod,
    .user        = OCP_USER_MPU,
};

// linux/drivers/gpio/gpio-omap.c
static int __init omap_gpio_drv_reg(void)
{
    return platform_driver_register(&omap_gpio_driver);    -----------+
}                                                                     |
postcore_initcall(omap_gpio_drv_reg);                                 |
                                                                      |
static int __init omap_gpio_sysinit(void)                             |
{                                                                     |
    mpuio_init();                                                     |
                                                                      |
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)   |
    if (cpu_is_omap16xx() || cpu_class_is_omap2())                    |
        register_syscore_ops(&omap_gpio_syscore_ops);                 |
#endif                                                                |
                                                                      |
    return 0;                                                         |
}                                                                     |
                                                                      |
arch_initcall(omap_gpio_sysinit);                                     |
                                                                      |
                                                                      |
static struct platform_driver omap_gpio_driver = {        <-----------+
    .probe        = omap_gpio_probe,   -----+
    .driver        = {                      |
        .name    = "omap_gpio",             |
    },                                      |
};                                          |
                                            V
static int __devinit omap_gpio_probe(struct platform_device *pdev)
{
    static int gpio_init_done;
    struct omap_gpio_platform_data *pdata;
    struct resource *res;
    int id;
    struct gpio_bank *bank;

    if (!pdev->dev.platform_data)
        return -EINVAL;

    pdata = pdev->dev.platform_data;

    if (!gpio_init_done) {
        int ret;

        ret = init_gpio_info(pdev);
        if (ret)
            return ret;
    }

    id = pdev->id;
    bank = &gpio_bank[id];

    res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    if (unlikely(!res)) {
        dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id);
        return -ENODEV;
    }

    bank->irq = res->start;
    bank->virtual_irq_start = pdata->virtual_irq_start;
    bank->method = pdata->bank_type;
    bank->dev = &pdev->dev;
    bank->dbck_flag = pdata->dbck_flag;
    bank->stride = pdata->bank_stride;
    bank->width = pdata->bank_width;

    bank->regs = pdata->regs;       //将寄存器地址复制给bank->regs结构体

    if (bank->regs->set_dataout && bank->regs->clr_dataout)
        bank->set_dataout = _set_gpio_dataout_reg;
    else
        bank->set_dataout = _set_gpio_dataout_mask;

    spin_lock_init(&bank->lock);

    /* Static mapping, never released */
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (unlikely(!res)) {
        dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id);
        return -ENODEV;
    }

    bank->base = ioremap(res->start, resource_size(res));
    if (!bank->base) {
        dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id);
        return -ENOMEM;
    }

    pm_runtime_enable(bank->dev);
    pm_runtime_get_sync(bank->dev);

    omap_gpio_mod_init(bank, id);         -----------------------------------+
    omap_gpio_chip_init(bank);        ------------------------------+        |
    omap_gpio_show_rev(bank);  ---+                                 |        |
                                  |                                 |        |
    if (!gpio_init_done)          |                                 |        |
        gpio_init_done = 1;       |                                 |        |
                                  |                                 |        |
    return 0;                     |                                 |        |
}                                 |                                 |        |
//查看版本号并打印                V                                 |        |
static void __init omap_gpio_show_rev(struct gpio_bank *bank)       |        |
{                                                                   |        |
    static bool called;                                             |        |
    u32 rev;                                                        |        |
                                                                    |        |
    if (called || bank->regs->revision == USHRT_MAX)                |        |
        return;                                                     |        |
                                                                    |        |
    rev = __raw_readw(bank->base + bank->regs->revision);           |        |
    pr_info("OMAP GPIO hardware version %d.%d\n",                   |        |
        (rev >> 4) & 0x0f, rev & 0x0f);                             |        |
                                                                    |        |
    called = true;                                                  |        |
}                                                                   |        |
                                                                    |        |
static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) <-+        |
{                                                                            |
    int j;                                                                   |
    static int gpio;                                                         |
                                                                             |
    bank->mod_usage = 0;                                                     |
    /*                                                                       |
     * REVISIT eventually switch from OMAP-specific gpio structs             |
     * over to the generic ones                                              |
     */                                                                      |
    bank->chip.request = omap_gpio_request;                                  |
    bank->chip.free = omap_gpio_free;                                        |
    bank->chip.direction_input = gpio_input;             ----------+         |
    bank->chip.get = gpio_get;                                     |         |
    bank->chip.direction_output = gpio_output;                     |         |
    bank->chip.set_debounce = gpio_debounce;                       |         |
    bank->chip.set = gpio_set;                                     |         |
    bank->chip.to_irq = gpio_2irq;                                 |         |
    if (bank_is_mpuio(bank)) {                                     |         |
        bank->chip.label = "mpuio";                                |         |
#ifdef CONFIG_ARCH_OMAP16XX                                        |         |
        bank->chip.dev = &omap_mpuio_device.dev;                   |         |
#endif                                                             |         |
        bank->chip.base = OMAP_MPUIO(0);                           |         |
    } else {                                                       |         |
        bank->chip.label = "gpio";                                 |         |
        bank->chip.base = gpio;                                    |         |
        gpio += bank->width;                                       |         |
    }                                                              |         |
    bank->chip.ngpio = bank->width;                                |         |
                                                                   |         |
    gpiochip_add(&bank->chip);                                     |         |
                                                                   |         |
    for (j = bank->virtual_irq_start;                              |         |
             j < bank->virtual_irq_start + bank->width; j++) {     |         |
        irq_set_lockdep_class(j, &gpio_lock_class);                |         |
        irq_set_chip_data(j, bank);                                |         |
        if (bank_is_mpuio(bank)) {                                 |         |
            omap_mpuio_alloc_gc(bank, j, bank->width);             |         |
        } else {                                                   |         |
            irq_set_chip(j, &gpio_irq_chip);                       |         |
            irq_set_handler(j, handle_simple_irq);                 |         |
            set_irq_flags(j, IRQF_VALID);                          |         |
        }                                                          |         |
    }                                                              |         |
    irq_set_chained_handler(bank->irq, gpio_irq_handler);          |         |
    irq_set_handler_data(bank->irq, bank);                         |         |
}                                                                  |         |
                                                                   |         |
static int gpio_input(struct gpio_chip *chip, unsigned offset)  <--+         |
{                                                                            |
    struct gpio_bank *bank;                                                  |
    unsigned long flags;                                                     |
                                                                             |
    bank = container_of(chip, struct gpio_bank, chip);                       |
    spin_lock_irqsave(&bank->lock, flags);                                   |
    _set_gpio_direction(bank, offset, 1);                          --------+ |
    spin_unlock_irqrestore(&bank->lock, flags);                            | |
    return 0;                                                              | |
}                                                                          | |
                                                                           | |
static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, <-+ |
                int dir)                                                     |
{                                                                            |
    unsigned int base = GPIO_BASE(offset / 32);                              |
    unsigned int reg;                                                        |
                                                                             |
    reg = __raw_readl(base + GPIO_DIR);                                      |
    if (dir)                                                                 |
        reg |= 1 << (offset % 32);                                           |
    else                                                                     |
        reg &= ~(1 << (offset % 32));                                        |
    __raw_writel(reg, base + GPIO_DIR);                                      |
}                                                                            |
                                                                             |
static void omap_gpio_mod_init(struct gpio_bank *bank, int id)         <-----+
{
    if (cpu_class_is_omap2()) {
        if (cpu_is_omap44xx() || cpu_is_am33xx()) {
            __raw_writel(0xffffffff, bank->base +
                    OMAP4_GPIO_IRQSTATUSCLR0);
            __raw_writel(0x00000000, bank->base +
                     OMAP4_GPIO_DEBOUNCENABLE);
            /* Initialize interface clk ungated, module enabled */
            __raw_writel(0, bank->base + OMAP4_GPIO_CTRL);
        } else if (cpu_is_omap34xx()) {
            __raw_writel(0x00000000, bank->base +
                    OMAP24XX_GPIO_IRQENABLE1);
            __raw_writel(0xffffffff, bank->base +
                    OMAP24XX_GPIO_IRQSTATUS1);
            __raw_writel(0x00000000, bank->base +
                    OMAP24XX_GPIO_DEBOUNCE_EN);

            /* Initialize interface clk ungated, module enabled */
            __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
        } else if (cpu_is_omap24xx()) {
            static const u32 non_wakeup_gpios[] = {
                0xe203ffc0, 0x08700040
            };
            if (id < ARRAY_SIZE(non_wakeup_gpios))
                bank->non_wakeup_gpios = non_wakeup_gpios[id];
        }
    } else if (cpu_class_is_omap1()) {
        if (bank_is_mpuio(bank))
            __raw_writew(0xffff, bank->base +
                OMAP_MPUIO_GPIO_MASKIT / bank->stride);
        if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
            __raw_writew(0xffff, bank->base
                        + OMAP1510_GPIO_INT_MASK);
            __raw_writew(0x0000, bank->base
                        + OMAP1510_GPIO_INT_STATUS);
        }
        if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
            __raw_writew(0x0000, bank->base
                        + OMAP1610_GPIO_IRQENABLE1);
            __raw_writew(0xffff, bank->base
                        + OMAP1610_GPIO_IRQSTATUS1);
            __raw_writew(0x0014, bank->base
                        + OMAP1610_GPIO_SYSCONFIG);

            /*
             * Enable system clock for GPIO module.
             * The CAM_CLK_CTRL *is* really the right place.
             */
            omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04,
                        ULPD_CAM_CLK_CTRL);
        }
        if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) {
            __raw_writel(0xffffffff, bank->base
                        + OMAP7XX_GPIO_INT_MASK);
            __raw_writel(0x00000000, bank->base
                        + OMAP7XX_GPIO_INT_STATUS);
        }
    }
}
时间: 2024-10-11 01:28:05

am335x gpio的相关文章

am335x gpio控制

1.执行下面的命令,可以显示目前驱动已经申请到的IO状态 : $ mount -t debugfs debugfs /sys/kernel/debug  $ cat /sys/kernel/debug/gpio    [email protected]:/# cat /sys/kernel/debug/gpio  GPIOs 0-31, gpio:   gpio-2   (volume-up           ) in  hi   gpio-3   (volume-down         )

am335x gpio 控制的另一种方法

#include <linux/gpio.h>  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/moduleparam.h>  #include <linux/delay.h>  #include <linux/types.h>  #include <linux/cdev.h>  #include <linux/device

am335x mux配置

/**************************************************************** * am335x mux配置 * * am335x的引脚复寄存器是CONTROL_MODULE Register(芯片手册Chapter 9) * 本文主要分析板级文件中如何实现复用. * * 参考链接: * http://blog.chinaunix.net/uid-29745891-id-4348350.html * * Tony Liu, 2016-4-30,

Am335x 下GPIO控制实例-驱动程序(转)

看了这么多的资料,现在决定上手了,下面将用两种方式来实现对GPIO 117的控制1,用直接添加到内核的方式,实现MISC的驱动(misc_register)2,用手工安装的方式,实现简单字符设备驱动(register_chrdev) 实现前提:当前所用的GPIO没有被其它设备所使用,大家可以用我前面BLOG说的方式查看GPIO的使用情况,当前我所用的GPIO本来是bluetooth的开关,需要屏蔽一个函数.不然后面的驱动申请IO都会失败.函数为Board-am335xevm.c 中的wl12xx

AM335x(TQ335x)学习笔记——GPIO按键

还是按照S5PV210的学习顺序来,我们首先解决按键问题.TQ335x有六个用户按键,分别是上.下.左.右.Enter和ESC.开始我想到的是跟学习S5PV210时一样,编写输入子系统驱动解决按键问题,但是浏览driver/input/keyboard目录时意外的发现了gpio-keys.c,大体上看下该驱动程序,其功能是实现了通用的gpio按键.再去看了下DTS,发现DTS中有对gpio-keys的引用,于是猜到,新的内核不需要自己编写输入子系统驱动,可以通过配置DTS直接解决按键问题.本人最

AM335X开发板外扩GPIO资源如何使用?

米尔MYD-AM335X-J开发板J11端子的外扩GPIO怎么才能使用,对应的GPIO定义或者引脚是多少?米尔技术支持回答:这个只需要配置一个设备树即可.参照下面的方式利用TI的pinmux工具进行配置.配置完之后就可以使用sysfs控制gpio了.具体的管脚定义可以结合底板的原理图和01-Documents\UserManual\Chinese\MYC_J335X PIN List.pdf 来确定.&am33xx_pinmux {pinctrl-names = "default&quo

AM335x(TQ335x)学习笔记——USB驱动移植

对于AM335x来讲,TI维护的USB驱动已经非常完善了,本文称之为移植,实际上仅仅是配置内核选项使能USB HOST/OTG功能.废话少说,直接动手开启AM335x的USB驱动配置项. Step1. 配置内核支持USB 默认的配置项没有配置USB相关的选项,但是DTS已经配置好了,我们不需要对DTS作任何修改,详细的内核配置项如下: Device Drivers ---> [*] USB support ---> [*] OTG support <*> EHCI HCD (USB

BeagleBone black的GPIO控制初探

刚刚读大学的时候就开始接触了 51,后来是stm32, 感觉MCU都是很好玩的 . 做过一些东西,循迹小车之类的,但是我的外围电路总是出问题,所以有很长一段时间没碰这东西了,现在呢到手一块bbbalck  熟悉了一个月  感觉用linux还是很不舒服的(没我pc跑得ubuntu舒服 很多东西看了半天设置不出来  ),于是从ti下载了starterware  结果发现没有bbblack 得从github上clone git clone https://github.com/embest-tech/

AM335x(TQ335x)学习笔记——Nand&amp;&amp;网卡驱动移植

移植完成声卡驱动之后本想再接再励,移植网卡驱动,但没想到的是TI维护的内核太健壮,移植网卡驱动跟之前移植按键驱动一样简单,Nand驱动也是如此,于是,本人将Nand和网卡放在同一篇文章中介绍.介绍之前先感慨一下:TI的维护的内核真的很健壮,DTS真的很强大. 1. Nand驱动移植 阅读TQ335x的原理图可知,TQ335x的Nand连接到了GPMC上,且都是使用的相应引脚的MODE0复用功能,AM335x上上电复位后这些引脚的默认状态就处于MODE0模式,故无需进行pinmux设置,原始的DT