On Fri, 1 Aug 2008, Jon Smirl wrote: > I don't like the third choice. Keep a simple Linux driver for i2c and > the platform, and then move all of the messy code into uboot. BTW, > the messy code is about 10 lines. It's going to take more than 10 > lines to hide those 10 lines.
It's not being _moved_ to u-boot, it's already there. U-boot needs it because u-boot uses i2c. It would need to be duplicated in linux, and then both u-boot and linux would need to be updated each time a new platform is added. It's pretty much a given that a u-boot binary will only work on one platform. The same is not true with a compiled kernel. That makes it harder to all the platform specific stuff in linux. It's a little more than 10 lines too. Keep in mind that accessing all these devices registers isn't as easy in linux as u-boot. In linux you have to look up the register location in device tree and map the registers. All this code uses a system clock as a starting point, which u-boot already passes to linux. #if defined(CONFIG_MPC83XX) volatile immap_t *im = (immap_t *) CFG_IMMR; sccr = im->clk.sccr; #if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) || defined(CONFIG_MPC837X) switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) { case 0: tsec1_clk = 0; break; case 1: tsec1_clk = csb_clk; break; case 2: tsec1_clk = csb_clk / 2; break; case 3: tsec1_clk = csb_clk / 3; break; default: /* unkown SCCR_TSEC1CM value */ return -2; } #endif #if defined(CONFIG_MPC834X) || defined(CONFIG_MPC837X) || defined(CONFIG_MPC8315) switch ((sccr & SCCR_TSEC2CM) >> SCCR_TSEC2CM_SHIFT) { case 0: tsec2_clk = 0; break; case 1: tsec2_clk = csb_clk; break; case 2: tsec2_clk = csb_clk / 2; break; case 3: tsec2_clk = csb_clk / 3; break; default: /* unkown SCCR_TSEC2CM value */ return -4; } #elif defined(CONFIG_MPC8313) tsec2_clk = tsec1_clk; if (!(sccr & SCCR_TSEC1ON)) tsec1_clk = 0; if (!(sccr & SCCR_TSEC2ON)) tsec2_clk = 0; #endif switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) { case 0: enc_clk = 0; break; case 1: enc_clk = csb_clk; break; case 2: enc_clk = csb_clk / 2; break; case 3: enc_clk = csb_clk / 3; break; default: /* unkown SCCR_ENCCM value */ return -7; } #if defined(CONFIG_MPC837X) switch ((sccr & SCCR_SDHCCM) >> SCCR_SDHCCM_SHIFT) { case 0: sdhc_clk = 0; break; case 1: sdhc_clk = csb_clk; break; case 2: sdhc_clk = csb_clk / 2; break; case 3: sdhc_clk = csb_clk / 3; break; default: /* unkown SCCR_SDHCCM value */ return -8; } #endif #if defined(CONFIG_MPC834X) i2c1_clk = tsec2_clk; #elif defined(CONFIG_MPC8360) i2c1_clk = csb_clk; #elif defined(CONFIG_MPC832X) i2c1_clk = enc_clk; #elif defined(CONFIG_MPC831X) i2c1_clk = enc_clk; #elif defined(CONFIG_MPC837X) i2c1_clk = sdhc_clk; #endif #if !defined(CONFIG_MPC832X) i2c2_clk = csb_clk; /* i2c-2 clk is equal to csb clk */ #endif #elif defined (CONFIG_MPC85XX) #if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555) gd->i2c1_clk = sys_info.freqSystemBus; #elif defined(CONFIG_MPC8544) volatile ccsr_gur_t *gur = (void *) CFG_MPC85xx_GUTS_ADDR; /* * On the 8544, the I2C clock is the same as the SEC clock. This can be * either CCB/2 or CCB/3, depending on the value of cfg_sec_freq. See * 4.4.3.3 of the 8544 RM. Note that this might actually work for all * 85xx, but only the 8544 has cfg_sec_freq, so it's unknown if the * PORDEVSR2_SEC_CFG bit is 0 on all 85xx boards that are not an 8544. */ if (gur->pordevsr2 & MPC85xx_PORDEVSR2_SEC_CFG) gd->i2c1_clk = sys_info.freqSystemBus / 3; else gd->i2c1_clk = sys_info.freqSystemBus / 2; #else /* Most 85xx SOCs use CCB/2, so this is the default behavior. */ gd->i2c1_clk = sys_info.freqSystemBus / 2; #endif gd->i2c2_clk = gd->i2c1_clk; #elif defined(CONFIG_MPC86XX) #ifdef CONFIG_MPC8610 gd->i2c1_clk = sys_info.freqSystemBus; #else gd->i2c1_clk = sys_info.freqSystemBus / 2; #endif gd->i2c2_clk = gd->i2c1_clk; #endif _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev