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