root/drivers/mfd/dm355evm_msp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dm355evm_msp_write
  2. dm355evm_msp_read
  3. msp_gpio_in
  4. msp_gpio_get
  5. msp_gpio_out
  6. msp_gpio_set
  7. add_child
  8. add_children
  9. dm355evm_command
  10. dm355evm_power_off
  11. dm355evm_msp_remove
  12. dm355evm_msp_probe
  13. dm355evm_msp_init
  14. dm355evm_msp_exit

   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 
  61 static 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  */
  70 int dm355evm_msp_write(u8 value, u8 reg)
  71 {
  72         return i2c_smbus_write_byte_data(msp430, reg, value);
  73 }
  74 EXPORT_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  */
  82 int dm355evm_msp_read(u8 reg)
  83 {
  84         return i2c_smbus_read_byte_data(msp430, reg);
  85 }
  86 EXPORT_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 
  96 static 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 
 122 static 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 
 134 static u8 msp_led_cache;
 135 
 136 static 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 
 149 static 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 
 171 static void msp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 172 {
 173         msp_gpio_out(chip, offset, value);
 174 }
 175 
 176 static 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 
 190 static 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 
 231 put_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 
 237 static 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 
 339 static 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 
 349 static void dm355evm_power_off(void)
 350 {
 351         dm355evm_command(MSP_COMMAND_POWEROFF);
 352 }
 353 
 354 static int dm355evm_msp_remove(struct i2c_client *client)
 355 {
 356         pm_power_off = NULL;
 357         msp430 = NULL;
 358         return 0;
 359 }
 360 
 361 static int
 362 dm355evm_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 
 399 fail:
 400         /* FIXME remove children ... */
 401         dm355evm_msp_remove(client);
 402         return status;
 403 }
 404 
 405 static const struct i2c_device_id dm355evm_msp_ids[] = {
 406         { "dm355evm_msp", 0 },
 407         { /* end of list */ },
 408 };
 409 MODULE_DEVICE_TABLE(i2c, dm355evm_msp_ids);
 410 
 411 static 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 
 418 static int __init dm355evm_msp_init(void)
 419 {
 420         return i2c_add_driver(&dm355evm_msp_driver);
 421 }
 422 subsys_initcall(dm355evm_msp_init);
 423 
 424 static void __exit dm355evm_msp_exit(void)
 425 {
 426         i2c_del_driver(&dm355evm_msp_driver);
 427 }
 428 module_exit(dm355evm_msp_exit);
 429 
 430 MODULE_DESCRIPTION("Interface to MSP430 firmware on DM355EVM");
 431 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */