u-boot/arch/arm/mach-sunxi/p2wi.c
Alexander Graf e6e505b93c sunxi: Move cpu independent code to mach directory
Some of the code in arch/arm/cpu/armv7/sunxi is actually armv7 specific, while
most of it is just generic code that could as well be used on an AArch64 SoC.

Move all files that are not really tied to armv7 into a new mach-sunxi
directory.

Signed-off-by: Alexander Graf <agraf@suse.de>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2016-04-01 09:52:28 +02:00

117 lines
2.9 KiB
C

/*
* Sunxi A31 Power Management Unit
*
* (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
* http://linux-sunxi.org
*
* Based on sun6i sources and earlier U-Boot Allwiner A10 SPL work
*
* (C) Copyright 2006-2013
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Berg Xing <bergxing@allwinnertech.com>
* Tom Cubie <tangliang@allwinnertech.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
#include <asm/arch/p2wi.h>
#include <asm/arch/prcm.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
void p2wi_init(void)
{
struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
/* Enable p2wi and PIO clk, and de-assert their resets */
prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI);
sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK);
sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA);
/* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */
writel(P2WI_CTRL_RESET, &p2wi->ctrl);
sdelay(0x100);
writel(P2WI_CC_SDA_OUT_DELAY(1) | P2WI_CC_CLK_DIV(8),
&p2wi->cc);
}
int p2wi_change_to_p2wi_mode(u8 slave_addr, u8 ctrl_reg, u8 init_data)
{
struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
unsigned long tmo = timer_get_us() + 1000000;
writel(P2WI_PM_DEV_ADDR(slave_addr) |
P2WI_PM_CTRL_ADDR(ctrl_reg) |
P2WI_PM_INIT_DATA(init_data) |
P2WI_PM_INIT_SEND,
&p2wi->pm);
while ((readl(&p2wi->pm) & P2WI_PM_INIT_SEND)) {
if (timer_get_us() > tmo)
return -ETIME;
}
return 0;
}
static int p2wi_await_trans(void)
{
struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
unsigned long tmo = timer_get_us() + 1000000;
int ret;
u8 reg;
while (1) {
reg = readl(&p2wi->status);
if (reg & P2WI_STAT_TRANS_ERR) {
ret = -EIO;
break;
}
if (reg & P2WI_STAT_TRANS_DONE) {
ret = 0;
break;
}
if (timer_get_us() > tmo) {
ret = -ETIME;
break;
}
}
writel(reg, &p2wi->status); /* Clear status bits */
return ret;
}
int p2wi_read(const u8 addr, u8 *data)
{
struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
int ret;
writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0);
writel(P2WI_DATA_NUM_BYTES(1) |
P2WI_DATA_NUM_BYTES_READ, &p2wi->numbytes);
writel(P2WI_STAT_TRANS_DONE, &p2wi->status);
writel(P2WI_CTRL_TRANS_START, &p2wi->ctrl);
ret = p2wi_await_trans();
*data = readl(&p2wi->data0) & P2WI_DATA_BYTE_1_MASK;
return ret;
}
int p2wi_write(const u8 addr, u8 data)
{
struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE;
writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0);
writel(P2WI_DATA_BYTE_1(data), &p2wi->data0);
writel(P2WI_DATA_NUM_BYTES(1), &p2wi->numbytes);
writel(P2WI_STAT_TRANS_DONE, &p2wi->status);
writel(P2WI_CTRL_TRANS_START, &p2wi->ctrl);
return p2wi_await_trans();
}