svn commit: r345948 - head/sys/dev/iicbus/twsi

2019-09-03 Thread Emmanuel Vadot
Author: manu
Date: Fri Apr  5 14:44:23 2019
New Revision: 345948
URL: https://svnweb.freebsd.org/changeset/base/345948

Log:
  twsi: Add interrupt mode
  
  Add the ability to use interrupts for i2c message.
  We still use polling for early boot i2c transfer (for PMIC
  for example) but as soon as interrupts are available use them.
  On Allwinner SoC >A20 is seems that polling mode is broken for some
  reason, this is now fixed by using interrupt mode.
  For Allwinner also fix the frequency calculation, the one in the code
  was for when the APB frequency is at 48Mhz while it is at 24Mhz on most
  (all?) Allwinner SoCs. We now support both cases.
  
  While here add more debug info when it's compiled in.
  
  Tested On: A20, H3, A64
  MFC after:1 month

Modified:
  head/sys/dev/iicbus/twsi/a10_twsi.c
  head/sys/dev/iicbus/twsi/twsi.c
  head/sys/dev/iicbus/twsi/twsi.h

Modified: head/sys/dev/iicbus/twsi/a10_twsi.c
==
--- head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr  5 14:27:48 2019
(r345947)
+++ head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr  5 14:44:23 2019
(r345948)
@@ -1,6 +1,5 @@
 /*-
- * Copyright (c) 2016 Emmanuel Vadot 
- * All rights reserved.
+ * Copyright (c) 2016-2019 Emmanuel Vadot 
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -90,6 +89,7 @@ a10_twsi_attach(device_t dev)
struct twsi_softc *sc;
clk_t clk;
hwreset_t rst;
+   uint64_t freq;
int error;
 
sc = device_get_softc(dev);
@@ -124,10 +124,31 @@ a10_twsi_attach(device_t dev)
sc->reg_soft_reset = TWI_SRST;
 
/* Setup baud rate params */
-   sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 2);
-   sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 2);
-   sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2);
+   clk_get_freq(clk, &freq);
+   switch (freq) {
+   /* 
+* Formula is
+* F0 = FINT / 2 ^ CLK_N
+* F1 = F0 / (CLK_M + 1)
+* 
+* Doc says that the output freq is F1/10 but my logic analyzer 
says otherwise
+*/
+   case 4800:
+   sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 1);
+   sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 1);
+   sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 1);
+   break;
+   case 2400:
+   sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(5, 2);
+   sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(5, 2);
+   sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2);
+   break;
+   default:
+   device_printf(dev, "Non supported frequency\n");
+   return (ENXIO);
+   }
 
+   sc->need_ack = true;
return (twsi_attach(dev));
 }
 
@@ -154,7 +175,7 @@ DEFINE_CLASS_1(iichb, a10_twsi_driver, a10_twsi_method
 static devclass_t a10_twsi_devclass;
 
 EARLY_DRIVER_MODULE(a10_twsi, simplebus, a10_twsi_driver, a10_twsi_devclass,
-0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
 EARLY_DRIVER_MODULE(iicbus, a10_twsi, iicbus_driver, iicbus_devclass,
-0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
 MODULE_DEPEND(a10_twsi, iicbus, 1, 1, 1);

Modified: head/sys/dev/iicbus/twsi/twsi.c
==
--- head/sys/dev/iicbus/twsi/twsi.c Fri Apr  5 14:27:48 2019
(r345947)
+++ head/sys/dev/iicbus/twsi/twsi.c Fri Apr  5 14:44:23 2019
(r345948)
@@ -31,7 +31,7 @@
 
 /*
  * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell
- * and Allwinner SoCs. Supports master operation only, and works in polling 
mode.
+ * and Allwinner SoCs. Supports master operation only.
  *
  * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software
  * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices".
@@ -75,8 +75,11 @@ __FBSDID("$FreeBSD$");
 #defineTWSI_STATUS_START   0x08
 #defineTWSI_STATUS_RPTD_START  0x10
 #defineTWSI_STATUS_ADDR_W_ACK  0x18
+#defineTWSI_STATUS_ADDR_W_NACK 0x20
 #defineTWSI_STATUS_DATA_WR_ACK 0x28
+#defineTWSI_STATUS_DATA_WR_NACK0x30
 #defineTWSI_STATUS_ADDR_R_ACK  0x40
+#defineTWSI_STATUS_ADDR_R_NACK 0x48
 #defineTWSI_STATUS_DATA_RD_ACK 0x50
 #defineTWSI_STATUS_DATA_RD_NOACK   0x58
 
@@ -84,27 +87,32 @@ __FBSDID("$FreeBSD$");
 #undef TWSI_DEBUG
 
 #ifdef TWSI_DEBUG
-#definedebugf(fmt, args...) do { printf("%s(): ", __func__); 
printf(f

svn commit: r345948 - head/sys/dev/iicbus/twsi

2019-04-05 Thread Emmanuel Vadot
Author: manu
Date: Fri Apr  5 14:44:23 2019
New Revision: 345948
URL: https://svnweb.freebsd.org/changeset/base/345948

Log:
  twsi: Add interrupt mode
  
  Add the ability to use interrupts for i2c message.
  We still use polling for early boot i2c transfer (for PMIC
  for example) but as soon as interrupts are available use them.
  On Allwinner SoC >A20 is seems that polling mode is broken for some
  reason, this is now fixed by using interrupt mode.
  For Allwinner also fix the frequency calculation, the one in the code
  was for when the APB frequency is at 48Mhz while it is at 24Mhz on most
  (all?) Allwinner SoCs. We now support both cases.
  
  While here add more debug info when it's compiled in.
  
  Tested On: A20, H3, A64
  MFC after:1 month

Modified:
  head/sys/dev/iicbus/twsi/a10_twsi.c
  head/sys/dev/iicbus/twsi/twsi.c
  head/sys/dev/iicbus/twsi/twsi.h

Modified: head/sys/dev/iicbus/twsi/a10_twsi.c
==
--- head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr  5 14:27:48 2019
(r345947)
+++ head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr  5 14:44:23 2019
(r345948)
@@ -1,6 +1,5 @@
 /*-
- * Copyright (c) 2016 Emmanuel Vadot 
- * All rights reserved.
+ * Copyright (c) 2016-2019 Emmanuel Vadot 
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -90,6 +89,7 @@ a10_twsi_attach(device_t dev)
struct twsi_softc *sc;
clk_t clk;
hwreset_t rst;
+   uint64_t freq;
int error;
 
sc = device_get_softc(dev);
@@ -124,10 +124,31 @@ a10_twsi_attach(device_t dev)
sc->reg_soft_reset = TWI_SRST;
 
/* Setup baud rate params */
-   sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 2);
-   sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 2);
-   sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2);
+   clk_get_freq(clk, &freq);
+   switch (freq) {
+   /* 
+* Formula is
+* F0 = FINT / 2 ^ CLK_N
+* F1 = F0 / (CLK_M + 1)
+* 
+* Doc says that the output freq is F1/10 but my logic analyzer 
says otherwise
+*/
+   case 4800:
+   sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 1);
+   sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 1);
+   sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 1);
+   break;
+   case 2400:
+   sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(5, 2);
+   sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(5, 2);
+   sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2);
+   break;
+   default:
+   device_printf(dev, "Non supported frequency\n");
+   return (ENXIO);
+   }
 
+   sc->need_ack = true;
return (twsi_attach(dev));
 }
 
@@ -154,7 +175,7 @@ DEFINE_CLASS_1(iichb, a10_twsi_driver, a10_twsi_method
 static devclass_t a10_twsi_devclass;
 
 EARLY_DRIVER_MODULE(a10_twsi, simplebus, a10_twsi_driver, a10_twsi_devclass,
-0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
 EARLY_DRIVER_MODULE(iicbus, a10_twsi, iicbus_driver, iicbus_devclass,
-0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
 MODULE_DEPEND(a10_twsi, iicbus, 1, 1, 1);

Modified: head/sys/dev/iicbus/twsi/twsi.c
==
--- head/sys/dev/iicbus/twsi/twsi.c Fri Apr  5 14:27:48 2019
(r345947)
+++ head/sys/dev/iicbus/twsi/twsi.c Fri Apr  5 14:44:23 2019
(r345948)
@@ -31,7 +31,7 @@
 
 /*
  * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell
- * and Allwinner SoCs. Supports master operation only, and works in polling 
mode.
+ * and Allwinner SoCs. Supports master operation only.
  *
  * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software
  * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices".
@@ -75,8 +75,11 @@ __FBSDID("$FreeBSD$");
 #defineTWSI_STATUS_START   0x08
 #defineTWSI_STATUS_RPTD_START  0x10
 #defineTWSI_STATUS_ADDR_W_ACK  0x18
+#defineTWSI_STATUS_ADDR_W_NACK 0x20
 #defineTWSI_STATUS_DATA_WR_ACK 0x28
+#defineTWSI_STATUS_DATA_WR_NACK0x30
 #defineTWSI_STATUS_ADDR_R_ACK  0x40
+#defineTWSI_STATUS_ADDR_R_NACK 0x48
 #defineTWSI_STATUS_DATA_RD_ACK 0x50
 #defineTWSI_STATUS_DATA_RD_NOACK   0x58
 
@@ -84,27 +87,32 @@ __FBSDID("$FreeBSD$");
 #undef TWSI_DEBUG
 
 #ifdef TWSI_DEBUG
-#definedebugf(fmt, args...) do { printf("%s(): ", __func__); 
printf(f