OK335xS pwm device register hacking
/************************************************************************* * 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; }