Re: [PATCH] smsc95xx: Add module parameter to override MAC address

2010-06-25 Thread Sebastien Jan
On 06/25/2010 03:25 AM, Simon Horman wrote:
 On Thu, Jun 24, 2010 at 10:14:14AM +0200, Sebastien Jan wrote:
 Define a new module parameter 'macaddr' to override the MAC address
 fetched either from eeprom, or randomly generated.

 The expected MAC address shall be in the 01:23:45:67:89:AB format.
 
 I'm confused as to why this is desirable when the mac address
 can already be configured after module insertion via
 smsc95xx_netdev_ops.eth_mac_addr().

For example for booting over NFS using a pre-defined MAC address, with 
a minimal setup (no initrd). Or is there another way to force a MAC
address for this use-case?
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] smsc95xx: Add module parameter to override MAC address

2010-06-25 Thread Sebastien Jan
Hi Steve,

Thanks for your answer.

On 06/25/2010 10:43 AM, steve.glendinn...@smsc.com wrote:
[...]
 I can see you have a different use case, but I don't think this specific
 driver is the place for this logic.  I'd rather see it added to either
 the usbnet framework or (preferably) the netdev framework so *all*
 ethernet drivers can do this the same way.  otherwise we could end up
 with slight variations of this code in every single driver!

I perfectly understand your concerns. Unfortunately, I will probably not be
able to implement these changes into the netdev framework. However, I'd be 
happy to make some tests if someone proposes such changes.

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] smsc95xx: Add module parameter to override MAC address

2010-06-24 Thread Sebastien Jan
Define a new module parameter 'macaddr' to override the MAC address
fetched either from eeprom, or randomly generated.

The expected MAC address shall be in the 01:23:45:67:89:AB format.

Signed-off-by: Sebastien Jan s-...@ti.com
---
 drivers/net/usb/smsc95xx.c |   56 
 1 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 3135af6..0ba06d9 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -46,6 +46,7 @@
 #define SMSC95XX_INTERNAL_PHY_ID   (1)
 #define SMSC95XX_TX_OVERHEAD   (8)
 #define SMSC95XX_TX_OVERHEAD_CSUM  (12)
+#define MAC_ADDR_LEN   (6)
 
 struct smsc95xx_priv {
u32 mac_cr;
@@ -63,6 +64,10 @@ static int turbo_mode = true;
 module_param(turbo_mode, bool, 0644);
 MODULE_PARM_DESC(turbo_mode, Enable multiple frames per Rx transaction);
 
+static char *macaddr = :;
+module_param(macaddr, charp, 0);
+MODULE_PARM_DESC(macaddr, MAC address);
+
 static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
 {
u32 *buf = kmalloc(4, GFP_KERNEL);
@@ -637,8 +642,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, 
struct ifreq *rq, int cmd)
return generic_mii_ioctl(dev-mii, if_mii(rq), cmd, NULL);
 }
 
+/* Check the macaddr module parameter for a MAC address */
+static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac)
+{
+   int i, j, got_num, num;
+   u8 mtbl[MAC_ADDR_LEN];
+
+   if (macaddr[0] == ':')
+   return 0;
+
+   i = 0;
+   j = 0;
+   num = 0;
+   got_num = 0;
+   while (j  MAC_ADDR_LEN) {
+   if (macaddr[i]  macaddr[i] != ':') {
+   got_num++;
+   if ('0' = macaddr[i]  macaddr[i] = '9')
+   num = num * 16 + macaddr[i] - '0';
+   else if ('A' = macaddr[i]  macaddr[i] = 'F')
+   num = num * 16 + 10 + macaddr[i] - 'A';
+   else if ('a' = macaddr[i]  macaddr[i] = 'f')
+   num = num * 16 + 10 + macaddr[i] - 'a';
+   else
+   break;
+   i++;
+   } else if (got_num == 2) {
+   mtbl[j++] = (u8) num;
+   num = 0;
+   got_num = 0;
+   i++;
+   } else {
+   break;
+   }
+   }
+
+   if (j == MAC_ADDR_LEN  !macaddr[i]) {
+   netif_dbg(dev, ifup, dev-net, Overriding MAC address with: 
+   %02x:%02x:%02x:%02x:%02x:%02x\n, mtbl[0], mtbl[1], mtbl[2],
+   mtbl[3], mtbl[4], mtbl[5]);
+   for (i = 0; i  MAC_ADDR_LEN; i++)
+   dev_mac[i] = mtbl[i];
+   return 1;
+   } else {
+   return 0;
+   }
+}
+
 static void smsc95xx_init_mac_address(struct usbnet *dev)
 {
+   /* Check module parameters */
+   if (smsc95xx_is_macaddr_param(dev, dev-net-dev_addr))
+   return;
+
/* try reading mac address from EEPROM */
if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
dev-net-dev_addr) == 0) {
-- 
1.6.3.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCHv2 2/7] OMAP SSI: Introducing OMAP SSI driver

2010-05-18 Thread Sebastien Jan
On Tuesday 18 May 2010 11:07:20 Carlos Chinea wrote:
[cut]
   +   val |= __raw_readl(omap_ssi-sys +
   SSI_MPU_ENABLE_REG(port-num, 0)); +   __raw_writel(val,
   omap_ssi-sys +
SSI_MPU_ENABLE_REG(port-num, 0)); +
   +   msg-status = HSI_STATUS_COMPLETED;
   +   msg-actual_len = sg_dma_len(msg-sgt.sgl);
   +   spin_unlock(omap_ssi-lock);
   +}
 
  Don't you need to check the queue related to this transfer at this point,
  to start the potentially next queued transfer on the same channel?
  (calling ssi_start_transfer(), like in ssi_pio_complete()?)
 
 No this is done in ssi_pio_complete(). Notice that we do not call the
 complete callback at any point here. We just arm the pio interrupt for
 that channel and transfer direction. AFAIK, this is the SW logic
 expected by the OMAP SSI HW.

Ok, though I would not expect the interrupt to fire in an Rx scenario as the 
fifo would have already been emptied by the DMA for this transfer (unless you 
rely on the next transfer initiated by the peer to make the Rx interrupt fire 
on this channel?)?
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCHv2 1/7] HSI: Introducing HSI framework

2010-05-14 Thread Sebastien Jan
Hi Carlos,

After review, I do not have many comments on the interface, as we already 
aligned on most of it.

Please see my comments inlined below.

On Friday 07 May 2010 17:18:31 Carlos Chinea wrote:
[strip]
 diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h
[strip]
 +/**
 + * hsi_start_tx - Signal the port that the client wants to start a TX
 + * @cl: Pointer to the HSI client
 + *
 + * Return -errno on failure, 0 on success
 + */
 +static inline int hsi_start_tx(struct hsi_client *cl)
 +{
 +   if (!hsi_port_claimed(cl))
 +   return -EACCES;
 +   return hsi_get_port(cl)-start_tx(cl);
 +}
 +
 +/**
 + * hsi_stop_tx - Signal the port that the client no longer wants to
  transmit + * @cl: Pointer to the HSI client
 + *
 + * Return -errno on failure, 0 on success
 + */
 +static inline int hsi_stop_tx(struct hsi_client *cl)
 +{
 +   if (!hsi_port_claimed(cl))
 +   return -EACCES;
 +   return hsi_get_port(cl)-stop_tx(cl);
 +}

As I can see, these two I/F functions are the way an HSI protocol layer can 
play with Tx_wake lines if it has to, right? 
I suppose it allows more flexibility with regards to 3/4 wires HSI flavors 
management and avoids additional callbacks to Tx_wake related events?

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/4 v2] ks8851: read/write MAC address on companion eeprom through debugfs

2010-05-06 Thread Sebastien Jan
Hi david,

On Thursday 06 May 2010 09:25:08 David Miller wrote:
 From: Sebastien Jan s-...@ti.com
 Date: Wed,  5 May 2010 20:45:55 +0200
 
  A more elegant alternative to ethtool for updating the ks8851
  MAC address stored on its companion eeprom.
  Using this debugfs interface does not require any knowledge on the
  ks8851 companion eeprom organization to update the MAC address.
 
  Example to write 01:23:45:67:89:AB MAC address to the companion
  eeprom (assuming debugfs is mounted in /sys/kernel/debug):
  $ echo 01:23:45:67:89:AB  /sys/kernel/debug/ks8851/mac_eeprom
 
  Signed-off-by: Sebastien Jan s-...@ti.com
 
 Elegant?  This commit message is the biggest lie ever told.
 
 What makes your ethernet driver so god-damn special that it deserves
 to have a private, completely unique, and obscure interface for
 setting the permanent ethernet address of a network device?
 
 Tell me how damn elegant it is that users have to learn about this
 special, unique, and common with no other driver, interface for
 performing this task?
 
 Tell me how damn elegant it is when another driver wants to provide
 users with a way to do this too, and they (like you) come up with
 their own unique and different interface for doing this.
 
 No, this is the most inelegant patch ever conceived because it totally
 ignores the way in which we handle issues like this.
 
 There is no way in the world I'm applying this garbage patch, sorry.
 
 We have an ETHTOOL_GPERMADDR, add a new ETHTOOL_SPERMADDR operation
 and then any driver (not just your's) can portably provide this
 facility and users will have one, and only one, way of performing this
 task.
 

I agree that my commit message was probably too provocative, sorry for that.

Thank you for shedding some light on ETHTOOL_GPERMADDR and ETHTOOL_SPERMADDR. 
I will look into these interfaces for a proper and generic implementation.
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4 v2] ks8851: Add caching of CCR register

2010-05-05 Thread Sebastien Jan
CCR register contains information on companion eeprom availability.

Signed-off-by: Sebastien Jan s-...@ti.com
---
 drivers/net/ks8851.c |   12 
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index 9e9f9b3..a84e500 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -76,7 +76,9 @@ union ks8851_tx_hdr {
  * @msg_enable: The message flags controlling driver output (see ethtool).
  * @fid: Incrementing frame id tag.
  * @rc_ier: Cached copy of KS_IER.
+ * @rc_ccr: Cached copy of KS_CCR.
  * @rc_rxqcr: Cached copy of KS_RXQCR.
+ * @eeprom_size: Companion eeprom size in Bytes, 0 if no eeprom
  *
  * The @lock ensures that the chip is protected when certain operations are
  * in progress. When the read or write packet transfer is in progress, most
@@ -107,6 +109,8 @@ struct ks8851_net {
 
u16 rc_ier;
u16 rc_rxqcr;
+   u16 rc_ccr;
+   u16 eeprom_size;
 
struct mii_if_info  mii;
struct ks8851_rxctrlrxctrl;
@@ -1279,6 +1283,14 @@ static int __devinit ks8851_probe(struct spi_device *spi)
goto err_id;
}
 
+   /* cache the contents of the CCR register for EEPROM, etc. */
+   ks-rc_ccr = ks8851_rdreg16(ks, KS_CCR);
+
+   if (ks-rc_ccr  CCR_EEPROM)
+   ks-eeprom_size = 128;
+   else
+   ks-eeprom_size = 0;
+
ks8851_read_selftest(ks);
ks8851_init_mac(ks);
 
-- 
1.6.3.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/4 v2] ks8851: Low level functions for read/write to companion eeprom

2010-05-05 Thread Sebastien Jan
Low-level functions provide 16bits words read and write capability
to ks8851 companion eeprom.

Signed-off-by: Sebastien Jan s-...@ti.com
---
 drivers/net/ks8851.c |  228 ++
 drivers/net/ks8851.h |   14 +++-
 2 files changed, 241 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index a84e500..787f9df 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -1044,6 +1044,234 @@ static const struct net_device_ops ks8851_netdev_ops = {
.ndo_validate_addr  = eth_validate_addr,
 };
 
