From 6c07642c16ae09e9965081a0d531da24f6d2b616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lang=C3=A5s?= Date: Thu, 29 Jan 2015 23:37:19 +0100 Subject: [PATCH] Gonzo sysfs driver for controlling LEDs. --- arch/arm/mach-msm/Makefile | 4 + arch/arm/mach-msm/board-msm7x27a.c | 16 +++- arch/arm/mach-msm/gonzo-sysfs.c | 147 +++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-msm/gonzo-sysfs.c diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 26c40960f..d85afa490 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -318,3 +318,7 @@ obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o obj-$(CONFIG_MSM_RTB) += msm_rtb.o obj-$(CONFIG_MSM_CACHE_ERP) += cache_erp.o obj-$(CONFIG_MSM_CACHE_DUMP) += msm_cache_dump.o + + +# Ugly, forces gonzo-sysfs on all variants +obj-y += gonzo-sysfs.o diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c index a24917235..c1a76da93 100755 --- a/arch/arm/mach-msm/board-msm7x27a.c +++ b/arch/arm/mach-msm/board-msm7x27a.c @@ -777,6 +777,11 @@ static void msm_cfg_uart2dm_serial(void) static void msm_cfg_uart2dm_serial(void) { } #endif +static struct platform_device gonzo_sysfs = { + .name = "gonzo-sysfs", + .id = -1, +}; + static struct platform_device *rumi_sim_devices[] __initdata = { &msm_device_dmov, &msm_device_smd, @@ -808,6 +813,7 @@ static struct platform_device *surf_ffa_devices[] __initdata = { &msm_fb_device, &msm_batt_device, &smsc911x_device, + &gonzo_sysfs, #ifdef CONFIG_FB_MSM_MIPI_DSI &mipi_dsi_ILI9487_panel_device, #endif @@ -1135,8 +1141,10 @@ static struct i2c_board_info ktf2k_device[] = { }; #endif -// Cellon modify end, Zepeng Wu, 2013/2/17, for TP +// Disable keys for gonzo -- use as GPIO instead. +#if 0 +// Cellon modify end, Zepeng Wu, 2013/2/17, for TP #define KP_INDEX(row, col) ((row)*ARRAY_SIZE(kp_col_gpios) + (col)) static unsigned int kp_row_gpios[] = {31, 32};//cellon,zhihua 2013-1-3, 33, 34, 35}; @@ -1179,6 +1187,7 @@ static struct platform_device kp_pdev = { .platform_data = &kp_pdata, }, }; +#endif static struct msm_handset_platform_data hs_platform_data = { .hs_name = "7k_handset", @@ -1342,7 +1351,10 @@ static void __init msm7x2x_init(void) #if defined(CONFIG_MSM_CAMERA) msm7627a_camera_init(); #endif - platform_device_register(&kp_pdev); + +// Use GPIOs as output instead +// platform_device_register(&kp_pdev); + platform_device_register(&hs_pdev); /* configure it as a pdm function*/ diff --git a/arch/arm/mach-msm/gonzo-sysfs.c b/arch/arm/mach-msm/gonzo-sysfs.c new file mode 100644 index 000000000..b4ca8aa40 --- /dev/null +++ b/arch/arm/mach-msm/gonzo-sysfs.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define GREEN_LED 0 +#define RED_LED 1 + +static struct { + int gpio_index; // Control index + int gpio; // GPIO number + char *name; // GPIO name + bool output; // 1= output, 0=input + int value; // Default (only for output) + int pud; // Pull up/down register setting +} gonzo_gpio_map[] = { + { GREEN_LED, 32, "green_led", 1, 0, 0 }, + { RED_LED, 36, "red_led", 1, 0, 0 }, +}; + +/* Setup sysfs */ +static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static DEVICE_ATTR(green_led, S_IRWXUGO, show_gpio, set_gpio); +static DEVICE_ATTR(red_led, S_IRWXUGO, show_gpio, set_gpio); + +static struct attribute *gonzo_sysfs_entries[] = { + &dev_attr_green_led.attr, + &dev_attr_red_led.attr, + NULL +}; + +static struct attribute_group gonzo_sysfs_attr_group = { + .name = NULL, + .attrs = gonzo_sysfs_entries, +}; + + +static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf) +{ + int i; + for (i = 0; i < ARRAY_SIZE(gonzo_gpio_map); i++) { + if (gonzo_gpio_map[i].gpio && (strcmp(gonzo_gpio_map[i].name, attr->attr.name))) { + return sprintf(buf, "%d\n", gpio_get_value(gonzo_gpio_map[i].gpio) ? 1 : 0); + } + } + + return sprintf(buf, "ERROR: GPIO specified not found\n"); +} + +static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int val, i; + + if (!(sscanf(buf, "%d\n", &val))) { + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(gonzo_gpio_map); i++) { + if (gonzo_gpio_map[i].gpio && (strcmp(gonzo_gpio_map[i].name, attr->attr.name))) { + if (gonzo_gpio_map[i].output) { + gpio_set_value(gonzo_gpio_map[i].gpio, (val != 0) ? 1 : 0); + } else { + printk("This GPIO is configured for input, no value being set\n"); + } + } + } + + printk("ERROR: GPIO not found\n"); + return count; +} + + +/* Wire up the actual sysfs calls */ + +static int gonzo_sysfs_probe(struct platform_device *pdev) +{ + int i; + for (i = 0; i < ARRAY_SIZE(gonzo_gpio_map); i++) { + if (gonzo_gpio_map[i].gpio) { + if (gpio_request(gonzo_gpio_map[i].gpio, gonzo_gpio_map[i].name)) { + printk("%s : %s gpio_request error!\n", __FUNCTION__, gonzo_gpio_map[i].name); + continue; + } + + if (gonzo_gpio_map[i].output) { + gpio_direction_output(gonzo_gpio_map[i].gpio, gonzo_gpio_map[i].value); + } else { + gpio_direction_input(gonzo_gpio_map[i].gpio); + } + //setpull, if possible + } + } + + return sysfs_create_group(&pdev->dev.kobj, &gonzo_sysfs_attr_group); +} + +static int gonzo_sysfs_remove(struct platform_device *pdev) +{ + int i; + for (i = 0; i < ARRAY_SIZE(gonzo_gpio_map); i++) { + if (gonzo_gpio_map[i].gpio) { + gpio_free(gonzo_gpio_map[i].gpio); + } + } + + sysfs_remove_group(&pdev->dev.kobj, &gonzo_sysfs_attr_group); + return 0; +} + +static struct platform_driver gonzo_sysfs_driver = { + .driver = { + .name = "gonzo-sysfs", + .owner = THIS_MODULE, + }, + .probe = gonzo_sysfs_probe, + .remove = gonzo_sysfs_remove, +}; + +static int __init gonzo_sysfs_init(void) +{ + return platform_driver_register(&gonzo_sysfs_driver); +} + +static void __exit gonzo_sysfs_exit(void) +{ + return platform_driver_unregister(&gonzo_sysfs_driver); +} + + +module_init(gonzo_sysfs_init); +module_exit(gonzo_sysfs_exit); + + +MODULE_DESCRIPTION("SYSFS driver for LEDs on Gonzo"); +MODULE_AUTHOR("Telenor Digital AS"); +MODULE_LICENSE("GPL");