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