1 /* 2 * GPIO Driver for Dialog DA9052 PMICs. 3 * 4 * Copyright(c) 2011 Dialog Semiconductor Ltd. 5 * 6 * Author: David Dajun Chen <dchen@diasemi.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 #include <linux/module.h> 15 #include <linux/fs.h> 16 #include <linux/uaccess.h> 17 #include <linux/platform_device.h> 18 #include <linux/gpio.h> 19 #include <linux/syscalls.h> 20 #include <linux/seq_file.h> 21 22 #include <linux/mfd/da9052/da9052.h> 23 #include <linux/mfd/da9052/reg.h> 24 #include <linux/mfd/da9052/pdata.h> 25 #include <linux/mfd/da9052/gpio.h> 26 27 #define DA9052_INPUT 1 28 #define DA9052_OUTPUT_OPENDRAIN 2 29 #define DA9052_OUTPUT_PUSHPULL 3 30 31 #define DA9052_SUPPLY_VDD_IO1 0 32 33 #define DA9052_DEBOUNCING_OFF 0 34 #define DA9052_DEBOUNCING_ON 1 35 36 #define DA9052_OUTPUT_LOWLEVEL 0 37 38 #define DA9052_ACTIVE_LOW 0 39 #define DA9052_ACTIVE_HIGH 1 40 41 #define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8 42 #define DA9052_GPIO_SHIFT_COUNT(no) (no%8) 43 #define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0 44 #define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F 45 #define DA9052_GPIO_NIBBLE_SHIFT 4 46 47 struct da9052_gpio { 48 struct da9052 *da9052; 49 struct gpio_chip gp; 50 }; 51 52 static inline struct da9052_gpio *to_da9052_gpio(struct gpio_chip *chip) 53 { 54 return container_of(chip, struct da9052_gpio, gp); 55 } 56 57 static unsigned char da9052_gpio_port_odd(unsigned offset) 58 { 59 return offset % 2; 60 } 61 62 static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset) 63 { 64 struct da9052_gpio *gpio = to_da9052_gpio(gc); 65 int da9052_port_direction = 0; 66 int ret; 67 68 ret = da9052_reg_read(gpio->da9052, 69 DA9052_GPIO_0_1_REG + (offset >> 1)); 70 if (ret < 0) 71 return ret; 72 73 if (da9052_gpio_port_odd(offset)) { 74 da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN; 75 da9052_port_direction >>= 4; 76 } else { 77 da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN; 78 } 79 80 switch (da9052_port_direction) { 81 case DA9052_INPUT: 82 if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER) 83 ret = da9052_reg_read(gpio->da9052, 84 DA9052_STATUS_C_REG); 85 else 86 ret = da9052_reg_read(gpio->da9052, 87 DA9052_STATUS_D_REG); 88 if (ret < 0) 89 return ret; 90 if (ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset))) 91 return 1; 92 else 93 return 0; 94 case DA9052_OUTPUT_PUSHPULL: 95 if (da9052_gpio_port_odd(offset)) 96 return ret & DA9052_GPIO_ODD_PORT_MODE; 97 else 98 return ret & DA9052_GPIO_EVEN_PORT_MODE; 99 default: 100 return -EINVAL; 101 } 102 } 103 104 static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 105 { 106 struct da9052_gpio *gpio = to_da9052_gpio(gc); 107 unsigned char register_value = 0; 108 int ret; 109 110 if (da9052_gpio_port_odd(offset)) { 111 if (value) { 112 register_value = DA9052_GPIO_ODD_PORT_MODE; 113 ret = da9052_reg_update(gpio->da9052, (offset >> 1) + 114 DA9052_GPIO_0_1_REG, 115 DA9052_GPIO_ODD_PORT_MODE, 116 register_value); 117 if (ret != 0) 118 dev_err(gpio->da9052->dev, 119 "Failed to updated gpio odd reg,%d", 120 ret); 121 } 122 } else { 123 if (value) { 124 register_value = DA9052_GPIO_EVEN_PORT_MODE; 125 ret = da9052_reg_update(gpio->da9052, (offset >> 1) + 126 DA9052_GPIO_0_1_REG, 127 DA9052_GPIO_EVEN_PORT_MODE, 128 register_value); 129 if (ret != 0) 130 dev_err(gpio->da9052->dev, 131 "Failed to updated gpio even reg,%d", 132 ret); 133 } 134 } 135 } 136 137 static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset) 138 { 139 struct da9052_gpio *gpio = to_da9052_gpio(gc); 140 unsigned char register_value; 141 int ret; 142 143 /* Format: function - 2 bits type - 1 bit mode - 1 bit */ 144 register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 | 145 DA9052_DEBOUNCING_ON << 3; 146 147 if (da9052_gpio_port_odd(offset)) 148 ret = da9052_reg_update(gpio->da9052, (offset >> 1) + 149 DA9052_GPIO_0_1_REG, 150 DA9052_GPIO_MASK_UPPER_NIBBLE, 151 (register_value << 152 DA9052_GPIO_NIBBLE_SHIFT)); 153 else 154 ret = da9052_reg_update(gpio->da9052, (offset >> 1) + 155 DA9052_GPIO_0_1_REG, 156 DA9052_GPIO_MASK_LOWER_NIBBLE, 157 register_value); 158 159 return ret; 160 } 161 162 static int da9052_gpio_direction_output(struct gpio_chip *gc, 163 unsigned offset, int value) 164 { 165 struct da9052_gpio *gpio = to_da9052_gpio(gc); 166 unsigned char register_value; 167 int ret; 168 169 /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */ 170 register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 | 171 value << 3; 172 173 if (da9052_gpio_port_odd(offset)) 174 ret = da9052_reg_update(gpio->da9052, (offset >> 1) + 175 DA9052_GPIO_0_1_REG, 176 DA9052_GPIO_MASK_UPPER_NIBBLE, 177 (register_value << 178 DA9052_GPIO_NIBBLE_SHIFT)); 179 else 180 ret = da9052_reg_update(gpio->da9052, (offset >> 1) + 181 DA9052_GPIO_0_1_REG, 182 DA9052_GPIO_MASK_LOWER_NIBBLE, 183 register_value); 184 185 return ret; 186 } 187 188 static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset) 189 { 190 struct da9052_gpio *gpio = to_da9052_gpio(gc); 191 struct da9052 *da9052 = gpio->da9052; 192 193 return da9052->irq_base + DA9052_IRQ_GPI0 + offset; 194 } 195 196 static struct gpio_chip reference_gp __devinitdata = { 197 .label = "da9052-gpio", 198 .owner = THIS_MODULE, 199 .get = da9052_gpio_get, 200 .set = da9052_gpio_set, 201 .direction_input = da9052_gpio_direction_input, 202 .direction_output = da9052_gpio_direction_output, 203 .to_irq = da9052_gpio_to_irq, 204 .can_sleep = 1; 205 .ngpio = 16; 206 .base = -1; 207 }; 208 209 static int __devinit da9052_gpio_probe(struct platform_device *pdev) 210 { 211 struct da9052_gpio *gpio; 212 struct da9052_pdata *pdata; 213 int ret; 214 215 gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); 216 if (gpio == NULL) 217 return -ENOMEM; 218 219 gpio->da9052 = dev_get_drvdata(pdev->dev.parent); 220 pdata = gpio->da9052->dev->platform_data; 221 222 gpio->gp = reference_gp; 223 if (pdata && pdata->gpio_base) 224 gpio->gp.base = pdata->gpio_base; 225 226 ret = gpiochip_add(&gpio->gp); 227 if (ret < 0) { 228 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 229 goto err_mem; 230 } 231 232 platform_set_drvdata(pdev, gpio); 233 234 return 0; 235 236 err_mem: 237 kfree(gpio); 238 return ret; 239 } 240 241 static int __devexit da9052_gpio_remove(struct platform_device *pdev) 242 { 243 struct da9052_gpio *gpio = platform_get_drvdata(pdev); 244 int ret; 245 246 ret = gpiochip_remove(&gpio->gp); 247 if (ret == 0) 248 kfree(gpio); 249 250 return ret; 251 } 252 253 static struct platform_driver da9052_gpio_driver = { 254 .probe = da9052_gpio_probe, 255 .remove = __devexit_p(da9052_gpio_remove), 256 .driver = { 257 .name = "da9052-gpio", 258 .owner = THIS_MODULE, 259 }, 260 }; 261 262 static int __init da9052_gpio_init(void) 263 { 264 return platform_driver_register(&da9052_gpio_driver); 265 } 266 module_init(da9052_gpio_init); 267 268 static void __exit da9052_gpio_exit(void) 269 { 270 return platform_driver_unregister(&da9052_gpio_driver); 271 } 272 module_exit(da9052_gpio_exit); 273 274 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); 275 MODULE_DESCRIPTION("DA9052 GPIO Device Driver"); 276 MODULE_LICENSE("GPL"); 277 MODULE_ALIAS("platform:da9052-gpio"); 278