ARMEBS4  revision-26.06.2015
clock_gen_cs2200.c
2 #include "stm32/stm32f4xx_gpio.h"
3 #include "stm32/stm32f4xx_rcc.h"
4 #include "stm32/stm32f4xx_i2c.h"
5 #include "stm32/stm32f4xx_misc.h"
6 #include "heivs/stm32_gpio.h"
7 #include "heivs/stm32_i2c.h"
8 
9 #define EXTCLK_DIR_UP 0
10 #define EXTCLK_DIR_DOWN 1
11 
12 #define CS_DEVICE_ID 0x01
13 #define CS_DEVICE_CTRL 0x02
14 #define CS_DEVICE_CFG1 0x03
15 #define CS_GLOBAL_CFG 0x05
16 #define CS_RATIO_3 0x06 /* MSB byte of Ratio */
17 #define CS_RATIO_2 0x07 /* MSB - 1 byte of Ratio */
18 #define CS_RATIO_1 0x08 /* MSB - 2 byte of Ratio */
19 #define CS_RATIO_0 0x09 /* LSB byte of Ratio */
20 #define CS_FUNCT_CFG1 0x16
21 #define CS_FUNCT_CFG2 0x17
22 
23 static status_e clk_gen_WriteReg(struct clock_gen_t *dev, uint8_t reg, uint8_t Value)
24 {
25  status_e status;
26  const uint8_t cmd [] =
27  {
28  reg,
29  Value,
30  };
31 
32  status = bus_get(dev->bus);
33  if (status != NO_ERROR)
34  {
35  return status;
36  }
37 
38  status = bus_write(dev->bus, dev->i2c_address, cmd, ARRAY_SIZE(cmd));
39  if (status != NO_ERROR)
40  {
41  return status;
42  }
43 
44  status = bus_release(dev->bus);
45  if (status != NO_ERROR)
46  {
47  return status;
48  }
49 
50  return status;
51 }
52 
53 static uint32_t ratio_compute(const struct _clk_gen_info_t *g)
54 {
55  uint64_t ratio;
56  ratio = g->f_out;
57  ratio *= g->ppm;
58  ratio /= 1000000;
59  ratio += g->f_out;
60  ratio *= (1 << 20);
61  ratio /= g->f_in;
62 
63  return ratio;
64 }
65 
66 status_e clock_gen_init(struct clock_gen_t *dev, uint32_t OutFreq, uint32_t InFreq)
67 {
68  status_e status;
69  uint32_t ratio;
70 
71  dev->info.f_in = InFreq;
72  dev->info.f_out = OutFreq;
73  dev->info.ppm = 0;
74 
75  status = bus_init(dev->bus);
76  if (status != NO_ERROR)
77  {
78  return status;
79  }
80 
81  /* Get the ratio to be programmed */
82  ratio = ratio_compute(&dev->info);
83 
84  /* Freeze the configuration */
85  status = clk_gen_WriteReg(dev, CS_GLOBAL_CFG, 0x08);
86  if (status != NO_ERROR)
87  {
88  return status;
89  }
90 
91  /* Auxilary output disabled */
92  status = clk_gen_WriteReg(dev, CS_DEVICE_CTRL, 0x02);
93  if (status != NO_ERROR)
94  {
95  return status;
96  }
97 
98  /* No division on Ratio */
99  status = clk_gen_WriteReg(dev, CS_DEVICE_CFG1, 0x00);
100  if (status != NO_ERROR)
101  {
102  return status;
103  }
104 
105  status = clk_gen_WriteReg(dev, CS_RATIO_3, (uint8_t) (((ratio & 0xFF000000) >> 24)));
106  if (status != NO_ERROR)
107  {
108  return status;
109  }
110 
111  status = clk_gen_WriteReg(dev, CS_RATIO_2, (uint8_t) (((ratio & 0xFF0000) >> 16)));
112  if (status != NO_ERROR)
113  {
114  return status;
115  }
116 
117  status = clk_gen_WriteReg(dev, CS_RATIO_1, (uint8_t) (((ratio & 0xFF00) >> 8)));
118  if (status != NO_ERROR)
119  {
120  return status;
121  }
122 
123  status = clk_gen_WriteReg(dev, CS_RATIO_0, (uint8_t) (ratio & 0xFF));
124  if (status != NO_ERROR)
125  {
126  return status;
127  }
128 
129  /* Reference clock input divider set to 2 (input = 24 MHz) */
130  status = clk_gen_WriteReg(dev, CS_FUNCT_CFG1, 0x08);
131  if (status != NO_ERROR)
132  {
133  return status;
134  }
135 
136  /* Unfreeze: start clocking */
137  status = clk_gen_WriteReg(dev, CS_GLOBAL_CFG, 0x01);
138  if (status != NO_ERROR)
139  {
140  return status;
141  }
142 
143  return NO_ERROR;
144 }
145 
146 status_e clock_gen_adjust_ppm(struct clock_gen_t *dev, int32_t ppm)
147 {
148  status_e status;
149  uint32_t old_ratio;
150  uint32_t ratio;
151 
152  old_ratio = ratio_compute(&dev->info);
153  dev->info.ppm += ppm;
154  ratio = ratio_compute(&dev->info);
155 
156  if (old_ratio == ratio)
157  {
158  /* Nothing to be done */
159  return NO_ERROR;
160  }
161 
162  /* freeze */
163  status = clk_gen_WriteReg(dev, CS_GLOBAL_CFG, 0x09);
164  if (status != NO_ERROR)
165  {
166  return status;
167  }
168 
169  /* Write the Ratio bytes */
170  status = clk_gen_WriteReg(dev, CS_RATIO_3, (uint8_t) (((ratio & 0xFF000000) >> 24)));
171  if (status != NO_ERROR)
172  {
173  return status;
174  }
175 
176  status = clk_gen_WriteReg(dev, CS_RATIO_2, (uint8_t) (((ratio & 0xFF0000) >> 16)));
177  if (status != NO_ERROR)
178  {
179  return status;
180  }
181 
182  status = clk_gen_WriteReg(dev, CS_RATIO_1, (uint8_t) (((ratio & 0xFF00) >> 8)));
183  if (status != NO_ERROR)
184  {
185  return status;
186  }
187 
188  status = clk_gen_WriteReg(dev, CS_RATIO_0, (uint8_t) (ratio & 0xFF));
189  if (status != NO_ERROR)
190  {
191  return status;
192  }
193 
194  /* unfreeze */
195  status = clk_gen_WriteReg(dev, CS_GLOBAL_CFG, 0x01);
196  if (status != NO_ERROR)
197  {
198  return status;
199  }
200 
201  return status;
202 }
This file contains all the functions prototypes for the RCC firmware library.
This file contains all the functions prototypes for the GPIO firmware library.
status_e bus_release(const struct heivs_bus_t *bus)
Release exclusive access to the bus.
Definition: bus.c:149
status_e bus_write(const struct heivs_bus_t *bus, uint32_t address, const void *data, size_t len)
Write data to the bus.
Definition: bus.c:243
This file contains all the functions prototypes for the I2C firmware library.
board specific defines
Clock gen driver.
status_e bus_init(const struct heivs_bus_t *bus)
initialize the bus
Definition: bus.c:59
status_e bus_get(const struct heivs_bus_t *bus)
Get exclusive access to the bus.
Definition: bus.c:134
status_e
Known errors.
Definition: error.h:21
#define ARRAY_SIZE(x)
Number of elements in the array.
Definition: utils.h:19
No error.
Definition: error.h:28
i2c bus