18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/mach-pxa/gumstix.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Support for the Gumstix motherboards. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Original Author: Craig Hughes 88c2ecf20Sopenharmony_ci * Created: Feb 14, 2008 98c2ecf20Sopenharmony_ci * Copyright: Craig Hughes 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Implemented based on lubbock.c by Nicolas Pitre and code from Craig 128c2ecf20Sopenharmony_ci * Hughes 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 198c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 208c2ecf20Sopenharmony_ci#include <linux/delay.h> 218c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h> 228c2ecf20Sopenharmony_ci#include <linux/mtd/partitions.h> 238c2ecf20Sopenharmony_ci#include <linux/gpio/machine.h> 248c2ecf20Sopenharmony_ci#include <linux/gpio.h> 258c2ecf20Sopenharmony_ci#include <linux/err.h> 268c2ecf20Sopenharmony_ci#include <linux/clk.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <asm/setup.h> 298c2ecf20Sopenharmony_ci#include <asm/memory.h> 308c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 318c2ecf20Sopenharmony_ci#include <mach/hardware.h> 328c2ecf20Sopenharmony_ci#include <asm/irq.h> 338c2ecf20Sopenharmony_ci#include <linux/sizes.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <asm/mach/arch.h> 368c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 378c2ecf20Sopenharmony_ci#include <asm/mach/irq.h> 388c2ecf20Sopenharmony_ci#include <asm/mach/flash.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include "pxa25x.h" 418c2ecf20Sopenharmony_ci#include <linux/platform_data/mmc-pxamci.h> 428c2ecf20Sopenharmony_ci#include "udc.h" 438c2ecf20Sopenharmony_ci#include "gumstix.h" 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include "generic.h" 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic struct resource flash_resource = { 488c2ecf20Sopenharmony_ci .start = 0x00000000, 498c2ecf20Sopenharmony_ci .end = SZ_64M - 1, 508c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic struct mtd_partition gumstix_partitions[] = { 548c2ecf20Sopenharmony_ci { 558c2ecf20Sopenharmony_ci .name = "Bootloader", 568c2ecf20Sopenharmony_ci .size = 0x00040000, 578c2ecf20Sopenharmony_ci .offset = 0, 588c2ecf20Sopenharmony_ci .mask_flags = MTD_WRITEABLE /* force read-only */ 598c2ecf20Sopenharmony_ci } , { 608c2ecf20Sopenharmony_ci .name = "rootfs", 618c2ecf20Sopenharmony_ci .size = MTDPART_SIZ_FULL, 628c2ecf20Sopenharmony_ci .offset = MTDPART_OFS_APPEND 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic struct flash_platform_data gumstix_flash_data = { 678c2ecf20Sopenharmony_ci .map_name = "cfi_probe", 688c2ecf20Sopenharmony_ci .parts = gumstix_partitions, 698c2ecf20Sopenharmony_ci .nr_parts = ARRAY_SIZE(gumstix_partitions), 708c2ecf20Sopenharmony_ci .width = 2, 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic struct platform_device gumstix_flash_device = { 748c2ecf20Sopenharmony_ci .name = "pxa2xx-flash", 758c2ecf20Sopenharmony_ci .id = 0, 768c2ecf20Sopenharmony_ci .dev = { 778c2ecf20Sopenharmony_ci .platform_data = &gumstix_flash_data, 788c2ecf20Sopenharmony_ci }, 798c2ecf20Sopenharmony_ci .resource = &flash_resource, 808c2ecf20Sopenharmony_ci .num_resources = 1, 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic struct platform_device *devices[] __initdata = { 848c2ecf20Sopenharmony_ci &gumstix_flash_device, 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#ifdef CONFIG_MMC_PXA 888c2ecf20Sopenharmony_cistatic struct pxamci_platform_data gumstix_mci_platform_data = { 898c2ecf20Sopenharmony_ci .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic void __init gumstix_mmc_init(void) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci pxa_set_mci_info(&gumstix_mci_platform_data); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci#else 978c2ecf20Sopenharmony_cistatic void __init gumstix_mmc_init(void) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci pr_debug("Gumstix mmc disabled\n"); 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci#endif 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_PXA25X 1048c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table gumstix_gpio_vbus_gpiod_table = { 1058c2ecf20Sopenharmony_ci .dev_id = "gpio-vbus", 1068c2ecf20Sopenharmony_ci .table = { 1078c2ecf20Sopenharmony_ci GPIO_LOOKUP("gpio-pxa", GPIO_GUMSTIX_USB_GPIOn, 1088c2ecf20Sopenharmony_ci "vbus", GPIO_ACTIVE_HIGH), 1098c2ecf20Sopenharmony_ci GPIO_LOOKUP("gpio-pxa", GPIO_GUMSTIX_USB_GPIOx, 1108c2ecf20Sopenharmony_ci "pullup", GPIO_ACTIVE_HIGH), 1118c2ecf20Sopenharmony_ci { }, 1128c2ecf20Sopenharmony_ci }, 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic struct platform_device gumstix_gpio_vbus = { 1168c2ecf20Sopenharmony_ci .name = "gpio-vbus", 1178c2ecf20Sopenharmony_ci .id = -1, 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic void __init gumstix_udc_init(void) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci gpiod_add_lookup_table(&gumstix_gpio_vbus_gpiod_table); 1238c2ecf20Sopenharmony_ci platform_device_register(&gumstix_gpio_vbus); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci#else 1268c2ecf20Sopenharmony_cistatic void gumstix_udc_init(void) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci pr_debug("Gumstix udc is disabled\n"); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci#endif 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#ifdef CONFIG_BT 1338c2ecf20Sopenharmony_ci/* Normally, the bootloader would have enabled this 32kHz clock but many 1348c2ecf20Sopenharmony_ci** boards still have u-boot 1.1.4 so we check if it has been turned on and 1358c2ecf20Sopenharmony_ci** if not, we turn it on with a warning message. */ 1368c2ecf20Sopenharmony_cistatic void gumstix_setup_bt_clock(void) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci int timeout = 500; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (!(readl(OSCC) & OSCC_OOK)) 1418c2ecf20Sopenharmony_ci pr_warn("32kHz clock was not on. Bootloader may need to be updated\n"); 1428c2ecf20Sopenharmony_ci else 1438c2ecf20Sopenharmony_ci return; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci writel(readl(OSCC) | OSCC_OON, OSCC); 1468c2ecf20Sopenharmony_ci do { 1478c2ecf20Sopenharmony_ci if (readl(OSCC) & OSCC_OOK) 1488c2ecf20Sopenharmony_ci break; 1498c2ecf20Sopenharmony_ci udelay(1); 1508c2ecf20Sopenharmony_ci } while (--timeout); 1518c2ecf20Sopenharmony_ci if (!timeout) 1528c2ecf20Sopenharmony_ci pr_err("Failed to start 32kHz clock\n"); 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic void __init gumstix_bluetooth_init(void) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci int err; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci gumstix_setup_bt_clock(); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci err = gpio_request(GPIO_GUMSTIX_BTRESET, "BTRST"); 1628c2ecf20Sopenharmony_ci if (err) { 1638c2ecf20Sopenharmony_ci pr_err("gumstix: failed request gpio for bluetooth reset\n"); 1648c2ecf20Sopenharmony_ci return; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci err = gpio_direction_output(GPIO_GUMSTIX_BTRESET, 1); 1688c2ecf20Sopenharmony_ci if (err) { 1698c2ecf20Sopenharmony_ci pr_err("gumstix: can't reset bluetooth\n"); 1708c2ecf20Sopenharmony_ci return; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci gpio_set_value(GPIO_GUMSTIX_BTRESET, 0); 1738c2ecf20Sopenharmony_ci udelay(100); 1748c2ecf20Sopenharmony_ci gpio_set_value(GPIO_GUMSTIX_BTRESET, 1); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci#else 1778c2ecf20Sopenharmony_cistatic void gumstix_bluetooth_init(void) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci pr_debug("Gumstix Bluetooth is disabled\n"); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci#endif 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic unsigned long gumstix_pin_config[] __initdata = { 1848c2ecf20Sopenharmony_ci GPIO12_32KHz, 1858c2ecf20Sopenharmony_ci /* BTUART */ 1868c2ecf20Sopenharmony_ci GPIO42_HWUART_RXD, 1878c2ecf20Sopenharmony_ci GPIO43_HWUART_TXD, 1888c2ecf20Sopenharmony_ci GPIO44_HWUART_CTS, 1898c2ecf20Sopenharmony_ci GPIO45_HWUART_RTS, 1908c2ecf20Sopenharmony_ci /* MMC */ 1918c2ecf20Sopenharmony_ci GPIO6_MMC_CLK, 1928c2ecf20Sopenharmony_ci GPIO53_MMC_CLK, 1938c2ecf20Sopenharmony_ci GPIO8_MMC_CS0, 1948c2ecf20Sopenharmony_ci}; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ciint __attribute__((weak)) am200_init(void) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci return 0; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ciint __attribute__((weak)) am300_init(void) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic void __init carrier_board_init(void) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci /* 2098c2ecf20Sopenharmony_ci * put carrier/expansion board init here if 2108c2ecf20Sopenharmony_ci * they cannot be detected programatically 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ci am200_init(); 2138c2ecf20Sopenharmony_ci am300_init(); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic void __init gumstix_init(void) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci pxa2xx_mfp_config(ARRAY_AND_SIZE(gumstix_pin_config)); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci pxa_set_ffuart_info(NULL); 2218c2ecf20Sopenharmony_ci pxa_set_btuart_info(NULL); 2228c2ecf20Sopenharmony_ci pxa_set_stuart_info(NULL); 2238c2ecf20Sopenharmony_ci pxa_set_hwuart_info(NULL); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci gumstix_bluetooth_init(); 2268c2ecf20Sopenharmony_ci gumstix_udc_init(); 2278c2ecf20Sopenharmony_ci gumstix_mmc_init(); 2288c2ecf20Sopenharmony_ci (void) platform_add_devices(devices, ARRAY_SIZE(devices)); 2298c2ecf20Sopenharmony_ci carrier_board_init(); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ciMACHINE_START(GUMSTIX, "Gumstix") 2338c2ecf20Sopenharmony_ci .atag_offset = 0x100, /* match u-boot bi_boot_params */ 2348c2ecf20Sopenharmony_ci .map_io = pxa25x_map_io, 2358c2ecf20Sopenharmony_ci .nr_irqs = PXA_NR_IRQS, 2368c2ecf20Sopenharmony_ci .init_irq = pxa25x_init_irq, 2378c2ecf20Sopenharmony_ci .handle_irq = pxa25x_handle_irq, 2388c2ecf20Sopenharmony_ci .init_time = pxa_timer_init, 2398c2ecf20Sopenharmony_ci .init_machine = gumstix_init, 2408c2ecf20Sopenharmony_ci .restart = pxa_restart, 2418c2ecf20Sopenharmony_ciMACHINE_END 242