Skip to content
Snippets Groups Projects
board-gpr.c 6.96 KiB
Newer Older
  • Learn to ignore specific revisions
  • Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    /*
     * GPR board platform device registration (Au1550)
     *
     * Copyright (C) 2010 Wolfgang Grandegger <wg@denx.de>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     */
    
    #include <linux/delay.h>
    #include <linux/init.h>
    #include <linux/interrupt.h>
    #include <linux/kernel.h>
    #include <linux/platform_device.h>
    #include <linux/pm.h>
    #include <linux/mtd/partitions.h>
    #include <linux/mtd/physmap.h>
    #include <linux/leds.h>
    #include <linux/gpio.h>
    #include <linux/i2c.h>
    
    #include <linux/platform_data/i2c-gpio.h>
    #include <linux/gpio/machine.h>
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    #include <asm/bootinfo.h>
    
    #include <asm/idle.h>
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    #include <asm/reboot.h>
    
    #include <asm/setup.h>
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    #include <asm/mach-au1x00/au1000.h>
    
    #include <asm/mach-au1x00/gpio-au1000.h>
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    #include <prom.h>
    
    const char *get_system_type(void)
    {
    	return "GPR";
    }
    
    void __init prom_init(void)
    {
    	unsigned char *memsize_str;
    	unsigned long memsize;
    
    	prom_argc = fw_arg0;
    	prom_argv = (char **)fw_arg1;
    	prom_envp = (char **)fw_arg2;
    
    	prom_init_cmdline();
    
    	memsize_str = prom_getenv("memsize");
    
    	if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    		memsize = 0x04000000;
    	add_memory_region(0, memsize, BOOT_MEM_RAM);
    }
    
    
    void prom_putchar(char c)
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    {
    	alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
    }
    
    static void gpr_reset(char *c)
    {
    	/* switch System-LED to orange (red# and green# on) */
    	alchemy_gpio_direction_output(4, 0);
    	alchemy_gpio_direction_output(5, 0);
    
    	/* trigger watchdog to reset board in 200ms */
    	printk(KERN_EMERG "Triggering watchdog soft reset...\n");
    	raw_local_irq_disable();
    	alchemy_gpio_direction_output(1, 0);
    	udelay(1);
    	alchemy_gpio_set_value(1, 1);
    	while (1)
    		cpu_wait();
    }
    
    static void gpr_power_off(void)
    {
    	while (1)
    		cpu_wait();
    }
    
    void __init board_setup(void)
    {
    	printk(KERN_INFO "Trapeze ITS GPR board\n");
    
    	pm_power_off = gpr_power_off;
    	_machine_halt = gpr_power_off;
    	_machine_restart = gpr_reset;
    
    	/* Enable UART1/3 */
    	alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
    	alchemy_uart_enable(AU1000_UART1_PHYS_ADDR);
    
    	/* Take away Reset of UMTS-card */
    	alchemy_gpio_direction_output(215, 1);
    }
    
    /*
     * Watchdog
     */
    static struct resource gpr_wdt_resource[] = {
    	[0] = {
    		.start	= 1,
    		.end	= 1,
    		.name	= "gpr-adm6320-wdt",
    		.flags	= IORESOURCE_IRQ,
    	}
    };
    
    static struct platform_device gpr_wdt_device = {
    	.name = "adm6320-wdt",
    	.id = 0,
    	.num_resources = ARRAY_SIZE(gpr_wdt_resource),
    	.resource = gpr_wdt_resource,
    };
    
    /*
     * FLASH
     *
     * 0x00000000-0x00200000 : "kernel"
     * 0x00200000-0x00a00000 : "rootfs"
     * 0x01d00000-0x01f00000 : "config"
     * 0x01c00000-0x01d00000 : "yamon"
     * 0x01d00000-0x01d40000 : "yamon env vars"
     * 0x00000000-0x00a00000 : "kernel+rootfs"
     */
    static struct mtd_partition gpr_mtd_partitions[] = {
    	{
    		.name	= "kernel",
    		.size	= 0x00200000,
    
    		.offset = 0,
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	},
    	{
    		.name	= "rootfs",
    		.size	= 0x00800000,
    
    		.offset = MTDPART_OFS_APPEND,
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    		.mask_flags = MTD_WRITEABLE,
    	},
    	{
    		.name	= "config",
    		.size	= 0x00200000,
    
    		.offset = 0x01d00000,
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	},
    	{
    		.name	= "yamon",
    		.size	= 0x00100000,
    
    		.offset = 0x01c00000,
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	},
    	{
    		.name	= "yamon env vars",
    		.size	= 0x00040000,
    
    		.offset = MTDPART_OFS_APPEND,
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	},
    	{
    		.name	= "kernel+rootfs",
    		.size	= 0x00a00000,
    
    		.offset = 0,
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	},
    };
    
    static struct physmap_flash_data gpr_flash_data = {
    	.width		= 4,
    	.nr_parts	= ARRAY_SIZE(gpr_mtd_partitions),
    	.parts		= gpr_mtd_partitions,
    };
    
    static struct resource gpr_mtd_resource = {
    	.start	= 0x1e000000,
    	.end	= 0x1fffffff,
    	.flags	= IORESOURCE_MEM,
    };
    
    static struct platform_device gpr_mtd_device = {
    	.name		= "physmap-flash",
    	.dev		= {
    		.platform_data	= &gpr_flash_data,
    	},
    	.num_resources	= 1,
    	.resource	= &gpr_mtd_resource,
    };
    
    /*
     * LEDs
     */
    
    static const struct gpio_led gpr_gpio_leds[] = {
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	{	/* green */
    		.name			= "gpr:green",
    		.gpio			= 4,
    		.active_low		= 1,
    	},
    	{	/* red */
    		.name			= "gpr:red",
    		.gpio			= 5,
    		.active_low		= 1,
    	}
    };
    
    static struct gpio_led_platform_data gpr_led_data = {
    	.num_leds = ARRAY_SIZE(gpr_gpio_leds),
    	.leds = gpr_gpio_leds,
    };
    
    static struct platform_device gpr_led_devices = {
    	.name = "leds-gpio",
    	.id = -1,
    	.dev = {
    		.platform_data = &gpr_led_data,
    	}
    };
    
    /*
     * I2C
     */
    
    static struct gpiod_lookup_table gpr_i2c_gpiod_table = {
    	.dev_id = "i2c-gpio",
    	.table = {
    		/*
    		 * This should be on "GPIO2" which has base at 200 so
    		 * the global numbers 209 and 210 should correspond to
    		 * local offsets 9 and 10.
    		 */
    		GPIO_LOOKUP_IDX("alchemy-gpio2", 9, NULL, 0,
    				GPIO_ACTIVE_HIGH),
    		GPIO_LOOKUP_IDX("alchemy-gpio2", 10, NULL, 1,
    				GPIO_ACTIVE_HIGH),
    	},
    };
    
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    static struct i2c_gpio_platform_data gpr_i2c_data = {
    
    	/*
    	 * The open drain mode is hardwired somewhere or an electrical
    	 * property of the alchemy GPIO controller.
    	 */
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	.sda_is_open_drain	= 1,
    	.scl_is_open_drain	= 1,
    	.udelay			= 2,		/* ~100 kHz */
    	.timeout		= HZ,
    };
    
    static struct platform_device gpr_i2c_device = {
    	.name			= "i2c-gpio",
    	.id			= -1,
    	.dev.platform_data	= &gpr_i2c_data,
    };
    
    static struct i2c_board_info gpr_i2c_info[] __initdata = {
    	{
    		I2C_BOARD_INFO("lm83", 0x18),
    	}
    };
    
    
    
    static struct resource alchemy_pci_host_res[] = {
    	[0] = {
    		.start	= AU1500_PCI_PHYS_ADDR,
    		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
    		.flags	= IORESOURCE_MEM,
    	},
    };
    
    static int gpr_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
    {
    	if ((slot == 0) && (pin == 1))
    		return AU1550_PCI_INTA;
    	else if ((slot == 0) && (pin == 2))
    		return AU1550_PCI_INTB;
    
    	return 0xff;
    }
    
    static struct alchemy_pci_platdata gpr_pci_pd = {
    	.board_map_irq	= gpr_map_pci_irq,
    	.pci_cfg_set	= PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
    			  PCI_CONFIG_CH |
    #if defined(__MIPSEB__)
    			  PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
    #else
    			  0,
    #endif
    };
    
    static struct platform_device gpr_pci_host_dev = {
    	.dev.platform_data = &gpr_pci_pd,
    	.name		= "alchemy-pci",
    	.id		= 0,
    	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
    	.resource	= alchemy_pci_host_res,
    };
    
    static struct platform_device *gpr_devices[] __initdata = {
    	&gpr_wdt_device,
    	&gpr_mtd_device,
    	&gpr_i2c_device,
    	&gpr_led_devices,
    };
    
    static int __init gpr_pci_init(void)
    {
    	return platform_device_register(&gpr_pci_host_dev);
    }
    /* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
    arch_initcall(gpr_pci_init);
    
    
    static int __init gpr_dev_init(void)
    {
    
    	gpiod_add_lookup_table(&gpr_i2c_gpiod_table);
    
    Greg Kroah-Hartman's avatar
    Greg Kroah-Hartman committed
    	i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info));
    
    	return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices));
    }
    device_initcall(gpr_dev_init);