1/* 2 * dm355evm_msp.c - driver for MSP430 firmware on DM355EVM board 3 * 4 * Copyright (C) 2008 David Brownell 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12#include <linux/init.h> 13#include <linux/mutex.h> 14#include <linux/platform_device.h> 15#include <linux/clk.h> 16#include <linux/module.h> 17#include <linux/err.h> 18#include <linux/gpio.h> 19#include <linux/leds.h> 20#include <linux/i2c.h> 21#include <linux/i2c/dm355evm_msp.h> 22 23 24/* 25 * The DM355 is a DaVinci chip with video support but no C64+ DSP. Its 26 * EVM board has an MSP430 programmed with firmware for various board 27 * support functions. This driver exposes some of them directly, and 28 * supports other drivers (e.g. RTC, input) for more complex access. 29 * 30 * Because this firmware is entirely board-specific, this file embeds 31 * knowledge that would be passed as platform_data in a generic driver. 32 * 33 * This driver was tested with firmware revision A4. 34 */ 35 36#if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE) 37#define msp_has_keyboard() true 38#else 39#define msp_has_keyboard() false 40#endif 41 42#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) 43#define msp_has_leds() true 44#else 45#define msp_has_leds() false 46#endif 47 48#if defined(CONFIG_RTC_DRV_DM355EVM) || defined(CONFIG_RTC_DRV_DM355EVM_MODULE) 49#define msp_has_rtc() true 50#else 51#define msp_has_rtc() false 52#endif 53 54#if defined(CONFIG_VIDEO_TVP514X) || defined(CONFIG_VIDEO_TVP514X_MODULE) 55#define msp_has_tvp() true 56#else 57#define msp_has_tvp() false 58#endif 59 60 61/*----------------------------------------------------------------------*/ 62 63/* REVISIT for paranoia's sake, retry reads/writes on error */ 64 65static struct i2c_client *msp430; 66 67/** 68 * dm355evm_msp_write - Writes a register in dm355evm_msp 69 * @value: the value to be written 70 * @reg: register address 71 * 72 * Returns result of operation - 0 is success, else negative errno 73 */ 74int dm355evm_msp_write(u8 value, u8 reg) 75{ 76 return i2c_smbus_write_byte_data(msp430, reg, value); 77} 78EXPORT_SYMBOL(dm355evm_msp_write); 79 80/** 81 * dm355evm_msp_read - Reads a register from dm355evm_msp 82 * @reg: register address 83 * 84 * Returns result of operation - value, or negative errno 85 */ 86int dm355evm_msp_read(u8 reg) 87{ 88 return i2c_smbus_read_byte_data(msp430, reg); 89} 90EXPORT_SYMBOL(dm355evm_msp_read); 91 92/*----------------------------------------------------------------------*/ 93 94/* 95 * Many of the msp430 pins are just used as fixed-direction GPIOs. 96 * We could export a few more of them this way, if we wanted. 97 */ 98#define MSP_GPIO(bit, reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit)) 99 100static const u8 msp_gpios[] = { 101 /* eight leds */ 102 MSP_GPIO(0, LED), MSP_GPIO(1, LED), 103 MSP_GPIO(2, LED), MSP_GPIO(3, LED), 104 MSP_GPIO(4, LED), MSP_GPIO(5, LED), 105 MSP_GPIO(6, LED), MSP_GPIO(7, LED), 106 /* SW6 and the NTSC/nPAL jumper */ 107 MSP_GPIO(0, SWITCH1), MSP_GPIO(1, SWITCH1), 108 MSP_GPIO(2, SWITCH1), MSP_GPIO(3, SWITCH1), 109 MSP_GPIO(4, SWITCH1), 110 /* switches on MMC/SD sockets */ 111 /* 112 * Note: EVMDM355_ECP_VA4.pdf suggests that Bit 2 and 4 should be 113 * checked for card detection. However on the EVM bit 1 and 3 gives 114 * this status, for 0 and 1 instance respectively. The pdf also 115 * suggests that Bit 1 and 3 should be checked for write protection. 116 * However on the EVM bit 2 and 4 gives this status,for 0 and 1 117 * instance respectively. 118 */ 119 MSP_GPIO(2, SDMMC), MSP_GPIO(1, SDMMC), /* mmc0 WP, nCD */ 120 MSP_GPIO(4, SDMMC), MSP_GPIO(3, SDMMC), /* mmc1 WP, nCD */ 121}; 122 123#define MSP_GPIO_REG(offset) (msp_gpios[(offset)] >> 3) 124#define MSP_GPIO_MASK(offset) BIT(msp_gpios[(offset)] & 0x07) 125 126static int msp_gpio_in(struct gpio_chip *chip, unsigned offset) 127{ 128 switch (MSP_GPIO_REG(offset)) { 129 case DM355EVM_MSP_SWITCH1: 130 case DM355EVM_MSP_SWITCH2: 131 case DM355EVM_MSP_SDMMC: 132 return 0; 133 default: 134 return -EINVAL; 135 } 136} 137 138static u8 msp_led_cache; 139 140static int msp_gpio_get(struct gpio_chip *chip, unsigned offset) 141{ 142 int reg, status; 143 144 reg = MSP_GPIO_REG(offset); 145 status = dm355evm_msp_read(reg); 146 if (status < 0) 147 return status; 148 if (reg == DM355EVM_MSP_LED) 149 msp_led_cache = status; 150 return status & MSP_GPIO_MASK(offset); 151} 152 153static int msp_gpio_out(struct gpio_chip *chip, unsigned offset, int value) 154{ 155 int mask, bits; 156 157 /* NOTE: there are some other signals that could be 158 * packaged as output GPIOs, but they aren't as useful 159 * as the LEDs ... so for now we don't. 160 */ 161 if (MSP_GPIO_REG(offset) != DM355EVM_MSP_LED) 162 return -EINVAL; 163 164 mask = MSP_GPIO_MASK(offset); 165 bits = msp_led_cache; 166 167 bits &= ~mask; 168 if (value) 169 bits |= mask; 170 msp_led_cache = bits; 171 172 return dm355evm_msp_write(bits, DM355EVM_MSP_LED); 173} 174 175static void msp_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 176{ 177 msp_gpio_out(chip, offset, value); 178} 179 180static struct gpio_chip dm355evm_msp_gpio = { 181 .label = "dm355evm_msp", 182 .owner = THIS_MODULE, 183 .direction_input = msp_gpio_in, 184 .get = msp_gpio_get, 185 .direction_output = msp_gpio_out, 186 .set = msp_gpio_set, 187 .base = -EINVAL, /* dynamic assignment */ 188 .ngpio = ARRAY_SIZE(msp_gpios), 189 .can_sleep = true, 190}; 191 192/*----------------------------------------------------------------------*/ 193 194static struct device *add_child(struct i2c_client *client, const char *name, 195 void *pdata, unsigned pdata_len, 196 bool can_wakeup, int irq) 197{ 198 struct platform_device *pdev; 199 int status; 200 201 pdev = platform_device_alloc(name, -1); 202 if (!pdev) { 203 dev_dbg(&client->dev, "can't alloc dev\n"); 204 status = -ENOMEM; 205 goto err; 206 } 207 208 device_init_wakeup(&pdev->dev, can_wakeup); 209 pdev->dev.parent = &client->dev; 210 211 if (pdata) { 212 status = platform_device_add_data(pdev, pdata, pdata_len); 213 if (status < 0) { 214 dev_dbg(&pdev->dev, "can't add platform_data\n"); 215 goto err; 216 } 217 } 218 219 if (irq) { 220 struct resource r = { 221 .start = irq, 222 .flags = IORESOURCE_IRQ, 223 }; 224 225 status = platform_device_add_resources(pdev, &r, 1); 226 if (status < 0) { 227 dev_dbg(&pdev->dev, "can't add irq\n"); 228 goto err; 229 } 230 } 231 232 status = platform_device_add(pdev); 233 234err: 235 if (status < 0) { 236 platform_device_put(pdev); 237 dev_err(&client->dev, "can't add %s dev\n", name); 238 return ERR_PTR(status); 239 } 240 return &pdev->dev; 241} 242 243static int add_children(struct i2c_client *client) 244{ 245 static const struct { 246 int offset; 247 char *label; 248 } config_inputs[] = { 249 /* 8 == right after the LEDs */ 250 { 8 + 0, "sw6_1", }, 251 { 8 + 1, "sw6_2", }, 252 { 8 + 2, "sw6_3", }, 253 { 8 + 3, "sw6_4", }, 254 { 8 + 4, "NTSC/nPAL", }, 255 }; 256 257 struct device *child; 258 int status; 259 int i; 260 261 /* GPIO-ish stuff */ 262 dm355evm_msp_gpio.dev = &client->dev; 263 status = gpiochip_add(&dm355evm_msp_gpio); 264 if (status < 0) 265 return status; 266 267 /* LED output */ 268 if (msp_has_leds()) { 269#define GPIO_LED(l) .name = l, .active_low = true 270 static struct gpio_led evm_leds[] = { 271 { GPIO_LED("dm355evm::ds14"), 272 .default_trigger = "heartbeat", }, 273 { GPIO_LED("dm355evm::ds15"), 274 .default_trigger = "mmc0", }, 275 { GPIO_LED("dm355evm::ds16"), 276 /* could also be a CE-ATA drive */ 277 .default_trigger = "mmc1", }, 278 { GPIO_LED("dm355evm::ds17"), 279 .default_trigger = "nand-disk", }, 280 { GPIO_LED("dm355evm::ds18"), }, 281 { GPIO_LED("dm355evm::ds19"), }, 282 { GPIO_LED("dm355evm::ds20"), }, 283 { GPIO_LED("dm355evm::ds21"), }, 284 }; 285#undef GPIO_LED 286 287 struct gpio_led_platform_data evm_led_data = { 288 .num_leds = ARRAY_SIZE(evm_leds), 289 .leds = evm_leds, 290 }; 291 292 for (i = 0; i < ARRAY_SIZE(evm_leds); i++) 293 evm_leds[i].gpio = i + dm355evm_msp_gpio.base; 294 295 /* NOTE: these are the only fully programmable LEDs 296 * on the board, since GPIO-61/ds22 (and many signals 297 * going to DC7) must be used for AEMIF address lines 298 * unless the top 1 GB of NAND is unused... 299 */ 300 child = add_child(client, "leds-gpio", 301 &evm_led_data, sizeof(evm_led_data), 302 false, 0); 303 if (IS_ERR(child)) 304 return PTR_ERR(child); 305 } 306 307 /* configuration inputs */ 308 for (i = 0; i < ARRAY_SIZE(config_inputs); i++) { 309 int gpio = dm355evm_msp_gpio.base + config_inputs[i].offset; 310 311 gpio_request_one(gpio, GPIOF_IN, config_inputs[i].label); 312 313 /* make it easy for userspace to see these */ 314 gpio_export(gpio, false); 315 } 316 317 /* MMC/SD inputs -- right after the last config input */ 318 if (dev_get_platdata(&client->dev)) { 319 void (*mmcsd_setup)(unsigned) = dev_get_platdata(&client->dev); 320 321 mmcsd_setup(dm355evm_msp_gpio.base + 8 + 5); 322 } 323 324 /* RTC is a 32 bit counter, no alarm */ 325 if (msp_has_rtc()) { 326 child = add_child(client, "rtc-dm355evm", 327 NULL, 0, false, 0); 328 if (IS_ERR(child)) 329 return PTR_ERR(child); 330 } 331 332 /* input from buttons and IR remote (uses the IRQ) */ 333 if (msp_has_keyboard()) { 334 child = add_child(client, "dm355evm_keys", 335 NULL, 0, true, client->irq); 336 if (IS_ERR(child)) 337 return PTR_ERR(child); 338 } 339 340 return 0; 341} 342 343/*----------------------------------------------------------------------*/ 344 345static void dm355evm_command(unsigned command) 346{ 347 int status; 348 349 status = dm355evm_msp_write(command, DM355EVM_MSP_COMMAND); 350 if (status < 0) 351 dev_err(&msp430->dev, "command %d failure %d\n", 352 command, status); 353} 354 355static void dm355evm_power_off(void) 356{ 357 dm355evm_command(MSP_COMMAND_POWEROFF); 358} 359 360static int dm355evm_msp_remove(struct i2c_client *client) 361{ 362 pm_power_off = NULL; 363 msp430 = NULL; 364 return 0; 365} 366 367static int 368dm355evm_msp_probe(struct i2c_client *client, const struct i2c_device_id *id) 369{ 370 int status; 371 const char *video = msp_has_tvp() ? "TVP5146" : "imager"; 372 373 if (msp430) 374 return -EBUSY; 375 msp430 = client; 376 377 /* display revision status; doubles as sanity check */ 378 status = dm355evm_msp_read(DM355EVM_MSP_FIRMREV); 379 if (status < 0) 380 goto fail; 381 dev_info(&client->dev, "firmware v.%02X, %s as video-in\n", 382 status, video); 383 384 /* mux video input: either tvp5146 or some external imager */ 385 status = dm355evm_msp_write(msp_has_tvp() ? 0 : MSP_VIDEO_IMAGER, 386 DM355EVM_MSP_VIDEO_IN); 387 if (status < 0) 388 dev_warn(&client->dev, "error %d muxing %s as video-in\n", 389 status, video); 390 391 /* init LED cache, and turn off the LEDs */ 392 msp_led_cache = 0xff; 393 dm355evm_msp_write(msp_led_cache, DM355EVM_MSP_LED); 394 395 /* export capabilities we support */ 396 status = add_children(client); 397 if (status < 0) 398 goto fail; 399 400 /* PM hookup */ 401 pm_power_off = dm355evm_power_off; 402 403 return 0; 404 405fail: 406 /* FIXME remove children ... */ 407 dm355evm_msp_remove(client); 408 return status; 409} 410 411static const struct i2c_device_id dm355evm_msp_ids[] = { 412 { "dm355evm_msp", 0 }, 413 { /* end of list */ }, 414}; 415MODULE_DEVICE_TABLE(i2c, dm355evm_msp_ids); 416 417static struct i2c_driver dm355evm_msp_driver = { 418 .driver.name = "dm355evm_msp", 419 .id_table = dm355evm_msp_ids, 420 .probe = dm355evm_msp_probe, 421 .remove = dm355evm_msp_remove, 422}; 423 424static int __init dm355evm_msp_init(void) 425{ 426 return i2c_add_driver(&dm355evm_msp_driver); 427} 428subsys_initcall(dm355evm_msp_init); 429 430static void __exit dm355evm_msp_exit(void) 431{ 432 i2c_del_driver(&dm355evm_msp_driver); 433} 434module_exit(dm355evm_msp_exit); 435 436MODULE_DESCRIPTION("Interface to MSP430 firmware on DM355EVM"); 437MODULE_LICENSE("GPL"); 438