This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

To change EVM code of TI814X-LINUX-PSP-04.01.00.05 to support the RMII mode on custom board

Hi,

 Code flow for EVM board is as follows

arch/arm/mach-omap2/board-ti8148evm.c

----------------------------------------------------------

MACHINE_START(TI8148EVM, "ti8148evm")

     /* Maintainer: Texas Instruments */

         .boot_params    = 0x80000100,

         .map_io         = ti8148_evm_map_io,

         .reserve         = ti81xx_reserve,

         .init_irq       = ti8148_evm_init_irq,

         .init_machine   = ti8148_evm_init,

         .timer          = &omap_timer,

 MACHINE_END

 

48 #ifdef CONFIG_OMAP_MUX

 49 static struct omap_board_mux board_mux[] __initdata = {

 50         { .reg_offset = OMAP_MUX_TERMINATOR },

 51 };

 52 #else

 53 #define board_mux     NULL

 54 #endif

 

static void __init ti8148_evm_init(void)

271 {

272         printk(KERN_CRIT "ETHERNET:inside ti8148_evm_init b4 calling the ti814x_mux_init\n");

273         ti814x_mux_init(board_mux);

 

arch/arm/mach-omap2/muxti814x.c

------------------------------------------------

int __init ti814x_mux_init(struct omap_board_mux *board_subset)

833 {

834         printk(KERN_CRIT "ETHERNET:Inside the ti814x_mux_init b4 calling omap_mux_init with 8 args\n");

835         return omap_mux_init("core", OMAP_MUX_REG_32BIT,

836                         TI81XX_CONTROL_PADCONF_MUX_PBASE,

837                         TI814X_CONTROL_PADCONF_MUX_SIZE, ti814x_muxmodes, NULL,

838                         board_subset, NULL);

839 }

 

arch/arm/mach-omap2/mux.c

----------------------------------------

1023 int __init omap_mux_init(const char *name, u32 flags,

1024                          u32 mux_pbase, u32 mux_size,

1025                          struct omap_mux *superset,

1026                          struct omap_mux *package_subset,

1027                          struct omap_board_mux *board_mux,

1028                          struct omap_ball *package_balls)

1029 {

1030         struct omap_mux_partition *partition;

1031

1032         printk(KERN_CRIT "ETHERNET:inside the omap_mux_init\n");

1033         partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);

1034         if (!partition)

1035                 return -ENOMEM;

1036

1037         partition->name = name;

1038         partition->flags = flags;

1039         partition->size = mux_size;

1040         partition->phys = mux_pbase;

1041         partition->base = ioremap(mux_pbase, mux_size);

1042         if (!partition->base) {

1043                 pr_err("%s: Could not ioremap mux partition at 0x%08x\n",

1044                         __func__, partition->phys);

1045                 return -ENODEV;

1046         }

1047

1048         INIT_LIST_HEAD(&partition->muxmodes);

1049

1050         list_add_tail(&partition->node, &mux_partitions);

1051         mux_partitions_cnt++;

1052         pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,

1053                 mux_partitions_cnt, partition->name, partition->flags);

1054

1055         omap_mux_init_package(superset, package_subset, package_balls);

1056         omap_mux_init_list(partition, superset);

1057         omap_mux_init_signals(partition, board_mux);

1058

1059         return 0;

1060 }

 

998 static void omap_mux_init_signals(struct omap_mux_partition *partition,

 999                                   struct omap_board_mux *board_mux)

1000 {

1001         printk(KERN_CRIT "ETHERNET:inside omap_mux_init_signals b4 calling omap_mux_set_cmdline_signals\n");

1002         omap_mux_set_cmdline_signals();

1003         omap_mux_write_array(partition, board_mux);

1004 }

 

785 static void __init omap_mux_set_cmdline_signals(void)

 786 {

 787         char *options, *next_opt, *token;

 788

 789         printk(KERN_CRIT "ETHERNET:inside omap_mux_set_cmdline_signals\n");

 790

 791         if (!omap_mux_options)

{                   printk(KERN_CRIT”gets returned here\n”);

                return;

}

 793

 794         options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL);

 795         if (!options)

 796                 return;

 797

 798         strcpy(options, omap_mux_options);

 799         next_opt = options;

 800

 801         while ((token = strsep(&next_opt, ",")) != NULL) {

 802                 char *keyval, *name;

 803                 unsigned long val;

 804

 805                 keyval = token;

 806                 name = strsep(&keyval, "=");

 807                 if (name) {

 808                         int res;

 809

 810                         res = strict_strtoul(keyval, 0x10, &val);

 811                         if (res < 0)

 812                                 continue;

 813

 814                         printk(KERN_CRIT "ETHERNET:inside while of omap_mux_set_cmdline_signals\n");

 815                         omap_mux_init_signal(name, (int)val);

 816                 }

 817         }

 818

 819         kfree(options);

 820 }          

253 int __init omap_mux_init_signal(const char *muxname, int val)

 254 {

 255         struct omap_mux_partition *partition = NULL;

 256         struct omap_mux *mux = NULL;

 257         u16 old_mode;

 258         int mux_mode;

 259

 260         printk(KERN_CRIT "ETHERNET:inside omap_mux_init_signal\n");

 261         mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);

 262         if (mux_mode < 0)

 263                 return mux_mode;

 264

 265         old_mode = omap_mux_read(partition, mux->reg_offset);

 266

 267         mux_mode |= val;

 268         pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",

 269                          __func__, muxname, old_mode, mux_mode);

 270         omap_mux_write(partition, mux_mode, mux->reg_offset);

 271

 272         return 0;

 273 }

76 void omap_mux_write(struct omap_mux_partition *partition, u32 val,

  77                            u16 reg)

  78 {

  79         /* Avoid unintentional change of bits 18-31 on TI814x */

  80         //printk(KERN_CRIT "ETHERNET:inside the omap_mux_write\n");

  81         printk(KERN_CRIT "ETHERNET:inside the omap_mux_write\n");

  82         if (cpu_is_ti814x())

  83                 val |= __raw_readl(partition->base + reg) & 0xFFFC0000;

  84

  85         if (partition->flags & OMAP_MUX_REG_8BIT)

  86                 __raw_writeb(val, partition->base + reg);

  87         if (partition->flags & OMAP_MUX_REG_32BIT)

  88                 __raw_writel(val, partition->base + reg);

  89         else

  90                 __raw_writew(val, partition->base + reg);

  91 }

 

