From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 2/6] ARM: tegra: i2c: add slave mode support
Date: Tue, 29 Apr 2014 07:36:59 +0200 [thread overview]
Message-ID: <535F3A7B.5070802@denx.de> (raw)
In-Reply-To: <1398561270-25091-3-git-send-email-danindrey@mail.ru>
Hello Andrey,
Am 27.04.2014 03:14, schrieb Andrey Danin:
> Signed-off-by: Andrey Danin<danindrey@mail.ru>
> CC: Stephen Warren<swarren@nvidia.com>
> CC: Marc Dietrich<marvin24@gmx.de>
> CC: Julian Andres Klode<jak@jak-linux.org>
> CC: ac100 at lists.launchpad.net
> ---
> arch/arm/include/asm/arch-tegra/tegra_i2c.h | 6 +
> drivers/i2c/tegra_i2c.c | 199 ++++++++++++++++++++++++++-
> 2 files changed, 202 insertions(+), 3 deletions(-)
only some nitpicking comments ...
[...]
> diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
> index 594e5dd..287a5df 100644
> --- a/drivers/i2c/tegra_i2c.c
> +++ b/drivers/i2c/tegra_i2c.c
> @@ -22,6 +22,7 @@ DECLARE_GLOBAL_DATA_PTR;
> /* Information about i2c controller */
> struct i2c_bus {
> int id;
> + int node;
> enum periph_id periph_id;
> int speed;
> int pinmux_config;
> @@ -30,10 +31,31 @@ struct i2c_bus {
> int is_dvc; /* DVC type, rather than I2C */
> int is_scs; /* single clock source (T114+) */
> int inited; /* bus is inited */
> + int slave_addr;
> };
>
> static struct i2c_bus i2c_controllers[TEGRA_I2C_NUM_CONTROLLERS];
>
> +/**
> + * Init i2c controller to operate in slave mode.
> + *
> + * @param bus i2c bus/controller state struct
> + */
> +static void set_slave_mode(struct i2c_bus *bus)
> +{
> + unsigned long val;
> +
> + val = I2C_CNFG_NEW_MASTER_FSM_MASK | I2C_CNFG_PACKET_MODE_MASK |
> + I2C_CNFG_DEBOUNCE_CNT_MASK;
> + writel(val,&bus->regs->cnfg);
> +
> + writel(I2C_SL_CNFG_NEWSL_MASK,&bus->regs->sl_cnfg);
> + writel(0x1E,&bus->regs->sl_delay_count);
Space after "," please. Please check globally.
> +
> + writel(bus->slave_addr>> 1,&bus->regs->sl_addr1);
> + writel(0,&bus->regs->sl_addr2);
> +}
> +
> static void set_packet_mode(struct i2c_bus *i2c_bus)
> {
> u32 config;
> @@ -59,8 +81,12 @@ static void i2c_reset_controller(struct i2c_bus *i2c_bus)
> /* Reset I2C controller. */
> reset_periph(i2c_bus->periph_id, 1);
>
> - /* re-program config register to packet mode */
> - set_packet_mode(i2c_bus);
> + if (i2c_bus->slave_addr == 0) {
> + /* re-program config register to packet mode */
> + set_packet_mode(i2c_bus);
> + } else {
> + set_slave_mode(i2c_bus);
> + }
> }
>
> static void i2c_init_controller(struct i2c_bus *i2c_bus)
> @@ -193,6 +219,121 @@ static int wait_for_transfer_complete(struct i2c_control *control)
> return -1;
> }
>
> +
> +#define I2C_SL_IRQ (1<<3)
> +#define END_TRANS (1<<4)
> +#define RCVD (1<<2)
> +#define RNW (1<<1)
> +
> +
only one empty line please. Please check globally.
> +static inline int is_ready(unsigned long status)
> +{
> + return status& I2C_SL_IRQ;
> +}
> +
> +static inline int is_read(unsigned long status)
> +{
> + return (status& RNW) == 0;
> +}
> +
> +static inline int is_trans_start(unsigned long status)
> +{
> + return status& RCVD;
> +}
> +
> +static inline int is_trans_end(unsigned long status)
> +{
> + return status& END_TRANS;
> +}
> +
> +
> +/**
> + * Send or receive packet in slave mode.
> + *
> + * @param i2c_bus pointer to bus structure
> + * @param trans I2C transaction object
> + *
> + * @return 0 if succeeded,
> + * 1 if not ready,
> + * 2 if operation timed out,
> + * 3 if not our packet,
> + * other - unknown error.
> + */
See my reply to your patch 1/6. Can we use negativ error codes and
defines?
> +static int slave_send_recv_packets(struct i2c_bus *i2c_bus,
> + struct i2c_transaction *trans)
> +{
> + unsigned int poll_start_ms = 0;
> + unsigned long status;
> +
> + unsigned int received = 0;
> + unsigned int to_send = 0;
> + unsigned int timer_ms = 0;
> + int addr = -1;
> +
> + poll_start_ms = get_timer(0);
> +
> + while (1) {
> + status = readl(&i2c_bus->regs->sl_status);
> + if (!is_ready(status)) {
> + timer_ms = get_timer(poll_start_ms);
> + if (addr != i2c_bus->slave_addr&&
> + trans->start_timeout&&
> + timer_ms> trans->start_timeout) {
please add a space before "&&" and ">". Please check globally.
> + trans->res = 1;
> + return 1; /*not ready*/
> + }
> +
> + if (timer_ms> trans->timeout) {
> + trans->res = 2;
> + return 2; /*timeout*/
> + }
> +
> + udelay(100);
> + continue;
> + }
> +
> + if (!is_trans_start(status)&& addr != i2c_bus->slave_addr) {
> + trans->res = 3;
> + return 3; /* not our packet, retry */
> + }
> +
> + if (is_trans_start(status)) {
> + if (!is_read(status)&& addr != i2c_bus->slave_addr) {
> + trans->res = 3;
> + return 3; /* not our packet, retry */
> + }
> + if (is_read(status)) {
> + addr = readl(&i2c_bus->regs->sl_rcvd);
> + trans->rx_buf[trans->rx_pos++] = addr;
> + continue;
> + }
> + }
> +
> + if (is_trans_end(status)) {
> + /* Check for repeated start */
> + if (!is_trans_start(status)) {
> + trans->res = 0;
> + return 0;
> + }
> + }
> +
> + if (is_read(status)) {
> + /* TODO Check sizes */
> + received = readl(&i2c_bus->regs->sl_rcvd);
> + trans->rx_buf[trans->rx_pos++] = received;
> + } else {
> + /* TODO Check sizes */
> + to_send = trans->tx_buf[trans->tx_pos++];
> + writel(to_send,&i2c_bus->regs->sl_rcvd);
> + }
> + }
> +
> + /* not reachable */
> + trans->res = 4;
> + return 4;
What is error code 4? Please use defines ...
> +}
> +
> +
> static int send_recv_packets(struct i2c_bus *i2c_bus,
> struct i2c_trans_info *trans)
> {
> @@ -343,6 +484,7 @@ static unsigned int tegra_i2c_set_bus_speed(struct i2c_adapter *adap,
>
> static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus)
> {
> + i2c_bus->node = node;
> i2c_bus->regs = (struct i2c_ctlr *)fdtdec_get_addr(blob, node, "reg");
>
> /*
> @@ -365,6 +507,8 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus)
> if (i2c_bus->periph_id == -1)
> return -FDT_ERR_NOTFOUND;
>
> + i2c_bus->slave_addr = fdtdec_get_int(blob, node, "slave-addr", -1);
> +
> return 0;
> }
>
> @@ -422,6 +566,28 @@ static int process_nodes(const void *blob, int node_list[], int count,
> return 0;
> }
>
> +static int tegra_i2c_slave_io(struct i2c_adapter *adap,
> + struct i2c_transaction *trans)
> +{
> + struct i2c_bus *bus;
> + debug("tegra_i2c_slave_io: hwadapnr=%d\n", adap->hwadapnr);
> +
> + bus = tegra_i2c_get_bus(adap);
> + if (!bus) {
> + error("tegra_i2c_slave_io: no bus for adapter %d\n",
> + adap->hwadapnr);
> + return -1;
> + }
> +
> + if (!bus->slave_addr) {
> + error("tegra_i2c_slave_io: adapter %d isn't in slave mode\n",
> + adap->hwadapnr);
> + return -2;
> + }
> +
> + return slave_send_recv_packets(bus, trans);
> +}
> +
> /* Sadly there is no error return from this function */
> void i2c_init_board(void)
> {
> @@ -453,11 +619,20 @@ void i2c_init_board(void)
>
> static void tegra_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
> {
> + struct i2c_bus *bus;
> +
> /* No i2c support prior to relocation */
> if (!(gd->flags& GD_FLG_RELOC))
> return;
>
> - /* This will override the speed selected in the fdt for that port */
> + bus = tegra_i2c_get_bus(adap);
> + if (bus) {
> + adap->slave_io = tegra_i2c_slave_io;
> + debug("i2c_init: ignore static init for adapter %d\n",
> + adap->hwadapnr);
> + return;
> + }
> +
> debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
> i2c_set_bus_speed(speed);
> }
> @@ -614,6 +789,24 @@ int tegra_i2c_get_dvc_bus_num(void)
> return -1;
> }
>
> +/**
> + * Find the I2C bus number by given a FDT I2C node.
> + *
> + * @param blob Device tree blbo
> + * @param node FDT I2C node to find
> + * @return the number of I2C bus (zero based), or -1 on error
> + */
> +int i2c_get_bus_num_fdt(int node)
> +{
> + int i;
> +
> + for (i = 0; i< TEGRA_I2C_NUM_CONTROLLERS; ++i)
> + if (i2c_controllers[i].node == node)
> + return i2c_controllers[i].id;
> +
> + return -1;
> +}
> +
> /*
> * Register soft i2c adapters
> */
bye,
Heiko
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
next prev parent reply other threads:[~2014-04-29 5:36 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <[PATCH 0/3] ARM: tegra: add nvec keyboard support for paz00>
2014-04-27 1:14 ` [U-Boot] [PATCH v2 0/6] ARM: tegra: add nvec keyboard support for paz00 Andrey Danin
2014-04-27 1:14 ` [U-Boot] [PATCH v2 1/6] i2c: add slave mode support Andrey Danin
2014-04-28 23:06 ` [U-Boot] [Ac100] " Stephen Warren
2014-04-30 5:31 ` Andrey Danin
2014-04-29 5:30 ` [U-Boot] " Heiko Schocher
2014-04-27 1:14 ` [U-Boot] [PATCH v2 2/6] ARM: tegra: " Andrey Danin
2014-04-29 5:36 ` Heiko Schocher [this message]
2014-04-27 1:14 ` [U-Boot] [PATCH v2 3/6] ARM: tegra: i2c: add nvec driver Andrey Danin
2014-04-29 5:43 ` Heiko Schocher
2014-04-29 7:15 ` Andrey Danin
2014-04-29 8:07 ` Heiko Schocher
2014-04-27 1:14 ` [U-Boot] [PATCH v2 4/6] ARM: tegra: nvec: add keyboard support Andrey Danin
2014-04-28 23:23 ` [U-Boot] [Ac100] " Stephen Warren
2014-04-27 1:14 ` [U-Boot] [PATCH v2 5/6] ARM: tegra: paz00: add dt bindings for nvec Andrey Danin
2014-04-28 23:04 ` [U-Boot] [Ac100] " Stephen Warren
2014-04-30 7:52 ` [U-Boot] [Ac100] [PATCH v2 5/6] ARM: tegra: paz00: add dtbindings " Marc Dietrich
2014-04-30 16:21 ` Stephen Warren
2014-04-30 21:03 ` [U-Boot] [Ac100] [PATCH v2 5/6] ARM: tegra: paz00: add dtbindingsfor nvec Marc Dietrich
2014-04-27 1:14 ` [U-Boot] [PATCH v2 6/6] ARM: tegra: paz00: enable nvec keyboard Andrey Danin
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=535F3A7B.5070802@denx.de \
--to=hs@denx.de \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox