changeset 2562:14c67833f954

* cdl/hal_arm_lpc24xx.cdl: Added I2C configuration options for interrupt priority, peripheral clock divider and I2C bus frequency * include/lpc24xx_misc.h: Added function hal_lpc_set_power() and peripheral identifiers for enabling peripheral modules in a common way * include/var_io.h: Removed CYGARC_HAL_LPC24XX_SET_PIN_FUN() * src/lpc24xx_misc.c: Bugfix in hal_lpc_get_pclk(), Added function hal_lpc_set_power(), Added hal_set_pin_function(), Added peripheral clock divider configuration for I2C modules in hal_hardware_init()
author asl
date Mon, 22 Sep 2008 19:20:59 +0000
parents 55c015cde894
children 73921684f287
files packages/hal/arm/lpc24xx/var/current/ChangeLog packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl packages/hal/arm/lpc24xx/var/current/include/lpc24xx_misc.h packages/hal/arm/lpc24xx/var/current/include/var_io.h packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c
diffstat 5 files changed, 220 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/packages/hal/arm/lpc24xx/var/current/ChangeLog
+++ b/packages/hal/arm/lpc24xx/var/current/ChangeLog
@@ -1,3 +1,17 @@
+2008-09-18  Uwe Kindler  <uwe_kindler@web.de>
+
+	* cdl/hal_arm_lpc24xx.cdl: Added I2C configuration options for
+	  interrupt priority, peripheral clock divider and I2C bus
+	  frequency
+	* include/lpc24xx_misc.h: Added function hal_lpc_set_power() and
+	  peripheral identifiers for enabling peripheral modules in a
+	  common way
+	* include/var_io.h: Removed CYGARC_HAL_LPC24XX_SET_PIN_FUN()
+	* src/lpc24xx_misc.c: Bugfix in hal_lpc_get_pclk(), Added function
+	  hal_lpc_set_power(), Added hal_set_pin_function(), Added
+	  peripheral clock divider configuration for I2C modules in
+	  hal_hardware_init()
+	
 2008-09-11  Uwe Kindler  <uwe_kindler@web.de>
 
 	* include/var_io.h: Added CYGARC_HAL_LPC2XXX_REG_EMAC_BASE to support
--- a/packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl
+++ b/packages/hal/arm/lpc24xx/var/current/cdl/hal_arm_lpc24xx.cdl
@@ -65,7 +65,7 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
     implements    CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT
     implements    CYGINT_HAL_ARM_ARCH_ARM7
     implements    CYGINT_HAL_ARM_THUMB_ARCH
-
+    
     # Let the architectural HAL see this variant's files
     define_proc {
         puts $::cdl_header "#define CYGBLD_HAL_VAR_INTS_H <cyg/hal/hal_var_ints.h>"
@@ -272,9 +272,67 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
                     channels. The divider divides the CPU clock to get the 
                     clock for the CAN peripherals."
             }
-        }      
+        }
+        
+        for { set ::channel 0 } { $::channel < 3 } { incr ::channel } { 
+            cdl_component CYGNUM_HAL_ARM_LPC24XX_I2C[set ::channel]_CLK {
+                display       "I2C channel [set ::channel] clock speed"
+                flavor        data
+                calculated    CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / \
+                              CYGNUM_HAL_ARM_LPC24XX_I2C[set ::channel]_CLK_DIV
+                description "
+                    The I2C clock speed is the CPU clock output divided by the 
+                    I2C clock divider" 
+                    
+                cdl_option CYGNUM_HAL_ARM_LPC24XX_I2C[set ::channel]_CLK_DIV {
+                    display       "I2C channel [set ::channel] clock divider"
+                    flavor        data
+                    legal_values  { 1 2 4 8 }
+                    default_value { 1 }
+                    description "
+                        This divider selects the peripheral clock for I2C 
+                        channel [set ::channel]. The divider divides the CPU 
+                        clock to get the clock for the I2C peripheral."
+                } 
+            }   
+        } 
     }
     