93 void omap_mux_write_array(struct omap_mux_partition *partition,

  94                                  struct omap_board_mux *board_mux)

  95 {

  96         printk(KERN_CRIT "ETHERNET:inside omap_mux_write_array\n");

  97         while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {

  98                 printk(KERN_CRIT "ETHERNET:inside omap_mux_write_array\n");

  99                 omap_mux_write(partition, board_mux->value,

 100                                board_mux->reg_offset);

 101                 board_mux++;

 102         }

#ifdef CONFIG_OMAP_MUX

 

#define _TI814X_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)                  \

{                                                                                                                                               \

                .reg_offset            = (TI814X_CONTROL_PADCONF_##M0##_OFFSET),    \

                .gpio                       = (g),                                                                                       \

                .muxnames            = { m0, m1, m2, m3, m4, m5, m6, m7 },                            \

}

 

/*

 * Superset of all mux modes for TI814X

 */

static struct omap_mux __initdata ti814x_muxmodes[] = {

                _TI814X_MUXENTRY(MMC1_CLK, 0,

                                                "mmc1_clk", NULL, NULL, NULL,

                                       :

                                      :

                                     :

              

_TI814X_MUXENTRY(GMII0_COL, 0,

                                                "gmii0_col", "vin1b_d1", "rmii0_rxd0", NULL, NULL, NULL,

                                                NULL, "gpio3_24"),

                _TI814X_MUXENTRY(GMII0_CRS, 0,

                                                "gmii0_crs", "vin1b_d2", "rmii0_rxd1", NULL, NULL, NULL,

                                                NULL, "gpio3_25"),

                _TI814X_MUXENTRY(GMII0_RXER, 0,

                                                "gmii0_rxer", "vin1b_d3", "rmii0_rxer", NULL, NULL,

                                                NULL, NULL, "gpio3_26"),

                _TI814X_MUXENTRY(GMII0_RXCLK, 0,

                                                "gmii0_rxclk", "vin1b_d4", "rmii0_crs", NULL, NULL,

                                                "spi3_cs2", NULL, "gpio3_27"),

                _TI814X_MUXENTRY(GMII0_RXD0, 0,

                                                "gmii0_rxd0", "vin1b_d5", "rmii0_txd0", NULL, NULL,

                                                NULL, NULL, "gpio3_28"),

                _TI814X_MUXENTRY(GMII0_RXD1, 0,

                                                "gmii0_rxd1", "vin1b_d6", "rmii0_txd1", NULL, NULL,

                                                NULL, NULL, "gpio3_29"),

                _TI814X_MUXENTRY(GMII0_RXD2, 0,

                                                "gmii0_rxd2", "vin1b_d7", "rmii0_txen", NULL, NULL,

                                                NULL, NULL, "gpio3_30_mux0"),

 

                                               :

 

                                               :

                                                :

                                              :

                _TI814X_MUXENTRY(RMII_REFCLK, 0,

                                                "rmii_refclk", NULL, NULL, NULL, NULL, NULL,

                                                "timer2_mux3", "gpio1_10_mux0"),

                _TI814X_MUXENTRY(MDIO_MCLK, 0,

                                                "mdio_mclk", NULL, NULL, NULL, NULL, NULL, NULL,

                                                "gpio1_11_mux0"),

                _TI814X_MUXENTRY(MDIO_D, 0,

                                                "mdio_d", NULL, NULL, NULL, NULL, NULL, NULL,

                                                "gpio1_12_mux0"),

                                           :

                                         :

                                            :

After all the above thing we come for

 

 

arch/arm/mach-omap2/devices.c#

============================

#ifdef CONFIG_ARCH_TI814X
#define TI814X_CPSW_BASE  (0x4A100000)
#define TI814X_CPSW_MDIO_BASE  (0x4A100800)
#define TI814X_CPSW_SS_BASE  (0x4A100900)
#define TI814X_EMAC_MDIO_FREQ  (1000000)

static u64 cpsw_dma_mask = DMA_BIT_MASK(32);
/* TODO : Verify the offsets */
struct cpsw_slave_data cpsw_slaves[] = {
 {
  .slave_reg_ofs  = 0x50,
  .sliver_reg_ofs = 0x700,
  .phy_id  = "0:00",
 },
 {
  .slave_reg_ofs  = 0x90,
  .sliver_reg_ofs = 0x740,
  .phy_id  = "0:01",
 },
};

static struct cpsw_platform_data ti814x_cpsw_pdata = {
 .ss_reg_ofs  = 0x900,
 .channels  = 8,
 .cpdma_reg_ofs  = 0x100,
 .slaves   = 1,
 .slave_data  = cpsw_slaves,
 .ale_reg_ofs  = 0x600,
 .ale_entries  = 1024,
 .host_port_reg_ofs      = 0x28,
 .hw_stats_reg_ofs       = 0x400,
 .bd_ram_ofs  = 0x2000,
 .bd_ram_size  = SZ_8K,
 .rx_descs               = 64,
 .mac_control            = BIT(5), /* MIIEN */
 .gigabit_en  = 1,
 .host_port_num  = 0,
 .no_bd_ram  = false,
};

static struct resource ti814x_cpsw_resources[] = {
 {
  .start  = TI814X_CPSW_BASE,
  .end    = TI814X_CPSW_BASE + SZ_2K - 1,
  .flags  = IORESOURCE_MEM,
 },
 {
  .start  = TI814X_CPSW_SS_BASE,
  .end    = TI814X_CPSW_SS_BASE + SZ_256 - 1,
  .flags  = IORESOURCE_MEM,
 },
 {
  .start = TI814X_IRQ_GSWRXTHR0,
  .end = TI814X_IRQ_GSWRXTHR0,
  .flags = IORESOURCE_IRQ,
 },
 {
  .start = TI814X_IRQ_GSWRXINT0,
  .end = TI814X_IRQ_GSWRXINT0,
  .flags = IORESOURCE_IRQ,
 },
 {
  .start = TI814X_IRQ_GSWTXINT0,
  .end = TI814X_IRQ_GSWTXINT0,
  .flags = IORESOURCE_IRQ,
 },
 {
  .start = TI814X_IRQ_GSWMISC0,
  .end = TI814X_IRQ_GSWMISC0,
  .flags = IORESOURCE_IRQ,
 },
};

static struct platform_device ti814x_cpsw_device = {
 .name  = "cpsw",
 .id  = 0,
 .num_resources = ARRAY_SIZE(ti814x_cpsw_resources),
 .resource = ti814x_cpsw_resources,
 .dev  = {
     .platform_data    = &ti814x_cpsw_pdata,
     .dma_mask    = &cpsw_dma_mask,
     .coherent_dma_mask = DMA_BIT_MASK(32),
    },
};

static int __init omap2_init_devices(void)

{

                /*

                 * please keep these calls, and their implementations above,

                 * in alphabetical order so they're easier to sort through.

                 */

                omap_hsmmc_reset();

#if !defined(CONFIG_ARCH_TI81XX)

                omap_init_audio();

#endif

                omap_init_camera();

                omap_init_mbox();

                omap_init_mcspi();

                omap_init_pmu();

                omap_hdq_init();

                omap_init_sti();

                omap_init_sham();

                omap_init_aes();

                omap_init_vout();

#ifdef CONFIG_ARCH_TI81XX

                ti81xx_ethernet_init();

                ti816x_init_pcie();

                ti81xx_register_edma();

                ti81xx_init_pcm();

                ti816x_sr_init();

#endif

                omap_init_ahci();

                return 0;

}

arch_initcall(omap2_init_devices);

 

1879 #ifdef CONFIG_ARCH_TI81XX

1880 static void ti81xx_ethernet_init(void)

1881 {

1882         printk(KERN_CRIT "ETHERNET:inside ti81xx_ethernet_init\n");

1883         if (cpu_is_ti816x())

1884                 ti816x_ethernet_init();

1885         else

1886                 ti814x_cpsw_init();

1887 }

 

void ti814x_cpsw_init(void)

{

                u32 mac_lo, mac_hi;

 

                printk(KERN_CRIT "ETHERNET:inside ti814x_cpsw_init\n");

                mac_lo = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID0_LO);

                mac_hi = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID0_HI);

                cpsw_slaves[0].mac_addr[0] = mac_hi & 0xFF;

                cpsw_slaves[0].mac_addr[1] = (mac_hi & 0xFF00) >> 8;

                cpsw_slaves[0].mac_addr[2] = (mac_hi & 0xFF0000) >> 16;

                cpsw_slaves[0].mac_addr[3] = (mac_hi & 0xFF000000) >> 24;

                cpsw_slaves[0].mac_addr[4] = mac_lo & 0xFF;

                cpsw_slaves[0].mac_addr[5] = (mac_lo & 0xFF00) >> 8;

 

                mac_lo = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID1_LO);

                mac_hi = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID1_HI);

                cpsw_slaves[1].mac_addr[0] = mac_hi & 0xFF;

                cpsw_slaves[1].mac_addr[1] = (mac_hi & 0xFF00) >> 8;

                cpsw_slaves[1].mac_addr[2] = (mac_hi & 0xFF0000) >> 16;

                cpsw_slaves[1].mac_addr[3] = (mac_hi & 0xFF000000) >> 24;

                cpsw_slaves[1].mac_addr[4] = mac_lo & 0xFF;

                cpsw_slaves[1].mac_addr[5] = (mac_lo & 0xFF00) >> 8;

#if 0

                ti814x_cpsw_mux();

#endif

                if (omap_rev() == TI8148_REV_ES1_0)

                                cpsw_slaves[0].phy_id = "0:01";

                else {

                                cpsw_slaves[0].phy_id = "0:00";

                                cpsw_slaves[1].phy_id = "0:01";

                }

 

                platform_device_register(&cpsw_mdio_device);

                platform_device_register(&ti814x_cpsw_device);

                clk_add_alias(NULL, dev_name(&cpsw_mdio_device.dev),

                                                NULL, &ti814x_cpsw_device.dev);

}

#else

static inline void ti814x_cpsw_init(void) {}

#endif

 

void ti814x_cpsw_mux(void)

{

#if 0 /* No pinmux for now */

                omap_mux_init_signal("gmii1_rxclk", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd0", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd1", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd2", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd3", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd4", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd5", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd6", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd7", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxdv", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_gtxclk", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd0", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd1", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd2", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd3", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd4", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd5", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd6", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd7", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txen", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txclk", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_col", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_crs", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxer", OMAP_MUX_MODE1);

#endif

}

 

Now in docs section of TI814X-LINUX-PSP-04.01.00.05, in DM814x C6A814x AM387x PSP User Guide

under the section its told that

 

Modifying Pin Mux settings

=====================

On DM814x devices, the pins are tri-stated and set to Mode 0 or any other mode as required for specific module

(e.g., MMC) in U-Boot. If you desire to use a particular pin to any other function than Mode 0 or override any other

pin mode which was already set in U-Boot, the kernel needs to be modified and rebuilt.

 

You can change default mux mode by adding specific mux entry in the beginning of board_mux array in

arch/arm/mach-omap2/board-ti8148evm.c or calling omap_mux_init_signal() during

initialization (e.g., in device specific initialization function called from omap2_init_devices() in

arch/arm/mach-omap2/devices.c).

 

The names of multiplexed signals are specified in arch/arm/mach-omap2/mux814x.c file in kernel source directory.

e.g., for setting xref_clk0 pin (mode 0) to usb1_drvvbus (mode 7 or FUNCTION 8), add

TI814X_MUX(XREF_CLK0, OMAP_MUX_MODE7) to board_mux structure in board file or call

omap_mux_init_signal("xref_clk0", OMAP_MUX_MODE7)

The API approach is useful if you desire to set the pin-mux run time depending upon the board/hardware detected

without need of maintaining separate kernel binaries.

 

Note: On DM814x devices, the bit positions for pull up/down are different and hence use macros

TI814X_PULL_DIS (to disable pull up/down) or TI814X_PULL_UP to select pull up.

 

So now to make our custom board work is it enough if we give something like

omap_mux_init_signal("rmii0_rxer", OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_rxd1", OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_rxd0", OMAP_MUX_MODE2);

 

 

 

omap_mux_init_signal("rmii0_crs", OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_txen" , OMAP_MUX_MODE2);

omap_mux_init_signal("rmii_refclk" , OMAP_MUX_MODE0); in

void ti814x_cpsw_mux(void)

{

}

in as datsheet says the same.

Without doing this right now we get the error when we execute  the function davinci_mdio_reset

static void __davinci_mdio_reset(struct davinci_mdio_data *data)

{

      u32 mdio_in, div, mdio_out_khz, access_time;

 

      mdio_in = clk_get_rate(data->clk);

      div = (mdio_in / data->pdata.bus_freq) - 1;

      if (div > CONTROL_MAX_DIV)

            div = CONTROL_MAX_DIV;

 

      /* set enable and clock divider */

      __raw_writel(div | CONTROL_ENABLE, &data->regs->control);

 

      /*

       * One mdio transaction consists of:

       *    32 bits of preamble

       *    32 bits of transferred data

       *    24 bits of bus yield (not needed unless shared?)

       */

      mdio_out_khz = mdio_in / (1000 * (div + 1));

      access_time  = (88 * 1000) / mdio_out_khz;

 

      /*

       * In the worst case, we could be kicking off a user-access immediately

       * after the mdio bus scan state-machine triggered its own read.  If

       * so, our request could get deferred by one access cycle.  We

       * defensively allow for 4 access cycles.

       */

      data->access_time = usecs_to_jiffies(access_time * 4);

      if (!data->access_time)

            data->access_time = 1;

}

 

static int davinci_mdio_reset(struct mii_bus *bus)

{

      struct davinci_mdio_data *data = bus->priv;

      u32 phy_mask, ver;

 

      printk(KERN_CRIT "ETHERNET:inside the davinci_mdio_reset\n");

      __davinci_mdio_reset(data);

 

      /* wait for scan logic to settle */

      msleep(PHY_MAX_ADDR * data->access_time);

 

      /* dump hardware version info */

      ver = __raw_readl(&data->regs->version);

      dev_info(data->dev, "davinci mdio revision %d.%d\n",

             (ver >> 8) & 0xff, ver & 0xff);

 

      /* get phy mask from the alive register */

      phy_mask = __raw_readl(&data->regs->alive);

      if (phy_mask) {

            /* restrict mdio bus to live phys only */

            dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);//things will go wrong here as no clock as pimuxing not done

            phy_mask = ~phy_mask;

      } else {

            /* desperately scan all phys */

            dev_warn(data->dev, "no live phy, scanning all\n");

            phy_mask = 0;

      }

      data->bus->phy_mask = phy_mask;

 

      return 0;

}

 

/* wait until hardware is ready for another user access */

static inline int wait_for_user_access(struct davinci_mdio_data *data)

{

      struct davinci_mdio_regs __iomem *regs = data->regs;

      unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);

      u32 reg;

 

      while (time_after(timeout, jiffies)) {

            reg = __raw_readl(&regs->user[0].access);

            if ((reg & USERACCESS_GO) == 0)

                  return 0;

 

            reg = __raw_readl(&regs->control);

            if ((reg & CONTROL_IDLE) == 0)

                  continue;

 

            /*

             * An emac soft_reset may have clobbered the mdio controller's

             * state machine.  We need to reset and retry the current

             * operation

             */

            dev_warn(data->dev, "resetting idled controller\n");

            __davinci_mdio_reset(data);

            return -EAGAIN;

      }

      dev_err(data->dev, "timed out waiting for user access\n");

      return -ETIMEDOUT;

}

 

/* wait until hardware state machine is idle */

static inline int wait_for_idle(struct davinci_mdio_data *data)

{

      struct davinci_mdio_regs __iomem *regs = data->regs;

      unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);

 

      while (time_after(timeout, jiffies)) {

            if (__raw_readl(&regs->control) & CONTROL_IDLE)

                  return 0;

      }

      dev_err(data->dev, "timed out waiting for idle\n");

      return -ETIMEDOUT;

}

 

static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)

{

      struct davinci_mdio_data *data = bus->priv;

      u32 reg;

      int ret;

 

      if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)

            return -EINVAL;

 

      spin_lock(&data->lock);

 

      if (data->suspended) {

            spin_unlock(&data->lock);

            return -ENODEV;

      }

 

      reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |

             (phy_id << 16));

 

      while (1) {

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            if (ret < 0)

                  break;

 

            __raw_writel(reg, &data->regs->user[0].access);

 

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            if (ret < 0)

                  break;

 

            reg = __raw_readl(&data->regs->user[0].access);

            ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;

            break;

      }

 

      spin_unlock(&data->lock);

 

      return ret;

}

 

static int davinci_mdio_write(struct mii_bus *bus, int phy_id,

                        int phy_reg, u16 phy_data)

{

      struct davinci_mdio_data *data = bus->priv;

      u32 reg;

      int ret;

 

      if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)

            return -EINVAL;

 

      spin_lock(&data->lock);

 

      if (data->suspended) {

            spin_unlock(&data->lock);

            return -ENODEV;

      }

 

      reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |

               (phy_id << 16) | (phy_data & USERACCESS_DATA));

 

      while (1) {

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            if (ret < 0)

                  break;

 

            __raw_writel(reg, &data->regs->user[0].access);

 

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            break;

      }

 

      spin_unlock(&data->lock);

 

      return 0;

}

 

static int __devinit davinci_mdio_probe(struct platform_device *pdev)

{

      struct mdio_platform_data *pdata = pdev->dev.platform_data;

      struct device *dev = &pdev->dev;

      struct davinci_mdio_data *data;

      struct resource *res;

      struct phy_device *phy;

      int ret, addr;

 

      printk(KERN_CRIT "ETHERNET:inside the davinci_mdio_probe\n");

      data = kzalloc(sizeof(*data), GFP_KERNEL);

      if (!data) {

            dev_err(dev, "failed to alloc device data\n");

            return -ENOMEM;

      }

 

      data->pdata = pdata ? (*pdata) : default_pdata;

 

      data->bus = mdiobus_alloc();

      if (!data->bus) {

            dev_err(dev, "failed to alloc mii bus\n");

            ret = -ENOMEM;

            goto bail_out;

      }

 

      data->bus->name         = dev_name(dev);

      data->bus->read         = davinci_mdio_read,

      data->bus->write  = davinci_mdio_write,

      data->bus->reset  = davinci_mdio_reset,

      data->bus->parent = dev;

      data->bus->priv         = data;

      snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);

 

      data->clk = clk_get(dev, NULL);

      if (IS_ERR(data->clk)) {

            data->clk = NULL;

            dev_err(dev, "failed to get device clock\n");

//          ret = PTR_ERR(data->clk);

//          goto bail_out;

      }

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 clk_enable\n");

      clk_enable(data->clk);

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe after clk_enable b4 dev_set_drvdata\n");

      dev_set_drvdata(dev, data);

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe after dev_set_drvdata\n");

      data->dev = dev;

      spin_lock_init(&data->lock);

 

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling platform_get_resource\n");

      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

      if (!res) {

            dev_err(dev, "could not find register map resource\n");

            ret = -ENOENT;

            goto bail_out;

      }

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling devm_request_mem_region\n");

 

      res = devm_request_mem_region(dev, res->start, resource_size(res),

                                  dev_name(dev));

      if (!res) {

            dev_err(dev, "could not allocate register map resource\n");

            ret = -ENXIO;

            goto bail_out;

      }

 

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling devm_ioremap_nocache\n");

      data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));

      if (!data->regs) {

            dev_err(dev, "could not map mdio registers\n");

            ret = -ENOMEM;

            goto bail_out;

      }

 

      /* register the mii bus */

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling mdiobus_register\n");

      ret = mdiobus_register(data->bus); //after this davinci_mdio_reset gets called

      if (ret)

            goto bail_out;

 

      /* scan and dump the bus */

      for (addr = 0; addr < PHY_MAX_ADDR; addr++) {

            phy = data->bus->phy_map[addr];

            if (phy) {

                  dev_info(dev, "phy[%d]: device %s, driver %s\n",

                         phy->addr, dev_name(&phy->dev),

                         phy->drv ? phy->drv->name : "unknown");

            }

      }

 

      return 0;

 

bail_out:

      if (data->bus)

            mdiobus_free(data->bus);

 

      if (data->clk) {

            clk_disable(data->clk);

            clk_put(data->clk);

      }

 

      kfree(data);

 

      return ret;

}

 

static int __devexit davinci_mdio_remove(struct platform_device *pdev)

{

      struct device *dev = &pdev->dev;

      struct davinci_mdio_data *data = dev_get_drvdata(dev);

 

      if (data->bus)

            mdiobus_free(data->bus);

 

      if (data->clk) {

            clk_disable(data->clk);

            clk_put(data->clk);

      }

 

      dev_set_drvdata(dev, NULL);

 

      kfree(data);

 

      return 0;

}

 

static int davinci_mdio_suspend(struct device *dev)

{

      struct davinci_mdio_data *data = dev_get_drvdata(dev);

      u32 ctrl;

 

      spin_lock(&data->lock);

 

      /* shutdown the scan state machine */

      ctrl = __raw_readl(&data->regs->control);

      ctrl &= ~CONTROL_ENABLE;

      __raw_writel(ctrl, &data->regs->control);

      wait_for_idle(data);

 

      if (data->clk)

            clk_disable(data->clk);

 

      data->suspended = true;

      spin_unlock(&data->lock);

 

      return 0;

}

 

static int davinci_mdio_resume(struct device *dev)

{

      struct davinci_mdio_data *data = dev_get_drvdata(dev);

      u32 ctrl;

 

      spin_lock(&data->lock);

      if (data->clk)

            clk_enable(data->clk);

 

      /* restart the scan state machine */

      ctrl = __raw_readl(&data->regs->control);

      ctrl |= CONTROL_ENABLE;

      __raw_writel(ctrl, &data->regs->control);

 

      data->suspended = false;

      spin_unlock(&data->lock);

 

      return 0;

}

 

static const struct dev_pm_ops davinci_mdio_pm_ops = {

      .suspend    = davinci_mdio_suspend,

      .resume           = davinci_mdio_resume,

};

 

static struct platform_driver davinci_mdio_driver = {

      .driver = {

            .name = "davinci_mdio",

            .owner      = THIS_MODULE,

            .pm   = &davinci_mdio_pm_ops,

      },

      .probe = davinci_mdio_probe,

      .remove = __devexit_p(davinci_mdio_remove),

};

 

static int __init davinci_mdio_init(void)

{

      return platform_driver_register(&davinci_mdio_driver);

}

device_initcall(davinci_mdio_init);

 

static void __exit davinci_mdio_exit(void)

{

      platform_driver_unregister(&davinci_mdio_driver);

}

module_exit(davinci_mdio_exit);

 

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("DaVinci MDIO driver");

 

 

 

 

 So adding just the pinmuxing will it do for phy to be recognised and start working in RMII mode.

or more has to be done like at

static struct cpsw_platform_data ti814x_cpsw_pdata = {
 .ss_reg_ofs  = 0x900,
 .channels  = 8,
 .cpdma_reg_ofs  = 0x100,
 .slaves   = 1,
 .slave_data  = cpsw_slaves,
 .ale_reg_ofs  = 0x600,
 .ale_entries  = 1024,
 .host_port_reg_ofs      = 0x28,
 .hw_stats_reg_ofs       = 0x400,
 .bd_ram_ofs  = 0x2000,
 .bd_ram_size  = SZ_8K,
 .rx_descs               = 64,
 .mac_control            = BIT(5), /* MIIEN */
 .gigabit_en  = 1,
 .host_port_num  = 0,
 .no_bd_ram  = false,
};

Thanks and Regards,