+/* Companion eeprom access */
+
+enum { /* EEPROM programming states */
+   EEPROM_CONTROL,
+   EEPROM_ADDRESS,
+   EEPROM_DATA,
+   EEPROM_COMPLETE
+};
+
+/**
+ * ks8851_eeprom_read - read a 16bits word in ks8851 companion EEPROM
+ * @dev: The network device the PHY is on.
+ * @addr: EEPROM address to read
+ *
+ * eeprom_size: used to define the data coding length. Can be changed
+ * through debug-fs.
+ *
+ * Programs a read on the EEPROM using ks8851 EEPROM SW access feature.
+ * Warning: The READ feature is not supported on ks8851 revision 0.
+ *
+ * Rough programming model:
+ *  - on period start: set clock high and read value on bus
+ *  - on period / 2: set clock low and program value on bus
+ *  - start on period / 2
+ */
+unsigned int ks8851_eeprom_read(struct net_device *dev, unsigned int addr)
+{
+   struct ks8851_net *ks = netdev_priv(dev);
+   int eepcr;
+   int ctrl = EEPROM_OP_READ;
+   int state = EEPROM_CONTROL;
+   int bit_count = EEPROM_OP_LEN - 1;
+   unsigned int data = 0;
+   int dummy;
+   unsigned int addr_len;
+
+   addr_len = (ks-eeprom_size == 128) ? 6 : 8;
+
+   /* start transaction: chip select high, authorize write */
+   mutex_lock(ks-lock);
+   eepcr = EEPCR_EESA | EEPCR_EESRWA;
+   ks8851_wrreg16(ks, KS_EEPCR, eepcr);
+   eepcr |= EEPCR_EECS;
+   ks8851_wrreg16(ks, KS_EEPCR, eepcr);
+   mutex_unlock(ks-lock);
+
+   while (state != EEPROM_COMPLETE) {
+   /* falling clock period starts... */
+   /* set EED_IO pin for control and address */
+   eepcr = ~EEPCR_EEDO;
+   switch (state) {
+   case EEPROM_CONTROL:
+   eepcr |= ((ctrl  bit_count)  1)  2;
+   if (bit_count-- = 0) {
+   bit_count = addr_len - 1;
+   state = EEPROM_ADDRESS;
+   }
+   break;
+   case EEPROM_ADDRESS:
+   eepcr |= ((addr  bit_count)  1)  2;
+   bit_count--;
+   break;
+   case EEPROM_DATA:
+   /* Change to receive mode */
+   eepcr = ~EEPCR_EESRWA;
+   break;
+   }
+
+   /* lower clock  */
+   eepcr = ~EEPCR_EESCK;
+
+   mutex_lock(ks-lock);
+   ks8851_wrreg16(ks, KS_EEPCR, eepcr);
+   mutex_unlock(ks-lock);
+
+   /* waitread period / 2 */
+   udelay(EEPROM_SK_PERIOD / 2);
+
+   /* rising clock period starts... */
+
+   /* raise clock */
+   mutex_lock(ks-lock);
+   eepcr |= EEPCR_EESCK;
+   ks8851_wrreg16(ks, KS_EEPCR, eepcr);
+   mutex_unlock(ks-lock);
+
+   /* Manage read */
+   switch (state) {
+   case EEPROM_ADDRESS:
+   if (bit_count  0) {
+   bit_count = EEPROM_DATA_LEN - 1;
+   state = EEPROM_DATA;
+   }
+   break;
+   case EEPROM_DATA:
+   mutex_lock(ks-lock);
+   dummy = ks8851_rdreg16(ks, KS_EEPCR);
+   mutex_unlock(ks-lock);
+   data |= ((dummy  EEPCR_EESB_OFFSET)  1)  bit_count;
+   if (bit_count-- = 0)
+   state = EEPROM_COMPLETE;
+   break;
+   }
+
+   /* wait period / 2 */
+   udelay(EEPROM_SK_PERIOD / 2);
+   }
+
+   /* close transaction */
+   mutex_lock(ks-lock);
+   eepcr = ~EEPCR_EECS;
+   ks8851_wrreg16(ks, KS_EEPCR, eepcr);
+   eepcr = 0;
+   ks8851_wrreg16(ks, KS_EEPCR, eepcr);
+   mutex_unlock(ks-lock);
+
+   return data;
+}
+
+/**
+ * ks8851_eeprom_write - write a 16bits word in ks8851 companion EEPROM
+ * @dev: The network device the PHY is on.
+ * @op: operand (can be WRITE, EWEN, EWDS)
+ * @addr: EEPROM address to write
+ * @data: data to write
+ *
+ * eeprom_size: used to define the data coding length. Can be changed
+ * through debug-fs.
+ *
+ * Programs a write on the EEPROM using ks8851 EEPROM SW access feature.
+ *
+ * Note

[PATCH 3/4 v2] ks8851: companion eeprom access through ethtool

2010-05-05 Thread Sebastien Jan
Accessing ks8851 companion eeprom permits modifying the ks8851 stored
MAC address.

Example how to change the MAC address using ethtool, to set the
01:23:45:67:89:AB MAC address:
$ echo 0:AB8976452301 | xxd -r  mac.bin
$ sudo ethtool -E eth0 magic 0x8870 offset 2  mac.bin

Signed-off-by: Sebastien Jan s-...@ti.com
---
 drivers/net/ks8851.c |  114 ++
 1 files changed, 114 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index 787f9df..8e38c36 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -1318,6 +1318,117 @@ static int ks8851_nway_reset(struct net_device *dev)
return mii_nway_restart(ks-mii);
 }
 
+static int ks8851_get_eeprom_len(struct net_device *dev)
+{
+   struct ks8851_net *ks = netdev_priv(dev);
+   return ks-eeprom_size;
+}
+
+static int ks8851_get_eeprom(struct net_device *dev,
+   struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+   struct ks8851_net *ks = netdev_priv(dev);
+   u16 *eeprom_buff;
+   int first_word;
+   int last_word;
+   int ret_val = 0;
+   u16 i;
+
+   if (eeprom-len == 0)
+   return -EINVAL;
+
+   if (eeprom-len  ks-eeprom_size)
+   return -EINVAL;
+
+   eeprom-magic = ks8851_rdreg16(ks, KS_CIDER);
+
+   first_word = eeprom-offset  1;
+   last_word = (eeprom-offset + eeprom-len - 1)  1;
+
+   eeprom_buff = kmalloc(sizeof(u16) *
+   (last_word - first_word + 1), GFP_KERNEL);
+   if (!eeprom_buff)
+   return -ENOMEM;
+
+   for (i = 0; i  last_word - first_word + 1; i++)
+   eeprom_buff[i] = ks8851_eeprom_read(dev, first_word + 1);
+
+   /* Device's eeprom is little-endian, word addressable */
+   for (i = 0; i  last_word - first_word + 1; i++)
+   le16_to_cpus(eeprom_buff[i]);
+
+   memcpy(bytes, (u8 *)eeprom_buff + (eeprom-offset  1), eeprom-len);
+   kfree(eeprom_buff);
+
+   return ret_val;
+}
+
+static int ks8851_set_eeprom(struct net_device *dev,
+   struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+   struct ks8851_net *ks = netdev_priv(dev);
+   u16 *eeprom_buff;
+   void *ptr;
+   int max_len;
+   int first_word;
+   int last_word;
+   int ret_val = 0;
+   u16 i;
+
+   if (eeprom-len == 0)
+   return -EOPNOTSUPP;
+
+   if (eeprom-len  ks-eeprom_size)
+   return -EINVAL;
+
+   if (eeprom-magic != ks8851_rdreg16(ks, KS_CIDER))
+   return -EFAULT;
+
+   first_word = eeprom-offset  1;
+   last_word = (eeprom-offset + eeprom-len - 1)  1;
+   max_len = (last_word - first_word + 1) * 2;
+   eeprom_buff = kmalloc(max_len, GFP_KERNEL);
+   if (!eeprom_buff)
+   return -ENOMEM;
+
+   ptr = (void *)eeprom_buff;
+
+   if (eeprom-offset  1) {
+   /* need read/modify/write of first changed EEPROM word */
+   /* only the second byte of the word is being modified */
+   eeprom_buff[0] = ks8851_eeprom_read(dev, first_word);
+   ptr++;
+   }
+   if ((eeprom-offset + eeprom-len)  1)
+   /* need read/modify/write of last changed EEPROM word */
+   /* only the first byte of the word is being modified */
+   eeprom_buff[last_word - first_word] =
+   ks8851_eeprom_read(dev, last_word);
+
+
+   /* Device's eeprom is little-endian, word addressable */
+   le16_to_cpus(eeprom_buff[0]);
+   le16_to_cpus(eeprom_buff[last_word - first_word]);
+
+   memcpy(ptr, bytes, eeprom-len);
+
+   for (i = 0; i  last_word - first_word + 1; i++)
+   eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
+
+   ks8851_eeprom_write(dev, EEPROM_OP_EWEN, 0, 0);
+
+   for (i = 0; i  last_word - first_word + 1; i++) {
+   ks8851_eeprom_write(dev, EEPROM_OP_WRITE, first_word + i,
+   eeprom_buff[i]);
+   mdelay(EEPROM_WRITE_TIME);
+   }
+
+   ks8851_eeprom_write(dev, EEPROM_OP_EWDS, 0, 0);
+
+   kfree(eeprom_buff);
+   return ret_val;
+}
+
 static const struct ethtool_ops ks8851_ethtool_ops = {
.get_drvinfo= ks8851_get_drvinfo,
.get_msglevel   = ks8851_get_msglevel,
@@ -1326,6 +1437,9 @@ static const struct ethtool_ops ks8851_ethtool_ops = {
.set_settings   = ks8851_set_settings,
.get_link   = ks8851_get_link,
.nway_reset = ks8851_nway_reset,
+   .get_eeprom_len = ks8851_get_eeprom_len,
+   .get_eeprom = ks8851_get_eeprom,
+   .set_eeprom = ks8851_set_eeprom,
 };
 
 /* MII interface controls */
-- 
1.6.3.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http

[PATCH 4/4 v2] ks8851: read/write MAC address on companion eeprom through debugfs

2010-05-05 Thread Sebastien Jan
A more elegant alternative to ethtool for updating the ks8851
MAC address stored on its companion eeprom.
Using this debugfs interface does not require any knowledge on the
ks8851 companion eeprom organization to update the MAC address.

Example to write 01:23:45:67:89:AB MAC address to the companion
eeprom (assuming debugfs is mounted in /sys/kernel/debug):
$ echo 01:23:45:67:89:AB  /sys/kernel/debug/ks8851/mac_eeprom

Signed-off-by: Sebastien Jan s-...@ti.com
---
 drivers/net/ks8851.c |  216 ++
 1 files changed, 216 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index 8e38c36..1b62ec5 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -22,6 +22,11 @@
 
 #include linux/spi/spi.h
 
+#ifdef CONFIG_DEBUG_FS
+#include linux/debugfs.h
+#include linux/ctype.h
+#endif
+
 #include ks8851.h
 
 /**
@@ -1550,6 +1555,214 @@ static int ks8851_read_selftest(struct ks8851_net *ks)
return 0;
 }
 
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *ks8851_dir;
+
+static int ks8851_mac_eeprom_open(struct inode *inode, struct file *file)
+{
+   file-private_data = inode-i_private;
+   return 0;
+}
+
+static int ks8851_mac_eeprom_release(struct inode *inode, struct file *file)
+{
+   return 0;
+}
+
+static loff_t ks8851_mac_eeprom_seek(struct file *file, loff_t off, int whence)
+{
+   return 0;
+}
+
+/**
+ * ks8851_mac_eeprom_read - Read a MAC address in ks8851 companion EEPROM
+ *
+ * Warning: The READ feature is not supported on ks8851 revision 0.
+ */
+static ssize_t ks8851_mac_eeprom_read(struct file *filep, char __user *buff,
+   size_t count, loff_t *offp)
+{
+   ssize_t ret;
+   struct net_device *dev = filep-private_data;
+   char str[50];
+   unsigned int data;
+   unsigned char mac_addr[6];
+
+   if (*offp  0) {
+   ret = 0;
+   goto ks8851_cnt_rd_bk;
+   }
+
+   data = ks8851_eeprom_read(dev, 1);
+   mac_addr[5] = data  0xFF;
+   mac_addr[4] = (data  8)  0xFF;
+   data = ks8851_eeprom_read(dev, 2);
+   mac_addr[3] = data  0xFF;
+   mac_addr[2] = (data  8)  0xFF;
+   data = ks8851_eeprom_read(dev, 3);
+   mac_addr[1] = data  0xFF;
+   mac_addr[0] = (data  8)  0xFF;
+
+   sprintf(str, %02x:%02x:%02x:%02x:%02x:%02x\n, mac_addr[0],
+   mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4],
+   mac_addr[5]);
+
+   ret = strlen(str);
+
+   if (copy_to_user((void __user *)buff, str, ret)) {
+   dev_err(dev-dev, ks8851 - copy_to_user failed\n);
+   ret = 0;
+   } else {
+   *offp = ret;
+   }
+
+ks8851_cnt_rd_bk:
+   return ret;
+}
+
+/*
+ * Split the buffer `buf' into ':'-separated words.
+ * Return the number of words or 0 on error.
+ */
+#define isdelimiter(c) ((c) == ':')
+static int ks8851_debug_tokenize(char *buf, char *words[], int maxwords)
+{
+   int nwords = 0;
+
+   while (*buf) {
+   char *end;
+
+   /* Skip leading whitespace */
+   while (*buf  isspace(*buf))
+   buf++;
+   if (!*buf)
+   break;  /* oh, it was trailing whitespace */
+
+   /* Run `end' over a word */
+   for (end = buf ; *end  !isdelimiter(*end) ; end++)
+   ;
+   /* `buf' is the start of the word, `end' is one past the end */
+
+   if (nwords == maxwords)
+   return -EINVAL; /* ran out of words[] before bytes */
+   if (*end)
+   *end++ = '\0';  /* terminate the word */
+   words[nwords++] = buf;
+   buf = end;
+   }
+   return nwords;
+}
+
+/**
+ * ks8851_mac_eeprom_write - Write a MAC address in ks8851 companion EEPROM
+ *
+ */
+static ssize_t ks8851_mac_eeprom_write(struct file *filep,
+   const char __user *buff, size_t count, loff_t *offp)
+{
+   struct net_device *dev = filep-private_data;
+   ssize_t ret;
+#define MAXWORDS 6
+   int nwords, i;
+   char *words[MAXWORDS];
+   char tmpbuf[256];
+   unsigned long mac_addr[6];
+
+   if (count == 0)
+   return 0;
+   if (count  sizeof(tmpbuf)-1)
+   return -E2BIG;
+   if (copy_from_user(tmpbuf, buff, count))
+   return -EFAULT;
+   tmpbuf[count] = '\0';
+   dev_dbg(dev-dev, %s: read %d bytes from userspace\n,
+   __func__, (int)count);
+
+   nwords = ks8851_debug_tokenize(tmpbuf, words, MAXWORDS);
+   if (nwords != 6) {
+   dev_warn(dev-dev,
+   ks8851 MAC address write to EEPROM requires a MAC address  \
+   like 01:23:45:67:89:AB\n);
+   return -EINVAL

[RFC PATCH 0/9] MIPI HSI device support for OMAP platforms

2009-10-30 Thread Sebastien Jan
This is an RFC for a series of patch to add the support of MIPI HSI and SSI
devices to OMAP platforms.
The patch includes the HSI device driver and the device files for MIPI HSI and
SSI.

The driver is made of 2 distinct modules:
 - omap_hsi: is the Low-Level Driver (or hardware driver). It provides a
   kernel functional interface, to be used by other kernel modules and
   abstracts the HW.
   This part of the patch is based on Nokia SSI driver, already submitted as
   RFC by Carlos Chinea [1].
 - hsi-char: is a char device driver proposing a user-space interface for
   using the HSI and relies on omap_hsi.
   This part of the patch is based on a development from Andras Domokos.
The intent is to propose a single HSI driver that can support MIPI HSI 1.1 as
well as previous implementations (SSI) for OMAP platforms (OMAP3 / OMAP4).

The driver core functionalities are there and ready for review. The following
updates will come in the following weeks / months:
 - Clocks and Power Management support for OMAP4 platform (HSI device file)
 - HSI-char interface documentation

Validation: The driver is validated on 3430 SDP (with a HW loopback on the SSI
device), and is being validated on 4430 Virtio platform (MIPI HSI device).

[1] http://lwn.net/Articles/301918/

Thanks for your comments!

Sebastien JAN

Sebastien Jan (9):
  HSI: Low Level Driver interface
  HSI: Low Level Driver core
  HSI: Low Level Driver device management
  HSI: Low Level Driver debugfs support
  HSI: Low Level Driver documentation
  HSI: character driver interface
  HSI: character driver low level interface
  HSI: HSI device support
  HSI: SSI device support and integration on 3430SDP platform

 Documentation/hsi/hsi.txt |  319 
 arch/arm/mach-omap2/Makefile  |2 +
 arch/arm/mach-omap2/board-3430sdp.c   |   12 +
 arch/arm/mach-omap2/hsi.c |  497 +
 arch/arm/mach-omap2/mux.c |   17 +
 arch/arm/mach-omap2/ssi.c |  530 ++
 arch/arm/plat-omap/include/mach/hsi.h |  432 ++
 arch/arm/plat-omap/include/mach/mux.h |   10 +
 drivers/Kconfig   |2 +
 drivers/Makefile  |1 +
 drivers/hsi/Kconfig   |   58 +++
 drivers/hsi/Makefile  |   17 +
 drivers/hsi/hsi-char.c|  526 ++
 drivers/hsi/hsi-char.h|   31 ++
 drivers/hsi/hsi-if.c  |  642 
 drivers/hsi/hsi-if.h  |   65 
 drivers/hsi/hsi_driver.c  |  644 
 drivers/hsi/hsi_driver.h  |  308 +++
 drivers/hsi/hsi_driver_bus.c  |  182 +
 drivers/hsi/hsi_driver_debugfs.c  |  486 
 drivers/hsi/hsi_driver_dma.c  |  469 +++
 drivers/hsi/hsi_driver_fifo.c |  289 +++
 drivers/hsi/hsi_driver_gpio.c |   79 
 drivers/hsi/hsi_driver_if.c   |  657 +
 drivers/hsi/hsi_driver_int.c  |  339 +
 include/linux/hsi_char.h  |   71 
 include/linux/hsi_driver_if.h |  180 +
 27 files changed, 6865 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/hsi/hsi.txt
 create mode 100644 arch/arm/mach-omap2/hsi.c
 create mode 100644 arch/arm/mach-omap2/ssi.c
 create mode 100644 arch/arm/plat-omap/include/mach/hsi.h
 create mode 100644 drivers/hsi/Kconfig
 create mode 100644 drivers/hsi/Makefile
 create mode 100644 drivers/hsi/hsi-char.c
 create mode 100644 drivers/hsi/hsi-char.h
 create mode 100644 drivers/hsi/hsi-if.c
 create mode 100644 drivers/hsi/hsi-if.h
 create mode 100644 drivers/hsi/hsi_driver.c
 create mode 100644 drivers/hsi/hsi_driver.h
 create mode 100644 drivers/hsi/hsi_driver_bus.c
 create mode 100644 drivers/hsi/hsi_driver_debugfs.c
 create mode 100644 drivers/hsi/hsi_driver_dma.c
 create mode 100644 drivers/hsi/hsi_driver_fifo.c
 create mode 100644 drivers/hsi/hsi_driver_gpio.c
 create mode 100644 drivers/hsi/hsi_driver_if.c
 create mode 100644 drivers/hsi/hsi_driver_int.c
 create mode 100644 include/linux/hsi_char.h
 create mode 100644 include/linux/hsi_driver_if.h

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 1/9] HSI: Low Level Driver interface

2009-10-30 Thread Sebastien Jan
Driver kernel interface headers and implementation
Driver Makefile and configuration integration

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
---
 drivers/Makefile  |1 +
 drivers/hsi/Kconfig   |   44 +++
 drivers/hsi/Makefile  |   14 +
 drivers/hsi/hsi_driver_if.c   |  657 +
 include/linux/hsi_driver_if.h |  180 +++
 5 files changed, 896 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hsi/Kconfig
 create mode 100644 drivers/hsi/Makefile
 create mode 100644 drivers/hsi/hsi_driver_if.c
 create mode 100644 include/linux/hsi_driver_if.h

diff --git a/drivers/Makefile b/drivers/Makefile
index 086857c..05b4190 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -111,3 +111,4 @@ obj-$(CONFIG_VLYNQ) += vlynq/
 obj-$(CONFIG_STAGING)  += staging/
 obj-y  += platform/
 obj-y  += ieee802154/
+obj-$(CONFIG_OMAP_HSI) += hsi/
diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig
new file mode 100644
index 000..e10b522
--- /dev/null
+++ b/drivers/hsi/Kconfig
@@ -0,0 +1,44 @@
+#
+# OMAP HSI driver configuration
+#
+menuconfig HSI
+   bool HSI support
+   default n
+   help
+ The MIPI HSI is a High Speed Synchronous Serial Interface and is
+ defined for communication between two Integrated Circuits (the
+ typical scenario is an application IC and cellular modem IC
+ communication). Data transaction model is peer-to-peer. MIPI HSI
+ physical layer provides logical channeling and several modes of
+ operation.
+
+if HSI
+
+config OMAP_HSI
+   tristate OMAP HSI hardware driver
+   depends on (ARCH_OMAP34XX || ARCH_OMAP4)
+   default n
+   ---help---
+ If you say Y here, you will enable the OMAP HSI hardware driver.
+
+ If unsure, say N.
+
+ Note that the HSI driver supports either:
+   - the OMAP MIPI HSI device
+   - the OMAP SSI device
+
+choice
+   prompt Selected device support file
+   depends on OMAP_HSI  y
+   default OMAP_HSI_DEVICE
+   ---help---
+ Adds the device support for one of the devices handled by the HSI
+ driver.
+
+config OMAP_HSI_DEVICE
+   bool HSI (OMAP MIPI HSI)
+
+config OMAP_SSI_DEVICE
+   bool SSI (OMAP SSI)
+
+endchoice
diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile
new file mode 100644
index 000..a7f579b
--- /dev/null
+++ b/drivers/hsi/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for HSI drivers
+#
+EXTRA_CFLAGS :=
+
+omap_hsi-objs  :=  hsi_driver.o hsi_driver_dma.o hsi_driver_int.o \
+   hsi_driver_if.o hsi_driver_bus.o hsi_driver_gpio.o \
+   hsi_driver_fifo.o
+
+ifeq ($(CONFIG_DEBUG_FS), y)
+   omap_hsi-objs += hsi_driver_debugfs.o
+endif
+
+obj-$(CONFIG_OMAP_HSI) += omap_hsi.o
diff --git a/drivers/hsi/hsi_driver_if.c b/drivers/hsi/hsi_driver_if.c
new file mode 100644
index 000..fb0035d
--- /dev/null
+++ b/drivers/hsi/hsi_driver_if.c
@@ -0,0 +1,657 @@
+/*
+ * hsi_driver_if.c
+ *
+ * Implements HSI hardware driver interfaces for the upper layers.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Carlos Chinea carlos.chi...@nokia.com
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include hsi_driver.h
+
+#define NOT_SET(-1)
+
+/* Manage HSR divisor update
+ * A special divisor value allows switching to auto-divisor mode in Rx
+ * (but with error counters deactivated). This function implements the
+ * the transitions to/from this mode.
+ */
+int hsi_set_rx_divisor(struct hsi_port *sport, u32 divisor)
+{
+   struct hsi_dev *hsi_ctrl = sport-hsi_controller;
+   void __iomem *base = hsi_ctrl-base;
+   int port = sport-port_number;
+   struct platform_device *pdev = to_platform_device(hsi_ctrl-dev);
+
+   if (divisor == NOT_SET)
+   return 0;
+
+   if (hsi_driver_device_is_hsi(pdev)) {
+   if (divisor == HSI_HSR_DIVISOR_AUTO  sport-counters_on) {
+   /* auto mode: deactivate counters + set divisor = 0 */
+   sport-reg_counters = hsi_inl(base,
+   HSI_HSR_COUNTERS_REG(port));
+   sport-counters_on = 0;
+   hsi_outl(0, base, HSI_HSR_COUNTERS_REG(port));
+   hsi_outl(0, base

[RFC PATCH 2/9] HSI: Low Level Driver core

2009-10-30 Thread Sebastien Jan
Driver core implementation (driver registration, ...)
Driver types definitions
HSI bus implementation

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
---
 drivers/hsi/hsi_driver.c |  644 ++
 drivers/hsi/hsi_driver.h |  308 
 drivers/hsi/hsi_driver_bus.c |  182 
 3 files changed, 1134 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hsi/hsi_driver.c
 create mode 100644 drivers/hsi/hsi_driver.h
 create mode 100644 drivers/hsi/hsi_driver_bus.c

diff --git a/drivers/hsi/hsi_driver.c b/drivers/hsi/hsi_driver.c
new file mode 100644
index 000..4abaf08
--- /dev/null
+++ b/drivers/hsi/hsi_driver.c
@@ -0,0 +1,644 @@
+/*
+ * hsi_driver.c
+ *
+ * Implements HSI module interface, initialization, and PM related functions.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Carlos Chinea carlos.chi...@nokia.com
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include linux/err.h
+#include linux/io.h
+#include linux/gpio.h
+#include linux/list.h
+#include mach/clock.h
+#include hsi_driver.h
+
+#defineHSI_DRIVER_VERSION  0.1
+#define HSI_RESETDONE_TIMEOUT  10  /* 10 ms */
+#define HSI_RESETDONE_RETRIES  20  /* = max 200 ms waiting for reset */
+
+/* NOTE: Function called in interrupt context */
+int hsi_port_event_handler(struct hsi_port *p, unsigned int event, void *arg)
+{
+   struct hsi_channel *hsi_channel;
+   int ch;
+
+   if (event == HSI_EVENT_HSR_DATAAVAILABLE) {
+   /* The data-available event is channel-specific and must not be
+* broadcasted
+*/
+   hsi_channel = p-hsi_channel + (int)arg;
+   read_lock(hsi_channel-rw_lock);
+   if ((hsi_channel-dev)  (hsi_channel-port_event))
+   hsi_channel-port_event(hsi_channel-dev, event, arg);
+   read_unlock(hsi_channel-rw_lock);
+   } else {
+   for (ch = 0; ch  p-max_ch; ch++) {
+   hsi_channel = p-hsi_channel + ch;
+   read_lock(hsi_channel-rw_lock);
+   if ((hsi_channel-dev)  (hsi_channel-port_event))
+   hsi_channel-port_event(hsi_channel-dev,
+   event, arg);
+   read_unlock(hsi_channel-rw_lock);
+   }
+   }
+   return 0;
+}
+
+static int hsi_clk_event(struct notifier_block *nb, unsigned long event,
+void *data)
+{
+/* TODO - implement support for clocks changes
+   switch (event) {
+   case CLK_PRE_RATE_CHANGE:
+   break;
+   case CLK_ABORT_RATE_CHANGE:
+   break;
+   case CLK_POST_RATE_CHANGE:
+   break;
+   default:
+   break;
+   }
+*/
+
+   /*
+* TODO: At this point we may emit a port event warning about the
+* clk frequency change to the upper layers.
+*/
+   return NOTIFY_DONE;
+}
+
+static void hsi_dev_release(struct device *dev)
+{
+   /* struct device kfree is already made in unregister_hsi_devices().
+* Registering this function is necessary to avoid an error from
+* the device_release() function.
+*/
+}
+
+static int __init reg_hsi_dev_ch(struct hsi_dev *hsi_ctrl, unsigned int p,
+unsigned int ch)
+{
+   struct hsi_device *dev;
+   struct hsi_port *port = hsi_ctrl-hsi_port[p];
+   int err;
+
+   dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+   if (!dev)
+   return -ENOMEM;
+
+   dev-n_ctrl = hsi_ctrl-id;
+   dev-n_p = p;
+   dev-n_ch = ch;
+   dev-ch = port-hsi_channel[ch];
+   dev-device.bus = hsi_bus_type;
+   dev-device.parent = hsi_ctrl-dev;
+   dev-device.release = hsi_dev_release;
+   if (dev-n_ctrl  0)
+   dev_set_name(dev-device, omap_hsi-p%u.c%u, p, ch);
+   else
+   dev_set_name(dev-device, omap_hsi%d-p%u.c%u, dev-n_ctrl, p,
+ch);
+
+   err = device_register(dev-device);
+   if (err = 0) {
+   write_lock_bh(port-hsi_channel[ch].rw_lock);
+   port-hsi_channel[ch].dev = dev;
+   write_unlock_bh(port-hsi_channel[ch].rw_lock);
+   } else {
+   kfree(dev);
+   }
+   return err;
+}
+
+static int __init register_hsi_devices(struct

[RFC PATCH 3/9] HSI: Low Level Driver device management

2009-10-30 Thread Sebastien Jan
Low-level managment of interrupts, DMA, GPIO (SSI) and FIFO (HSI).

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
---
 drivers/hsi/hsi_driver_dma.c  |  469 +
 drivers/hsi/hsi_driver_fifo.c |  289 +
 drivers/hsi/hsi_driver_gpio.c |   79 +++
 drivers/hsi/hsi_driver_int.c  |  339 +
 4 files changed, 1176 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hsi/hsi_driver_dma.c
 create mode 100644 drivers/hsi/hsi_driver_fifo.c
 create mode 100644 drivers/hsi/hsi_driver_gpio.c
 create mode 100644 drivers/hsi/hsi_driver_int.c

diff --git a/drivers/hsi/hsi_driver_dma.c b/drivers/hsi/hsi_driver_dma.c
new file mode 100644
index 000..4514e98
--- /dev/null
+++ b/drivers/hsi/hsi_driver_dma.c
@@ -0,0 +1,469 @@
+/*
+ * hsi_driver_dma.c
+ *
+ * Implements HSI low level interface driver functionality with DMA support.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Carlos Chinea carlos.chi...@nokia.com
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include linux/dma-mapping.h
+#include hsi_driver.h
+
+#define HSI_SYNC_WRITE 0
+#define HSI_SYNC_READ  1
+#define HSI_L3_TPUT13428 /* 13428 KiB/s = ~110 Mbit/s*/
+
+static unsigned char hsi_sync_table[2][2][8] = {
+   {
+   {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
+   {0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}
+   }, {
+   {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17},
+   {0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}
+   }
+};
+
+/**
+ * hsi_get_free_lch - Get a free GDD(DMA)logical channel
+ * @hsi_ctrl- HSI controller of the GDD.
+ *
+ * Needs to be called holding the hsi_controller lock
+ *
+ * Return a free logical channel number. If there is no free lch
+ * then returns an out of range value
+ */
+static unsigned int hsi_get_free_lch(struct hsi_dev *hsi_ctrl)
+{
+   unsigned int enable_reg;
+   unsigned int i;
+   unsigned int lch = hsi_ctrl-last_gdd_lch;
+
+   enable_reg = hsi_inl(hsi_ctrl-base, HSI_SYS_GDD_MPU_IRQ_ENABLE_REG);
+   for (i = 1; i = hsi_ctrl-gdd_chan_count; i++) {
+   lch = (lch + i)  (hsi_ctrl-gdd_chan_count - 1);
+   if (!(enable_reg  HSI_GDD_LCH(lch))) {
+   hsi_ctrl-last_gdd_lch = lch;
+   return lch;
+   }
+   }
+
+   return lch;
+}
+
+/**
+ * hsi_driver_write_dma - Program GDD [DMA] to write data from memory to
+ * the hsi channel buffer.
+ * @hsi_channel - pointer to the hsi_channel to write data to.
+ * @data - 32-bit word pointer to the data.
+ * @size - Number of 32bit words to be transfered.
+ *
+ * hsi_controller lock must be held before calling this function.
+ *
+ * Return 0 on success and  0 on error.
+ */
+int hsi_driver_write_dma(struct hsi_channel *hsi_channel, u32 *data,
+unsigned int size)
+{
+   struct hsi_dev *hsi_ctrl = hsi_channel-hsi_port-hsi_controller;
+   void __iomem *base = hsi_ctrl-base;
+   unsigned int port = hsi_channel-hsi_port-port_number;
+   unsigned int channel = hsi_channel-channel_number;
+   unsigned int sync;
+   long buff_offset;
+   int lch;
+   dma_addr_t dma_data;
+   dma_addr_t s_addr;
+   u16 tmp;
+
+   if ((size  1) || (data == NULL))
+   return -EINVAL;
+
+   clk_enable(hsi_ctrl-hsi_clk);
+
+   lch = hsi_get_free_lch(hsi_ctrl);
+   if (lch = hsi_ctrl-gdd_chan_count) {
+   dev_err(hsi_ctrl-dev, No free GDD logical channels.\n);
+   clk_disable(hsi_ctrl-hsi_clk);
+   return -EBUSY;  /* No free GDD logical channels. */
+   }
+
+   /* NOTE: Getting a free gdd logical channel and
+* reserve it must be done atomicaly. */
+   hsi_channel-write_data.lch = lch;
+
+   /* Sync is required for SSI but not for HSI */
+   sync = hsi_sync_table[HSI_SYNC_WRITE][port - 1][channel];
+
+   dma_data = dma_map_single(hsi_ctrl-dev, data, size * 4,
+   DMA_TO_DEVICE);
+
+   tmp = HSI_SRC_SINGLE_ACCESS0 |
+   HSI_SRC_MEMORY_PORT |
+   HSI_DST_SINGLE_ACCESS0 |
+   HSI_DST_PERIPHERAL_PORT |
+   HSI_DATA_TYPE_S32;
+   hsi_outw(tmp, base, HSI_GDD_CSDP_REG(lch));
+
+   tmp = HSI_SRC_AMODE_POSTINC | HSI_DST_AMODE_CONST | sync;
+   hsi_outw(tmp, base

[RFC PATCH 4/9] HSI: Low Level Driver debugfs support

2009-10-30 Thread Sebastien Jan
All registers dump, and counters configuration

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
---
 drivers/hsi/hsi_driver_debugfs.c |  486 ++
 1 files changed, 486 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hsi/hsi_driver_debugfs.c

diff --git a/drivers/hsi/hsi_driver_debugfs.c b/drivers/hsi/hsi_driver_debugfs.c
new file mode 100644
index 000..d600a88
--- /dev/null
+++ b/drivers/hsi/hsi_driver_debugfs.c
@@ -0,0 +1,486 @@
+/*
+ * hsi_driver_debugfs.c
+ *
+ * Implements HSI debugfs.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Carlos Chinea carlos.chi...@nokia.com
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include linux/err.h
+#include linux/list.h
+#include mach/clock.h
+#include linux/uaccess.h
+#include linux/ctype.h
+#include hsi_driver.h
+
+#define HSI_DIR_NAME_SIZE  64
+
+static struct dentry *hsi_dir;
+
+static int hsi_debug_show(struct seq_file *m, void *p)
+{
+   struct hsi_dev *hsi_ctrl = m-private;
+   struct platform_device *pdev = to_platform_device(hsi_ctrl-dev);
+
+   clk_enable(hsi_ctrl-hsi_clk);
+
+   seq_printf(m, REVISION\t: 0x%08x\n,
+   hsi_inl(hsi_ctrl-base, HSI_SYS_REVISION_REG));
+   if (hsi_driver_device_is_hsi(pdev))
+   seq_printf(m, HWINFO\t\t: 0x%08x\n,
+   hsi_inl(hsi_ctrl-base, HSI_SYS_HWINFO_REG));
+   seq_printf(m, SYSCONFIG\t: 0x%08x\n,
+   hsi_inl(hsi_ctrl-base, HSI_SYS_SYSCONFIG_REG));
+   seq_printf(m, SYSSTATUS\t: 0x%08x\n,
+   hsi_inl(hsi_ctrl-base, HSI_SYS_SYSSTATUS_REG));
+
+   clk_disable(hsi_ctrl-hsi_clk);
+   return 0;
+}
+
+static int hsi_debug_port_show(struct seq_file *m, void *p)
+{
+   struct hsi_port *hsi_port = m-private;
+   struct hsi_dev *hsi_ctrl = hsi_port-hsi_controller;
+   void __iomem *base = hsi_ctrl-base;
+   unsigned int port = hsi_port-port_number;
+   int ch, fifo;
+   long buff_offset;
+   struct platform_device *pdev = to_platform_device(hsi_ctrl-dev);
+
+   clk_enable(hsi_ctrl-hsi_clk);
+
+   if (hsi_port-cawake_gpio = 0)
+   seq_printf(m, CAWAKE\t\t: %d\n, hsi_cawake(hsi_port));
+
+   seq_printf(m, WAKE\t\t: 0x%08x\n,
+   hsi_inl(base, HSI_SYS_WAKE_REG(port)));
+   seq_printf(m, MPU_ENABLE_IRQ%d\t: 0x%08x\n, hsi_port-n_irq,
+   hsi_inl(base, HSI_SYS_MPU_ENABLE_REG(port, hsi_port-n_irq)));
+   seq_printf(m, MPU_STATUS_IRQ%d\t: 0x%08x\n, hsi_port-n_irq,
+   hsi_inl(base, HSI_SYS_MPU_STATUS_REG(port, hsi_port-n_irq)));
+   if (hsi_driver_device_is_hsi(pdev)) {
+   seq_printf(m, MPU_U_ENABLE_IRQ%d\t: 0x%08x\n,
+   hsi_port-n_irq,
+   hsi_inl(base, HSI_SYS_MPU_U_ENABLE_REG(port,
+   hsi_port-n_irq)));
+   seq_printf(m, MPU_U_STATUS_IRQ%d\t: 0x%08x\n,
+   hsi_port-n_irq,
+   hsi_inl(base, HSI_SYS_MPU_U_STATUS_REG(port,
+   hsi_port-n_irq)));
+   }
+   /* HST */
+   seq_printf(m, \nHST\n===\n);
+   seq_printf(m, MODE\t\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_MODE_REG(port)));
+   seq_printf(m, FRAMESIZE\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_FRAMESIZE_REG(port)));
+   seq_printf(m, DIVISOR\t\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_DIVISOR_REG(port)));
+   seq_printf(m, CHANNELS\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_CHANNELS_REG(port)));
+   seq_printf(m, ARBMODE\t\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_ARBMODE_REG(port)));
+   seq_printf(m, TXSTATE\t\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_TXSTATE_REG(port)));
+   if (hsi_driver_device_is_hsi(pdev)) {
+   seq_printf(m, BUFSTATE P1\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_BUFSTATE_REG(1)));
+   seq_printf(m, BUFSTATE P2\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_BUFSTATE_REG(2)));
+   } else {
+   seq_printf(m, BUFSTATE\t: 0x%08x\n,
+   hsi_inl(base, HSI_HST_BUFSTATE_REG(port

[RFC PATCH 5/9] HSI: Low Level Driver documentation

2009-10-30 Thread Sebastien Jan
Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
---
 Documentation/hsi/hsi.txt |  319 +
 1 files changed, 319 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/hsi/hsi.txt

diff --git a/Documentation/hsi/hsi.txt b/Documentation/hsi/hsi.txt
new file mode 100644
index 000..0890cff
--- /dev/null
+++ b/Documentation/hsi/hsi.txt
@@ -0,0 +1,319 @@
+OMAP HSI API's How To
+=
+
+The MIPI High Speed Synchronous Serial Interface (HSI) is a high speed
+communication interface that is used for connecting OMAP to a cellular modem
+engine.
+It is specified by the MIPI alliance (www.mipi.org). An introduction to the
+MIPI HSI working group can be found here: http://www.mipi.org/wgoverview.shtml
+
+The HSI interface supports full duplex communication over multiple channels and
+is capable of reaching speeds up to 200 Mbit/s.
+
+The OMAP HSI driver supports both OMAP MIPI HSI (as defined in
+MIPI documentation mipi_HSI-PL_specification_v01-01-00a.pdf) and OMAP SSI
+devices through different device files, and a generic SW driver.
+
+Please refer to the MIPI specifications for more details on this device.
+
+
+I OMAP HSI driver API overview
+-
+
+A) HSI Bus, HSI channels and protocol drivers overview.
+
+The OMAP HSI driver implements the low-level support for the HSI device. It
+abstracts device specifics and provides a simple interface inside the kernel
+for data transmission on the HSI channels.
+The OMAP HSI driver does not implement any communication protocol.
+The SW layers using the OMAP HSI driver may implement a communication protocol
+if required, and are commonly called 'protocol drivers' in this document.
+
+The OMAP HSI abstracts the concept of HSI channels by creating an HSI bus and
+attaching HSI channel devices to it. (see Figure 1)
+
+Protocol drivers will then claim one or more HSI channels, after registering
+with the OMAP HSI driver.
+
+   +-+ ++
+   +  HSI channel device + +  HSI protocol  +
+   +  (omap_hsi.pX-cY)   + ---+  driver+
+   +-+ ++
+   |   |
+(/sys/bus/hsi/devices/omap_hsi.pX-cy)  (/sys/bus/hsi/drivers/hsi_protocol)
+   |   |
+++
++  HSI bus  +
+++
+
+   Figure 1.
+
+(NOTE: omap_hsi.pX-cY represents the HSI channel Y on port X from the omap_hsi
+device)
+
+B) Data transfers
+
+The OMAP HSI driver exports an asynchronous interface for sending and receiving
+data over the HSI channels. Protocol drivers will register a set of read and
+write completion callbacks for each HSI channel they use.
+
+Protocol drivers call hsi_write/hsi_read functions to signal the OMAP HSI 
driver
+that is willing to write/read data to/from a channel. Transfers are completed
+only when the OMAP HSI driver calls the completion callback.
+
+An HSI channel can simultaneously have both a read and a write request
+pending, however, requests cannot be queued.
+
+It is safe to call hsi_write/hsi_read functions inside the callback functions.
+In fact, a protocol driver should normally re-issue the read request from 
within
+the read callback, in order to not miss any incoming messages.
+
+Note on read / write operations:
+A read or write is performed using a HSI internal DMA channel, unless the size
+of data to transmit is one 32bits Word, where the transmission is directly
+managed through interrupts.
+
+C) Error handling
+
+HSI is a multi channel interface but the channels share the same physical 
wires.
+Therefore, any transmission error potentially affects all the protocol drivers
+that sit on top of the HSI driver. Whenever an error occurs, it is broadcast
+to all protocol drivers.
+
+Errors are signaled to the protocol drivers through the port_event callback.
+
+Completion callbacks functions are only called when a transfer has succeess.
+
+D) Supported modes of operation
+
+The driver supports stream and frame transmission modes and synchronized and
+pipelined data flows.
+The driver implements the HSI support for the core MPU and not for the
+potential co-processors.
+
+
+II OMAP HSI API's
+-
+
+A) Include
+
+#includelinux/hsi_driver_if.h
+
+B) int hsi_register_driver(struct hsi_device_driver *driver);
+
+  Description: Register an HSI protocol driver
+
+  Parameter: A protocol driver declaration (see struct hsi_device_driver)
+
+C) void hsi_unregister_driver(struct hsi_device_driver *driver);
+
+  Description: Unregister an HSI protocol driver
+
+  Parameter: A protocol driver declaration (see struct hsi_device_driver)
+
+D) int hsi_open(struct

[RFC PATCH 6/9] HSI: character driver interface

2009-10-30 Thread Sebastien Jan
Character driver header and interface implementation
Integration in the build and configuration

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Andras Domokos andras.domo...@nokia.com
---
 drivers/Kconfig  |2 +
 drivers/hsi/Kconfig  |   14 ++
 drivers/hsi/Makefile |3 +
 drivers/hsi/hsi-char.c   |  526 ++
 drivers/hsi/hsi-char.h   |   31 +++
 include/linux/hsi_char.h |   71 +++
 6 files changed, 647 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hsi/hsi-char.c
 create mode 100644 drivers/hsi/hsi-char.h
 create mode 100644 include/linux/hsi_char.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 48bbdbe..8fc1c36 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@ source drivers/i2c/Kconfig
 
 source drivers/spi/Kconfig
 
+source drivers/hsi/Kconfig
+
 source drivers/pps/Kconfig
 
 source drivers/gpio/Kconfig
diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig
index e10b522..79e0e02 100644
--- a/drivers/hsi/Kconfig
+++ b/drivers/hsi/Kconfig
@@ -42,3 +42,17 @@ config OMAP_SSI_DEVICE
bool SSI (OMAP SSI)
 
 endchoice
+
+#
+# OMAP HSI char device kernel configuration
+#
+
+config HSI_CHAR
+   tristate HSI character driver
+   depends on OMAP_HSI
+   ---help---
+ If you say Y here, you will enable the HSI character driver.
+ This driver provides a simple character device interface for
+ serial communication over the HSI bus.
+
+endif # HSI
diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile
index a7f579b..81270ec 100644
--- a/drivers/hsi/Makefile
+++ b/drivers/hsi/Makefile
@@ -11,4 +11,7 @@ ifeq ($(CONFIG_DEBUG_FS), y)
omap_hsi-objs += hsi_driver_debugfs.o
 endif
 
+hsi_char-objs  :=  hsi-char.o hsi-if.o
+
 obj-$(CONFIG_OMAP_HSI) += omap_hsi.o
+obj-$(CONFIG_HSI_CHAR) += hsi_char.o
diff --git a/drivers/hsi/hsi-char.c b/drivers/hsi/hsi-char.c
new file mode 100644
index 000..29fbd73
--- /dev/null
+++ b/drivers/hsi/hsi-char.c
@@ -0,0 +1,526 @@
+/*
+ * hsi-char.c
+ *
+ * HSI character device driver, implements the character device
+ * interface.
+ *
+ * Copyright (C) 2009 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Andras Domokos andras.domo...@nokia.com
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include linux/errno.h
+#include linux/module.h
+#include linux/types.h
+#include linux/init.h
+#include linux/device.h
+#include linux/err.h
+#include linux/miscdevice.h
+#include linux/file.h
+#include linux/mm.h
+#include linux/fs.h
+#include linux/cdev.h
+#include linux/poll.h
+#include asm/mach-types.h
+#include linux/ioctl.h
+#include linux/uaccess.h
+
+#include mach/hsi.h
+#include linux/hsi_driver_if.h
+#include linux/hsi_char.h
+
+#include hsi-char.h
+
+#define DRIVER_VERSION  0.1.0
+
+static unsigned int port = 1;
+module_param(port, uint, 1);
+MODULE_PARM_DESC(port, HSI port to be probed);
+
+static unsigned int channels_map[HSI_MAX_CHAR_DEVS] = {1};
+module_param_array(channels_map, uint, NULL, 0);
+MODULE_PARM_DESC(channels_map, HSI channels to be probed);
+
+dev_t hsi_char_dev;
+
+struct char_queue {
+   struct list_head list;
+   u32 *data;
+   unsigned int count;
+};
+
+struct hsi_char {
+   unsigned int opened;
+   int poll_event;
+   struct list_head rx_queue;
+   struct list_head tx_queue;
+   spinlock_t lock; /* Serialize access to driver data and API */
+   struct fasync_struct *async_queue;
+   wait_queue_head_t rx_wait;
+   wait_queue_head_t tx_wait;
+   wait_queue_head_t poll_wait;
+};
+
+static struct hsi_char hsi_char_data[HSI_MAX_CHAR_DEVS];
+
+void if_notify(int ch, struct hsi_event *ev)
+{
+   struct char_queue *entry;
+
+   pr_debug(%s, ev = {0x%x, 0x%p, %u}\n, __func__, ev-event, ev-data,
+   ev-count);
+
+   spin_lock(hsi_char_data[ch].lock);
+
+   if (!hsi_char_data[ch].opened) {
+   pr_debug(%s, device not opened\n!, __func__);
+   spin_unlock(hsi_char_data[ch].lock);
+   return;
+   }
+
+   switch (HSI_EV_TYPE(ev-event)) {
+   case HSI_EV_IN:
+   entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+   if (!entry) {
+   pr_err(HSI-CHAR: entry allocation failed.\n);
+   spin_unlock(hsi_char_data[ch].lock);
+   return;
+   }
+   entry-data = ev-data;
+   entry-count = ev-count

[RFC PATCH 7/9] HSI: character driver low level interface

2009-10-30 Thread Sebastien Jan
Character driver interface with omap_hsi driver (LLD)

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Andras Domokos andras.domo...@nokia.com
---
 drivers/hsi/hsi-if.c |  642 ++
 drivers/hsi/hsi-if.h |   65 +
 2 files changed, 707 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hsi/hsi-if.c
 create mode 100644 drivers/hsi/hsi-if.h

diff --git a/drivers/hsi/hsi-if.c b/drivers/hsi/hsi-if.c
new file mode 100644
index 000..2c9ba0c
--- /dev/null
+++ b/drivers/hsi/hsi-if.c
@@ -0,0 +1,642 @@
+/*
+ * hsi-if.c
+ *
+ * Part of the HSI character driver, implements the HSI interface.
+ *
+ * Copyright (C) 2009 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Andras Domokos andras.domo...@nokia.com
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include linux/errno.h
+#include linux/module.h
+#include linux/init.h
+#include linux/device.h
+#include linux/err.h
+#include linux/platform_device.h
+#include asm/mach-types.h
+#include linux/ioctl.h
+#include linux/delay.h
+#include linux/ktime.h
+#include linux/bitmap.h
+
+#include linux/hsi_driver_if.h
+#include linux/hsi_char.h
+
+#include hsi-char.h
+#include hsi-if.h
+
+#define HSI_CHANNEL_STATE_UNAVAIL  (1  0)
+#define HSI_CHANNEL_STATE_READING  (1  1)
+#define HSI_CHANNEL_STATE_WRITING  (1  2)
+
+#define PORT1  0
+#define PORT2  1
+
+#define RXCONV(dst, src) \
+   do { \
+   (dst)-mode = (src)-mode; \
+   (dst)-flow = (src)-flow; \
+   (dst)-frame_size = (src)-frame_size; \
+   (dst)-channels = (src)-channels; \
+   (dst)-divisor = (src)-divisor; \
+   } while (0)
+
+#define TXCONV(dst, src) \
+   do { \
+   (dst)-mode = (src)-mode; \
+   (dst)-flow = (src)-flow; \
+   (dst)-frame_size = (src)-frame_size; \
+   (dst)-channels = (src)-channels; \
+   (dst)-divisor = (src)-divisor; \
+   (dst)-arb_mode = (src)-arb_mode; \
+   } while (0)
+
+struct if_hsi_channel {
+   struct hsi_device *dev;
+   unsigned int channel_id;
+   u32 *tx_data;
+   unsigned int tx_count;
+   u32 *rx_data;
+   unsigned int rx_count;
+   unsigned int opened;
+   unsigned int state;
+   spinlock_t lock; /* Serializes access to channel data */
+};
+
+struct if_hsi_iface {
+   struct if_hsi_channel channels[HSI_MAX_CHAR_DEVS];
+   int bootstrap;
+   unsigned long init_chan_map;
+   spinlock_t lock; /* Serializes access to HSI functional interface */
+};
+
+static void if_hsi_port_event(struct hsi_device *dev, unsigned int event,
+   void *arg);
+static int __devinit if_hsi_probe(struct hsi_device *dev);
+static int __devexit if_hsi_remove(struct hsi_device *dev);
+
+static struct hsi_device_driver if_hsi_char_driver = {
+   .ctrl_mask = ANY_HSI_CONTROLLER,
+   .probe = if_hsi_probe,
+   .remove = __devexit_p(if_hsi_remove),
+   .driver = {
+   .name = hsi_char
+   },
+};
+
+static struct if_hsi_iface hsi_iface;
+
+static int if_hsi_read_on(int ch, u32 *data, unsigned int count)
+{
+   struct if_hsi_channel *channel;
+   int ret;
+
+   channel = hsi_iface.channels[ch];
+   dev_dbg(channel-dev-device, %s, ch = %d\n, __func__, ch);
+
+   spin_lock(channel-lock);
+   if (channel-state  HSI_CHANNEL_STATE_READING) {
+   pr_err(Read still pending on channel %d\n, ch);
+   spin_unlock(channel-lock);
+   return -EBUSY;
+   }
+   channel-state |= HSI_CHANNEL_STATE_READING;
+   channel-rx_data = data;
+   channel-rx_count = count;
+   spin_unlock(channel-lock);
+
+   ret = hsi_read(channel-dev, data, count/4);
+   dev_dbg(channel-dev-device, %s, ch = %d, ret = %d\n, __func__, ch,
+   ret);
+
+   return ret;
+}
+
+static void if_hsi_read_done(struct hsi_device *dev, unsigned int size)
+{
+   struct if_hsi_channel *channel;
+   struct hsi_event ev;
+
+   channel = hsi_iface.channels[dev-n_ch];
+   dev_dbg(channel-dev-device, %s, ch = %d\n, __func__, dev-n_ch);
+   spin_lock(channel-lock);
+   channel-state = ~HSI_CHANNEL_STATE_READING;
+   ev.event = HSI_EV_IN;
+   ev.data = channel-rx_data;
+   ev.count = size;
+   spin_unlock(channel-lock);
+   if_notify(dev-n_ch, ev);
+}
+
+int if_hsi_read(int ch, u32 *data, unsigned

[RFC PATCH 8/9] HSI: HSI device support

2009-10-30 Thread Sebastien Jan
Common registers definition for HSI like devices (common to MIPI HSI and SSI
for OMAP platforms)
HSI device definition

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
---
 arch/arm/mach-omap2/Makefile  |1 +
 arch/arm/mach-omap2/hsi.c |  497 +
 arch/arm/plat-omap/include/mach/hsi.h |  432 
 3 files changed, 930 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/hsi.c
 create mode 100644 arch/arm/plat-omap/include/mach/hsi.h

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 6b7702f..3de1c20 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -87,3 +87,4 @@ obj-y += $(onenand-m) 
$(onenand-y)
 
 smc91x-$(CONFIG_SMC91X):= gpmc-smc91x.o
 obj-y  += $(smc91x-m) $(smc91x-y)
+obj-$(CONFIG_OMAP_HSI_DEVICE)  += hsi.o
diff --git a/arch/arm/mach-omap2/hsi.c b/arch/arm/mach-omap2/hsi.c
new file mode 100644
index 000..a920934
--- /dev/null
+++ b/arch/arm/mach-omap2/hsi.c
@@ -0,0 +1,497 @@
+/*
+ * arch/arm/mach-omap2/hsi.c
+ *
+ * HSI device definition
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include linux/platform_device.h
+#include linux/err.h
+#include linux/clk.h
+#include linux/io.h
+#include linux/gpio.h
+#include linux/irq.h
+#include linux/jiffies.h
+#include linux/notifier.h
+#include mach/clock.h
+#include mach/hsi.h
+#include linux/hsi_driver_if.h
+#include clock.h
+#include asm/clkdev.h
+#include mach/mux.h
+
+#definehsi_inl(p)  inl((unsigned long) p)
+#definehsi_outl(v, p)  outl(v, (unsigned long) p)
+
+/**
+ * struct hsi_internal_clk - Generic virtual hsi clock
+ * @clk: clock data
+ * @nb: notfier block for the DVFS notification chain
+ * @childs: Array of HSI FCK and ICK clocks
+ * @n_childs: Number of clocks in childs array
+ * @rate_change: Tracks if we are in the middle of a clock rate change
+ * @pdev: Reference to the HSI platform device associated to the clock
+ * @drv_nb: Reference to driver nb, use to propagate the DVFS notification
+ */
+struct hsi_internal_clk {
+   struct clk clk;
+   struct notifier_block nb;
+
+   struct clk **childs;
+   int n_childs;
+
+   unsigned int rate_change:1;
+
+   struct platform_device *pdev;
+   struct notifier_block *drv_nb;
+};
+
+static void hsi_set_mode(struct platform_device *pdev, u32 mode)
+{
+   struct hsi_platform_data *pdata = pdev-dev.platform_data;
+   void __iomem *base = OMAP2_IO_ADDRESS(pdev-resource[0].start);
+   int port;
+
+   for (port = 1; port = pdata-num_ports; port++) {
+   /* FIXME - to update: need read/modify/write or something else:
+* this register now also contains flow and wake ctrl
+*/
+   hsi_outl(mode, base + HSI_HST_MODE_REG(port));
+   hsi_outl(mode, base + HSI_HSR_MODE_REG(port));
+   }
+}
+
+static void hsi_save_mode(struct platform_device *pdev)
+{
+   struct hsi_platform_data *pdata = pdev-dev.platform_data;
+   void __iomem *base = OMAP2_IO_ADDRESS(pdev-resource[0].start);
+   struct port_ctx *p;
+   int port;
+
+   for (port = 1; port = pdata-num_ports; port++) {
+   p = pdata-ctx.pctx[port - 1];
+   p-hst.mode = hsi_inl(base + HSI_HST_MODE_REG(port));
+   p-hsr.mode = hsi_inl(base + HSI_HSR_MODE_REG(port));
+   }
+}
+
+static void hsi_restore_mode(struct platform_device *pdev)
+{
+   struct hsi_platform_data *pdata = pdev-dev.platform_data;
+   void __iomem *base = OMAP2_IO_ADDRESS(pdev-resource[0].start);
+   struct port_ctx *p;
+   int port;
+
+   for (port = 1; port = pdata-num_ports; port++) {
+   p = pdata-ctx.pctx[port - 1];
+   hsi_outl(p-hst.mode, base + HSI_HST_MODE_REG(port));
+   hsi_outl(p-hsr.mode, base + HSI_HSR_MODE_REG(port));
+   }
+}
+
+static int hsi_clk_event(struct notifier_block *nb, unsigned long event,
+   void *data)
+{
+/* FIXME
+   struct hsi_internal_clk *hsi_clk =
+   container_of(nb, struct hsi_internal_clk, nb);
+   switch (event) {
+   case CLK_PRE_RATE_CHANGE:
+   hsi_clk-drv_nb-notifier_call(hsi_clk-drv_nb, event, data

[RFC PATCH 9/9] HSI: SSI device support and integration on 3430SDP platform

2009-10-30 Thread Sebastien Jan
SSI device definition
Integration on 3430 SDP (pin muxing, platform init)

Signed-off-by: Sebastien Jan s-...@ti.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
---
 arch/arm/mach-omap2/Makefile  |1 +
 arch/arm/mach-omap2/board-3430sdp.c   |   12 +
 arch/arm/mach-omap2/mux.c |   17 +
 arch/arm/mach-omap2/ssi.c |  530 +
 arch/arm/plat-omap/include/mach/mux.h |   10 +
 5 files changed, 570 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/ssi.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 3de1c20..34d3e7f 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -87,4 +87,5 @@ obj-y += $(onenand-m) 
$(onenand-y)
 
 smc91x-$(CONFIG_SMC91X):= gpmc-smc91x.o
 obj-y  += $(smc91x-m) $(smc91x-y)
+obj-$(CONFIG_OMAP_SSI_DEVICE)  += ssi.o
 obj-$(CONFIG_OMAP_HSI_DEVICE)  += hsi.o
diff --git a/arch/arm/mach-omap2/board-3430sdp.c 
b/arch/arm/mach-omap2/board-3430sdp.c
index 2dfab17..f982fd1 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -40,6 +40,7 @@
 #include mach/control.h
 #include mach/keypad.h
 #include mach/gpmc-smc91x.h
+#include mach/hsi.h
 
 #include sdram-qimonda-hyb18m512160af-6.h
 #include mmc-twl4030.h
@@ -496,6 +497,13 @@ static struct ehci_hcd_omap_platform_data ehci_pdata 
__initconst = {
.reset_gpio_port[2]  = -EINVAL
 };
 
+#ifdef CONFIG_OMAP_SSI_DEVICE
+static struct omap_ssi_board_config ssi_board_config = {
+   .num_ports = 1,
+   .cawake_gpio = { 151 },
+};
+#endif
+
 static void __init omap_3430sdp_init(void)
 {
omap3430_i2c_init();
@@ -513,6 +521,10 @@ static void __init omap_3430sdp_init(void)
board_smc91x_init();
enable_board_wakeup_source();
usb_ehci_init(ehci_pdata);
+
+#ifdef CONFIG_OMAP_SSI_DEVICE
+   omap_ssi_config(ssi_board_config);
+#endif
 }
 
 static void __init omap_3430sdp_map_io(void)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index b5fac32..8464034 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -451,6 +451,23 @@ MUX_CFG_34XX(AD2_3430_USB3FS_PHY_MM3_TXDAT, 0x188,
 MUX_CFG_34XX(AC1_3430_USB3FS_PHY_MM3_TXEN_N, 0x18a,
OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT)
 
+/* SSI support */
+MUX_CFG_34XX(AA8_3430_SSI1_DAT_TX, 0x17c,
+   OMAP34XX_MUX_MODE1) /* AC Data */
+MUX_CFG_34XX(AA9_3430_SSI1_FLAG_TX, 0x17e,
+   OMAP34XX_MUX_MODE1) /* AC Flag */
+MUX_CFG_34XX(W8_3430_SSI1_RDY_TX, 0x180,
+   OMAP34XX_MUX_MODE1 | OMAP3_INPUT_EN) /* CA Ready */
+MUX_CFG_34XX(Y8_3430_GPIO_151, 0x182,
+   OMAP34XX_MUX_MODE4 | OMAP3_INPUT_EN) /* CA Wake */
+MUX_CFG_34XX(AE1_3430_SSI1_DAT_RX, 0x184,
+   OMAP34XX_MUX_MODE1 | OMAP3_INPUT_EN) /* CA Data */
+MUX_CFG_34XX(AD1_3430_SSI1_FLAG_RX, 0x186,
+   OMAP34XX_MUX_MODE1 | OMAP3_INPUT_EN) /* CA Flag */
+MUX_CFG_34XX(AD2_3430_SSI1_RDY_RX, 0x188,
+   OMAP34XX_MUX_MODE1) /* AC Ready */
+MUX_CFG_34XX(AC1_3430_SSI1_WAKE, 0x18a,
+   OMAP34XX_MUX_MODE1) /* AC Wake */
 
 /* 34XX GPIO - bidirectional, unless the name has an _OUT suffix.
  * (Always specify PIN_INPUT, except for names suffixed by _OUT.)
diff --git a/arch/arm/mach-omap2/ssi.c b/arch/arm/mach-omap2/ssi.c
new file mode 100644
index 000..676254a
--- /dev/null
+++ b/arch/arm/mach-omap2/ssi.c
@@ -0,0 +1,530 @@
+/*
+ * arch/arm/mach-omap2/ssi.c
+ *
+ * SSI device definition
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author: Carlos Chinea carlos.chi...@nokia.com
+ * Author: Sebastien JAN s-...@ti.com
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include linux/platform_device.h
+#include linux/err.h
+#include linux/clk.h
+#include linux/io.h
+#include linux/gpio.h
+#include linux/irq.h
+#include linux/jiffies.h
+#include linux/notifier.h
+#include mach/clock.h
+#include mach/hsi.h
+#include linux/hsi_driver_if.h
+#include clock.h
+#include asm/clkdev.h
+#include mach/mux.h
+
+#definehsi_inl(p)  inl((unsigned long) p)
+#definehsi_outl(v, p)  outl(v, (unsigned long) p)
+
+/**
+ * struct ssi_internal_clk - Generic virtual ssi clock
+ * @clk: clock data
+ * @nb: notfier block for the DVFS notification chain
+ * @childs: Array of SSI FCK and ICK clocks
+ * @n_childs: Number of clocks in childs array
+ * @rate_change: Tracks

Re: [RFC PATCH 0/9] MIPI HSI device support for OMAP platforms

2009-10-30 Thread Sebastien Jan
On Friday 30 October 2009 13:57:50 Felipe Balbi wrote:
 On Fri, Oct 30, 2009 at 10:59:59AM +0100, ext Sebastien Jan wrote:
  This is an RFC for a series of patch to add the support of MIPI HSI and
  SSI devices to OMAP platforms.
  The patch includes the HSI device driver and the device files for MIPI
  HSI and SSI.
 
  The driver is made of 2 distinct modules:
   - omap_hsi: is the Low-Level Driver (or hardware driver). It provides a
 kernel functional interface, to be used by other kernel modules and
 abstracts the HW.
 This part of the patch is based on Nokia SSI driver, already submitted
  as RFC by Carlos Chinea [1].
   - hsi-char: is a char device driver proposing a user-space interface for
 using the HSI and relies on omap_hsi.
 This part of the patch is based on a development from Andras Domokos.
  The intent is to propose a single HSI driver that can support MIPI HSI
  1.1 as well as previous implementations (SSI) for OMAP platforms (OMAP3 /
  OMAP4).
 
  The driver core functionalities are there and ready for review. The
  following updates will come in the following weeks / months:
   - Clocks and Power Management support for OMAP4 platform (HSI device
  file) - HSI-char interface documentation
 
  Validation: The driver is validated on 3430 SDP (with a HW loopback on
  the SSI device), and is being validated on 4430 Virtio platform (MIPI HSI
  device).
 
  [1] http://lwn.net/Articles/301918/

 pass all your drivers on checkpatch.pl --strict and to sparse as well.

Thanks to point this out: I forgot to mention that I did run checkpatch.pl -- 
strict and sparse on these patches.

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html