From: Hans de Goede <hdegoede@redhat.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [linux-sunxi] [PATCH 1/9] sun6i: Add new p2wi controller driver
Date: Wed, 05 Nov 2014 13:59:32 +0100 [thread overview]
Message-ID: <545A1F34.1060204@redhat.com> (raw)
In-Reply-To: <CAGb2v648GBr3m2UY993SoQbpK-dy1sCnbVCOPfzDDAvBbSq3Vg@mail.gmail.com>
Hi,
On 11/03/2014 04:59 PM, Chen-Yu Tsai wrote:
> Hi,
>
> On Mon, Nov 3, 2014 at 11:34 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> From: Oliver Schinagl <oliver@schinagl.nl>
>>
>> The A31 uses a new push-pull two wire interface, which features higher
>> transfer speeds (upto 6 MHz) in theory. While the hardware can burst 8
>> bytes each time, this driver will only see very little use and thus is
>> limited to single byte transmission only.
>>
>> Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>> arch/arm/cpu/armv7/sunxi/Makefile | 1 +
>> arch/arm/cpu/armv7/sunxi/p2wi.c | 117 +++++++++++++++++++++++++++
>> arch/arm/include/asm/arch-sunxi/gpio.h | 3 +
>> arch/arm/include/asm/arch-sunxi/p2wi.h | 140 +++++++++++++++++++++++++++++++++
>> 4 files changed, 261 insertions(+)
>> create mode 100644 arch/arm/cpu/armv7/sunxi/p2wi.c
>> create mode 100644 arch/arm/include/asm/arch-sunxi/p2wi.h
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
>> index 82dbf76..b3a3601 100644
>> --- a/arch/arm/cpu/armv7/sunxi/Makefile
>> +++ b/arch/arm/cpu/armv7/sunxi/Makefile
>> @@ -13,6 +13,7 @@ obj-y += clock.o
>> obj-y += pinmux.o
>> obj-$(CONFIG_MACH_SUN6I) += prcm.o
>> obj-$(CONFIG_MACH_SUN8I) += prcm.o
>> +obj-$(CONFIG_MACH_SUN6I) += p2wi.o
>> obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o
>> obj-$(CONFIG_MACH_SUN5I) += clock_sun4i.o
>> obj-$(CONFIG_MACH_SUN6I) += clock_sun6i.o
>> diff --git a/arch/arm/cpu/armv7/sunxi/p2wi.c b/arch/arm/cpu/armv7/sunxi/p2wi.c
>> new file mode 100644
>> index 0000000..10df348
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/sunxi/p2wi.c
>> @@ -0,0 +1,117 @@
>> +/*
>> + * 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 *)SUNXI_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), SUNXI_GPL0_R_P2WI_SCK);
>> + sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUNXI_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_set_pmu_address(u8 slave_addr, u8 ctrl_reg, u8 init_data)
>
> set_pmu_address is actually a misnomer. What it actually does is
> write <init_data> to <ctrl_reg> on device found at <slave_addr>,
> probably using I2C, with the sole purpose of putting the device
> into P2WI mode (or RSB mode for later AXPs).
>
> According to the docs/code we have, it is always writing 0x3e to
> register 0x3e.
I've renamed this to p2wi_change_to_p2wi_mode for the next version
of this patch-set.
>> +{
>> + struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUNXI_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 -EFAULT;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int p2wi_await_trans(void)
>> +{
>> + struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUNXI_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 *)SUNXI_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 *)SUNXI_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();
>> +}
>> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
>> index 437dd35..c734cf0 100644
>> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
>> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
>> @@ -172,6 +172,9 @@ enum sunxi_gpio_number {
>>
>> #define SUN4I_GPI4_SDC3 2
>>
>> +#define SUNXI_GPL0_R_P2WI_SCK 3
>> +#define SUNXI_GPL1_R_P2WI_SDA 3
>> +
>> #define SUN8I_GPL2_R_UART_TX 2
>> #define SUN8I_GPL3_R_UART_RX 2
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/p2wi.h b/arch/arm/include/asm/arch-sunxi/p2wi.h
>> new file mode 100644
>> index 0000000..1788fa4
>> --- /dev/null
>> +++ b/arch/arm/include/asm/arch-sunxi/p2wi.h
>> @@ -0,0 +1,140 @@
>> +/*
>> + * Sunxi platform Push-Push i2c register definition.
>> + *
>> + * (c) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
>> + * http://linux-sunxi.org
>> + *
>> + * (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+
>> + */
>> +
>> +#ifndef _SUNXI_P2WI_H
>> +#define _SUNXI_P2WI_H
>> +
>> +#include <linux/types.h>
>> +
>> +#define P2WI_CTRL_RESET (0x1 << 0)
>> +#define P2WI_CTRL_IRQ_EN (0x1 << 1)
>> +#define P2WI_CTRL_TRANS_ABORT (0x1 << 6)
>> +#define P2WI_CTRL_TRANS_START (0x1 << 7)
>> +
>> +#define __P2WI_CC_CLK(n) (((n) & 0xff) << 0)
>> +#define P2WI_CC_CLK_MASK __P2WI_CC_CLK_DIV(0xff)
>> +#define __P2WI_CC_CLK_DIV(n) (((n) >> 1) - 1)
>> +#define P2WI_CC_CLK_DIV(n) \
>> + __P2WI_CC_CLK(__P2WI_CC_CLK_DIV(n))
>> +#define P2WI_CC_SDA_OUT_DELAY(n) (((n) & 0x7) << 8)
>> +#define P2WI_CC_SDA_OUT_DELAY_MASK P2WI_CC_SDA_OUT_DELAY(0x7)
>> +
>> +#define P2WI_IRQ_TRANS_DONE (0x1 << 0)
>> +#define P2WI_IRQ_TRANS_ERR (0x1 << 1)
>> +#define P2WI_IRQ_LOAD_BUSY (0x1 << 2)
>> +
>> +#define P2WI_STAT_TRANS_DONE (0x1 << 0)
>> +#define P2WI_STAT_TRANS_ERR (0x1 << 1)
>> +#define P2WI_STAT_LOAD_BUSY (0x1 << 2)
>> +#define __P2WI_STAT_TRANS_ERR(n) (((n) & 0xff) << 8)
>> +#define P2WI_STAT_TRANS_ERR_MASK __P2WI_STAT_TRANS_ERR_ID(0xff)
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_1 0x01
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_2 0x02
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_3 0x04
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_4 0x08
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_5 0x10
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_6 0x20
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_7 0x40
>> +#define __P2WI_STAT_TRANS_ERR_BYTE_8 0x80
>> +#define P2WI_STAT_TRANS_ERR_BYTE_1 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_1)
>> +#define P2WI_STAT_TRANS_ERR_BYTE_2 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_2)
>> +#define P2WI_STAT_TRANS_ERR_BYTE_3 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_3)
>> +#define P2WI_STAT_TRANS_ERR_BYTE_4 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_4)
>> +#define P2WI_STAT_TRANS_ERR_BYTE_5 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_5)
>> +#define P2WI_STAT_TRANS_ERR_BYTE_6 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_6)
>> +#define P2WI_STAT_TRANS_ERR_BYTE_7 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_7)
>> +#define P2WI_STAT_TRANS_ERR_BYTE_8 \
>> + __P2WI_STAT_TRANS_ERR(__P2WI_STAT_TRANS_ERR_BYTE_8)
>> +
>> +#define P2WI_DATADDR_BYTE_1(n) (((n) & 0xff) << 0)
>> +#define P2WI_DATADDR_BYTE_1_MASK P2WI_DATADDR_BYTE_1(0xff)
>> +#define P2WI_DATADDR_BYTE_2(n) (((n) & 0xff) << 8)
>> +#define P2WI_DATADDR_BYTE_2_MASK P2WI_DATADDR_BYTE_2(0xff)
>> +#define P2WI_DATADDR_BYTE_3(n) (((n) & 0xff) << 16)
>> +#define P2WI_DATADDR_BYTE_3_MASK P2WI_DATADDR_BYTE_3(0xff)
>> +#define P2WI_DATADDR_BYTE_4(n) (((n) & 0xff) << 24)
>> +#define P2WI_DATADDR_BYTE_4_MASK P2WI_DATADDR_BYTE_4(0xff)
>> +#define P2WI_DATADDR_BYTE_5(n) (((n) & 0xff) << 0)
>> +#define P2WI_DATADDR_BYTE_5_MASK P2WI_DATADDR_BYTE_5(0xff)
>> +#define P2WI_DATADDR_BYTE_6(n) (((n) & 0xff) << 8)
>> +#define P2WI_DATADDR_BYTE_6_MASK P2WI_DATADDR_BYTE_6(0xff)
>> +#define P2WI_DATADDR_BYTE_7(n) (((n) & 0xff) << 16)
>> +#define P2WI_DATADDR_BYTE_7_MASK P2WI_DATADDR_BYTE_7(0xff)
>> +#define P2WI_DATADDR_BYTE_8(n) (((n) & 0xff) << 24)
>> +#define P2WI_DATADDR_BYTE_8_MASK P2WI_DATADDR_BYTE_8(0xff)
>> +
>> +#define __P2WI_DATA_NUM_BYTES(n) (((n) & 0x7) << 0)
>> +#define P2WI_DATA_NUM_BYTES_MASK __P2WI_DATA_NUM_BYTES(0x7)
>> +#define P2WI_DATA_NUM_BYTES(n) __P2WI_DATA_NUM_BYTES((n) - 1)
>> +#define P2WI_DATA_NUM_BYTES_READ (0x1 << 4)
>> +
>> +#define P2WI_DATA_BYTE_1(n) (((n) & 0xff) << 0)
>> +#define P2WI_DATA_BYTE_1_MASK P2WI_DATA_BYTE_1(0xff)
>> +#define P2WI_DATA_BYTE_2(n) (((n) & 0xff) << 8)
>> +#define P2WI_DATA_BYTE_2_MASK P2WI_DATA_BYTE_2(0xff)
>> +#define P2WI_DATA_BYTE_3(n) (((n) & 0xff) << 16)
>> +#define P2WI_DATA_BYTE_3_MASK P2WI_DATA_BYTE_3(0xff)
>> +#define P2WI_DATA_BYTE_4(n) (((n) & 0xff) << 24)
>> +#define P2WI_DATA_BYTE_4_MASK P2WI_DATA_BYTE_4(0xff)
>> +#define P2WI_DATA_BYTE_5(n) (((n) & 0xff) << 0)
>> +#define P2WI_DATA_BYTE_5_MASK P2WI_DATA_BYTE_5(0xff)
>> +#define P2WI_DATA_BYTE_6(n) (((n) & 0xff) << 8)
>> +#define P2WI_DATA_BYTE_6_MASK P2WI_DATA_BYTE_6(0xff)
>> +#define P2WI_DATA_BYTE_7(n) (((n) & 0xff) << 16)
>> +#define P2WI_DATA_BYTE_7_MASK P2WI_DATA_BYTE_7(0xff)
>> +#define P2WI_DATA_BYTE_8(n) (((n) & 0xff) << 24)
>> +#define P2WI_DATA_BYTE_8_MASK P2WI_DATA_BYTE_8(0xff)
>> +
>> +#define P2WI_LINECTRL_SDA_CTRL_EN (0x1 << 0)
>> +#define P2WI_LINECTRL_SDA_OUT_HIGH (0x1 << 1)
>> +#define P2WI_LINECTRL_SCL_CTRL_EN (0x1 << 2)
>> +#define P2WI_LINECTRL_SCL_OUT_HIGH (0x1 << 3)
>> +#define P2WI_LINECTRL_SDA_STATE_HIGH (0x1 << 4)
>> +#define P2WI_LINECTRL_SCL_STATE_HIGH (0x1 << 5)
>> +
>> +#define P2WI_PM_DEV_ADDR(n) (((n) & 0xff) << 0)
>> +#define P2WI_PM_DEV_ADDR_MASK P2WI_PM_DEV_ADDR(0xff)
>> +#define P2WI_PM_CTRL_ADDR(n) (((n) & 0xff) << 8)
>> +#define P2WI_PM_CTRL_ADDR_MASK P2WI_PM_CTRL_ADDR(0xff)
>> +#define P2WI_PM_INIT_DATA(n) (((n) & 0xff) << 16)
>> +#define P2WI_PM_INIT_DATA_MASK P2WI_PM_INIT_DATA(0xff)
>> +#define P2WI_PM_INIT_SEND (0x1 << 31)
>> +
>> +struct sunxi_p2wi_reg {
>> + u32 ctrl; /* 0x00 control */
>> + u32 cc; /* 0x04 clock control */
>> + u32 irq; /* 0x08 interrupt */
>> + u32 status; /* 0x0c status */
>> + u32 dataddr0; /* 0x10 data address 0 */
>> + u32 dataddr1; /* 0x14 data address 1 */
>> + u32 numbytes; /* 0x18 num bytes */
>> + u32 data0; /* 0x1c data buffer 0 */
>> + u32 data1; /* 0x20 data buffer 1 */
>> + u32 linectrl; /* 0x24 line control */
>> + u32 pm; /* 0x28 power management */
>> +};
>
> Is there any reason not to put all of the above in the driver (.c) itself?
Not really, this is what all the axpXXX drivers also do, and I prefer it
this way as it keeps the .c file a lot more readable.
>> +
>> +void p2wi_init(void);
>> +int p2wi_set_pmu_address(u8 slave_addr, u8 ctrl_reg, u8 init_data);
>> +int p2wi_read(const u8 addr, u8 *data);
>> +int p2wi_write(const u8 addr, u8 data);
>> +
>> +#endif /* _SUNXI_P2WI_H */
>> --
>> 2.1.0
>
> Thanks for working on this! I haven't had time to mainline the p2wi driver.
You're welcome.
Regards,
Hans
next prev parent reply other threads:[~2014-11-05 12:59 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-03 15:34 [U-Boot] [PATCH 0/9] sun6i: dram-init & SPL support Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 1/9] sun6i: Add new p2wi controller driver Hans de Goede
2014-11-03 15:59 ` [U-Boot] [linux-sunxi] " Chen-Yu Tsai
2014-11-04 6:10 ` Olliver Schinagl
2014-11-04 6:31 ` Chen-Yu Tsai
2014-11-05 12:59 ` Hans de Goede [this message]
2014-11-03 15:34 ` [U-Boot] [PATCH 2/9] sun6i: Add basic axp221 driver Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 3/9] sun6i: Add clock functions needed for SPL / DRAM init Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 4/9] sun6i: Add cpucfg register definitions Hans de Goede
2014-11-03 16:05 ` [U-Boot] [linux-sunxi] " Chen-Yu Tsai
2014-11-05 15:30 ` Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 5/9] sun4i: Rename dram files to dram_sun4i.x Hans de Goede
2014-11-03 16:02 ` [U-Boot] [linux-sunxi] " Chen-Yu Tsai
2014-11-04 4:23 ` Julian Calaby
2014-11-05 15:31 ` Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 6/9] sun6i: Add dram initialization code Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 7/9] sun6i: Poke magic sram controller register to avoid cache issues Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 8/9] sun6i: Enable SPL Hans de Goede
2014-11-03 15:34 ` [U-Boot] [PATCH 9/9] sun6i: Add Mele M9 board Hans de Goede
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=545A1F34.1060204@redhat.com \
--to=hdegoede@redhat.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.