[PATCH RTEMS] bsps/beagle: Refactored i2c driver

G S Niteesh Babu niteesh.gs at gmail.com
Mon Mar 22 17:48:12 UTC 2021


Refactored the i2c driver to parse register values from the device
tree rather than hardcoding them. But still the clocks have to
initialized manually.
---
 bsps/arm/beagle/i2c/bbb-i2c.c     | 100 ++++++++++++++++--------------
 bsps/arm/beagle/include/bsp.h     |   4 ++
 bsps/arm/beagle/include/bsp/i2c.h |  32 +---------
 bsps/arm/beagle/start/bspstart.c  |  53 +++++++++++-----
 4 files changed, 96 insertions(+), 93 deletions(-)

diff --git a/bsps/arm/beagle/i2c/bbb-i2c.c b/bsps/arm/beagle/i2c/bbb-i2c.c
index b2a7cf814d..c315b6fc3b 100644
--- a/bsps/arm/beagle/i2c/bbb-i2c.c
+++ b/bsps/arm/beagle/i2c/bbb-i2c.c
@@ -25,6 +25,7 @@
 #include <bsp/bbb-gpio.h>
 #include <rtems/score/assert.h>
 #include <dev/i2c/i2c.h>
+#include <ofw/ofw.h>
 
 typedef struct bbb_i2c_bus {
   i2c_bus base;
@@ -34,12 +35,6 @@ typedef struct bbb_i2c_bus {
     volatile uint32_t *i2c_clkctrl;
     volatile uint32_t *clkstctrl;
   } clkregs;
-  struct {
-    volatile uint32_t *conf_sda;
-    uint32_t mmode_sda;
-    volatile uint32_t *conf_scl;
-    uint32_t mmode_scl;
-  } pinregs;
   rtems_id task_id;
   rtems_vector_number irq;
   i2c_msg *buffer;
@@ -56,19 +51,29 @@ typedef struct bbb_i2c_bus {
 #else
 #define debug_print(fmt, args...)
 #endif
+/*
+ * Here we assume the number of i2c nodes
+ * will be less than 100.
+ */
+#define PATH_LEN strlen("/dev/i2c-xx")
 
 static int am335x_i2c_fill_registers(
   bbb_i2c_bus *bus,
-  uintptr_t register_base
+  phandle_t    node
 )
 {
-  /* FIXME: The pin handling should be replaced by a proper pin handling during
-   * initialization. This one is heavily board specific. */
-#if ! IS_AM335X
-  printk ("The I2C driver currently only works on Beagle Bone. Please add your pin configs.");
-  return EINVAL;
-#endif
-  bus->regs = (volatile bbb_i2c_regs *) register_base;
+  ssize_t rv;
+  rtems_ofw_memory_area reg;
+
+  rv = rtems_ofw_get_reg(node, &reg, sizeof(reg));
+  if (rv <= 0)
+    return EINVAL;
+
+  bus->regs = (volatile bbb_i2c_regs *)reg.start;
+
+  /*
+   * FIXME: Implement a clock driver to parse and setup clocks
+   */
   switch ((intptr_t) bus->regs) {
   case AM335X_I2C0_BASE:
     bus->clkregs.ctrl_clkctrl = &REG(AM335X_SOC_CM_WKUP_REGS +
@@ -77,10 +82,6 @@ static int am335x_i2c_fill_registers(
                                  AM335X_CM_WKUP_I2C0_CLKCTRL);
     bus->clkregs.clkstctrl = &REG(AM335X_SOC_CM_WKUP_REGS +
                                    AM335X_CM_WKUP_CLKSTCTRL);
-    bus->pinregs.conf_sda = &REG(AM335X_PADCONF_BASE + AM335X_CONF_I2C0_SDA);
-    bus->pinregs.mmode_sda = 0;
-    bus->pinregs.conf_scl = &REG(AM335X_PADCONF_BASE + AM335X_CONF_I2C0_SCL);
-    bus->pinregs.mmode_scl = 0;
     break;
   case AM335X_I2C1_BASE:
     bus->clkregs.ctrl_clkctrl = &REG(AM335X_SOC_CM_WKUP_REGS +
@@ -88,10 +89,6 @@ static int am335x_i2c_fill_registers(
     bus->clkregs.i2c_clkctrl = &REG(AM335X_CM_PER_ADDR +
                                  AM335X_CM_PER_I2C1_CLKCTRL);
     bus->clkregs.clkstctrl = NULL;
-    bus->pinregs.conf_sda = &REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D1);
-    bus->pinregs.mmode_sda = 2;
-    bus->pinregs.conf_scl = &REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_CS0);
-    bus->pinregs.mmode_scl = 2;
     break;
   case AM335X_I2C2_BASE:
     bus->clkregs.ctrl_clkctrl = &REG(AM335X_SOC_CM_WKUP_REGS +
@@ -99,24 +96,12 @@ static int am335x_i2c_fill_registers(
     bus->clkregs.i2c_clkctrl = &REG(AM335X_CM_PER_ADDR +
                                  AM335X_CM_PER_I2C2_CLKCTRL);
     bus->clkregs.clkstctrl = NULL;
-    bus->pinregs.conf_sda = &REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_CTSN);
-    bus->pinregs.mmode_sda = 3;
-    bus->pinregs.conf_scl = &REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RTSN);
-    bus->pinregs.mmode_scl = 3;
     break;
   default:
     return EINVAL;
   }
-  return 0;
-}
 
-static void am335x_i2c_pinmux( bbb_i2c_bus *bus )
-{
-  *bus->pinregs.conf_sda =
-    ( BBB_RXACTIVE | BBB_SLEWCTRL | bus->pinregs.mmode_sda);
-
-  *bus->pinregs.conf_scl =
-    ( BBB_RXACTIVE | BBB_SLEWCTRL | bus->pinregs.mmode_scl);
+  return 0;
 }
 
 static void am335x_i2c_module_clk_enable( bbb_i2c_bus *bus )
@@ -453,18 +438,16 @@ static void am335x_i2c_destroy( i2c_bus *base )
   i2c_bus_destroy_and_free( &bus->base );
 }
 
-int am335x_i2c_bus_register(
-  const char         *bus_path,
-  uintptr_t           register_base,
-  uint32_t            input_clock,
-  rtems_vector_number irq
+static int am335x_i2c_bus_register(
+  phandle_t           node
 )
 {
-  bbb_i2c_bus      *bus;
-  rtems_status_code sc;
-  int               err;
-
-  (void) input_clock; /* FIXME: Unused. Left for compatibility. */
+  bbb_i2c_bus        *bus;
+  rtems_status_code   sc;
+  rtems_vector_number irq;
+  int                 err;
+  int                 unit;
+  char                bus_path[PATH_LEN];
 
   bus = (bbb_i2c_bus *) i2c_bus_alloc_and_init( sizeof( *bus ) );
 
@@ -472,15 +455,24 @@ int am335x_i2c_bus_register(
     return -1;
   }
 
+  unit = beagle_get_node_unit(node);
+
+  snprintf(bus_path, PATH_LEN, "/dev/i2c-%d", unit);
+
+  err = rtems_ofw_get_interrupts(node, &irq, sizeof(irq));
+  if (err < 1) {
+    ( *bus->base.destroy )( &bus->base );
+    rtems_set_errno_and_return_minus_one( err );
+  }
   bus->irq = irq;
 
-  err = am335x_i2c_fill_registers(bus, register_base);
+  err = am335x_i2c_fill_registers(bus, node);
   if (err != 0) {
     ( *bus->base.destroy )( &bus->base );
     rtems_set_errno_and_return_minus_one( err );
   }
-  am335x_i2c_module_clk_enable(bus);
-  am335x_i2c_pinmux( bus );
+
+  am335x_i2c_module_clk_enable( bus );
   err = am335x_i2c_reset( bus );
   if (err != 0) {
     ( *bus->base.destroy )( &bus->base );
@@ -506,3 +498,15 @@ int am335x_i2c_bus_register(
 
   return i2c_bus_register( &bus->base, bus_path );
 }
+
+void beagle_i2c_init(phandle_t node)
+{
+  int rv;
+
+  if (!rtems_ofw_is_node_compatible(node, "ti,omap4-i2c"))
+    return ;
+
+  rv = am335x_i2c_bus_register(node);
+  if (rv != 0)
+    printk("i2c: Could not register device (%d)\n", rv);
+}
diff --git a/bsps/arm/beagle/include/bsp.h b/bsps/arm/beagle/include/bsp.h
index cb415fda89..80a9cc291d 100644
--- a/bsps/arm/beagle/include/bsp.h
+++ b/bsps/arm/beagle/include/bsp.h
@@ -49,6 +49,8 @@
 #include <libcpu/omap3.h>
 #include <libcpu/am335x.h>
 
+#include <ofw/ofw.h>
+
 #define BSP_FEATURE_IRQ_EXTENSION
 
 /* UART base clock frequency */
@@ -68,6 +70,8 @@
 
 #define udelay(u) rtems_task_wake_after(1 + ((u)/rtems_configuration_get_microseconds_per_tick()))
 
+int beagle_get_node_unit(phandle_t node);
+
 /* Write a uint32_t value to a memory address. */
 static inline void
 write32(uint32_t address, uint32_t value)
diff --git a/bsps/arm/beagle/include/bsp/i2c.h b/bsps/arm/beagle/include/bsp/i2c.h
index 60f71194bf..d80b376fa0 100644
--- a/bsps/arm/beagle/include/bsp/i2c.h
+++ b/bsps/arm/beagle/include/bsp/i2c.h
@@ -26,6 +26,7 @@
 #include <rtems.h>
 #include <bsp.h>
 #include <dev/i2c/i2c.h>
+#include <ofw/ofw.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -38,10 +39,6 @@ extern "C" {
 #define BBB_I2C_1_BUS_PATH "/dev/i2c-1"
 #define BBB_I2C_2_BUS_PATH "/dev/i2c-2"
 
-#define BBB_I2C0_IRQ 70
-#define BBB_I2C1_IRQ 71
-#define BBB_I2C2_IRQ 30
-
 typedef enum {
   I2C0,
   I2C1,
@@ -87,32 +84,7 @@ typedef struct i2c_regs {
   uint32_t BBB_I2C_SBLOCK;
 } bbb_i2c_regs;
 
-int am335x_i2c_bus_register(
-  const char         *bus_path,
-  uintptr_t           register_base,
-  uint32_t            input_clock, /* FIXME: Unused. Left for compatibility. */
-  rtems_vector_number irq
-);
-
-static inline int bbb_register_i2c_1( void )
-{
-  return am335x_i2c_bus_register(
-    BBB_I2C_1_BUS_PATH,
-    AM335X_I2C1_BASE,
-    I2C_BUS_CLOCK_DEFAULT,
-    BBB_I2C1_IRQ
-  );
-}
-
-static inline int bbb_register_i2c_2( void )
-{
-  return am335x_i2c_bus_register(
-    BBB_I2C_2_BUS_PATH,
-    AM335X_I2C2_BASE,
-    I2C_BUS_CLOCK_DEFAULT,
-    BBB_I2C2_IRQ
-  );
-}
+void beagle_i2c_init( phandle_t node );
 
 #ifdef __cplusplus
 }
diff --git a/bsps/arm/beagle/start/bspstart.c b/bsps/arm/beagle/start/bspstart.c
index a0736294c9..d45eec9e92 100644
--- a/bsps/arm/beagle/start/bspstart.c
+++ b/bsps/arm/beagle/start/bspstart.c
@@ -22,9 +22,15 @@
 #include "bsp-soc-detect.h"
 #include <arm/ti/ti_pinmux.h>
 #include <ofw/ofw.h>
+#include <bsp/i2c.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
 
 #include "bspdebug.h"
 
+#define MIN(l,r) ((l) < (r) ? (l) : (r))
+
 void bsp_start(void)
 {
   const char *type;
@@ -70,6 +76,7 @@ static void traverse_fdt_nodes( phandle_t node )
      * Put all driver initialization functions here
      */
     beagle_pinmux_init(node);
+    beagle_i2c_init(node);
   }
 }
 
@@ -80,24 +87,40 @@ static void bbb_drivers_initialize(void)
   traverse_fdt_nodes(node);
 }
 
-static void bbb_i2c_0_initialize(void)
+int beagle_get_node_unit(phandle_t node)
 {
-  int err;
-
-  err = am335x_i2c_bus_register(BBB_I2C_0_BUS_PATH,
-                                AM335X_I2C0_BASE,
-                                I2C_BUS_CLOCK_DEFAULT,
-                                BBB_I2C0_IRQ);
-  if (err != 0) {
-    printk("rtems i2c-0: Device could not be registered (%d)", err);
+  char name[30];
+  char prop[30];
+  char prop_val[30];
+  static int unit;
+  phandle_t aliases;
+  int rv;
+  int i;
+
+  rv = rtems_ofw_get_prop(node, "name", name, sizeof(name));
+  if (rv <= 0)
+    return unit++;
+
+  aliases = rtems_ofw_find_device("/aliases");
+
+  rv = rtems_ofw_next_prop(aliases, NULL, &prop[0], sizeof(prop));
+
+  while (rv > 0) {
+    rv = rtems_ofw_get_prop(aliases, prop, prop_val, sizeof(prop_val));
+
+    if (strstr(prop_val, name) != NULL) {
+      for (i = strlen(prop) - 1; i >= 0; i--) {
+        if (!isdigit(prop[i]))
+          break;
+      }
+
+      return strtol(&prop[i + 1], NULL, 10);
+    }
+    rv = rtems_ofw_next_prop(aliases, prop, prop, sizeof(prop));
   }
-}
 
-RTEMS_SYSINIT_ITEM(
-  bbb_i2c_0_initialize,
-  RTEMS_SYSINIT_LAST,
-  RTEMS_SYSINIT_ORDER_LAST_BUT_5
-);
+  return unit++;
+}
 
 RTEMS_SYSINIT_ITEM(
 	bbb_drivers_initialize,
-- 
2.17.1



More information about the devel mailing list