diff --git a/firmware/target/hosted/samsungypr/gpio-ypr.c b/firmware/target/hosted/samsungypr/gpio-ypr.c index e5abc4cdc9..d6a19da34f 100644 --- a/firmware/target/hosted/samsungypr/gpio-ypr.c +++ b/firmware/target/hosted/samsungypr/gpio-ypr.c @@ -8,7 +8,7 @@ * * Module wrapper for GPIO, using kernel module of Samsung YP-R0/YP-R1 * - * Copyright (c) 2011 Lorenzo Miori + * Copyright (c) 2011-2015 Lorenzo Miori * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,16 +23,42 @@ #include #include #include -#include /* includes common ioctl device definitions */ #include +#include "panic.h" +#include "gpio-ypr.h" /* includes common ioctl device definitions */ + static int gpio_dev = 0; +#ifdef GPIO_DEBUG +// 3 banks of 32 pins +static const char *pin_use[3][32]; + +void gpio_acquire(unsigned bank, unsigned pin, const char *name) +{ + if(pin_use[bank][pin] != NULL && pin_use[bank][pin] != name) + panicf("acquire B%dP%02d for %s, was %s!", bank, pin, name, pin_use[bank][pin]); + pin_use[bank][pin] = name; +} + +void gpio_release(unsigned bank, unsigned pin, const char *name) +{ + if(pin_use[bank][pin] != NULL && pin_use[bank][pin] != name) + panicf("release B%dP%02d for %s: was %s!", bank, pin, name, pin_use[bank][pin]); + pin_use[bank][pin] = NULL; +} + +const char *gpio_blame(unsigned bank, unsigned pin) +{ + return pin_use[bank][pin]; +} +#endif + void gpio_init(void) { gpio_dev = open(GPIO_DEVICE, O_RDONLY); if (gpio_dev < 0) - printf("GPIO device open error!"); + panicf("GPIO device open error!"); } void gpio_close(void) @@ -41,8 +67,68 @@ void gpio_close(void) close(gpio_dev); } -int gpio_control(int request, int num, int mode, int val) +static int gpio_control(int request, int num, int mode, int val) { struct gpio_info r = { .num = num, .mode = mode, .val = val, }; return ioctl(gpio_dev, request, &r); } + +void gpio_set_iomux(int pin, int iomux) +{ + if (gpio_control(DEV_CTRL_GPIO_SET_MUX, pin, iomux, 0) != 0) + { + panicf("Unable to set iomux to pin %d", pin); + } +} + +void gpio_free_iomux(int pin, int iomux) +{ + if (gpio_control(DEV_CTRL_GPIO_UNSET_MUX, pin, iomux, 0) != 0) + { + panicf("Unable to free iomux to pin %d", pin); + } +} + +void gpio_set_pad(int pin, int type) +{ + if (gpio_control(DEV_CTRL_GPIO_SET_TYPE, pin, type, 0) != 0) + { + panicf("Unable to set pad to pin %d", pin); + } +} + +void gpio_direction_output(int pin) +{ + if (gpio_control(DEV_CTRL_GPIO_SET_OUTPUT, pin, 0, 0) != 0) + { + panicf("Unable to set output direction to pin %d", pin); + } +} + +void gpio_direction_input(int pin) +{ + if (gpio_control(DEV_CTRL_GPIO_SET_INPUT, pin, 0, 0) != 0) + { + panicf("Unable to set input direction to pin %d", pin); + } +} + +bool gpio_get(int pin) +{ + return gpio_control(DEV_CTRL_GPIO_GET_VAL, pin, 0, 0); +} + +void gpio_set(int pin, bool value) +{ + int ret = -1; + + if (value) + ret = gpio_control(DEV_CTRL_GPIO_SET_HIGH, pin, 0, 0); + else + ret = gpio_control(DEV_CTRL_GPIO_SET_LOW, pin, 0, 0); + + if (ret != 0) + { + panicf("Unable to set input direction to pin %d", pin); + } +} diff --git a/firmware/target/hosted/samsungypr/gpio-ypr.h b/firmware/target/hosted/samsungypr/gpio-ypr.h index c10991e20c..c7214de6c0 100644 --- a/firmware/target/hosted/samsungypr/gpio-ypr.h +++ b/firmware/target/hosted/samsungypr/gpio-ypr.h @@ -24,6 +24,20 @@ /* Specifies device name and ioctl magic */ #include "gpio-target.h" #include "sys/ioctl.h" +#include "stdbool.h" + +// set to debug pinctrl use +#define GPIO_DEBUG + +#ifdef GPIO_DEBUG +void imx233_pinctrl_acquire(unsigned bank, unsigned pin, const char *name); +void imx233_pinctrl_release(unsigned bank, unsigned pin, const char *name); +const char *imx233_pinctrl_blame(unsigned bank, unsigned pin); +#else +#define imx233_pinctrl_acquire(...) +#define imx233_pinctrl_release(...) +#define imx233_pinctrl_get_pin_use(...) NULL +#endif struct gpio_info { int num; @@ -193,9 +207,16 @@ enum PAD_CTL_DRV_VOT_HIGH = 0x1 << 13, }; +/* Driver-related functions */ void gpio_init(void); void gpio_close(void); -int gpio_control_struct(int request, struct gpio_info pin); -int gpio_control(int request, int num, int mode, int val); +/* Exported API */ +void gpio_set_iomux(int pin, int iomux); +void gpio_free_iomux(int pin, int iomux); +void gpio_set_pad(int pin, int type); +void gpio_direction_output(int pin); +void gpio_direction_input(int pin); +bool gpio_get(int pin); +void gpio_set(int pin, bool value); #endif diff --git a/firmware/target/hosted/samsungypr/ypr0/button-ypr0.c b/firmware/target/hosted/samsungypr/ypr0/button-ypr0.c index 08aacd18c6..860ad50cae 100644 --- a/firmware/target/hosted/samsungypr/ypr0/button-ypr0.c +++ b/firmware/target/hosted/samsungypr/ypr0/button-ypr0.c @@ -31,31 +31,31 @@ int button_read_device(void) int key = BUTTON_NONE; /* Check for all the keys */ - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_USER_KEY, 0, 0)) { + if (!gpio_get(GPIO_USER_KEY)) { key |= BUTTON_USER; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_CENTRAL_KEY, 0, 0)) { + if (!gpio_get(GPIO_CENTRAL_KEY)) { key |= BUTTON_SELECT; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_UP_KEY, 0, 0)) { + if (!gpio_get(GPIO_UP_KEY)) { key |= BUTTON_UP; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_DOWN_KEY, 0, 0)) { + if (!gpio_get(GPIO_DOWN_KEY)) { key |= BUTTON_DOWN; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_LEFT_KEY, 0, 0)) { + if (!gpio_get(GPIO_LEFT_KEY)) { key |= BUTTON_LEFT; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_RIGHT_KEY, 0, 0)) { + if (!gpio_get(GPIO_RIGHT_KEY)) { key |= BUTTON_RIGHT; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_MENU_KEY, 0, 0)) { + if (!gpio_get(GPIO_MENU_KEY)) { key |= BUTTON_MENU; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_BACK_KEY, 0, 0)) { + if (!gpio_get(GPIO_BACK_KEY)) { key |= BUTTON_BACK; } - if (gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_POWER_KEY, 0, 0)) { + if (gpio_get(GPIO_POWER_KEY)) { key |= BUTTON_POWER; } @@ -65,14 +65,15 @@ int button_read_device(void) bool headphones_inserted(void) { /* GPIO low - 0 - means headphones inserted */ - return !gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_HEADPHONE_SENSE, 0, 0); + return !gpio_get(GPIO_HEADPHONE_SENSE); } void button_init_device(void) { /* Setup GPIO pin for headphone sense, copied from OF */ - gpio_control(DEV_CTRL_GPIO_SET_MUX, GPIO_HEADPHONE_SENSE, CONFIG_SION, PAD_CTL_47K_PU); - gpio_control(DEV_CTRL_GPIO_SET_INPUT, GPIO_HEADPHONE_SENSE, CONFIG_SION, PAD_CTL_47K_PU); + gpio_set_iomux(GPIO_HEADPHONE_SENSE, CONFIG_GPIO); + gpio_set_pad(GPIO_HEADPHONE_SENSE, PAD_CTL_47K_PU); + gpio_direction_input(GPIO_HEADPHONE_SENSE); /* No need to initialize any GPIO pin, since this is done loading the r0Btn module */ } @@ -82,6 +83,6 @@ void button_init_device(void) void button_close_device(void) { /* Don't know the precise meaning, but it's done as in the OF, so copied there */ - gpio_control(DEV_CTRL_GPIO_UNSET_MUX, GPIO_HEADPHONE_SENSE, CONFIG_SION, 0); + gpio_free_iomux(GPIO_HEADPHONE_SENSE, CONFIG_GPIO); } #endif /* BUTTON_DRIVER_CLOSE */ diff --git a/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c b/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c index 9cc307073b..2544174252 100644 --- a/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c +++ b/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c @@ -88,7 +88,7 @@ bool hostfs_present(IF_MD_NONVOID(int drive)) { #ifdef HAVE_MULTIDRIVE if (drive > 0) /* Active LOW */ - return (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_SD_SENSE, 0, 0)); + return (!gpio_get(GPIO_SD_SENSE)); else #endif return true; /* internal: always present */ @@ -229,8 +229,9 @@ static void NORETURN_ATTR sd_thread(void) int hostfs_init(void) { /* Setup GPIO pin for microSD sense, copied from OF */ - gpio_control(DEV_CTRL_GPIO_SET_MUX, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); - gpio_control(DEV_CTRL_GPIO_SET_INPUT, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); + gpio_set_iomux(GPIO_SD_SENSE, CONFIG_DEFAULT); + gpio_set_pad(GPIO_SD_SENSE, PAD_CTL_SRE_SLOW); + gpio_direction_input(GPIO_SD_SENSE); #ifdef HAVE_MULTIDRIVE if (storage_present(IF_MD(1))) mount_sd(); diff --git a/firmware/target/hosted/samsungypr/ypr1/button-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/button-ypr1.c index d12b8486b6..26755716f4 100644 --- a/firmware/target/hosted/samsungypr/ypr1/button-ypr1.c +++ b/firmware/target/hosted/samsungypr/ypr1/button-ypr1.c @@ -45,13 +45,13 @@ int button_read_device(int *data) struct mcs5000_raw_data touchpad_data; /* Check for all the keys */ - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_VOL_UP_KEY, 0, 0)) { + if (!gpio_get(GPIO_VOL_UP_KEY)) { key |= BUTTON_VOL_UP; } - if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_VOL_DOWN_KEY, 0, 0)) { + if (!gpio_get(GPIO_VOL_DOWN_KEY)) { key |= BUTTON_VOL_DOWN; } - if (gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_POWER_KEY, 0, 0)) { + if (gpio_get(GPIO_POWER_KEY)) { key |= BUTTON_POWER; } @@ -99,7 +99,7 @@ void touchscreen_enable_device(bool en) bool headphones_inserted(void) { /* GPIO low - 0 - means headphones inserted */ - return !gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_HEADPHONE_SENSE, 0, 0); + return !gpio_get(GPIO_HEADPHONE_SENSE); } void button_init_device(void) @@ -107,8 +107,9 @@ void button_init_device(void) /* Setup GPIO pin for headphone sense, copied from OF * Pins for the other buttons are already set up by OF button module */ - gpio_control(DEV_CTRL_GPIO_SET_MUX, GPIO_HEADPHONE_SENSE, 4, 0); - gpio_control(DEV_CTRL_GPIO_SET_INPUT, GPIO_HEADPHONE_SENSE, 4, 0); + gpio_set_iomux(GPIO_HEADPHONE_SENSE, CONFIG_ALT4); + gpio_set_pad(GPIO_HEADPHONE_SENSE, PAD_CTL_SRE_SLOW); + gpio_direction_input(GPIO_HEADPHONE_SENSE); /* Turn on touchscreen */ mcs5000_init(); @@ -120,7 +121,7 @@ void button_init_device(void) /* I'm not sure it's called at shutdown...give a check! */ void button_close_device(void) { - gpio_control(DEV_CTRL_GPIO_UNSET_MUX, GPIO_HEADPHONE_SENSE, 0, 0); + gpio_free_iomux(GPIO_HEADPHONE_SENSE, CONFIG_ALT4); /* Turn off touchscreen device */ mcs5000_shutdown();