-P

 

 

 

 

  • Hi,

     Using the EVM TI8148 which has phy in MII mode, now we have moved to our custom board.

    After Kernel comes up want to configure Phy in MII mode because the hardware has support only for it.

    How to go about it ?  Is it enough if the below code is added

    So now to make our custom board work is it enough if we give something like as told in documnets

    omap_mux_init_signal("rmii0_rxer", OMAP_MUX_MODE2);

    TI814X-LINUX-PSP-04.01.00.05, in DM814x C6A814x AM387x PSP User Guide  under the section its told that

     

    Modifying Pin Mux settings

    =====================

    On DM814x devices, the pins are tri-stated and set to Mode 0 or any other mode as required for specific module

    (e.g., MMC) in U-Boot. If you desire to use a particular pin to any other function than Mode 0 or override any other

    pin mode which was already set in U-Boot, the kernel needs to be modified and rebuilt.

     

    You can change default mux mode by adding specific mux entry in the beginning of board_mux array in

    arch/arm/mach-omap2/board-ti8148evm.c or calling omap_mux_init_signal() during

    initialization (e.g., in device specific initialization function called from omap2_init_devices() in

    arch/arm/mach-omap2/devices.c).

     

    The names of multiplexed signals are specified in arch/arm/mach-omap2/mux814x.c file in kernel source directory.

    e.g., for setting xref_clk0 pin (mode 0) to usb1_drvvbus (mode 7 or FUNCTION 8), add

    TI814X_MUX(XREF_CLK0, OMAP_MUX_MODE7) to board_mux structure in board file or call

    omap_mux_init_signal("xref_clk0", OMAP_MUX_MODE7)

    The API approach is useful if you desire to set the pin-mux run time depending upon the board/hardware detected

    without need of maintaining separate kernel binaries.

     

    Note: On DM814x devices, the bit positions for pull up/down are different and hence use macros

    TI814X_PULL_DIS (to disable pull up/down) or TI814X_PULL_UP to select pull up.

    --Thanks and Regards,

    P

    omap_mux_init_signal("rmii0_rxd1", OMAP_MUX_MODE2);

    omap_mux_init_signal("rmii0_crs", OMAP_MUX_MODE2);

    omap_mux_init_signal("rmii0_rxd0", OMAP_MUX_MODE2);

     

     omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);

    omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);

    omap_mux_init_signal("rmii0_txen" , OMAP_MUX_MODE2);

    omap_mux_init_signal("rmii_refclk" , OMAP_MUX_MODE0);

     

  • Hi Pradeep,

    Your shared information is very useful to us and you really help us a lot.

    Besides your code suggestion, I also refer to Ti's suggestion to config mii below:


    CPSW MII Phy @ http://processors.wiki.ti.com/index.php/TI81xx_PSP_Porting_Guide#CPSW_MII_Phy

    While a PHY is populated on the board, its address on the MDIO bus is to be noted. This is to be supplied as a mask to the CPSW driver platform data for probing the PHY by the MDIO bus framework. For example, if the PHY address on the bus is 2 (in decimal), then this goes into the phy_mask of the cpsw_mdio_device as 0x04 (bit position/weight represents the PHY address). Please refer arch/arm/mach-omap2/devices.c and drivers/net/cpsw.c

    • Pinmux configuration to support mii interface
    • Program GMII_SEL in control module with 0x0 for MII Interface
    • Reset Interface Control A of CPGMAC_SLx MAC Control Register to use MII Phy


    My code change is showed as blow:

    static int mac_init = 0;
    static int __iomem *regs = 0;

    static void _cpsw_adjust_link(struct cpsw_slave *slave,
    struct cpsw_priv *priv, bool *link)
    {
    struct phy_device *phy = slave->phy;
    u32 mac_control = 0;


    if (!phy)
    return;

    if (phy->link) {
    mac_control = priv->data.mac_control;
    if (phy->speed == 1000)
    mac_control |= BIT(7); /* GIGABITEN */
    if (phy->duplex)
    mac_control |= BIT(0); /* FULLDUPLEXEN */
    *link = true;
    } else {
    mac_control = 0;
    }

    if(!mac_init)
    {
    regs = ioremap((resource_size_t)0x48140650, (resource_size_t)4);
    if (!regs)
    {
    printk("error!! unable to map i/o region\n");
    return;
    }
    else
    {
    mac_init = 1;
    printk("succeed, map i/o region, %x\n", *regs);
    }


    }

    if (mac_control != slave->mac_control) {
    phy_print_status(phy);
    }

    //Program GMII_SEL in control module with 0x0 for MII Interface
    __raw_writel((u32)0, regs);
    //Reset Interface Control A of CPGMAC_SLx MAC Control Register to use MII Phy
    mac_control &= ~EMAC_MACCONTROL_RMIISPEED_MASK;
    __raw_writel(mac_control, &slave->sliver->mac_control);

    slave->mac_control = mac_control;
    }

    Thank you!!

    Best Wishes,

    Rocky