Changeset d75b29d in rtems


Ignore:
Timestamp:
Apr 10, 2021, 7:15:27 PM (5 weeks ago)
Author:
G S Niteesh Babu <niteesh.gs@…>
Branches:
master
Children:
03747b50
Parents:
8854aec1
git-author:
G S Niteesh Babu <niteesh.gs@…> (04/10/21 19:15:27)
git-committer:
Christian Mauderer <oss@…> (04/22/21 16:43:35)
Message:

bsps/beagle: Refactored i2c driver

Refactored the i2c driver to parse register values from the device
tree rather than hardcoding them. But still the clocks have to
initialized manually.

Location:
bsps/arm/beagle
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • bsps/arm/beagle/i2c/bbb-i2c.c

    r8854aec1 rd75b29d  
    2626#include <rtems/score/assert.h>
    2727#include <dev/i2c/i2c.h>
     28#include <ofw/ofw.h>
    2829
    2930typedef struct bbb_i2c_bus {
     
    3536    volatile uint32_t *clkstctrl;
    3637  } clkregs;
    37   struct {
    38     volatile uint32_t *conf_sda;
    39     uint32_t mmode_sda;
    40     volatile uint32_t *conf_scl;
    41     uint32_t mmode_scl;
    42   } pinregs;
    4338  rtems_id task_id;
    4439  rtems_vector_number irq;
     
    5752#define debug_print(fmt, args...)
    5853#endif
     54/*
     55 * Here we assume the number of i2c nodes
     56 * will be less than 100.
     57 */
     58#define PATH_LEN (strlen("/dev/i2c-xx") + 1)
    5959
    6060static int am335x_i2c_fill_registers(
    6161  bbb_i2c_bus *bus,
    62   uintptr_t register_base
     62  uint32_t base
    6363)
    6464{
    65   /* FIXME: The pin handling should be replaced by a proper pin handling during
    66    * initialization. This one is heavily board specific. */
    67 #if ! IS_AM335X
    68   printk ("The I2C driver currently only works on Beagle Bone. Please add your pin configs.");
    69   return EINVAL;
    70 #endif
    71   bus->regs = (volatile bbb_i2c_regs *) register_base;
     65  bus->regs = (volatile bbb_i2c_regs *)base;
     66
     67  /*
     68   * FIXME: Implement a clock driver to parse and setup clocks
     69   */
    7270  switch ((intptr_t) bus->regs) {
    7371  case AM335X_I2C0_BASE:
     
    7876    bus->clkregs.clkstctrl = &REG(AM335X_SOC_CM_WKUP_REGS +
    7977                                   AM335X_CM_WKUP_CLKSTCTRL);
    80     bus->pinregs.conf_sda = &REG(AM335X_PADCONF_BASE + AM335X_CONF_I2C0_SDA);
    81     bus->pinregs.mmode_sda = 0;
    82     bus->pinregs.conf_scl = &REG(AM335X_PADCONF_BASE + AM335X_CONF_I2C0_SCL);
    83     bus->pinregs.mmode_scl = 0;
    8478    break;
    8579  case AM335X_I2C1_BASE:
     
    8983                                 AM335X_CM_PER_I2C1_CLKCTRL);
    9084    bus->clkregs.clkstctrl = NULL;
    91     bus->pinregs.conf_sda = &REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D1);
    92     bus->pinregs.mmode_sda = 2;
    93     bus->pinregs.conf_scl = &REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_CS0);
    94     bus->pinregs.mmode_scl = 2;
    9585    break;
    9686  case AM335X_I2C2_BASE:
     
    10090                                 AM335X_CM_PER_I2C2_CLKCTRL);
    10191    bus->clkregs.clkstctrl = NULL;
    102     bus->pinregs.conf_sda = &REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_CTSN);
    103     bus->pinregs.mmode_sda = 3;
    104     bus->pinregs.conf_scl = &REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RTSN);
    105     bus->pinregs.mmode_scl = 3;
    10692    break;
    10793  default:
    10894    return EINVAL;
    10995  }
     96
    11097  return 0;
    111 }
    112 
    113 static void am335x_i2c_pinmux( bbb_i2c_bus *bus )
    114 {
    115   *bus->pinregs.conf_sda =
    116     ( BBB_RXACTIVE | BBB_SLEWCTRL | bus->pinregs.mmode_sda);
    117 
    118   *bus->pinregs.conf_scl =
    119     ( BBB_RXACTIVE | BBB_SLEWCTRL | bus->pinregs.mmode_scl);
    12098}
    12199
     
    454432}
    455433
    456 int am335x_i2c_bus_register(
    457   const char         *bus_path,
    458   uintptr_t           register_base,
    459   uint32_t            input_clock,
    460   rtems_vector_number irq
     434static int am335x_i2c_bus_register(
     435  uint32_t reg_base,
     436  rtems_vector_number irq,
     437  const char *bus_path
    461438)
    462439{
    463   bbb_i2c_bus      *bus;
    464   rtems_status_code sc;
    465   int               err;
    466 
    467   (void) input_clock; /* FIXME: Unused. Left for compatibility. */
     440  bbb_i2c_bus        *bus;
     441  rtems_status_code   sc;
     442  int                 err;
    468443
    469444  bus = (bbb_i2c_bus *) i2c_bus_alloc_and_init( sizeof( *bus ) );
     445  bus->irq = irq;
    470446
    471447  if ( bus == NULL ) {
     
    473449  }
    474450
    475   bus->irq = irq;
    476 
    477   err = am335x_i2c_fill_registers(bus, register_base);
     451  err = am335x_i2c_fill_registers(bus, reg_base);
    478452  if (err != 0) {
     453    printf("i2c: invalid register base\n");
    479454    ( *bus->base.destroy )( &bus->base );
    480455    rtems_set_errno_and_return_minus_one( err );
    481456  }
    482   am335x_i2c_module_clk_enable(bus);
    483   am335x_i2c_pinmux( bus );
     457
     458  am335x_i2c_module_clk_enable( bus );
    484459  err = am335x_i2c_reset( bus );
    485460  if (err != 0) {
     461    printk("i2c: reset timed out\n");
    486462    ( *bus->base.destroy )( &bus->base );
    487463    rtems_set_errno_and_return_minus_one( err );
     
    507483  return i2c_bus_register( &bus->base, bus_path );
    508484}
     485
     486void beagle_i2c_init(phandle_t node)
     487{
     488  int                   err;
     489  int                   unit;
     490  char                  bus_path[PATH_LEN];
     491  rtems_vector_number   irq;
     492  rtems_ofw_memory_area reg;
     493
     494  if (!rtems_ofw_is_node_compatible(node, "ti,omap4-i2c"))
     495    /* We cannot handle this device */
     496    return ;
     497
     498  unit = beagle_get_node_unit(node);
     499  if (unit < 0 || unit >= 100) {
     500    printk("i2c: cannot register device, node unit number invalid.");
     501    printk(" Valid range is 0 <= unit < 100\n");
     502    return ;
     503  }
     504
     505  err = rtems_ofw_get_prop(node, "rtems,path", (void *)bus_path, PATH_LEN);
     506  if (err < 0) {
     507    /* No path was provided in the device tree therefore use the default one */
     508    snprintf(bus_path, PATH_LEN, "/dev/i2c-%d", unit);
     509  } else if (err >= PATH_LEN) {
     510    /* Null terminate the string */
     511    bus_path[PATH_LEN - 1] = 0;
     512    printk("i2c: bus path too long, trucated %s\n", bus_path);
     513  }
     514
     515  err = rtems_ofw_get_interrupts(node, &irq, sizeof(irq));
     516  if (err < 1) {
     517    printk("i2c: cannot register device, irq missing in device tree\n");
     518    return ;
     519  }
     520
     521  err = rtems_ofw_get_reg(node, &reg, sizeof(reg));
     522  if (err <= 0) {
     523    printk("i2c: cannot register device, regs field missing\n");
     524    return ;
     525  }
     526
     527  err = am335x_i2c_bus_register(reg.start, irq, bus_path);
     528  if (err != 0)
     529    printk("i2c: Could not register device (%d)\n", err);
     530}
  • bsps/arm/beagle/include/bsp.h

    r8854aec1 rd75b29d  
    5050#include <libcpu/am335x.h>
    5151
     52#include <ofw/ofw.h>
     53
    5254#define BSP_FEATURE_IRQ_EXTENSION
    5355
     
    6870
    6971#define udelay(u) rtems_task_wake_after(1 + ((u)/rtems_configuration_get_microseconds_per_tick()))
     72
     73int beagle_get_node_unit(phandle_t node);
    7074
    7175/* Write a uint32_t value to a memory address. */
  • bsps/arm/beagle/include/bsp/i2c.h

    r8854aec1 rd75b29d  
    2727#include <bsp.h>
    2828#include <dev/i2c/i2c.h>
     29#include <ofw/ofw.h>
    2930
    3031#ifdef __cplusplus
     
    3839#define BBB_I2C_1_BUS_PATH "/dev/i2c-1"
    3940#define BBB_I2C_2_BUS_PATH "/dev/i2c-2"
    40 
    41 #define BBB_I2C0_IRQ 70
    42 #define BBB_I2C1_IRQ 71
    43 #define BBB_I2C2_IRQ 30
    4441
    4542typedef enum {
     
    8885} bbb_i2c_regs;
    8986
    90 int am335x_i2c_bus_register(
    91   const char         *bus_path,
    92   uintptr_t           register_base,
    93   uint32_t            input_clock, /* FIXME: Unused. Left for compatibility. */
    94   rtems_vector_number irq
    95 );
    96 
    97 static inline int bbb_register_i2c_1( void )
    98 {
    99   return am335x_i2c_bus_register(
    100     BBB_I2C_1_BUS_PATH,
    101     AM335X_I2C1_BASE,
    102     I2C_BUS_CLOCK_DEFAULT,
    103     BBB_I2C1_IRQ
    104   );
    105 }
    106 
    107 static inline int bbb_register_i2c_2( void )
    108 {
    109   return am335x_i2c_bus_register(
    110     BBB_I2C_2_BUS_PATH,
    111     AM335X_I2C2_BASE,
    112     I2C_BUS_CLOCK_DEFAULT,
    113     BBB_I2C2_IRQ
    114   );
    115 }
     87void beagle_i2c_init( phandle_t node );
    11688
    11789#ifdef __cplusplus
  • bsps/arm/beagle/start/bspstart.c

    r8854aec1 rd75b29d  
    2323#include <arm/ti/ti_pinmux.h>
    2424#include <ofw/ofw.h>
     25#include <bsp/i2c.h>
     26#include <string.h>
     27#include <stdlib.h>
     28#include <ctype.h>
    2529
    2630#include "bspdebug.h"
     
    7175     */
    7276    beagle_pinmux_init(node);
     77    beagle_i2c_init(node);
    7378  }
    7479}
     
    8186}
    8287
    83 static void bbb_i2c_0_initialize(void)
     88int beagle_get_node_unit(phandle_t node)
    8489{
    85   int err;
     90  char name[30];
     91  char prop[30];
     92  char prop_val[30];
     93  static int unit;
     94  phandle_t aliases;
     95  int rv;
     96  int i;
    8697
    87   err = am335x_i2c_bus_register(BBB_I2C_0_BUS_PATH,
    88                                 AM335X_I2C0_BASE,
    89                                 I2C_BUS_CLOCK_DEFAULT,
    90                                 BBB_I2C0_IRQ);
    91   if (err != 0) {
    92     printk("rtems i2c-0: Device could not be registered (%d)", err);
     98  rv = rtems_ofw_get_prop(node, "name", name, sizeof(name));
     99  if (rv <= 0)
     100    return unit++;
     101
     102  aliases = rtems_ofw_find_device("/aliases");
     103
     104  rv = rtems_ofw_next_prop(aliases, NULL, &prop[0], sizeof(prop));
     105
     106  while (rv > 0) {
     107    rv = rtems_ofw_get_prop(aliases, prop, prop_val, sizeof(prop_val));
     108
     109    if (strstr(prop_val, name) != NULL) {
     110      for (i = strlen(prop) - 1; i >= 0; i--) {
     111        if (!isdigit(prop[i]))
     112          break;
     113      }
     114
     115      return strtol(&prop[i + 1], NULL, 10);
     116    }
     117    rv = rtems_ofw_next_prop(aliases, prop, prop, sizeof(prop));
    93118  }
     119
     120  return unit++;
    94121}
    95 
    96 RTEMS_SYSINIT_ITEM(
    97   bbb_i2c_0_initialize,
    98   RTEMS_SYSINIT_LAST,
    99   RTEMS_SYSINIT_ORDER_LAST_BUT_5
    100 );
    101122
    102123RTEMS_SYSINIT_ITEM(
Note: See TracChangeset for help on using the changeset viewer.