+    for { set ::channel 0 } { $::channel < 3 } { incr ::channel } { 
+        cdl_component CYGHWR_HAL_ARM_LPC24XX_I2C[set ::channel]_SUPP {
+            display       "I2C channel [set ::channel] configuration"
+            parent        CYGPKG_DEVS_I2C_ARM_LPC2XXX
+            flavor         bool
+            default_value  [set ::channel] == 0
+            description "
+                I2C channel [set ::channel] configuration data."         
+           
+            cdl_option CYGNUM_HAL_ARM_LPC24XX_I2C[set ::channel]_INT_PRIO {
+                display       "I2C channel [set ::channel] interrupt priority"
+                flavor        data
+                legal_values  0 to 15
+                default_value 15
+                description "
+                    There are 16 priority levels, corresponding to the
+                    values 0 through 15 decimal, of which 15 is the
+                    lowest priority.  The reset value of these
+                    interrupt priority registers defaults all
+                    interrupts to the lowest priority 15, allowing a
+                    single write to elevate the priority of an
+                    individual interrupt."  
+            }
+        
+            cdl_option CYGNUM_HAL_ARM_LPC24XX_I2C[set ::channel]_BUS_FREQ {
+                display       "I2C channel [set ::channel] bus frequency (Hz)"
+                flavor        data
+                legal_values  {100000 400000}
+                default_value 100000
+                description "
+                    This option selects the data rate for the I2C bus."
+            }
+        }
+    } 
+    
     cdl_component CYGNUM_HAL_RTC_CONSTANTS {
         display       "Real-time clock constants"
         flavor        none
@@ -316,7 +374,7 @@ cdl_package CYGPKG_HAL_ARM_LPC24XX {
 	    legal_values  { 0 to 15 }
         default_value 15
 	    description "
-            There are 16 priority levels, corresponding to the values 0 through 
+            There are 16 priority levels, corresponding to the values 0 through
             15 decimal, of which 15 is the lowest priority. The reset value of 
             these interrupt priority registers defaults all interrupts to the 
             lowest priority, allowing a single write to elevate the priority 
--- a/packages/hal/arm/lpc24xx/var/current/include/lpc24xx_misc.h
+++ b/packages/hal/arm/lpc24xx/var/current/include/lpc24xx_misc.h
@@ -51,9 +51,10 @@
 //=============================================================================
 
 //-----------------------------------------------------------------------------
-// Functions to obtain the current processor clock settings
-//-----------------------------------------------------------------------------
-externC cyg_uint32 hal_lpc_get_pclk(cyg_uint32 peripheral_id);
+// Function to obtain the current processor clock settings
+// Use PCLK identifiers below
+//
+externC cyg_uint32 hal_lpc_get_pclk(cyg_uint32 pclk_id);
 
 //
 // Identifiers for peripheral clock. Use these identifiers with the function
@@ -91,10 +92,55 @@ externC cyg_uint32 hal_lpc_get_pclk(cyg_
 
 
 //-----------------------------------------------------------------------------
+// Function to enable/disable power for certain peripheral
+// Use PCONP identifiers from below
+//
+externC void hal_lpc_set_power(cyg_uint8 pconp_id, int on);
+
+//
+// Identifiers for power control
+// hal_get_pclk()
+//
+#define CYNUM_HAL_LPC24XX_PCONP_TIMER0 1
+#define CYNUM_HAL_LPC24XX_PCONP_TIMER1 2
+#define CYNUM_HAL_LPC24XX_PCONP_UART0  3
+#define CYNUM_HAL_LPC24XX_PCONP_UART1  4
+#define CYNUM_HAL_LPC24XX_PCONP_PWM0   5
+#define CYNUM_HAL_LPC24XX_PCONP_PWM1   6
+#define CYNUM_HAL_LPC24XX_PCONP_I2C0   7
+#define CYNUM_HAL_LPC24XX_PCONP_SPI    8
+#define CYNUM_HAL_LPC24XX_PCONP_RTC    9
+#define CYNUM_HAL_LPC24XX_PCONP_SSP1   10
+#define CYNUM_HAL_LPC24XX_PCONP_EMC    11
+#define CYNUM_HAL_LPC24XX_PCONP_ADC    12
+#define CYNUM_HAL_LPC24XX_PCONP_CAN1   13
+#define CYNUM_HAL_LPC24XX_PCONP_CAN2   14
+#define CYNUM_HAL_LPC24XX_PCONP_I2C1   19
+#define CYNUM_HAL_LPC24XX_PCONP_LCD    20
+#define CYNUM_HAL_LPC24XX_PCONP_SSP0   21
+#define CYNUM_HAL_LPC24XX_PCONP_TIMER2 22
+#define CYNUM_HAL_LPC24XX_PCONP_TIMER3 23
+#define CYNUM_HAL_LPC24XX_PCONP_UART2  24
+#define CYNUM_HAL_LPC24XX_PCONP_UART3  25
+#define CYNUM_HAL_LPC24XX_PCONP_I2C2   26
+#define CYNUM_HAL_LPC24XX_PCONP_I2S    27
+#define CYNUM_HAL_LPC24XX_PCONP_SDC    28
+#define CYNUM_HAL_LPC24XX_PCONP_GPDMA  29
+#define CYNUM_HAL_LPC24XX_PCONP_ENET   30
+#define CYNUM_HAL_LPC24XX_PCONP_USB    31
+
+
+//-----------------------------------------------------------------------------
+// Configure pin function
+//
+void hal_set_pin_function(cyg_uint8 port, cyg_uint8 pin, cyg_uint8 function);
+
+
+//-----------------------------------------------------------------------------
 // Macros to derive the baudrate divider values for the internal UARTs
-// The LPC24xx family supports differents baudrate clocks for each single
+// The LPC24xx family supports different baudrate clocks for each single
 // UART. So we need a way to calculate the baudrate for each single UART
-// Now we rely on the fact that we use the same baurate clock for all
+// Now we rely on the fact that we use the same baudrate clock for all
 // UARTs and we query only UART0
 //-----------------------------------------------------------------------------
 #define CYG_HAL_ARM_LPC24XX_PCLK(_pclkid_) hal_lpc_get_pclk(_pclkid_) 
--- a/packages/hal/arm/lpc24xx/var/current/include/var_io.h
+++ b/packages/hal/arm/lpc24xx/var/current/include/var_io.h
@@ -463,9 +463,6 @@
 #define CYGARC_HAL_LPC24XX_REG_PINMODE8                  0x060
 #define CYGARC_HAL_LPC24XX_REG_PINMODE9                  0x064
 
-#define CYGARC_HAL_LPC24XX_SET_PIN_FUN(_regval_, _pin_, _func_) \
-    (_regval_) = ((_regval_) & ~(0x3 << ((_pin_) << 1))) | ((_func_) << ((_pin_) << 1))
-
 
 //=============================================================================
 // SSP - Synchronous Serial Port
--- a/packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c
+++ b/packages/hal/arm/lpc24xx/var/current/src/lpc24xx_misc.c
@@ -78,7 +78,7 @@
 //===========================================================================
 // Get peripheral clock for a certain peripheral
 //===========================================================================
-cyg_uint32 hal_lpc_get_pclk(cyg_uint32 peripheral_id)
+cyg_uint32 hal_lpc_get_pclk(cyg_uint32 pclk_id)
 {
     static const cyg_uint8 divider_tbl[4] =
     {
@@ -87,18 +87,22 @@ cyg_uint32 hal_lpc_get_pclk(cyg_uint32 p
     cyg_uint32 pclkselreg;
     cyg_uint32 regval;
     cyg_uint8  divider;
+    
+    CYG_ASSERT(pclk_id >= CYNUM_HAL_LPC24XX_PCLK_WDT &&
+               pclk_id <= CYNUM_HAL_LPC24XX_PCLK_SYSCON,
+               "Invalid peripheral clock ID");
 
     //
     // decide if we need PCLKSEL0 or PCLKSEL1
     //
-    pclkselreg = ((peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_ACF) ? 
+    pclkselreg = ((pclk_id <= CYNUM_HAL_LPC24XX_PCLK_ACF) ? 
                    CYGARC_HAL_LPC24XX_REG_PCLKSEL0 : 
                    CYGARC_HAL_LPC24XX_REG_PCLKSEL1); 
     HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval);
-    regval  = (regval >> ((peripheral_id & 0xF) << 1)) & 0x03;
+    regval  = (regval >> ((pclk_id & 0xF) << 1)) & 0x03;
     divider = divider_tbl[regval];    
-    if ((8 == divider) && (peripheral_id >= CYNUM_HAL_LPC24XX_PCLK_CAN1)
-        && (peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_ACF))
+    if ((8 == divider) && (pclk_id >= CYNUM_HAL_LPC24XX_PCLK_CAN1)
+        && (pclk_id <= CYNUM_HAL_LPC24XX_PCLK_ACF))
     {
         divider = 6;
     }           
@@ -118,7 +122,10 @@ void hal_lpc_set_pclk(cyg_uint32 periphe
     cyg_uint32 clock;
     cyg_uint32 pclkselreg;
     cyg_uint32 regval;
-     
+    
+    CYG_ASSERT(peripheral_id >= CYNUM_HAL_LPC24XX_PCLK_WDT &&
+               peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_SYSCON,
+               "Invalid peripheral clock ID");
     CYG_ASSERT(divider <= 8, "Wrong peripheral clock divider value"); 
     //
     // decide if we need PCLKSEL0 or PCLKSEL1
@@ -129,8 +136,55 @@ void hal_lpc_set_pclk(cyg_uint32 periphe
     HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval);
     divider = (6 == divider) ? 8 : divider;
     clock = clock_tbl[divider >> 1];
+    regval &= ~(0x03 << ((peripheral_id & 0xF) << 1));
     regval |= (clock << ((peripheral_id & 0xF) << 1));   
-    HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval);             
+    HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval);
+}
+
+
+//===========================================================================
+// Enable/Disable power for certain peripheral
+//===========================================================================
+void hal_lpc_set_power(cyg_uint8 pconp_id, int on)
+{
+    cyg_uint32 regval;
+    
+    CYG_ASSERT(pconp_id >= CYNUM_HAL_LPC24XX_PCONP_TIMER0 &&
+               pconp_id <= CYNUM_HAL_LPC24XX_PCONP_USB,
+               "Invalid peripheral power ID");
+    HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + 
+                    CYGARC_HAL_LPC24XX_REG_PCONP, regval);
+    if (on)
+    {
+        regval |= (0x01 << pconp_id);
+    }
+    else
+    {
+        regval &= ~(0x01 << pconp_id);
+    }
+    
+    HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + 
+                     CYGARC_HAL_LPC24XX_REG_PCONP, regval);
+}
+
+
+//===========================================================================
+// Set pin function
+//===========================================================================
+void hal_set_pin_function(cyg_uint8 port, cyg_uint8 pin, cyg_uint8 function)
+{
+    CYG_ASSERT(port <= 4,  "Port value out of bounds");
+    CYG_ASSERT(pin  <= 31, "Pin value out of bounds");
+    CYG_ASSERT(function <= 3, "Invalid function value");
+    
+    cyg_uint32 regval;
+    cyg_uint8 pinsel_reg = port << 1;
+    pinsel_reg += (pin > 15) ? 1 :0;
+    pinsel_reg <<= 2;
+    HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_PIN_BASE + pinsel_reg, regval);
+    regval &= ~(0x03 << ((pin & 0xF) << 1));
+    regval |= (function << ((pin & 0xF) << 1));  
+    HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_PIN_BASE + pinsel_reg, regval);
 }
 
 
