Beispiel #1
0
void __init ux500_init_irq(void)
{
	void __iomem *dist_base;
	void __iomem *cpu_base;

	if (cpu_is_u5500()) {
		dist_base = __io_address(U5500_GIC_DIST_BASE);
		cpu_base = __io_address(U5500_GIC_CPU_BASE);
	} else if (cpu_is_u8500()) {
		dist_base = __io_address(U8500_GIC_DIST_BASE);
		cpu_base = __io_address(U8500_GIC_CPU_BASE);
	} else
		ux500_unknown_soc();

#ifdef CONFIG_OF
	if (of_have_populated_dt())
		of_irq_init(ux500_dt_irq_match);
	else
#endif
		gic_init(0, 29, dist_base, cpu_base);

	if (cpu_is_u5500())
		db5500_prcmu_early_init();
	if (cpu_is_u8500())
		db8500_prcmu_early_init();
	clk_init();
}
Beispiel #2
0
void __init ux500_init_irq(void)
{
	void __iomem *dist_base;
	void __iomem *cpu_base;

	if (cpu_is_u5500()) {
		dist_base = __io_address(U5500_GIC_DIST_BASE);
		cpu_base = __io_address(U5500_GIC_CPU_BASE);
	} else if (cpu_is_u8500()) {
		dist_base = __io_address(U8500_GIC_DIST_BASE);
		cpu_base = __io_address(U8500_GIC_CPU_BASE);
	} else
		ux500_unknown_soc();

	gic_init(0, 29, dist_base, cpu_base);

	/*
	 * Init clocks here so that they are available for system timer
	 * initialization.
	 */
	if (cpu_is_u5500())
		db5500_prcmu_early_init();
	if (cpu_is_u8500())
		prcmu_early_init();
	clk_init();
}
Beispiel #3
0
static int __init ux500_l2x0_init(void)
{
	uint32_t aux_val = 0x3e000000;

	if (cpu_is_u5500())
		l2x0_base = __io_address(U5500_L2CC_BASE);
	else if (cpu_is_u8500() || cpu_is_u9540())
		l2x0_base = __io_address(U8500_L2CC_BASE);
	else
		ux500_unknown_soc();

	/* u9540's L2 has 128KB way size */
	if (cpu_is_u9540())
		aux_val |=
		(0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); /* 128KB way size */
	else
		aux_val |=
		(0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); /* 64KB way size */

	/* 8 way associativity, force WA */
	l2x0_init(l2x0_base, aux_val, 0xc0000fff);

	/* Override invalidate function */
	outer_cache.disable = ux500_l2x0_disable;
	outer_cache.inv_all = ux500_l2x0_inv_all;

	return 0;
}
static int __init ux500_debug_last_io_init(void)
{
	size_t size;

	size = sizeof(struct ux500_debug_last_io) * num_possible_cpus();

	ux500_last_io = dma_alloc_coherent(NULL, size, &ux500_last_io_phys,
								GFP_KERNEL);
	if (!ux500_last_io) {
;
		return -ENOMEM;
	}

	if (cpu_is_u5500())
		l2x0_base = __io_address(U5500_L2CC_BASE);
	else if (cpu_is_u8500() || cpu_is_u9540())
		l2x0_base = __io_address(U8500_L2CC_BASE);

	/*
	 * CONFIG_UX500_DEBUG_LAST_IO is only intended for debugging.
	 * It should not be left enabled.
	 */
	WARN_ON(1);

	return 0;
}
static void ux500_restart(char mode, const char *cmd)
{
	unsigned short reset_code;
	unsigned short preset_code;

	local_irq_disable();
	local_fiq_disable();

	preset_code = reboot_reason_get_preset();

	if (preset_code != SW_RESET_CRASH)
		prcmu_system_reset(preset_code);
	else {
		reset_code = reboot_reason_code(cmd);
		prcmu_system_reset(reset_code);
	}

	mdelay(1000);

	/*
	 * On 5500, the PRCMU firmware waits for up to 2 seconds for the modem
	 * to respond.
	 */
	if (cpu_is_u5500())
		mdelay(2000);

	printk(KERN_ERR "Reboot via PRCMU failed -- System halted\n");
	while (1)
		;
}
static void __init ux500_timer_init(void)
{
	void __iomem *prcmu_timer_base;

	if (cpu_is_u5500()) {
		mtu_base = __io_address(U5500_MTU0_BASE);
		prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
	} else if (cpu_is_u8500()) {
		mtu_base = __io_address(U8500_MTU0_BASE);
		prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
	} else {
		ux500_unknown_soc();
	}

	/*
	 * Here we register the timerblocks active in the system.
	 * Localtimers (twd) is started when both cpu is up and running.
	 * MTU register a clocksource, clockevent and sched_clock.
	 * Since the MTU is located in the VAPE power domain
	 * it will be cleared in sleep which makes it unsuitable.
	 * We however need it as a timer tick (clockevent)
	 * during boot to calibrate delay until twd is started.
	 * RTC-RTT have problems as timer tick during boot since it is
	 * depending on delay which is not yet calibrated. RTC-RTT is in the
	 * always-on powerdomain and is used as clockevent instead of twd when
	 * sleeping.
	 * The PRCMU timer 4(3 for DB5500) register a clocksource and
	 * sched_clock with higher rating then MTU since is always-on.
	 *
	 */

	nmdk_timer_init();
	clksrc_dbx500_prcmu_init(prcmu_timer_base);
	ux500_twd_init();
}
static void dcg2900_exit(struct cg2900_chip_dev *dev)
{
	struct dcg2900_info *info = dev->b_data;

	if (machine_is_snowball()) {
		/* Turn off power if we have any */
		if (info->regulator_wlan) {
			regulator_disable(info->regulator_wlan);
			regulator_put(info->regulator_wlan);
		}
	}

	if (cpu_is_u5500())
		dcg2900_u5500_disable_chip(dev);
	else
		dcg2900_u8500_disable_chip(dev);

	if (info->bt_gpio != -1)
		gpio_free(info->bt_gpio);
	if (info->pmuen_gpio != -1)
		gpio_free(info->pmuen_gpio);
	if (info->gbf_gpio != -1)
		gpio_free(info->gbf_gpio);
	kfree(info);
	dev->b_data = NULL;
}
Beispiel #8
0
static void __init wakeup_secondary(void)
{
    void __iomem *backupram;

    if (cpu_is_u5500())
        backupram = __io_address(U5500_BACKUPRAM0_BASE);
    else if (cpu_is_u8500() || cpu_is_u9540())
        backupram = __io_address(U8500_BACKUPRAM0_BASE);
    else
        ux500_unknown_soc();

    /*
     * write the address of secondary startup into the backup ram register
     * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
     * backup ram register at offset 0x1FF0, which is what boot rom code
     * is waiting for. This would wake up the secondary core from WFE
     */
#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
    __raw_writel(virt_to_phys(u8500_secondary_startup),
                 backupram + UX500_CPU1_JUMPADDR_OFFSET);

#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
    __raw_writel(0xA1FEED01,
                 backupram + UX500_CPU1_WAKEMAGIC_OFFSET);

    /* make sure write buffer is drained */
    mb();
}
Beispiel #9
0
void ux500_pm_gpio_save_wake_up_status(void)
{
	int num_banks;
	u32 *banks;
	int i;

	if (cpu_is_u5500()) {
		num_banks = ARRAY_SIZE(u5500_gpio_banks);
		banks = u5500_gpio_banks;
	} else {
		num_banks = ARRAY_SIZE(u8500_gpio_banks);
		banks = u8500_gpio_banks;
	}

	nmk_gpio_clocks_enable();

	for (i = 0; i < num_banks; i++)
		ux500_gpio_wks[i] = readl(__io_address(banks[i]) + NMK_GPIO_WKS);

	// if gpio cause wakeup, then print wakeup status.
	for (i = 0; i < num_banks; i++)
#ifdef CONFIG_DEBUG_PRINTK
		if(ux500_gpio_wks[i])	printk(KERN_INFO "%s: bank%d: 0x%08x\n",
				__func__, i, ux500_gpio_wks[i]);
#else
		if(ux500_gpio_wks[i])	;
#endif

	nmk_gpio_clocks_disable();
}
Beispiel #10
0
void __init ux500_init_irq(void)
{
	void __iomem *dist_base;
	void __iomem *cpu_base;

	gic_arch_extn.irq_set_wake = ux500_gic_irq_set_wake;

	if (cpu_is_u5500()) {
		dist_base = __io_address(U5500_GIC_DIST_BASE);
		cpu_base = __io_address(U5500_GIC_CPU_BASE);
	} else if (cpu_is_u8500() || cpu_is_u9540()) {
		dist_base = __io_address(U8500_GIC_DIST_BASE);
		cpu_base = __io_address(U8500_GIC_CPU_BASE);
	} else
		ux500_unknown_soc();

	gic_init(0, 29, dist_base, cpu_base);

	/*
	 * On WD reboot gic is in some cases decoupled.
	 * This will make sure that the GIC is correctly configured.
	 */
	ux500_pm_gic_recouple();

	/*
	 * Init clocks here so that they are available for system timer
	 * initialization.
	 */
	prcmu_early_init();
	/* backwards compatible */
	if (!arm_pm_restart)
		arm_pm_restart = ux500_restart;
	clk_init();
}
int __init clk_init(void)
{
	if (cpu_is_u8500()) {
		prcmu_base = __io_address(U8500_PRCMU_BASE);
	} else if (cpu_is_u5500()) {
		prcmu_base = __io_address(U5500_PRCMU_BASE);
	} else {
		pr_err("clock: Unknown DB Asic.\n");
		return -EIO;
	}

	if (cpu_is_u8500())
		db8500_clk_init();
	else if (cpu_is_u5500())
		db5500_clk_init();

	return 0;
}
Beispiel #12
0
static void __iomem *scu_base_addr(void)
{
    if (cpu_is_u5500())
        return __io_address(U5500_SCU_BASE);
    else if (cpu_is_u8500() || cpu_is_u9540())
        return __io_address(U8500_SCU_BASE);
    else
        ux500_unknown_soc();

    return NULL;
}
Beispiel #13
0
u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_num)
{
	if (WARN_ON(cpu_is_u5500() && bank_num >=
		    ARRAY_SIZE(u5500_gpio_banks)))
		return 0;

	if (WARN_ON(cpu_is_u8500() && bank_num >=
		    ARRAY_SIZE(u8500_gpio_banks)))
		return 0;

	return ux500_gpio_wks[bank_num];
}
static void __init ux500_twd_init(void)
{
	struct twd_local_timer *twd_local_timer;
	int err;

	twd_local_timer = cpu_is_u5500() ? &u5500_twd_local_timer :
					   &u8500_twd_local_timer;

	err = twd_local_timer_register(twd_local_timer);
	if (err)
		pr_err("twd_local_timer_register failed %d\n", err);
}
void __init mtu_timer_init(void)
{
	unsigned long rate;
	struct clk *clk0;

	clk0 = clk_get_sys("mtu0", NULL);
	BUG_ON(IS_ERR(clk0));

	rate = clk_get_rate(clk0);

	clk_enable(clk0);

	/*
	 * Set scale and timer for sched_clock
	 */
	setup_sched_clock(rate);
	u8500_cycle = (rate + HZ/2) / HZ;

	/* Save global pointer to mtu, used by functions above */
	if (cpu_is_u5500()) {
		mtu0_base = ioremap(U5500_MTU0_BASE, SZ_4K);
	} else if (cpu_is_u8500()) {
		mtu0_base = ioremap(U8500_MTU0_BASE, SZ_4K);
	} else {
		ux500_unknown_soc();
	}

	/* Restart clock source */
	mtu_clocksource_reset();

	/* Now the scheduling clock is ready */
	u8500_clksrc.read = u8500_read_timer;
	u8500_clksrc.mult = clocksource_hz2mult(rate, u8500_clksrc.shift);

	clocksource_register(&u8500_clksrc);

	/* Register irq and clockevents */

	/* We can sleep for max 10s (actually max is longer) */
	clockevents_calc_mult_shift(&u8500_mtu_clkevt, rate, 10);

	u8500_mtu_clkevt.max_delta_ns = clockevent_delta2ns(0xffffffff,
							    &u8500_mtu_clkevt);
	u8500_mtu_clkevt.min_delta_ns = clockevent_delta2ns(0xff,
							    &u8500_mtu_clkevt);

	setup_irq(IRQ_MTU0, &u8500_timer_irq);
	clockevents_register_device(&u8500_mtu_clkevt);
#ifdef ARCH_HAS_READ_CURRENT_TIMER
	set_delay_fn(mtu_timer_delay_loop);
#endif
}
static int __init prefetch_ctrl_init(void)
{
	int err;
	int origin_err;
	/* Selects trustzone application needed for the job. */
	struct tee_uuid static_uuid = {
		L2X0_UUID_TEE_TA_START_LOW,
		L2X0_UUID_TEE_TA_START_MID,
		L2X0_UUID_TEE_TA_START_HIGH,
		L2X0_UUID_TEE_TA_START_CLOCKSEQ,
	};

	/* Get PL310 base address. It will be used as readonly. */
	if (cpu_is_u5500())
		l2x0_base = __io_address(U5500_L2CC_BASE);
	else if (cpu_is_u8500() || cpu_is_u9540())
		l2x0_base = __io_address(U8500_L2CC_BASE);
	else
		ux500_unknown_soc();

	err = teec_initialize_context(NULL, &context);
	if (err) {
		pr_err("l2x0-prefetch: unable to initialize tee context,"
			" err = %d\n", err);
		err = -EINVAL;
		goto error0;
	}

	err = teec_open_session(&context, &session, &static_uuid,
			TEEC_LOGIN_PUBLIC, NULL, NULL, &origin_err);
	if (err) {
		pr_err("l2x0-prefetch: unable to open tee session,"
			" tee error = %d, origin error = %d\n",
			err, origin_err);
		err = -EINVAL;
		goto error1;
	}

	outer_cache.prefetch_enable = prefetch_enable;
	outer_cache.prefetch_disable = prefetch_disable;

	pr_info("l2x0-prefetch: initialized.\n");

	return 0;

error1:
	(void)teec_finalize_context(&context);
error0:
	return err;
}
Beispiel #17
0
void dcg2900_init_platdata(struct cg2900_platform_data *data)
{
	data->init = dcg2900_init;
	data->exit = dcg2900_exit;
	if (cpu_is_u5500()) {
		data->enable_chip = dcg2900_u5500_enable_chip;
		data->disable_chip = dcg2900_u5500_disable_chip;
	} else {
		data->enable_chip = dcg2900_u8500_enable_chip;
		data->disable_chip = dcg2900_u8500_disable_chip;
	}
	data->get_power_switch_off_cmd = dcg2900_get_power_switch_off_cmd;

	data->uart.enable_uart = dcg2900_enable_uart;
	data->uart.disable_uart = dcg2900_disable_uart;
}
static int ux500_wdt_suspend(struct platform_device *pdev,
			     pm_message_t state)
{
	if (wdt_en && cpu_is_u5500()) {
		ux500_wdt_ops->disable(wdog_id);
		return 0;
	}

	if (wdt_en && !wdt_auto_off) {
		ux500_wdt_ops->disable(wdog_id);
		ux500_wdt_ops->config(1, true);

		ux500_wdt_ops->load(wdog_id, timeout * 1000);
		ux500_wdt_ops->enable(wdog_id);
	}
	return 0;
}
static int ux500_wdt_resume(struct platform_device *pdev)
{
	if (wdt_en && cpu_is_u5500()) {
		ux500_wdt_ops->load(wdog_id, timeout * 1000);
		ux500_wdt_ops->enable(wdog_id);
		return 0;
	}

	if (wdt_en && !wdt_auto_off) {
		ux500_wdt_ops->disable(wdog_id);
		ux500_wdt_ops->config(1, wdt_auto_off);

		ux500_wdt_ops->load(wdog_id, timeout * 1000);
		ux500_wdt_ops->enable(wdog_id);
	}
	return 0;
}
/*
 * Save VAPE context
 */
void context_vape_save(void)
{
	atomic_notifier_call_chain(&context_ape_notifier_list,
				   CONTEXT_APE_SAVE, NULL);

	if (cpu_is_u5500())
		u5500_context_save_icn();
	if (cpu_is_u8500())
		u8500_context_save_icn();
	if (cpu_is_u9540())
		u9540_context_save_icn();

	save_stm_ape();

	save_tpiu();

	save_prcc();
}
static int ux500_l2x0_init(void)
{
	if (cpu_is_u5500())
		l2x0_base = __io_address(U5500_L2CC_BASE);
	else if (cpu_is_u8500())
		l2x0_base = __io_address(U8500_L2CC_BASE);
	else
		ux500_unknown_soc();

	/* 64KB way size, 8 way associativity, force WA */
	l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);

	/* Override invalidate function */
	outer_cache.disable = ux500_l2x0_disable;
	outer_cache.inv_all = ux500_l2x0_inv_all;

	return 0;
}
/*
 * Restore VAPE context
 */
void context_vape_restore(void)
{
	restore_prcc();

	restore_tpiu();

	restore_stm_ape();

	if (cpu_is_u5500())
		u5500_context_restore_icn();
	if (cpu_is_u8500())
		u8500_context_restore_icn();
	if (cpu_is_u9540())
		u9540_context_restore_icn();

	atomic_notifier_call_chain(&context_ape_notifier_list,
				   CONTEXT_APE_RESTORE, NULL);
}
int __init db5500_prcmu_init(void)
{
	int r = 0;

	if (ux500_is_svp() || !cpu_is_u5500())
		return -ENODEV;

	
	writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);

	r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
		prcmu_irq_thread_fn, 0, "prcmu", NULL);
	if (r < 0) {
		pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n");
		return -EBUSY;
	}
	return 0;
}
static int modem_irq_init(void)
{
	int err;
	static struct irq_chip  modem_irq_chip;
	struct modem_irq *mi;

	if (!cpu_is_u5500())
		return -ENODEV;

	pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
		   IRQ_DB5500_MODEM);

	mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
	if (!mi) {
		pr_err("modem_irq: Could not allocate device\n");
		return -ENOMEM;
	}

	mi->modem_intcon_base =
		ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
	pr_debug("modem_irq: ioremapped modem_intcon_base from "
		 "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
		 (u32)mi->modem_intcon_base);

	setup_modem_intcon(mi->modem_intcon_base);

	modem_irq_chip = dummy_irq_chip;
	modem_irq_chip.name = "modem_irq";

	/* Create the virtual IRQ:s needed */
	create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
	create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
	create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);

	err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
				   modem_cpu_irq_handler,
				   IRQF_NO_SUSPEND | IRQF_ONESHOT,
				   "modem_irq", mi);
	if (err)
		pr_err("modem_irq: Could not register IRQ %d\n",
		       IRQ_DB5500_MODEM);

	return 0;
}
Beispiel #25
0
/**
 * funct_host_notify_timer() - Initialize the timer for USB host driver.
 * @data: usb host data.
 *
 * This function runs the timer for the USB host mode.
 */
