linux/arch/arm/mach-davinci/board-dm355-evm.c
<<
>>
Prefs
   1/*
   2 * TI DaVinci EVM board support
   3 *
   4 * Author: Kevin Hilman, Deep Root Systems, LLC
   5 *
   6 * 2007 (c) MontaVista Software, Inc. This file is licensed under
   7 * the terms of the GNU General Public License version 2. This program
   8 * is licensed "as is" without any warranty of any kind, whether express
   9 * or implied.
  10 */
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <linux/err.h>
  14#include <linux/platform_device.h>
  15#include <linux/mtd/mtd.h>
  16#include <linux/mtd/partitions.h>
  17#include <linux/mtd/rawnand.h>
  18#include <linux/i2c.h>
  19#include <linux/gpio.h>
  20#include <linux/gpio/machine.h>
  21#include <linux/clk.h>
  22#include <linux/dm9000.h>
  23#include <linux/videodev2.h>
  24#include <media/i2c/tvp514x.h>
  25#include <linux/spi/spi.h>
  26#include <linux/spi/eeprom.h>
  27#include <linux/platform_data/gpio-davinci.h>
  28#include <linux/platform_data/i2c-davinci.h>
  29#include <linux/platform_data/mtd-davinci.h>
  30#include <linux/platform_data/mmc-davinci.h>
  31#include <linux/platform_data/usb-davinci.h>
  32
  33#include <asm/mach-types.h>
  34#include <asm/mach/arch.h>
  35
  36#include <mach/serial.h>
  37#include <mach/common.h>
  38
  39#include "davinci.h"
  40
  41/* NOTE:  this is geared for the standard config, with a socketed
  42 * 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors.  If you
  43 * swap chips, maybe with a different block size, partitioning may
  44 * need to be changed.
  45 */
  46#define NAND_BLOCK_SIZE         SZ_128K
  47
  48static struct mtd_partition davinci_nand_partitions[] = {
  49        {
  50                /* UBL (a few copies) plus U-Boot */
  51                .name           = "bootloader",
  52                .offset         = 0,
  53                .size           = 15 * NAND_BLOCK_SIZE,
  54                .mask_flags     = MTD_WRITEABLE, /* force read-only */
  55        }, {
  56                /* U-Boot environment */
  57                .name           = "params",
  58                .offset         = MTDPART_OFS_APPEND,
  59                .size           = 1 * NAND_BLOCK_SIZE,
  60                .mask_flags     = 0,
  61        }, {
  62                .name           = "kernel",
  63                .offset         = MTDPART_OFS_APPEND,
  64                .size           = SZ_4M,
  65                .mask_flags     = 0,
  66        }, {
  67                .name           = "filesystem1",
  68                .offset         = MTDPART_OFS_APPEND,
  69                .size           = SZ_512M,
  70                .mask_flags     = 0,
  71        }, {
  72                .name           = "filesystem2",
  73                .offset         = MTDPART_OFS_APPEND,
  74                .size           = MTDPART_SIZ_FULL,
  75                .mask_flags     = 0,
  76        }
  77        /* two blocks with bad block table (and mirror) at the end */
  78};
  79
  80static struct davinci_nand_pdata davinci_nand_data = {
  81        .core_chipsel           = 0,
  82        .mask_chipsel           = BIT(14),
  83        .parts                  = davinci_nand_partitions,
  84        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
  85        .engine_type            = NAND_ECC_ENGINE_TYPE_ON_HOST,
  86        .bbt_options            = NAND_BBT_USE_FLASH,
  87        .ecc_bits               = 4,
  88};
  89
  90static struct resource davinci_nand_resources[] = {
  91        {
  92                .start          = DM355_ASYNC_EMIF_DATA_CE0_BASE,
  93                .end            = DM355_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1,
  94                .flags          = IORESOURCE_MEM,
  95        }, {
  96                .start          = DM355_ASYNC_EMIF_CONTROL_BASE,
  97                .end            = DM355_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
  98                .flags          = IORESOURCE_MEM,
  99        },
 100};
 101
 102static struct platform_device davinci_nand_device = {
 103        .name                   = "davinci_nand",
 104        .id                     = 0,
 105
 106        .num_resources          = ARRAY_SIZE(davinci_nand_resources),
 107        .resource               = davinci_nand_resources,
 108
 109        .dev                    = {
 110                .platform_data  = &davinci_nand_data,
 111        },
 112};
 113
 114#define DM355_I2C_SDA_PIN       GPIO_TO_PIN(0, 15)
 115#define DM355_I2C_SCL_PIN       GPIO_TO_PIN(0, 14)
 116
 117static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
 118        .dev_id = "i2c_davinci.1",
 119        .table = {
 120                GPIO_LOOKUP("davinci_gpio", DM355_I2C_SDA_PIN, "sda",
 121                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
 122                GPIO_LOOKUP("davinci_gpio", DM355_I2C_SCL_PIN, "scl",
 123                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
 124                { }
 125        },
 126};
 127
 128static struct davinci_i2c_platform_data i2c_pdata = {
 129        .bus_freq       = 400   /* kHz */,
 130        .bus_delay      = 0     /* usec */,
 131        .gpio_recovery  = true,
 132};
 133
 134static int dm355evm_mmc_gpios = -EINVAL;
 135
 136static void dm355evm_mmcsd_gpios(unsigned gpio)
 137{
 138        gpio_request(gpio + 0, "mmc0_ro");
 139        gpio_request(gpio + 1, "mmc0_cd");
 140        gpio_request(gpio + 2, "mmc1_ro");
 141        gpio_request(gpio + 3, "mmc1_cd");
 142
 143        /* we "know" these are input-only so we don't
 144         * need to call gpio_direction_input()
 145         */
 146
 147        dm355evm_mmc_gpios = gpio;
 148}
 149
 150static struct i2c_board_info dm355evm_i2c_info[] = {
 151        {       I2C_BOARD_INFO("dm355evm_msp", 0x25),
 152                .platform_data = dm355evm_mmcsd_gpios,
 153        },
 154        /* { plus irq  }, */
 155        { I2C_BOARD_INFO("tlv320aic33", 0x1b), },
 156};
 157
 158static void __init evm_init_i2c(void)
 159{
 160        gpiod_add_lookup_table(&i2c_recovery_gpiod_table);
 161        davinci_init_i2c(&i2c_pdata);
 162
 163        gpio_request(5, "dm355evm_msp");
 164        gpio_direction_input(5);
 165        dm355evm_i2c_info[0].irq = gpio_to_irq(5);
 166
 167        i2c_register_board_info(1, dm355evm_i2c_info,
 168                        ARRAY_SIZE(dm355evm_i2c_info));
 169}
 170
 171static struct resource dm355evm_dm9000_rsrc[] = {
 172        {
 173                /* addr */
 174                .start  = 0x04014000,
 175                .end    = 0x04014001,
 176                .flags  = IORESOURCE_MEM,
 177        }, {
 178                /* data */
 179                .start  = 0x04014002,
 180                .end    = 0x04014003,
 181                .flags  = IORESOURCE_MEM,
 182        }, {
 183                .flags  = IORESOURCE_IRQ
 184                        | IORESOURCE_IRQ_HIGHEDGE /* rising (active high) */,
 185        },
 186};
 187
 188static struct dm9000_plat_data dm335evm_dm9000_platdata;
 189
 190static struct platform_device dm355evm_dm9000 = {
 191        .name           = "dm9000",
 192        .id             = -1,
 193        .resource       = dm355evm_dm9000_rsrc,
 194        .num_resources  = ARRAY_SIZE(dm355evm_dm9000_rsrc),
 195        .dev            = {
 196                .platform_data = &dm335evm_dm9000_platdata,
 197        },
 198};
 199
 200static struct tvp514x_platform_data tvp5146_pdata = {
 201        .clk_polarity = 0,
 202        .hs_polarity = 1,
 203        .vs_polarity = 1
 204};
 205
 206#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
 207/* Inputs available at the TVP5146 */
 208static struct v4l2_input tvp5146_inputs[] = {
 209        {
 210                .index = 0,
 211                .name = "Composite",
 212                .type = V4L2_INPUT_TYPE_CAMERA,
 213                .std = TVP514X_STD_ALL,
 214        },
 215        {
 216                .index = 1,
 217                .name = "S-Video",
 218                .type = V4L2_INPUT_TYPE_CAMERA,
 219                .std = TVP514X_STD_ALL,
 220        },
 221};
 222
 223/*
 224 * this is the route info for connecting each input to decoder
 225 * ouput that goes to vpfe. There is a one to one correspondence
 226 * with tvp5146_inputs
 227 */
 228static struct vpfe_route tvp5146_routes[] = {
 229        {
 230                .input = INPUT_CVBS_VI2B,
 231                .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
 232        },
 233        {
 234                .input = INPUT_SVIDEO_VI2C_VI1C,
 235                .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
 236        },
 237};
 238
 239static struct vpfe_subdev_info vpfe_sub_devs[] = {
 240        {
 241                .name = "tvp5146",
 242                .grp_id = 0,
 243                .num_inputs = ARRAY_SIZE(tvp5146_inputs),
 244                .inputs = tvp5146_inputs,
 245                .routes = tvp5146_routes,
 246                .can_route = 1,
 247                .ccdc_if_params = {
 248                        .if_type = VPFE_BT656,
 249                        .hdpol = VPFE_PINPOL_POSITIVE,
 250                        .vdpol = VPFE_PINPOL_POSITIVE,
 251                },
 252                .board_info = {
 253                        I2C_BOARD_INFO("tvp5146", 0x5d),
 254                        .platform_data = &tvp5146_pdata,
 255                },
 256        }
 257};
 258
 259static struct vpfe_config vpfe_cfg = {
 260        .num_subdevs = ARRAY_SIZE(vpfe_sub_devs),
 261        .i2c_adapter_id = 1,
 262        .sub_devs = vpfe_sub_devs,
 263        .card_name = "DM355 EVM",
 264        .ccdc = "DM355 CCDC",
 265};
 266
 267/* venc standards timings */
 268static struct vpbe_enc_mode_info dm355evm_enc_preset_timing[] = {
 269        {
 270                .name           = "ntsc",
 271                .timings_type   = VPBE_ENC_STD,
 272                .std_id         = V4L2_STD_NTSC,
 273                .interlaced     = 1,
 274                .xres           = 720,
 275                .yres           = 480,
 276                .aspect         = {11, 10},
 277                .fps            = {30000, 1001},
 278                .left_margin    = 0x79,
 279                .upper_margin   = 0x10,
 280        },
 281        {
 282                .name           = "pal",
 283                .timings_type   = VPBE_ENC_STD,
 284                .std_id         = V4L2_STD_PAL,
 285                .interlaced     = 1,
 286                .xres           = 720,
 287                .yres           = 576,
 288                .aspect         = {54, 59},
 289                .fps            = {25, 1},
 290                .left_margin    = 0x7E,
 291                .upper_margin   = 0x16
 292        },
 293};
 294
 295#define VENC_STD_ALL    (V4L2_STD_NTSC | V4L2_STD_PAL)
 296
 297/*
 298 * The outputs available from VPBE + ecnoders. Keep the
 299 * the order same as that of encoders. First those from venc followed by that
 300 * from encoders. Index in the output refers to index on a particular encoder.
 301 * Driver uses this index to pass it to encoder when it supports more than
 302 * one output. Application uses index of the array to set an output.
 303 */
 304static struct vpbe_output dm355evm_vpbe_outputs[] = {
 305        {
 306                .output         = {
 307                        .index          = 0,
 308                        .name           = "Composite",
 309                        .type           = V4L2_OUTPUT_TYPE_ANALOG,
 310                        .std            = VENC_STD_ALL,
 311                        .capabilities   = V4L2_OUT_CAP_STD,
 312                },
 313                .subdev_name    = DM355_VPBE_VENC_SUBDEV_NAME,
 314                .default_mode   = "ntsc",
 315                .num_modes      = ARRAY_SIZE(dm355evm_enc_preset_timing),
 316                .modes          = dm355evm_enc_preset_timing,
 317                .if_params      = MEDIA_BUS_FMT_FIXED,
 318        },
 319};
 320
 321static struct vpbe_config dm355evm_display_cfg = {
 322        .module_name    = "dm355-vpbe-display",
 323        .i2c_adapter_id = 1,
 324        .osd            = {
 325                .module_name    = DM355_VPBE_OSD_SUBDEV_NAME,
 326        },
 327        .venc           = {
 328                .module_name    = DM355_VPBE_VENC_SUBDEV_NAME,
 329        },
 330        .num_outputs    = ARRAY_SIZE(dm355evm_vpbe_outputs),
 331        .outputs        = dm355evm_vpbe_outputs,
 332};
 333
 334static struct platform_device *davinci_evm_devices[] __initdata = {
 335        &dm355evm_dm9000,
 336        &davinci_nand_device,
 337};
 338
 339static void __init dm355_evm_map_io(void)
 340{
 341        dm355_init();
 342}
 343
 344static int dm355evm_mmc_get_cd(int module)
 345{
 346        if (!gpio_is_valid(dm355evm_mmc_gpios))
 347                return -ENXIO;
 348        /* low == card present */
 349        return !gpio_get_value_cansleep(dm355evm_mmc_gpios + 2 * module + 1);
 350}
 351
 352static int dm355evm_mmc_get_ro(int module)
 353{
 354        if (!gpio_is_valid(dm355evm_mmc_gpios))
 355                return -ENXIO;
 356        /* high == card's write protect switch active */
 357        return gpio_get_value_cansleep(dm355evm_mmc_gpios + 2 * module + 0);
 358}
 359
 360static struct davinci_mmc_config dm355evm_mmc_config = {
 361        .get_cd         = dm355evm_mmc_get_cd,
 362        .get_ro         = dm355evm_mmc_get_ro,
 363        .wires          = 4,
 364        .max_freq       = 50000000,
 365        .caps           = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
 366};
 367
 368/* Don't connect anything to J10 unless you're only using USB host
 369 * mode *and* have to do so with some kind of gender-bender.  If
 370 * you have proper Mini-B or Mini-A cables (or Mini-A adapters)
 371 * the ID pin won't need any help.
 372 */
 373#define USB_ID_VALUE    1       /* ID pulled low */
 374
 375static struct spi_eeprom at25640a = {
 376        .byte_len       = SZ_64K / 8,
 377        .name           = "at25640a",
 378        .page_size      = 32,
 379        .flags          = EE_ADDR2,
 380};
 381
 382static const struct spi_board_info dm355_evm_spi_info[] __initconst = {
 383        {
 384                .modalias       = "at25",
 385                .platform_data  = &at25640a,
 386                .max_speed_hz   = 10 * 1000 * 1000,     /* at 3v3 */
 387                .bus_num        = 0,
 388                .chip_select    = 0,
 389                .mode           = SPI_MODE_0,
 390        },
 391};
 392
 393static __init void dm355_evm_init(void)
 394{
 395        struct clk *aemif;
 396        int ret;
 397
 398        dm355_register_clocks();
 399
 400        ret = dm355_gpio_register();
 401        if (ret)
 402                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
 403
 404        gpio_request(1, "dm9000");
 405        gpio_direction_input(1);
 406        dm355evm_dm9000_rsrc[2].start = gpio_to_irq(1);
 407
 408        aemif = clk_get(&dm355evm_dm9000.dev, "aemif");
 409        if (!WARN(IS_ERR(aemif), "unable to get AEMIF clock\n"))
 410                clk_prepare_enable(aemif);
 411
 412        platform_add_devices(davinci_evm_devices,
 413                             ARRAY_SIZE(davinci_evm_devices));
 414        evm_init_i2c();
 415        davinci_serial_init(dm355_serial_device);
 416
 417        /* NOTE:  NAND flash timings set by the UBL are slower than
 418         * needed by MT29F16G08FAA chips ... EMIF.A1CR is 0x40400204
 419         * but could be 0x0400008c for about 25% faster page reads.
 420         */
 421
 422        gpio_request(2, "usb_id_toggle");
 423        gpio_direction_output(2, USB_ID_VALUE);
 424        /* irlml6401 switches over 1A in under 8 msec */
 425        davinci_setup_usb(1000, 8);
 426
 427        davinci_setup_mmc(0, &dm355evm_mmc_config);
 428        davinci_setup_mmc(1, &dm355evm_mmc_config);
 429
 430        dm355_init_video(&vpfe_cfg, &dm355evm_display_cfg);
 431
 432        dm355_init_spi0(BIT(0), dm355_evm_spi_info,
 433                        ARRAY_SIZE(dm355_evm_spi_info));
 434
 435        /* DM335 EVM uses ASP1; line-out is a stereo mini-jack */
 436        dm355_init_asp1(ASP1_TX_EVT_EN | ASP1_RX_EVT_EN);
 437}
 438
 439MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
 440        .atag_offset  = 0x100,
 441        .map_io       = dm355_evm_map_io,
 442        .init_irq     = dm355_init_irq,
 443        .init_time      = dm355_init_time,
 444        .init_machine = dm355_evm_init,
 445        .init_late      = davinci_init_late,
 446        .dma_zone_size  = SZ_128M,
 447MACHINE_END
 448
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.