public inbox for linux-mmc@vger.kernel.org
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@arndb.de>
To: Greg KH <greg@kroah.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>,
	linux-kernel@vger.kernel.org, linux-mmc@vger.kernel.org,
	"linux-arm-msm@vger.kernel.org" <linux-arm-msm@vger.kernel.org>,
	Alexander Kolesnikov <akolesni@codeaurora.org>,
	Konstantin Dorfman <kdorfman@codeaurora.org>
Subject: Re: char interface to sdio, chdio.c
Date: Thu, 17 Jul 2014 12:17 +0200	[thread overview]
Message-ID: <7228146.FsqiNq1Vpj@wuerfel> (raw)
In-Reply-To: <20140717053347.GB22970@kroah.com>

On Wednesday 16 July 2014 22:33:47 Greg KH wrote:
> + mmc: Char SDIO Device Driver

A few comments on the ioctl interface, since I suppose we'll have
to live with that once it gets merged.

> +Interface
> +=========
> +The Char SDIO Device Driver has two char device interfaces:
> + - Control Interface;
> + - Function Interface.
> +
> +Char SDIO Device Driver Control Interface consists of:
> + - open()   - device node is /dev/csdio0;
> + - close()
> + - ioctl()  - the following options are available:
> +   - CSDIO_IOC_ENABLE_HIGHSPEED_MODE;
> +   - CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS;
> +   - CSDIO_IOC_ENABLE_ISR;
> +   - CSDIO_IOC_DISABLE_ISR.


The documentation doesn't match the code.:

CSDIO_IOC_GET/SET_VDD are implemented in the control device,
not the function device, and that is probably a good idea.
CSDIO_IOC_ENABLE_HIGHSPEED_MODE is not implemented
at all. CSDIO_IOC_ENABLE_ISR seems redundant with what
the CSDIO_IOC_{DIS,}CONNECT_ISR functions do, but I could be
wrong here.

The sysfs interface may actually be more appropriate than the
control node, if I was to pick one of the two.

> +Char SDIO Device Driver Function Interface consists of:
> + - open()  - device node is /dev/csdiofX, where X is Function Id;
> + - close()
> + - read()  - send CMD53 read;
> + - write() - send CMD53 write;
> + - ioctl() - the following options are available:
> +   - CSDIO_IOC_SET_OP_CODE - 0 fixed adrress, 1 autoincrement.
> +   - CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE;
> +   - CSDIO_IOC_SET_BLOCK_MODE - 0 byte mode, 1 block mode;
> +   - CSDIO_IOC_CMD52 - execute CMD52, receives the
> +        following structure as a parameter:
> +            struct csdio_cmd52_ctrl_t {
> +	            uint32_t    m_write; // 0 - read, 1 -write
> +	            uint32_t    m_address;
> +	            uint32_t    m_data;  // data to write or read data
> +	            uint32_t    m_ret;   // command execution status
> +            }__attribute__ ((packed));
> +   - CSDIO_IOC_CMD53 - setup CMD53 data transfer, receives the
> +        following structure as a parameter:
> +            struct csdio_cmd53_ctrl_t {
> +	            uint32_t    m_block_mode;
> +	            uint32_t    m_op_code;
> +	            uint32_t    m_address;
> +            }__attribute__ ((packed));
> +   - CSDIO_IOC_CONNECT_ISR;
> +   - CSDIO_IOC_DISCONNECT_ISR;
> +   - CSDIO_IOC_GET_VDD;
> +   - CSDIO_IOC_SET_VDD.
> +
> +Additionally, user space application can use fcntl system call with
> +parameters F_SETOWN and F_SETFL in order to set an asynchronous
> +callback for SDIO interrupt.

The read/write API seems very strange. SDIO has multiple ways of
passing data between OS and device using CMD52 and CMD53, and they
are all done differently here:

- A one-byte read or write uses a single CSDIO_IOC_CMD52 ioctl.
  This could be done using pread/pwrite with length '1' rather than
  an ioctl, if we want to.

- a byte-addressed multi-byte read/write needs to first 'seek' using
  CSDIO_IOC_CMD53 or and then transfer using read() or write().

