diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 6661b17fee126e7b274528be6ec7a5fe21551b5e..da4a7e513c82213f027602017826c3904e998aa0 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -34,7 +34,7 @@ obj-$(CONFIG_ARCH_MDM9630) += board-9630.o board-9630-gpiomux.o obj-$(CONFIG_MSM_PP2S_FEMTO) += pp2s.o obj-$(CONFIG_ARCH_MSMFERRUM) += board-ferrum.o obj-$(CONFIG_ARCH_MSM8916) += board-8916.o -obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o board-8226-rfkill.o +obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o board-8226-rfkill.o board-8226-gpiomcu.o obj-$(CONFIG_ARCH_MSM8226) += clock-8226.o clock-mdss-8974.o obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o obj-$(CONFIG_ARCH_MSM8610) += clock-8610.o diff --git a/arch/arm/mach-msm/board-8226-gpiomcu.c b/arch/arm/mach-msm/board-8226-gpiomcu.c new file mode 100644 index 0000000000000000000000000000000000000000..c968983f538f47a974e114affd7a10d40ed1b80a --- /dev/null +++ b/arch/arm/mach-msm/board-8226-gpiomcu.c @@ -0,0 +1,240 @@ +/* Copyright (c) 2012-2015, mcu gpio init. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/gpio.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/gpiomux.h> +#include <soc/qcom/socinfo.h> + +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/spinlock.h> +#include <linux/timer.h> +#include <linux/uaccess.h> + + +#define MCU_GPIO_BOOT0 111 +#define MCU_GPIO_BOOT1 106 +#define MCU_GPIO_RESET 87 +#define GPIO_LEN 16 + +struct gpio_mcu_info +{ + unsigned gpio; + const char *label; +}; + +static struct gpio_mcu_info gpio_mcu []= +{ + {MCU_GPIO_BOOT0,"GPIO111"}, + {MCU_GPIO_BOOT1,"GPIO106"}, + {MCU_GPIO_RESET,"GPIO87"} +}; + +struct proc_dir_entry *mcu_dir; + +static ssize_t mcu_write_proc_gpio(unsigned gpio, const char __user *buffer, size_t count) +{ + char b; + unsigned i; + char buf[GPIO_LEN] = {0}; + + if (copy_from_user(&b, buffer, 1)) + { + pr_err("Set value failed copy\n"); + return -EFAULT; + } + if ( b != '0' && b != '1') + { + pr_err("Set value invalid\n"); + return -EINVAL; + } + + for(i = 0; i < sizeof(gpio_mcu) / sizeof(struct gpio_mcu_info); i ++) + { + if(gpio_mcu[i].gpio == gpio) + { + strncpy(buf, gpio_mcu[i].label, GPIO_LEN - 1); + break; + } + } + if(sizeof(gpio_mcu) / sizeof(struct gpio_mcu_info) == i) + { + pr_err("gpio %d for invalid.\n", gpio); + return -EINVAL; + } + if (gpio_request(gpio, (const char*)buf)) + { + pr_err( "Failed to request gpio %d\n", gpio); + + return -EFAULT; + } + + if (b == '0') + { + gpio_direction_output(gpio, 0); + pr_info("mcu_write_proc_gpio (%u) low.\n", gpio); + } + else if (b == '1') + { + gpio_direction_output(gpio, 1); + pr_info("mcu_write_proc_gpio (%u) high.\n", gpio); + } + gpio_free(gpio); + return count; + +} + +static ssize_t mcu_read_proc_gpio_boot0 + (struct file *file, char __user *userbuf, + size_t bytes, loff_t *off) +{ + return 0; +} + +static ssize_t mcu_write_proc_gpio_boot0 + (struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + if (count < 1) + { + return -EINVAL; + } + + return mcu_write_proc_gpio(MCU_GPIO_BOOT0, buffer, count); +} + +static ssize_t mcu_read_proc_gpio_boot1 + (struct file *file, char __user *userbuf, + size_t bytes, loff_t *off) +{ + return 0; +} + +static ssize_t mcu_write_proc_gpio_boot1 + (struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + if (count < 1) + { + return -EINVAL; + } + + return mcu_write_proc_gpio(MCU_GPIO_BOOT1, buffer, count); + +} + +static ssize_t mcu_read_proc_gpio_reset + (struct file *file, char __user *userbuf, + size_t bytes, loff_t *off) +{ + return 0; +} + +static ssize_t mcu_write_proc_gpio_reset + (struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + if (count < 1) + { + return -EINVAL; + } + + return mcu_write_proc_gpio(MCU_GPIO_RESET, buffer, count); +} + + +static const struct file_operations proc_fops_gpio_boot0 = { + .owner = THIS_MODULE, + .read = mcu_read_proc_gpio_boot0, + .write = mcu_write_proc_gpio_boot0, +}; + +static const struct file_operations proc_fops_gpio_boot1 = { + .owner = THIS_MODULE, + .read = mcu_read_proc_gpio_boot1, + .write = mcu_write_proc_gpio_boot1, +}; + +static const struct file_operations proc_fops_gpio_reset = { + .owner = THIS_MODULE, + .read = mcu_read_proc_gpio_reset, + .write = mcu_write_proc_gpio_reset, +}; + + +static int __init board_mcu_gpio_init(void) +{ + int retval; + struct proc_dir_entry *ent; + + mcu_dir = proc_mkdir("mcu", NULL); + if (mcu_dir == NULL) + { + pr_err("Unable to create /proc/mcu directory.\n"); + return -ENOMEM; + } + + /* read/write mcu boot0 proc entries */ + ent = proc_create("gpio_mcu_boot0", 0660, mcu_dir, &proc_fops_gpio_boot0); + if (ent == NULL) + { + pr_err("Unable to create /proc/mcu/gpio_mcu_boot0 entry.\n"); + retval = -ENOMEM; + goto fail; + } + + /* read/write mcu boot1 entries */ + ent = proc_create("gpio_mcu_boot1", 0660, mcu_dir, &proc_fops_gpio_boot1); + if (ent == NULL) + { + pr_err("Unable to create /proc/mcu/gpio_mcu_boot1 entry.\n"); + retval = -ENOMEM; + goto fail; + } + + /* read/write mcu reset proc entries */ + ent = proc_create("gpio_mcu_reset", 0660, mcu_dir, &proc_fops_gpio_reset); + if (ent == NULL) + { + pr_err("Unable to create /proc/mcu/gpio_mcu_reset entry.\n"); + retval = -ENOMEM; + goto fail; + } + + return 0; + +fail: + remove_proc_entry("gpio_mcu_boot0", mcu_dir); + remove_proc_entry("gpio_mcu_boot1", mcu_dir); + remove_proc_entry("gpio_mcu_reset", mcu_dir); + remove_proc_entry("mcu", 0); + return retval; +} + +/** + * Cleans up the module. + */ +static void __exit board_mcu_gpio_exit(void) +{ + remove_proc_entry("gpio_mcu_boot0", mcu_dir); + remove_proc_entry("gpio_mcu_boot1", mcu_dir); + remove_proc_entry("gpio_mcu_reset", mcu_dir); + remove_proc_entry("mcu", 0); +} + +module_init(board_mcu_gpio_init); +module_exit(board_mcu_gpio_exit); diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c index fc99428e53baf571c9297afaf03f316bae153cfd..0ada3b9e99d638700c81e94a41c0253dc27efcb6 100644 --- a/arch/arm/mach-msm/board-8226-gpiomux.c +++ b/arch/arm/mach-msm/board-8226-gpiomux.c @@ -166,13 +166,6 @@ static struct gpiomux_setting gpio_i2c_config = { }; static struct msm_gpiomux_config msm_keypad_configs[] __initdata = { - { - .gpio = 106, - .settings = { - [GPIOMUX_ACTIVE] = &gpio_keys_active, - [GPIOMUX_SUSPENDED] = &gpio_keys_suspend, - }, - }, { .gpio = 107, .settings = { @@ -598,6 +591,27 @@ static struct msm_gpiomux_config msm_uart1_configs[] __initdata = }, }; +static struct gpiomux_setting gpio_reset_config = +{ + .func = GPIOMUX_FUNC_2, //Please look @ GPIO function table for correct function + .drv = GPIOMUX_DRV_8MA, //Drive Strength + .pull = GPIOMUX_PULL_UP, //Should be PULL_UP for UART +}; + +/*added gpio define and uart for MCU*/ +static struct msm_gpiomux_config msm_mcureset_config[] __initdata = +{ + { + .gpio = 87, //BLSP1 UART1 reset + .settings = + { + [GPIOMUX_ACTIVE] = &gpio_reset_config, + [GPIOMUX_SUSPENDED] = &gpio_reset_config, + }, + }, +}; + + static struct msm_gpiomux_config msm_uart3_configs[] __initdata = { { @@ -952,6 +966,10 @@ void __init msm8226_init_gpiomux(void) msm_gpiomux_install(msm8226_tert_mi2s_configs, ARRAY_SIZE(msm8226_tert_mi2s_configs)); /*I2S for MIC*/ msm_gpiomux_install(msm8226_quat_mi2s_configs, ARRAY_SIZE(msm8226_quat_mi2s_configs)); + + /*RST MCU*/ + msm_gpiomux_install(msm_mcureset_config, ARRAY_SIZE(msm_mcureset_config)); + /* * HSIC STROBE gpio is also used by the ethernet. Install HSIC * gpio mux config only when HSIC is enabled. HSIC config will