static void funct_host_notify_timer(unsigned long data)
{
	if (!cpu_is_u5500()) {
		struct musb	*musb = (struct musb *)data;
		unsigned long	flags;
		u8	devctl;
		spin_lock_irqsave(&musb->lock, flags);

		stm_set_peripheral_clock(PERI5_CLK_ENABLE);

		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);

		switch (musb->xceiv->state) {
		case OTG_STATE_A_WAIT_BCON:
			if (devctl & MUSB_DEVCTL_BDEVICE) {
				musb->xceiv->state = OTG_STATE_B_IDLE;
				MUSB_DEV_MODE(musb);
			} else {
				musb->xceiv->state = OTG_STATE_A_IDLE;
				MUSB_HST_MODE(musb);
			}

#ifdef CONFIG_PM
		if (!(devctl & MUSB_DEVCTL_SESSION))
			stm_musb_context(USB_DISABLE);
#endif


		break;
		case OTG_STATE_A_SUSPEND:
		default:
		break;
		}

		stm_set_peripheral_clock(PERI5_CLK_DISABLE);

		spin_unlock_irqrestore(&musb->lock, flags);
		DBG(1, "otg_state %s devctl %d\n", otg_state_string(musb),
			devctl);
	}
}
Beispiel #26
0
int __init clk_init(void)
{
    if (cpu_is_u8500ed()) {
        clk_prcmu_ops.enable = clk_prcmu_ed_enable;
        clk_prcmu_ops.disable = clk_prcmu_ed_disable;
        clk_per6clk.rate = 100000000;
    } else if (cpu_is_u5500()) {
        /* Clock tree for U5500 not implemented yet */
        clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
        clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
        clk_per6clk.rate = 26000000;
    }

    clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
    if (cpu_is_u8500ed())
        clkdev_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
    else
        clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));

    return 0;
}
void __init ux500_init_irq(void)
{
	void __iomem *dist_base;

	if (cpu_is_u5500()) {
		gic_cpu_base_addr = __io_address(U5500_GIC_CPU_BASE);
		dist_base = __io_address(U5500_GIC_DIST_BASE);
	} else if (cpu_is_u8500()) {
		gic_cpu_base_addr = __io_address(U8500_GIC_CPU_BASE);
		dist_base = __io_address(U8500_GIC_DIST_BASE);
	} else
		ux500_unknown_soc();

	gic_dist_init(0, dist_base, 29);
	gic_cpu_init(0, gic_cpu_base_addr);

	/*
	 * Init clocks here so that they are available for system timer
	 * initialization.
	 */
	prcmu_early_init();
	arm_pm_restart = ux500_restart;
	clk_init();
}
static long ux500_wdt_ioctl(struct file *file, unsigned int cmd,
			   unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int interval;

	static const struct watchdog_info ident = {
		.options =	WDIOF_SETTIMEOUT |
				WDIOF_KEEPALIVEPING |
				WDIOF_MAGICCLOSE,
		.firmware_version =     1,
		.identity	= "Ux500 WDT",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident,
				    sizeof(ident)) ? -EFAULT : 0;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);

	case WDIOC_SETOPTIONS:
	{
		int options;
		int ret = -EINVAL;

		if (get_user(options, p))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			ux500_wdt_ops->disable(wdog_id);
			wdt_en = false;
			ret = 0;
		}

		if (options & WDIOS_ENABLECARD) {
			ux500_wdt_ops->enable(wdog_id);
			wdt_en = true;
			ret = 0;
		}

		return ret;
	}
	case WDIOC_KEEPALIVE:
		return ux500_wdt_ops->kick(wdog_id);

	case WDIOC_SETTIMEOUT:
		if (get_user(interval, p))
			return -EFAULT;

		if (cpu_is_u8500()) {
			/* 28 bit resolution in ms, becomes 268435.455 s */
			if (interval > 268435 || interval < 0)
				return -EINVAL;
		} else if (cpu_is_u5500()) {
			/* 32 bit resolution in ms, becomes 4294967.295 s */
			if (interval > 4294967 || interval < 0)
				return -EINVAL;
		} else
			return -EINVAL;

		timeout = interval;
		ux500_wdt_ops->disable(wdog_id);
		ux500_wdt_ops->load(wdog_id, timeout * 1000);
		ux500_wdt_ops->enable(wdog_id);

	/* Fall through */
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);

	default:
		return -ENOTTY;
	}

	return 0;
}

#ifdef CONFIG_SAMSUNG_LOG_BUF
void wdog_disable()
{
	ux500_wdt_ops->disable(wdog_id);
	wdt_en = false;
}
static int __init context_init(void)
{
	int i;
	void __iomem *ux500_backup_ptr;

	/* allocate backup pointer for RAM data */
	ux500_backup_ptr = (void *)__get_free_pages(GFP_KERNEL,
				  get_order(U8500_BACKUPRAM_SIZE));

	if (!ux500_backup_ptr) {
		pr_warning("context: could not allocate backup memory\n");
		return -ENOMEM;
	}

	/*
	 * ROM code addresses to store backup contents,
	 * pass the physical address of back up to ROM code
	 */
	writel(virt_to_phys(ux500_backup_ptr),
	       IO_ADDRESS(U8500_EXT_RAM_LOC_BACKUPRAM_ADDR));

	if (cpu_is_u5500()) {
		writel(IO_ADDRESS(U5500_PUBLIC_BOOT_ROM_BASE),
		       IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR));

		writel(IO_ADDRESS(U5500_PUBLIC_BOOT_ROM_BASE),
		       IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR));

		context_tpiu.base = ioremap(U5500_TPIU_BASE, SZ_4K);
		context_stm_ape.base = ioremap(U5500_STM_REG_BASE, SZ_4K);
		context_scu.base = ioremap(U5500_SCU_BASE, SZ_4K);

		context_prcc[0].base = ioremap(U5500_CLKRST1_BASE, SZ_4K);
		context_prcc[1].base = ioremap(U5500_CLKRST2_BASE, SZ_4K);
		context_prcc[2].base = ioremap(U5500_CLKRST3_BASE, SZ_4K);
		context_prcc[3].base = ioremap(U5500_CLKRST5_BASE, SZ_4K);
		context_prcc[4].base = ioremap(U5500_CLKRST6_BASE, SZ_4K);

		context_gic_dist_common.base = ioremap(U5500_GIC_DIST_BASE, SZ_4K);
		per_cpu(context_gic_cpu, 0).base = ioremap(U5500_GIC_CPU_BASE, SZ_4K);
	} else if (cpu_is_u8500() || cpu_is_u9540()) {
		/* Give logical address to backup RAM. For both CPUs */
		if (cpu_is_u9540()) {
			writel(IO_ADDRESS_DB9540_ROM(U9540_PUBLIC_BOOT_ROM_BASE),
					IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR));

			writel(IO_ADDRESS_DB9540_ROM(U9540_PUBLIC_BOOT_ROM_BASE),
					IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR));
		} else {
			writel(IO_ADDRESS(U8500_PUBLIC_BOOT_ROM_BASE),
					IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR));

			writel(IO_ADDRESS(U8500_PUBLIC_BOOT_ROM_BASE),
					IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR));
		}

		context_tpiu.base = ioremap(U8500_TPIU_BASE, SZ_4K);
		context_stm_ape.base = ioremap(U8500_STM_REG_BASE, SZ_4K);
		context_scu.base = ioremap(U8500_SCU_BASE, SZ_4K);

		/* PERIPH4 is always on, so no need saving prcc */
		context_prcc[0].base = ioremap(U8500_CLKRST1_BASE, SZ_4K);
		context_prcc[1].base = ioremap(U8500_CLKRST2_BASE, SZ_4K);
		context_prcc[2].base = ioremap(U8500_CLKRST3_BASE, SZ_4K);
		context_prcc[3].base = ioremap(U8500_CLKRST5_BASE, SZ_4K);
		context_prcc[4].base = ioremap(U8500_CLKRST6_BASE, SZ_4K);

		context_gic_dist_common.base = ioremap(U8500_GIC_DIST_BASE, SZ_4K);
		per_cpu(context_gic_cpu, 0).base = ioremap(U8500_GIC_CPU_BASE, SZ_4K);
	}

	per_cpu(context_gic_dist_cpu, 0).base = context_gic_dist_common.base;

	for (i = 1; i < num_possible_cpus(); i++) {
		per_cpu(context_gic_cpu, i).base
			= per_cpu(context_gic_cpu, 0).base;
		per_cpu(context_gic_dist_cpu, i).base
			= per_cpu(context_gic_dist_cpu, 0).base;
	}

	for (i = 0; i < ARRAY_SIZE(context_prcc); i++) {
		const int clusters[] = {1, 2, 3, 5, 6};
		char clkname[10];

		snprintf(clkname, sizeof(clkname), "PERIPH%d", clusters[i]);

		context_prcc[i].clk = clk_get_sys(clkname, NULL);
		BUG_ON(IS_ERR(context_prcc[i].clk));
	}

	if (cpu_is_u8500()) {
		u8500_context_init();
	} else if (cpu_is_u5500()) {
		u5500_context_init();
	} else if (cpu_is_u9540()) {
		u9540_context_init();
	} else {
		printk(KERN_ERR "context: unknown hardware!\n");
		return -EINVAL;
	}

	return 0;
}
Beispiel #30
0
static int dcg2900_init(struct cg2900_chip_dev *dev)
{
	int err = 0;
	struct dcg2900_info *info;
	struct cg2900_platform_data *pdata = dev_get_platdata(dev->dev);

	/* First retrieve and save the resources */
	info = kzalloc(sizeof(*info), GFP_KERNEL);
	if (!info) {
		dev_err(dev->dev, "Could not allocate dcg2900_info\n");
		return -ENOMEM;
	}

	info->gbf_gpio = -1;
	info->pmuen_gpio = -1;
	info->bt_gpio = -1;

	if (!dev->pdev->num_resources) {
		dev_dbg(dev->dev, "No resources available\n");
		goto finished;
	}

	if (cpu_is_u5500())
		err = dcg2900_u5500_setup(dev, info);
	else
		err = dcg2900_u8500_setup(dev, info);

	if (err)
		goto err_handling;

	/*
	 * Enable the power on snowball
	 */
	if (machine_is_snowball()) {
		/* Take the regulator */
		if (pdata->regulator_id) {
			info->regulator_wlan = regulator_get(dev->dev,
					pdata->regulator_id);
			if (IS_ERR(info->regulator_wlan)) {
				err = PTR_ERR(info->regulator_wlan);
				dev_warn(dev->dev,
					"%s: Failed to get regulator '%s'\n",
					__func__, pdata->regulator_id);
				info->regulator_wlan = NULL;
				goto err_handling_free_gpios;
			}
			/* Enable it also */
			err = regulator_enable(info->regulator_wlan);
			if (err < 0) {
				dev_warn(dev->dev, "%s: regulator_enable failed\n",
						__func__);
				goto err_handling_put_reg;
			}
		} else {
			dev_warn(dev->dev, "%s: no regulator defined for snowball.\n",
					__func__);
		}
	}

finished:
	dev->b_data = info;
	return 0;
err_handling_put_reg:
	regulator_put(info->regulator_wlan);
err_handling_free_gpios:
	if (info->bt_gpio != -1)
		gpio_free(info->bt_gpio);
	if (info->pmuen_gpio != -1)
		gpio_free(info->pmuen_gpio);
	if (info->gbf_gpio != -1)
		gpio_free(info->gbf_gpio);
err_handling:
	kfree(info);
	return err;
}