Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.0-rc1 344 lines 9.3 kB view raw
1/* 2 * max3107.c - spi uart protocol driver for Maxim 3107 3 * Based on max3100.c 4 * by Christian Pellegrin <chripell@evolware.org> 5 * and max3110.c 6 * by Feng Tang <feng.tang@intel.com> 7 * 8 * Copyright (C) Aavamobile 2009 9 * 10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 * 26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 * 28 */ 29 30#include <linux/delay.h> 31#include <linux/device.h> 32#include <linux/serial_core.h> 33#include <linux/serial.h> 34#include <linux/spi/spi.h> 35#include <linux/freezer.h> 36#include <linux/platform_device.h> 37#include <linux/gpio.h> 38#include <linux/sfi.h> 39#include <asm/mrst.h> 40#include "max3107.h" 41 42/* GPIO direction to input function */ 43static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) 44{ 45 struct max3107_port *s = container_of(chip, struct max3107_port, chip); 46 u16 buf[1]; /* Buffer for SPI transfer */ 47 48 if (offset >= MAX3107_GPIO_COUNT) { 49 dev_err(&s->spi->dev, "Invalid GPIO\n"); 50 return -EINVAL; 51 } 52 53 /* Read current GPIO configuration register */ 54 buf[0] = MAX3107_GPIOCFG_REG; 55 /* Perform SPI transfer */ 56 if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { 57 dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); 58 return -EIO; 59 } 60 buf[0] &= MAX3107_SPI_RX_DATA_MASK; 61 62 /* Set GPIO to input */ 63 buf[0] &= ~(0x0001 << offset); 64 65 /* Write new GPIO configuration register value */ 66 buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); 67 /* Perform SPI transfer */ 68 if (max3107_rw(s, (u8 *)buf, NULL, 2)) { 69 dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); 70 return -EIO; 71 } 72 return 0; 73} 74 75/* GPIO direction to output function */ 76static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, 77 int value) 78{ 79 struct max3107_port *s = container_of(chip, struct max3107_port, chip); 80 u16 buf[2]; /* Buffer for SPI transfers */ 81 82 if (offset >= MAX3107_GPIO_COUNT) { 83 dev_err(&s->spi->dev, "Invalid GPIO\n"); 84 return -EINVAL; 85 } 86 87 /* Read current GPIO configuration and data registers */ 88 buf[0] = MAX3107_GPIOCFG_REG; 89 buf[1] = MAX3107_GPIODATA_REG; 90 /* Perform SPI transfer */ 91 if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { 92 dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); 93 return -EIO; 94 } 95 buf[0] &= MAX3107_SPI_RX_DATA_MASK; 96 buf[1] &= MAX3107_SPI_RX_DATA_MASK; 97 98 /* Set GPIO to output */ 99 buf[0] |= (0x0001 << offset); 100 /* Set value */ 101 if (value) 102 buf[1] |= (0x0001 << offset); 103 else 104 buf[1] &= ~(0x0001 << offset); 105 106 /* Write new GPIO configuration and data register values */ 107 buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); 108 buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); 109 /* Perform SPI transfer */ 110 if (max3107_rw(s, (u8 *)buf, NULL, 4)) { 111 dev_err(&s->spi->dev, 112 "SPI transfer for GPIO conf data w failed\n"); 113 return -EIO; 114 } 115 return 0; 116} 117 118/* GPIO value query function */ 119static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) 120{ 121 struct max3107_port *s = container_of(chip, struct max3107_port, chip); 122 u16 buf[1]; /* Buffer for SPI transfer */ 123 124 if (offset >= MAX3107_GPIO_COUNT) { 125 dev_err(&s->spi->dev, "Invalid GPIO\n"); 126 return -EINVAL; 127 } 128 129 /* Read current GPIO data register */ 130 buf[0] = MAX3107_GPIODATA_REG; 131 /* Perform SPI transfer */ 132 if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { 133 dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); 134 return -EIO; 135 } 136 buf[0] &= MAX3107_SPI_RX_DATA_MASK; 137 138 /* Return value */ 139 return buf[0] & (0x0001 << offset); 140} 141 142/* GPIO value set function */ 143static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 144{ 145 struct max3107_port *s = container_of(chip, struct max3107_port, chip); 146 u16 buf[2]; /* Buffer for SPI transfers */ 147 148 if (offset >= MAX3107_GPIO_COUNT) { 149 dev_err(&s->spi->dev, "Invalid GPIO\n"); 150 return; 151 } 152 153 /* Read current GPIO configuration registers*/ 154 buf[0] = MAX3107_GPIODATA_REG; 155 buf[1] = MAX3107_GPIOCFG_REG; 156 /* Perform SPI transfer */ 157 if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { 158 dev_err(&s->spi->dev, 159 "SPI transfer for GPIO data and config read failed\n"); 160 return; 161 } 162 buf[0] &= MAX3107_SPI_RX_DATA_MASK; 163 buf[1] &= MAX3107_SPI_RX_DATA_MASK; 164 165 if (!(buf[1] & (0x0001 << offset))) { 166 /* Configured as input, can't set value */ 167 dev_warn(&s->spi->dev, 168 "Trying to set value for input GPIO\n"); 169 return; 170 } 171 172 /* Set value */ 173 if (value) 174 buf[0] |= (0x0001 << offset); 175 else 176 buf[0] &= ~(0x0001 << offset); 177 178 /* Write new GPIO data register value */ 179 buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); 180 /* Perform SPI transfer */ 181 if (max3107_rw(s, (u8 *)buf, NULL, 2)) 182 dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); 183} 184 185/* GPIO chip data */ 186static struct gpio_chip max3107_gpio_chip = { 187 .owner = THIS_MODULE, 188 .direction_input = max3107_gpio_direction_in, 189 .direction_output = max3107_gpio_direction_out, 190 .get = max3107_gpio_get, 191 .set = max3107_gpio_set, 192 .can_sleep = 1, 193 .base = MAX3107_GPIO_BASE, 194 .ngpio = MAX3107_GPIO_COUNT, 195}; 196 197/** 198 * max3107_aava_reset - reset on AAVA systems 199 * @spi: The SPI device we are probing 200 * 201 * Reset the device ready for probing. 202 */ 203 204static int max3107_aava_reset(struct spi_device *spi) 205{ 206 /* Reset the chip */ 207 if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { 208 pr_err("Requesting RESET GPIO failed\n"); 209 return -EIO; 210 } 211 if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { 212 pr_err("Setting RESET GPIO to 0 failed\n"); 213 gpio_free(MAX3107_RESET_GPIO); 214 return -EIO; 215 } 216 msleep(MAX3107_RESET_DELAY); 217 if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { 218 pr_err("Setting RESET GPIO to 1 failed\n"); 219 gpio_free(MAX3107_RESET_GPIO); 220 return -EIO; 221 } 222 gpio_free(MAX3107_RESET_GPIO); 223 msleep(MAX3107_WAKEUP_DELAY); 224 return 0; 225} 226 227static int max3107_aava_configure(struct max3107_port *s) 228{ 229 int retval; 230 231 /* Initialize GPIO chip data */ 232 s->chip = max3107_gpio_chip; 233 s->chip.label = s->spi->modalias; 234 s->chip.dev = &s->spi->dev; 235 236 /* Add GPIO chip */ 237 retval = gpiochip_add(&s->chip); 238 if (retval) { 239 dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); 240 return retval; 241 } 242 243 /* Temporary fix for EV2 boot problems, set modem reset to 0 */ 244 max3107_gpio_direction_out(&s->chip, 3, 0); 245 return 0; 246} 247 248#if 0 249/* This will get enabled once we have the board stuff merged for this 250 specific case */ 251 252static const struct baud_table brg13_ext[] = { 253 { 300, MAX3107_BRG13_B300 }, 254 { 600, MAX3107_BRG13_B600 }, 255 { 1200, MAX3107_BRG13_B1200 }, 256 { 2400, MAX3107_BRG13_B2400 }, 257 { 4800, MAX3107_BRG13_B4800 }, 258 { 9600, MAX3107_BRG13_B9600 }, 259 { 19200, MAX3107_BRG13_B19200 }, 260 { 57600, MAX3107_BRG13_B57600 }, 261 { 115200, MAX3107_BRG13_B115200 }, 262 { 230400, MAX3107_BRG13_B230400 }, 263 { 460800, MAX3107_BRG13_B460800 }, 264 { 921600, MAX3107_BRG13_B921600 }, 265 { 0, 0 } 266}; 267 268static void max3107_aava_init(struct max3107_port *s) 269{ 270 /*override for AAVA SC specific*/ 271 if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { 272 if (get_koski_build_id() <= KOSKI_EV2) 273 if (s->ext_clk) { 274 s->brg_cfg = MAX3107_BRG13_B9600; 275 s->baud_tbl = (struct baud_table *)brg13_ext; 276 } 277 } 278} 279#endif 280 281static int __devexit max3107_aava_remove(struct spi_device *spi) 282{ 283 struct max3107_port *s = dev_get_drvdata(&spi->dev); 284 285 /* Remove GPIO chip */ 286 if (gpiochip_remove(&s->chip)) 287 dev_warn(&spi->dev, "Removing GPIO chip failed\n"); 288 289 /* Then do the default remove */ 290 return max3107_remove(spi); 291} 292 293/* Platform data */ 294static struct max3107_plat aava_plat_data = { 295 .loopback = 0, 296 .ext_clk = 1, 297/* .init = max3107_aava_init, */ 298 .configure = max3107_aava_configure, 299 .hw_suspend = max3107_hw_susp, 300 .polled_mode = 0, 301 .poll_time = 0, 302}; 303 304 305static int __devinit max3107_probe_aava(struct spi_device *spi) 306{ 307 int err = max3107_aava_reset(spi); 308 if (err < 0) 309 return err; 310 return max3107_probe(spi, &aava_plat_data); 311} 312 313/* Spi driver data */ 314static struct spi_driver max3107_driver = { 315 .driver = { 316 .name = "aava-max3107", 317 .bus = &spi_bus_type, 318 .owner = THIS_MODULE, 319 }, 320 .probe = max3107_probe_aava, 321 .remove = __devexit_p(max3107_aava_remove), 322 .suspend = max3107_suspend, 323 .resume = max3107_resume, 324}; 325 326/* Driver init function */ 327static int __init max3107_init(void) 328{ 329 return spi_register_driver(&max3107_driver); 330} 331 332/* Driver exit function */ 333static void __exit max3107_exit(void) 334{ 335 spi_unregister_driver(&max3107_driver); 336} 337 338module_init(max3107_init); 339module_exit(max3107_exit); 340 341MODULE_DESCRIPTION("MAX3107 driver"); 342MODULE_AUTHOR("Aavamobile"); 343MODULE_ALIAS("aava-max3107-spi"); 344MODULE_LICENSE("GPL v2");