@@ -243,9 +297,39 @@ void hal_hardware_init(void)
     //
     // Setup peripheral clocks here according to configuration
     // 
-    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN1, CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
-    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN2, CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
-    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_ACF,  CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN1, 
+                     CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN2,   
+                     CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_ACF,    
+                     CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_I2C0,  
+                     CYGNUM_HAL_ARM_LPC24XX_I2C0_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_I2C1,  
+                     CYGNUM_HAL_ARM_LPC24XX_I2C1_CLK_DIV);
+    hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_I2C2,  
+                     CYGNUM_HAL_ARM_LPC24XX_I2C2_CLK_DIV);
+                     
+    //
+    // Enable power for all used on-chip peripherals
+    //
+#ifdef CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP
+    hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C0, 1);
+#else
+    hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C0, 0);
+#endif // CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP 
+
+#ifdef CYGHWR_HAL_ARM_LPC24XX_I2C1_SUPP
+    hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C1, 1);
+#else
+    hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C1, 0);
+#endif // CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP  
+
+#ifdef CYGHWR_HAL_ARM_LPC24XX_I2C2_SUPP
+    hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C2, 1);
+#else
+    hal_lpc_set_power(CYNUM_HAL_LPC24XX_PCONP_I2C2, 0);
+#endif // CYGHWR_HAL_ARM_LPC24XX_I2C0_SUPP    
     
     //
     // Fill vector address registers with interrupt number. If an interrupt