~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-davinci/board-dm365-evm.c

Version: ~ [ linux-6.6-rc1 ] ~ [ linux-6.5.2 ] ~ [ linux-6.4.15 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.52 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.131 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.194 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.256 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.294 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.325 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * TI DaVinci DM365 EVM board support
  3  *
  4  * Copyright (C) 2009 Texas Instruments Incorporated
  5  *
  6  * This program is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU General Public License as
  8  * published by the Free Software Foundation version 2.
  9  *
 10  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 11  * kind, whether express or implied; without even the implied warranty
 12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  * GNU General Public License for more details.
 14  */
 15 #include <linux/kernel.h>
 16 #include <linux/module.h>
 17 #include <linux/init.h>
 18 #include <linux/dma-mapping.h>
 19 #include <linux/i2c.h>
 20 #include <linux/io.h>
 21 #include <linux/clk.h>
 22 #include <linux/i2c/at24.h>
 23 #include <linux/leds.h>
 24 #include <linux/mtd/mtd.h>
 25 #include <linux/mtd/partitions.h>
 26 #include <linux/mtd/nand.h>
 27 #include <asm/setup.h>
 28 #include <asm/mach-types.h>
 29 #include <asm/mach/arch.h>
 30 #include <asm/mach/map.h>
 31 #include <mach/mux.h>
 32 #include <mach/hardware.h>
 33 #include <mach/dm365.h>
 34 #include <mach/psc.h>
 35 #include <mach/common.h>
 36 #include <mach/i2c.h>
 37 #include <mach/serial.h>
 38 #include <mach/mmc.h>
 39 #include <mach/nand.h>
 40 
 41 
 42 static inline int have_imager(void)
 43 {
 44         /* REVISIT when it's supported, trigger via Kconfig */
 45         return 0;
 46 }
 47 
 48 static inline int have_tvp7002(void)
 49 {
 50         /* REVISIT when it's supported, trigger via Kconfig */
 51         return 0;
 52 }
 53 
 54 
 55 #define DM365_ASYNC_EMIF_CONTROL_BASE   0x01d10000
 56 #define DM365_ASYNC_EMIF_DATA_CE0_BASE  0x02000000
 57 #define DM365_ASYNC_EMIF_DATA_CE1_BASE  0x04000000
 58 
 59 #define DM365_EVM_PHY_MASK              (0x2)
 60 #define DM365_EVM_MDIO_FREQUENCY        (2200000) /* PHY bus frequency */
 61 
 62 /*
 63  * A MAX-II CPLD is used for various board control functions.
 64  */
 65 #define CPLD_OFFSET(a13a8,a2a1)         (((a13a8) << 10) + ((a2a1) << 3))
 66 
 67 #define CPLD_VERSION    CPLD_OFFSET(0,0)        /* r/o */
 68 #define CPLD_TEST       CPLD_OFFSET(0,1)
 69 #define CPLD_LEDS       CPLD_OFFSET(0,2)
 70 #define CPLD_MUX        CPLD_OFFSET(0,3)
 71 #define CPLD_SWITCH     CPLD_OFFSET(1,0)        /* r/o */
 72 #define CPLD_POWER      CPLD_OFFSET(1,1)
 73 #define CPLD_VIDEO      CPLD_OFFSET(1,2)
 74 #define CPLD_CARDSTAT   CPLD_OFFSET(1,3)        /* r/o */
 75 
 76 #define CPLD_DILC_OUT   CPLD_OFFSET(2,0)
 77 #define CPLD_DILC_IN    CPLD_OFFSET(2,1)        /* r/o */
 78 
 79 #define CPLD_IMG_DIR0   CPLD_OFFSET(2,2)
 80 #define CPLD_IMG_MUX0   CPLD_OFFSET(2,3)
 81 #define CPLD_IMG_MUX1   CPLD_OFFSET(3,0)
 82 #define CPLD_IMG_DIR1   CPLD_OFFSET(3,1)
 83 #define CPLD_IMG_MUX2   CPLD_OFFSET(3,2)
 84 #define CPLD_IMG_MUX3   CPLD_OFFSET(3,3)
 85 #define CPLD_IMG_DIR2   CPLD_OFFSET(4,0)
 86 #define CPLD_IMG_MUX4   CPLD_OFFSET(4,1)
 87 #define CPLD_IMG_MUX5   CPLD_OFFSET(4,2)
 88 
 89 #define CPLD_RESETS     CPLD_OFFSET(4,3)
 90 
 91 #define CPLD_CCD_DIR1   CPLD_OFFSET(0x3e,0)
 92 #define CPLD_CCD_IO1    CPLD_OFFSET(0x3e,1)
 93 #define CPLD_CCD_DIR2   CPLD_OFFSET(0x3e,2)
 94 #define CPLD_CCD_IO2    CPLD_OFFSET(0x3e,3)
 95 #define CPLD_CCD_DIR3   CPLD_OFFSET(0x3f,0)
 96 #define CPLD_CCD_IO3    CPLD_OFFSET(0x3f,1)
 97 
 98 static void __iomem *cpld;
 99 
100 
101 /* NOTE:  this is geared for the standard config, with a socketed
102  * 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors.  If you
103  * swap chips with a different block size, partitioning will
104  * need to be changed. This NAND chip MT29F16G08FAA is the default
105  * NAND shipped with the Spectrum Digital DM365 EVM
106  */
107 #define NAND_BLOCK_SIZE         SZ_128K
108 
109 static struct mtd_partition davinci_nand_partitions[] = {
110         {
111                 /* UBL (a few copies) plus U-Boot */
112                 .name           = "bootloader",
113                 .offset         = 0,
114                 .size           = 28 * NAND_BLOCK_SIZE,
115                 .mask_flags     = MTD_WRITEABLE, /* force read-only */
116         }, {
117                 /* U-Boot environment */
118                 .name           = "params",
119                 .offset         = MTDPART_OFS_APPEND,
120                 .size           = 2 * NAND_BLOCK_SIZE,
121                 .mask_flags     = 0,
122         }, {
123                 .name           = "kernel",
124                 .offset         = MTDPART_OFS_APPEND,
125                 .size           = SZ_4M,
126                 .mask_flags     = 0,
127         }, {
128                 .name           = "filesystem1",
129                 .offset         = MTDPART_OFS_APPEND,
130                 .size           = SZ_512M,
131                 .mask_flags     = 0,
132         }, {
133                 .name           = "filesystem2",
134                 .offset         = MTDPART_OFS_APPEND,
135                 .size           = MTDPART_SIZ_FULL,
136                 .mask_flags     = 0,
137         }
138         /* two blocks with bad block table (and mirror) at the end */
139 };
140 
141 static struct davinci_nand_pdata davinci_nand_data = {
142         .mask_chipsel           = BIT(14),
143         .parts                  = davinci_nand_partitions,
144         .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
145         .ecc_mode               = NAND_ECC_HW,
146         .options                = NAND_USE_FLASH_BBT,
147 };
148 
149 static struct resource davinci_nand_resources[] = {
150         {
151                 .start          = DM365_ASYNC_EMIF_DATA_CE0_BASE,
152                 .end            = DM365_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1,
153                 .flags          = IORESOURCE_MEM,
154         }, {
155                 .start          = DM365_ASYNC_EMIF_CONTROL_BASE,
156                 .end            = DM365_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
157                 .flags          = IORESOURCE_MEM,
158         },
159 };
160 
161 static struct platform_device davinci_nand_device = {
162         .name                   = "davinci_nand",
163         .id                     = 0,
164         .num_resources          = ARRAY_SIZE(davinci_nand_resources),
165         .resource               = davinci_nand_resources,
166         .dev                    = {
167                 .platform_data  = &davinci_nand_data,
168         },
169 };
170 
171 static struct at24_platform_data eeprom_info = {
172         .byte_len       = (256*1024) / 8,
173         .page_size      = 64,
174         .flags          = AT24_FLAG_ADDR16,
175         .setup          = davinci_get_mac_addr,
176         .context        = (void *)0x7f00,
177 };
178 
179 static struct i2c_board_info i2c_info[] = {
180         {
181                 I2C_BOARD_INFO("24c256", 0x50),
182                 .platform_data  = &eeprom_info,
183         },
184 };
185 
186 static struct davinci_i2c_platform_data i2c_pdata = {
187         .bus_freq       = 400   /* kHz */,
188         .bus_delay      = 0     /* usec */,
189 };
190 
191 static int cpld_mmc_get_cd(int module)
192 {
193         if (!cpld)
194                 return -ENXIO;
195 
196         /* low == card present */
197         return !(__raw_readb(cpld + CPLD_CARDSTAT) & BIT(module ? 4 : 0));
198 }
199 
200 static int cpld_mmc_get_ro(int module)
201 {
202         if (!cpld)
203                 return -ENXIO;
204 
205         /* high == card's write protect switch active */
206         return !!(__raw_readb(cpld + CPLD_CARDSTAT) & BIT(module ? 5 : 1));
207 }
208 
209 static struct davinci_mmc_config dm365evm_mmc_config = {
210         .get_cd         = cpld_mmc_get_cd,
211         .get_ro         = cpld_mmc_get_ro,
212         .wires          = 4,
213         .max_freq       = 50000000,
214         .caps           = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
215         .version        = MMC_CTLR_VERSION_2,
216 };
217 
218 static void dm365evm_emac_configure(void)
219 {
220         /*
221          * EMAC pins are multiplexed with GPIO and UART
222          * Further details are available at the DM365 ARM
223          * Subsystem Users Guide(sprufg5.pdf) pages 125 - 127
224          */
225         davinci_cfg_reg(DM365_EMAC_TX_EN);
226         davinci_cfg_reg(DM365_EMAC_TX_CLK);
227         davinci_cfg_reg(DM365_EMAC_COL);
228         davinci_cfg_reg(DM365_EMAC_TXD3);
229         davinci_cfg_reg(DM365_EMAC_TXD2);
230         davinci_cfg_reg(DM365_EMAC_TXD1);
231         davinci_cfg_reg(DM365_EMAC_TXD0);
232         davinci_cfg_reg(DM365_EMAC_RXD3);
233         davinci_cfg_reg(DM365_EMAC_RXD2);
234         davinci_cfg_reg(DM365_EMAC_RXD1);
235         davinci_cfg_reg(DM365_EMAC_RXD0);
236         davinci_cfg_reg(DM365_EMAC_RX_CLK);
237         davinci_cfg_reg(DM365_EMAC_RX_DV);
238         davinci_cfg_reg(DM365_EMAC_RX_ER);
239         davinci_cfg_reg(DM365_EMAC_CRS);
240         davinci_cfg_reg(DM365_EMAC_MDIO);
241         davinci_cfg_reg(DM365_EMAC_MDCLK);
242 
243         /*
244          * EMAC interrupts are multiplexed with GPIO interrupts
245          * Details are available at the DM365 ARM
246          * Subsystem Users Guide(sprufg5.pdf) pages 133 - 134
247          */
248         davinci_cfg_reg(DM365_INT_EMAC_RXTHRESH);
249         davinci_cfg_reg(DM365_INT_EMAC_RXPULSE);
250         davinci_cfg_reg(DM365_INT_EMAC_TXPULSE);
251         davinci_cfg_reg(DM365_INT_EMAC_MISCPULSE);
252 }
253 
254 static void dm365evm_mmc_configure(void)
255 {
256         /*
257          * MMC/SD pins are multiplexed with GPIO and EMIF
258          * Further details are available at the DM365 ARM
259          * Subsystem Users Guide(sprufg5.pdf) pages 118, 128 - 131
260          */
261         davinci_cfg_reg(DM365_SD1_CLK);
262         davinci_cfg_reg(DM365_SD1_CMD);
263         davinci_cfg_reg(DM365_SD1_DATA3);
264         davinci_cfg_reg(DM365_SD1_DATA2);
265         davinci_cfg_reg(DM365_SD1_DATA1);
266         davinci_cfg_reg(DM365_SD1_DATA0);
267 }
268 
269 static void __init evm_init_i2c(void)
270 {
271         davinci_init_i2c(&i2c_pdata);
272         i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
273 }
274 
275 static struct platform_device *dm365_evm_nand_devices[] __initdata = {
276         &davinci_nand_device,
277 };
278 
279 static inline int have_leds(void)
280 {
281 #ifdef CONFIG_LEDS_CLASS
282         return 1;
283 #else
284         return 0;
285 #endif
286 }
287 
288 struct cpld_led {
289         struct led_classdev     cdev;
290         u8                      mask;
291 };
292 
293 static const struct {
294         const char *name;
295         const char *trigger;
296 } cpld_leds[] = {
297         { "dm365evm::ds2", },
298         { "dm365evm::ds3", },
299         { "dm365evm::ds4", },
300         { "dm365evm::ds5", },
301         { "dm365evm::ds6", "nand-disk", },
302         { "dm365evm::ds7", "mmc1", },
303         { "dm365evm::ds8", "mmc0", },
304         { "dm365evm::ds9", "heartbeat", },
305 };
306 
307 static void cpld_led_set(struct led_classdev *cdev, enum led_brightness b)
308 {
309         struct cpld_led *led = container_of(cdev, struct cpld_led, cdev);
310         u8 reg = __raw_readb(cpld + CPLD_LEDS);
311 
312         if (b != LED_OFF)
313                 reg &= ~led->mask;
314         else
315                 reg |= led->mask;
316         __raw_writeb(reg, cpld + CPLD_LEDS);
317 }
318 
319 static enum led_brightness cpld_led_get(struct led_classdev *cdev)
320 {
321         struct cpld_led *led = container_of(cdev, struct cpld_led, cdev);
322         u8 reg = __raw_readb(cpld + CPLD_LEDS);
323 
324         return (reg & led->mask) ? LED_OFF : LED_FULL;
325 }
326 
327 static int __init cpld_leds_init(void)
328 {
329         int     i;
330 
331         if (!have_leds() ||  !cpld)
332                 return 0;
333 
334         /* setup LEDs */
335         __raw_writeb(0xff, cpld + CPLD_LEDS);
336         for (i = 0; i < ARRAY_SIZE(cpld_leds); i++) {
337                 struct cpld_led *led;
338 
339                 led = kzalloc(sizeof(*led), GFP_KERNEL);
340                 if (!led)
341                         break;
342 
343                 led->cdev.name = cpld_leds[i].name;
344                 led->cdev.brightness_set = cpld_led_set;
345                 led->cdev.brightness_get = cpld_led_get;
346                 led->cdev.default_trigger = cpld_leds[i].trigger;
347                 led->mask = BIT(i);
348 
349                 if (led_classdev_register(NULL, &led->cdev) < 0) {
350                         kfree(led);
351                         break;
352                 }
353         }
354 
355         return 0;
356 }
357 /* run after subsys_initcall() for LEDs */
358 fs_initcall(cpld_leds_init);
359 
360 
361 static void __init evm_init_cpld(void)
362 {
363         u8 mux, resets;
364         const char *label;
365         struct clk *aemif_clk;
366 
367         /* Make sure we can configure the CPLD through CS1.  Then
368          * leave it on for later access to MMC and LED registers.
369          */
370         aemif_clk = clk_get(NULL, "aemif");
371         if (IS_ERR(aemif_clk))
372                 return;
373         clk_enable(aemif_clk);
374 
375         if (request_mem_region(DM365_ASYNC_EMIF_DATA_CE1_BASE, SECTION_SIZE,
376                         "cpld") == NULL)
377                 goto fail;
378         cpld = ioremap(DM365_ASYNC_EMIF_DATA_CE1_BASE, SECTION_SIZE);
379         if (!cpld) {
380                 release_mem_region(DM365_ASYNC_EMIF_DATA_CE1_BASE,
381                                 SECTION_SIZE);
382 fail:
383                 pr_err("ERROR: can't map CPLD\n");
384                 clk_disable(aemif_clk);
385                 return;
386         }
387 
388         /* External muxing for some signals */
389         mux = 0;
390 
391         /* Read SW5 to set up NAND + keypad _or_ OneNAND (sync read).
392          * NOTE:  SW4 bus width setting must match!
393          */
394         if ((__raw_readb(cpld + CPLD_SWITCH) & BIT(5)) == 0) {
395                 /* external keypad mux */
396                 mux |= BIT(7);
397 
398                 platform_add_devices(dm365_evm_nand_devices,
399                                 ARRAY_SIZE(dm365_evm_nand_devices));
400         } else {
401                 /* no OneNAND support yet */
402         }
403 
404         /* Leave external chips in reset when unused. */
405         resets = BIT(3) | BIT(2) | BIT(1) | BIT(0);
406 
407         /* Static video input config with SN74CBT16214 1-of-3 mux:
408          *  - port b1 == tvp7002 (mux lowbits == 1 or 6)
409          *  - port b2 == imager (mux lowbits == 2 or 7)
410          *  - port b3 == tvp5146 (mux lowbits == 5)
411          *
412          * Runtime switching could work too, with limitations.
413          */
414         if (have_imager()) {
415                 label = "HD imager";
416                 mux |= 2;
417 
418                 /* externally mux MMC1/ENET/AIC33 to imager */
419                 mux |= BIT(6) | BIT(5) | BIT(3);
420         } else {
421                 struct davinci_soc_info *soc_info = &davinci_soc_info;
422 
423                 /* we can use MMC1 ... */
424                 dm365evm_mmc_configure();
425                 davinci_setup_mmc(1, &dm365evm_mmc_config);
426 
427                 /* ... and ENET ... */
428                 dm365evm_emac_configure();
429                 soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK;
430                 soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY;
431                 resets &= ~BIT(3);
432 
433                 /* ... and AIC33 */
434                 resets &= ~BIT(1);
435 
436                 if (have_tvp7002()) {
437                         mux |= 1;
438                         resets &= ~BIT(2);
439                         label = "tvp7002 HD";
440                 } else {
441                         /* default to tvp5146 */
442                         mux |= 5;
443                         resets &= ~BIT(0);
444                         label = "tvp5146 SD";
445                 }
446         }
447         __raw_writeb(mux, cpld + CPLD_MUX);
448         __raw_writeb(resets, cpld + CPLD_RESETS);
449         pr_info("EVM: %s video input\n", label);
450 
451         /* REVISIT export switches: NTSC/PAL (SW5.6), EXTRA1 (SW5.2), etc */
452 }
453 
454 static struct davinci_uart_config uart_config __initdata = {
455         .enabled_uarts = (1 << 0),
456 };
457 
458 static void __init dm365_evm_map_io(void)
459 {
460         dm365_init();
461 }
462 
463 static __init void dm365_evm_init(void)
464 {
465         evm_init_i2c();
466         davinci_serial_init(&uart_config);
467 
468         dm365evm_emac_configure();
469         dm365evm_mmc_configure();
470 
471         davinci_setup_mmc(0, &dm365evm_mmc_config);
472 
473         /* maybe setup mmc1/etc ... _after_ mmc0 */
474         evm_init_cpld();
475 }
476 
477 static __init void dm365_evm_irq_init(void)
478 {
479         davinci_irq_init();
480 }
481 
482 MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
483         .phys_io        = IO_PHYS,
484         .io_pg_offst    = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
485         .boot_params    = (0x80000100),
486         .map_io         = dm365_evm_map_io,
487         .init_irq       = dm365_evm_irq_init,
488         .timer          = &davinci_timer,
489         .init_machine   = dm365_evm_init,
490 MACHINE_END
491 
492 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp