/* * Copyright (C) 2014 Spreadtrum Communications Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if (defined(CONFIG_INPUT_LIS3DH_I2C) || defined(CONFIG_INPUT_LIS3DH_I2C_MODULE)) #include #endif #if (defined(CONFIG_INPUT_LTR558_I2C) || defined(CONFIG_INPUT_LTR558_I2C_MODULE)) #include #endif #if (defined(CONFIG_TOUCHSCREEN_MSG2138) || defined(CONFIG_TOUCHSCREEN_MSG2138_MODULE)) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #if (defined(CONFIG_INV_MPU_IIO) || defined(CONFIG_INV_MPU_IIO_MODULE)) #include #endif #if (defined(CONFIG_SENSORS_AK8975) || defined(CONFIG_SENSORS_AK8975_MODULE)) #include #endif /* IRQ's for the multi sensor board */ #define MPUIRQ_GPIO 212 #include #include #if (defined(CONFIG_TOUCHSCREEN_FOCALTECH) || defined(CONFIG_TOUCHSCREEN_FOCALTECH_MODULE)) #include #endif #if (defined(CONFIG_KEYBOARD_SC) || defined (CONFIG_KEYBOARD_SC_MODULE)) #include #include #endif #if (defined(CONFIG_KEYBOARD_GPIO) || defined (CONFIG_KEYBOARD_GPIO_MODULE)) #include #endif #if (defined(CONFIG_KEYBOARD_SPRD_EIC) || defined(CONFIG_KEYBOARD_SPRD_EIC_MODULE)) #include #endif #if (defined(CONFIG_BACKLIGHT_SPRD_PWM) || defined(CONFIG_BACKLIGHT_SPRD_PWM_MODULE)) #include #endif #if (defined(CONFIG_INPUT_HEADSET_SPRD_SC2723) || defined(CONFIG_INPUT_HEADSET_SPRD_SC2723_MODULE)) #include #endif extern void bluesleep_setup_uart_port(struct platform_device *uart_dev); extern void __init sci_reserve(void); extern void __init sci_map_io(void); extern void __init sci_init_irq(void); extern void __init sci_timer_init(void); extern int __init sci_clock_init(void); extern int __init sci_regulator_init(void); int __init __clock_init_early(void) { #if !defined(CONFIG_ARCH_SCX15) pr_info("ahb ctl0 %08x, ctl2 %0x8 glb aon apb0 %08x aon apb1 %08x clk_en %08x\n", sci_glb_raw_read(REG_AP_AHB_AHB_EB), sci_glb_raw_read(REG_AP_AHB_AHB_RST), sci_glb_raw_read(REG_AON_APB_APB_EB0), sci_glb_raw_read(REG_AON_APB_APB_EB1), sci_glb_raw_read(REG_AON_CLK_PUB_AHB_CFG)); #endif sci_glb_clr(REG_AP_AHB_AHB_EB, BIT_BUSMON2_EB | BIT_BUSMON1_EB | BIT_BUSMON0_EB | BIT_SPINLOCK_EB | #if !defined(CONFIG_ARCH_SCX35L) BIT_GPS_EB | #endif BIT_EMMC_EB | BIT_SDIO2_EB | BIT_SDIO1_EB | BIT_SDIO0_EB | BIT_DRM_EB | BIT_NFC_EB | BIT_DMA_EB | BIT_USB_EB | #if !defined(CONFIG_ARCH_SCX35L) BIT_GSP_EB | BIT_DISPC1_EB | #endif 0); sci_glb_clr(REG_AP_APB_APB_EB, BIT_INTC3_EB | BIT_INTC2_EB | BIT_INTC1_EB | BIT_IIS1_EB | BIT_UART2_EB | BIT_UART0_EB | BIT_SPI1_EB | BIT_SPI0_EB | BIT_IIS0_EB | BIT_I2C0_EB | BIT_SPI2_EB | BIT_UART3_EB | 0); sci_glb_clr(REG_AON_APB_APB_RTC_EB, BIT_KPD_RTC_EB | BIT_KPD_EB | BIT_EFUSE_EB | 0); sci_glb_clr(REG_AON_APB_APB_EB0, BIT_AUDIF_EB | BIT_VBC_EB | BIT_PWM3_EB | BIT_PWM1_EB | 0); sci_glb_clr(REG_AON_APB_APB_EB1, BIT_AUX1_EB | BIT_AUX0_EB | 0); printk("sc clock module early init ok\n"); return 0; } static inline int __sci_get_chip_id(void) { return __raw_readl(CHIP_ID_LOW_REG); } const struct of_device_id of_sprd_default_bus_match_table[] = { { .compatible = "simple-bus", }, { .compatible = "sprd,adi-bus", }, {} }; static struct of_dev_auxdata of_sprd_default_bus_lookup[] = { { .compatible = "sprd,sprd_backlight", .name = "sprd_backlight" }, #if (defined(CONFIG_BACKLIGHT_SPRD_PWM) || defined(CONFIG_BACKLIGHT_SPRD_PWM_MODULE)) { .compatible = "sprd,sprd_pwm_bl", .name = "sprd_pwm_bl" }, #endif #if (defined(CONFIG_KEYBOARD_SC) || defined(CONFIG_KEYBOARD_SC_MODULE)) {.compatible = "sprd,sci-keypad", .name = "sci-keypad" }, #endif #if (defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)) {.compatible = "gpio-keys", .name = "gpio-keys" }, #endif #if (defined(CONFIG_KEYBOARD_SPRD_EIC) || defined(CONFIG_KEYBOARD_SPRD_EIC_MODULE)) {.compatible = "sprd,sprd-eic-keys", .name = "sprd-eic-keys" }, #endif #if (defined(CONFIG_INPUT_HEADSET_SPRD_SC2723) || defined(CONFIG_INPUT_HEADSET_SPRD_SC2723_MODULE)) { .compatible = "sprd,headset_sprd_sc2723", .name = "headset_sprd_sc2723" }, #endif {} }; struct iotable_sprd io_addr_sprd; EXPORT_SYMBOL(io_addr_sprd); int iotable_build() { struct device_node *np; struct resource res; #define ADD_SPRD_DEVICE(compat, id) \ do { \ np = of_find_compatible_node(NULL, NULL, compat);\ if (of_can_translate_address(np)) { \ of_address_to_resource(np, 0, &res); \ io_addr_sprd.id.paddr = res.start; \ io_addr_sprd.id.length = \ resource_size(&res); \ io_addr_sprd.id.vaddr = \ ioremap_nocache(res.start, io_addr_sprd.id.length);\ pr_debug("sprd io map: phys=%08x virt=%08x size=%08x\n", \ io_addr_sprd.id.paddr, io_addr_sprd.id.vaddr, io_addr_sprd.id.length);\ } \ } while (0) #define ADD_SPRD_DEVICE_BY_NAME(name, id) \ do { \ np = of_find_node_by_name(NULL, name); \ if (of_can_translate_address(np)) { \ of_address_to_resource(np, 0, &res); \ io_addr_sprd.id.paddr = res.start; \ io_addr_sprd.id.length = \ resource_size(&res); \ io_addr_sprd.id.vaddr = \ ioremap_nocache(res.start, io_addr_sprd.id.length);\ pr_debug("sprd io map: phys=%16lx virt=%16lx size=%16lx\n", \ io_addr_sprd.id.paddr, io_addr_sprd.id.vaddr, io_addr_sprd.id.length);\ } \ } while (0) ADD_SPRD_DEVICE("sprd,ahb", AHB); ADD_SPRD_DEVICE("sprd,aonapb", AONAPB); ADD_SPRD_DEVICE("sprd,aonckg", AONCKG); ADD_SPRD_DEVICE("sprd,apbreg", APBREG); ADD_SPRD_DEVICE("sprd,core", CORE); ADD_SPRD_DEVICE("sprd,mmahb", MMAHB); ADD_SPRD_DEVICE("sprd,pmu", PMU); ADD_SPRD_DEVICE("sprd,mmckg", MMCKG); ADD_SPRD_DEVICE("sprd,gpuapb", GPUAPB); ADD_SPRD_DEVICE("sprd,apbckg", APBCKG); ADD_SPRD_DEVICE("sprd,gpuckg", GPUCKG); ADD_SPRD_DEVICE("sprd,int", INT); ADD_SPRD_DEVICE("sprd,intc0", INTC0); ADD_SPRD_DEVICE("sprd,intc1", INTC1); ADD_SPRD_DEVICE("sprd,intc2", INTC2); ADD_SPRD_DEVICE("sprd,intc3", INTC3); ADD_SPRD_DEVICE("sprd,uidefuse", UIDEFUSE); ADD_SPRD_DEVICE("sprd,isp", ISP); ADD_SPRD_DEVICE("sprd,ca7wdg", CA7WDG); ADD_SPRD_DEVICE("sprd,csi2", CSI2); ADD_SPRD_DEVICE("sprd,d-eic-gpio", EIC); ADD_SPRD_DEVICE("sprd,wdg", WDG); ADD_SPRD_DEVICE("sprd,ipi", IPI); ADD_SPRD_DEVICE("sprd,dcam", DCAM); ADD_SPRD_DEVICE("sprd,syscnt", SYSCNT); ADD_SPRD_DEVICE("sprd,dma0", DMA0); ADD_SPRD_DEVICE("sprd,pub", PUB); ADD_SPRD_DEVICE("sprd,pin", PIN); ADD_SPRD_DEVICE("sprd,d-gpio-gpio", GPIO); ADD_SPRD_DEVICE_BY_NAME("hwspinlock0", HWSPINLOCK0); ADD_SPRD_DEVICE_BY_NAME("hwspinlock1", HWSPINLOCK1); return 0; } static void __init sc8830_init_machine(void) { printk("sci get chip id = 0x%x\n", __sci_get_chip_id()); sci_adc_init(); #ifndef CONFIG_MACH_SPX35LFPGA sci_regulator_init(); #endif of_sprd_default_bus_lookup[0].phys_addr = 0x20300000; of_sprd_default_bus_lookup[1].phys_addr = 0x20400000; of_sprd_default_bus_lookup[2].phys_addr = 0x20500000; of_sprd_default_bus_lookup[3].phys_addr = 0x20600000; of_platform_populate(NULL, of_sprd_default_bus_match_table, of_sprd_default_bus_lookup, NULL); } #ifdef CONFIG_OF const struct of_device_id of_sprd_late_bus_match_table[] = { { .compatible = "sprd,sound", }, {} }; #endif static void __init sc8830_init_late(void) { of_platform_populate(of_find_node_by_path("/sprd-audio-devices"), of_sprd_late_bus_match_table, NULL, NULL); } extern void __init sci_enable_timer_early(void); extern void __init sc_init_chip_id(void); void __init sprd_init_before_irq(void) { iotable_build(); sc_init_chip_id(); /* earlier init request than irq and timer */ __clock_init_early(); /*ipi reg init for sipc*/ sci_glb_set(REG_AON_APB_APB_EB0, BIT_IPI_EB); } static void __init sc8830_pmu_init(void) { __raw_writel(__raw_readl(REG_PMU_APB_PD_MM_TOP_CFG) & ~(BIT_PD_MM_TOP_FORCE_SHUTDOWN), REG_PMU_APB_PD_MM_TOP_CFG); while (__raw_readl(REG_PMU_APB_PWR_STATUS0_DBG) & 0xf0000000) {}; __raw_writel(__raw_readl(REG_PMU_APB_PD_GPU_TOP_CFG) & ~(BIT_PD_GPU_TOP_FORCE_SHUTDOWN), REG_PMU_APB_PD_GPU_TOP_CFG); while (__raw_readl(REG_PMU_APB_PWR_STATUS0_DBG) & 0x0f000000) {}; __raw_writel(__raw_readl(REG_AON_APB_APB_EB0) | BIT_MM_EB | BIT_GPU_EB, REG_AON_APB_APB_EB0); __raw_writel(__raw_readl(REG_MM_AHB_AHB_EB) | BIT_MM_CKG_EB, REG_MM_AHB_AHB_EB); __raw_writel(__raw_readl(REG_MM_AHB_GEN_CKG_CFG) | BIT_MM_MTX_AXI_CKG_EN | BIT_MM_AXI_CKG_EN, REG_MM_AHB_GEN_CKG_CFG); __raw_writel(__raw_readl(REG_MM_CLK_MM_AHB_CFG) | 0x3, REG_MM_CLK_MM_AHB_CFG); } static void sprd_init_time(void) { if (of_have_populated_dt()) { sc8830_pmu_init(); of_clk_init(NULL); clocksource_of_init(); } else { sci_clock_init(); sci_enable_timer_early(); sci_timer_init(); } } static const char *sprd_boards_compat[] __initdata = { "sprd,sp8835eb", NULL, }; extern struct smp_operations sprd_smp_ops; MACHINE_START(SCPHONE, "sc8830") .smp = smp_ops(sprd_smp_ops), .reserve = sci_reserve, .map_io = sci_map_io, .init_irq = sci_init_irq, .init_time = sprd_init_time, .init_machine = sc8830_init_machine, .init_late = sc8830_init_late, .dt_compat = sprd_boards_compat, MACHINE_END