gpio-tps65912.c (fcdcc79628a1919bde9acf239e364f65bab6327c) | gpio-tps65912.c (ca801a22f465eae39fadc770e15b5b7e82595f81) |
---|---|
1/* | 1/* |
2 * Copyright 2011 Texas Instruments Inc. | 2 * GPIO driver for TI TPS65912x PMICs |
3 * | 3 * |
4 * Author: Margarita Olaya <magi@slimlogic.co.uk> | 4 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 5 * Andrew F. Davis <afd@ti.com> |
5 * | 6 * |
6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. | 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. |
10 * | 10 * |
11 * This driver is based on wm8350 implementation. | 11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 * kind, whether expressed or implied; without even the implied warranty 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License version 2 for more details. 15 * 16 * Based on the Arizona GPIO driver and the previous TPS65912 driver by 17 * Margarita Olaya Cabrera <magi@slimlogic.co.uk> |
12 */ 13 | 18 */ 19 |
14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/errno.h> | |
17#include <linux/gpio.h> | 20#include <linux/gpio.h> |
18#include <linux/mfd/core.h> | 21#include <linux/module.h> |
19#include <linux/platform_device.h> | 22#include <linux/platform_device.h> |
20#include <linux/seq_file.h> 21#include <linux/slab.h> | 23 |
22#include <linux/mfd/tps65912.h> 23 | 24#include <linux/mfd/tps65912.h> 25 |
24struct tps65912_gpio_data { 25 struct tps65912 *tps65912; | 26struct tps65912_gpio { |
26 struct gpio_chip gpio_chip; | 27 struct gpio_chip gpio_chip; |
28 struct tps65912 *tps; |
|
27}; 28 | 29}; 30 |
29static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) | 31static int tps65912_gpio_get_direction(struct gpio_chip *gc, 32 unsigned offset) |
30{ | 33{ |
31 struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); 32 struct tps65912 *tps65912 = tps65912_gpio->tps65912; 33 int val; | 34 struct tps65912_gpio *gpio = gpiochip_get_data(gc); |
34 | 35 |
35 val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset); | 36 int ret, val; |
36 | 37 |
37 if (val & GPIO_STS_MASK) 38 return 1; | 38 ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); 39 if (ret) 40 return ret; |
39 | 41 |
40 return 0; | 42 if (val & GPIO_CFG_MASK) 43 return GPIOF_DIR_OUT; 44 else 45 return GPIOF_DIR_IN; |
41} 42 | 46} 47 |
43static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, 44 int value) | 48static int tps65912_gpio_direction_input(struct gpio_chip *gc, unsigned offset) |
45{ | 49{ |
46 struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); 47 struct tps65912 *tps65912 = tps65912_gpio->tps65912; | 50 struct tps65912_gpio *gpio = gpiochip_get_data(gc); |
48 | 51 |
49 if (value) 50 tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, 51 GPIO_SET_MASK); 52 else 53 tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, 54 GPIO_SET_MASK); | 52 return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 53 GPIO_CFG_MASK, 0); |
55} 56 | 54} 55 |
57static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset, 58 int value) | 56static int tps65912_gpio_direction_output(struct gpio_chip *gc, 57 unsigned offset, int value) |
59{ | 58{ |
60 struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); 61 struct tps65912 *tps65912 = tps65912_gpio->tps65912; | 59 struct tps65912_gpio *gpio = gpiochip_get_data(gc); |
62 63 /* Set the initial value */ | 60 61 /* Set the initial value */ |
64 tps65912_gpio_set(gc, offset, value); | 62 regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 63 GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); |
65 | 64 |
66 return tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, 67 GPIO_CFG_MASK); | 65 return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 66 GPIO_CFG_MASK, GPIO_CFG_MASK); |
68} 69 | 67} 68 |
70static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset) | 69static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) |
71{ | 70{ |
72 struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); 73 struct tps65912 *tps65912 = tps65912_gpio->tps65912; | 71 struct tps65912_gpio *gpio = gpiochip_get_data(gc); 72 int ret, val; |
74 | 73 |
75 return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, 76 GPIO_CFG_MASK); | 74 ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); 75 if (ret) 76 return ret; 77 78 if (val & GPIO_STS_MASK) 79 return 1; 80 81 return 0; |
77} 78 | 82} 83 |
84static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, 85 int value) 86{ 87 struct tps65912_gpio *gpio = gpiochip_get_data(gc); 88 89 regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, 90 GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); 91} 92 |
|
79static struct gpio_chip template_chip = { | 93static struct gpio_chip template_chip = { |
80 .label = "tps65912", | 94 .label = "tps65912-gpio", |
81 .owner = THIS_MODULE, | 95 .owner = THIS_MODULE, |
82 .direction_input = tps65912_gpio_input, 83 .direction_output = tps65912_gpio_output, | 96 .get_direction = tps65912_gpio_get_direction, 97 .direction_input = tps65912_gpio_direction_input, 98 .direction_output = tps65912_gpio_direction_output, |
84 .get = tps65912_gpio_get, 85 .set = tps65912_gpio_set, | 99 .get = tps65912_gpio_get, 100 .set = tps65912_gpio_set, |
86 .can_sleep = true, 87 .ngpio = 5, | |
88 .base = -1, | 101 .base = -1, |
102 .ngpio = 5, 103 .can_sleep = true, |
|
89}; 90 91static int tps65912_gpio_probe(struct platform_device *pdev) 92{ | 104}; 105 106static int tps65912_gpio_probe(struct platform_device *pdev) 107{ |
93 struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); 94 struct tps65912_board *pdata = dev_get_platdata(tps65912->dev); 95 struct tps65912_gpio_data *tps65912_gpio; | 108 struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); 109 struct tps65912_gpio *gpio; |
96 int ret; 97 | 110 int ret; 111 |
98 tps65912_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65912_gpio), 99 GFP_KERNEL); 100 if (tps65912_gpio == NULL) | 112 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 113 if (!gpio) |
101 return -ENOMEM; 102 | 114 return -ENOMEM; 115 |
103 tps65912_gpio->tps65912 = tps65912; 104 tps65912_gpio->gpio_chip = template_chip; 105 tps65912_gpio->gpio_chip.parent = &pdev->dev; 106 if (pdata && pdata->gpio_base) 107 tps65912_gpio->gpio_chip.base = pdata->gpio_base; | 116 gpio->tps = dev_get_drvdata(pdev->dev.parent); 117 gpio->gpio_chip = template_chip; 118 gpio->gpio_chip.parent = tps->dev; |
108 | 119 |
109 ret = gpiochip_add_data(&tps65912_gpio->gpio_chip, tps65912_gpio); | 120 ret = gpiochip_add_data(&gpio->gpio_chip, gpio); |
110 if (ret < 0) { | 121 if (ret < 0) { |
111 dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); | 122 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); |
112 return ret; 113 } 114 | 123 return ret; 124 } 125 |
115 platform_set_drvdata(pdev, tps65912_gpio); | 126 platform_set_drvdata(pdev, gpio); |
116 | 127 |
117 return ret; | 128 return 0; |
118} 119 120static int tps65912_gpio_remove(struct platform_device *pdev) 121{ | 129} 130 131static int tps65912_gpio_remove(struct platform_device *pdev) 132{ |
122 struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev); | 133 struct tps65912_gpio *gpio = platform_get_drvdata(pdev); |
123 | 134 |
124 gpiochip_remove(&tps65912_gpio->gpio_chip); | 135 gpiochip_remove(&gpio->gpio_chip); 136 |
125 return 0; 126} 127 | 137 return 0; 138} 139 |
140static const struct platform_device_id tps65912_gpio_id_table[] = { 141 { "tps65912-gpio", }, 142 { /* sentinel */ } 143}; 144MODULE_DEVICE_TABLE(platform, tps65912_gpio_id_table); 145 |
|
128static struct platform_driver tps65912_gpio_driver = { 129 .driver = { 130 .name = "tps65912-gpio", 131 }, 132 .probe = tps65912_gpio_probe, 133 .remove = tps65912_gpio_remove, | 146static struct platform_driver tps65912_gpio_driver = { 147 .driver = { 148 .name = "tps65912-gpio", 149 }, 150 .probe = tps65912_gpio_probe, 151 .remove = tps65912_gpio_remove, |
152 .id_table = tps65912_gpio_id_table, |
|
134}; | 153}; |
154module_platform_driver(tps65912_gpio_driver); |
|
135 | 155 |
136static int __init tps65912_gpio_init(void) 137{ 138 return platform_driver_register(&tps65912_gpio_driver); 139} 140subsys_initcall(tps65912_gpio_init); 141 142static void __exit tps65912_gpio_exit(void) 143{ 144 platform_driver_unregister(&tps65912_gpio_driver); 145} 146module_exit(tps65912_gpio_exit); 147 148MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>"); 149MODULE_DESCRIPTION("GPIO interface for TPS65912 PMICs"); | 156MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); 157MODULE_DESCRIPTION("TPS65912 GPIO driver"); |
150MODULE_LICENSE("GPL v2"); | 158MODULE_LICENSE("GPL v2"); |
151MODULE_ALIAS("platform:tps65912-gpio"); | |