- a block-addressed read/write is similar, but the number of bytes
  copied to/from user space is now multiplied with the block size (!).
  The block size needs to be set using both CSDIO_IOC_SET_BLOCK_MODE
  and CSDIO_IOC_CMD53, using the same value.

- to do a multi-byte read/write at a constant address rather than
  a block copy, CSDIO_IOC_CMD53 needs to set at least one bit (not
  necessarily the one used in the actual command) in m_op_code.

I guess all of this could be done using pread/pwrite, using the
loff_t value to encode the m_address in the lower bits and the
mode (single-byte, multi-byte, multi-byte auto-increment,
block, block auto-increment) in some of the upper bits.

Alternatively, the read/write functions could be removed completely
and everything be done in the ioctls, but in a more consistent
way.

> +
> +#define CSDIO_IOC_MAGIC  'm'
> +
> +#define CSDIO_IOC_ENABLE_HIGHSPEED_MODE      _IO(CSDIO_IOC_MAGIC, 0)
> +#define CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS   _IO(CSDIO_IOC_MAGIC, 1)
> +#define CSDIO_IOC_SET_OP_CODE                _IO(CSDIO_IOC_MAGIC, 2)
> +#define CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE    _IO(CSDIO_IOC_MAGIC, 3)
> +#define CSDIO_IOC_SET_BLOCK_MODE             _IO(CSDIO_IOC_MAGIC, 4)
> +#define CSDIO_IOC_CONNECT_ISR                _IO(CSDIO_IOC_MAGIC, 5)
> +#define CSDIO_IOC_DISCONNECT_ISR             _IO(CSDIO_IOC_MAGIC, 6)
> +#define CSDIO_IOC_CMD52                      _IO(CSDIO_IOC_MAGIC, 7)
> +#define CSDIO_IOC_CMD53                      _IO(CSDIO_IOC_MAGIC, 8)
> +#define CSDIO_IOC_ENABLE_ISR                 _IO(CSDIO_IOC_MAGIC, 9)
> +#define CSDIO_IOC_DISABLE_ISR                _IO(CSDIO_IOC_MAGIC, 10)
> +#define CSDIO_IOC_SET_VDD                    _IO(CSDIO_IOC_MAGIC, 11)
> +#define CSDIO_IOC_GET_VDD                    _IO(CSDIO_IOC_MAGIC, 12)
> +
> +#define CSDIO_IOC_MAXNR   12

The command codes above should use _IOR or _IOW where appropriate to
encode the size of the transferred data.

> +
> +struct csdio_cmd53_ctrl_t {
> +	uint32_t    m_block_mode;   /* data tran. byte(0)/block(1) mode */
> +	uint32_t    m_op_code;      /* address auto increment flag */
> +	uint32_t    m_address;
> +} __attribute__ ((packed));
> +
> +struct csdio_cmd52_ctrl_t {
> +	uint32_t    m_write;
> +	uint32_t    m_address;
> +	uint32_t    m_data;
> +	uint32_t    m_ret;
> +} __attribute__ ((packed));

The packing is not necessary here, but at least all of these are
compatible between 32 and 64 bit, so enabling compat mode is a one-line
change and requires no conversion.

	Arnd

  reply	other threads:[~2014-07-17 10:17 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-16  3:26 char interface to sdio, chdio.c Greg KH
2014-07-16 18:21 ` Stephen Boyd
2014-07-16 18:44   ` Greg KH
2014-07-16 19:38     ` Stephen Boyd
2014-07-16 23:08       ` Stephen Boyd
2014-07-16 23:11         ` Greg KH
2014-07-17  5:33         ` Greg KH
2014-07-17 10:17           ` Arnd Bergmann [this message]
2014-07-18  3:08             ` Greg KH

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=7228146.FsqiNq1Vpj@wuerfel \
    --to=arnd@arndb.de \
    --cc=akolesni@codeaurora.org \
    --cc=greg@kroah.com \
    --cc=kdorfman@codeaurora.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=sboyd@codeaurora.org \
    /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